区别

常用的可执行文件包含两类:原始二进制文件(bin)和可加载执行的二进制文件,在linux中可加载执行的二进制文件为elf文件。

BIN文件是直接的二进制文件,内部没有地址标记。bin文件内部数据按照代码段或者数据段的物理空间地址来排列。一般用编程器烧写时从00开始,而如果下载运行,则下载到编译时的地址即可。

在Linux OS上,为了运行可执行文件,他们是遵循ELF格式的,通常gcc -o test test.c,生成的test文件就是ELF格式的。执行elf文件时内核会使用加载器来解析elf文件并执行。

ELF文件格式是一个开放标准,各种UNIX系统的可执行文件都采用ELF格式,它有三种不同的类型:

  • 可重定位的目标文件(Relocatable,或者Object File)

  • 可执行文件(Executable)

  • 共享库(Shared Object,或者Shared Library)

$ file sum.o sub.o test.o libsub.so test
sum.o: ELF -bit LSB relocatable, Intel , version (SYSV), not stripped
sub.o: ELF -bit LSB relocatable, Intel , version (SYSV), not stripped
test.o: ELF -bit LSB relocatable, Intel , version (SYSV), not stripped
libsub.so: ELF -bit LSB shared object, Intel , version (SYSV), not stripped
test: ELF -bit LSB executable, Intel , version (SYSV), for GNU/Linux 2.2., dynamically linked (uses shared libs), not stripped 结果很清楚的告诉我们他们都属于哪一个类别。比方 sum.o 是应用在x86架构上的可重定位文件。这个结果也间接的告诉我们,x86是小端模式(LSB)的32位结构。
那对于 file 命令来说,它又能如何知道这些信息?答案是在ELF对象文件的最前面有一个ELF文件头,里面记载了所适用的处理器、对象文件类型等各种信息。

ELF格式提供了两种不同的视角,链接器把ELF文件看成是Section的集合,而加载器把ELF文件看成是Segment的集合。

在Embedded中,如果上电开始运行,没有OS系统,如果将ELF格式的文件烧写进去, 包含一些ELF文件的符号表字符表之类的section,运行碰到这些,就会导致失败,如果用objcopy生成纯粹的二进制文件,去除掉符号表之类的 section,只将代码段数据段保留下来,程序就可以一步一步运行。elf文件里面包含了符号表等。BIN文件是将elf文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像。并且elf文件中代码段数据段的位置并不是它实际的物理位置,实际物理位置是在表中标记出来的。

文件的内容

1. BIN文件是 raw binary 文件,这种文件只包含机器码。
2. ELF文件除了机器码外,还包含其它额外的信息,如段的加载地址,运行地址,重定位表,符号表等。
所以ELF文件的体积比对应的BIN文件要大。

文件的执行

1. 执行raw binary很简单,只需要将程序加载到其起始地址,就可以执行;

    FILE *fp = fopen("vmlinux.bin", "rb");
fread(VMLINUX_START, , VMLINUX_SIZE, fp);
((void (*)(void))VMLINUX_START)();

2. 执行ELF程序则需要一个ELF Loader。
uboot和Linux kernel启动的时候是没有ELF Loader的,所以烧在flash上的文件只能是raw binary格式的,即镜像文件image。

文件的转换

1. 通过gcc编译出来的是elf文件
2. 通过objcpy可以把elf文件转换为bin文件

    CC=ppc-gcc
LD=ppc-ld
OBJCOPY=ppc-objcopy
$(CC) -g $(CFLAG) -c boot.S
#先将boot.S文件生成boot.o
$(LD) -g -Bstatic -T$(LDFILE) \
-Ttext 0x12345600 boot.o \
--start-group -Map boot.map -o boot.elf
#再将boot.o生成boot.elf
$(OBJCOPY) -O binary -R .note -R .comment -S boot.elf boot.bin
#接着将 boot.elf 转换为 boot.bin
#使用 -O binary (或--out-target=binary) 输出为原始的二进制文件
#使用 -R .note (或--remove-section) 输出文件中不要.note这个section,缩小了文件尺寸
#使用 -S (或 --strip-all) 输出文件中不要重定位信息和符号信息,缩小了文件尺寸

编译完uboot后生成:
     u-boot         ELF文件可用来调试
     u-boot.bin     BIN文件用来烧在Flash上

编译linux生成:
     vmlinux        ELF文件可用来调试
     vmlinux.bin    BIN文件,没直接用过

zImage/vmlinuz/bzimage
          将vmlinux.bin压缩,并加上一段解压代码得到的,不可和bootloader共存?

uImage        
          uboot专用的内核镜像,在zImage前加了一个64字节的头,描述内核版本、加载地址、生成时间,文件大小等等。 其0x40后的内容和zImage一样。
          它是由uboot的工具mkImage生成的。

uImage相对于zImage的优点在于:uImage可以和uboot共存。

文件的调试

1. 我们调试一般都是使用elf文件,比如:

    nm elf文件         #得到符号表
objdump -D elf文件 #反汇编,且汇编代码与源码混排

2. bin文件比较杯具,里面全是机器码,所以只能反汇编

objdump -b binary -m powerpc uboot.bin

此外还有工具:readelf,objcopy,ldd,file等。

参考:

最新文章

  1. java基础杂烩
  2. PAT (Advanced Level) Practise:1001. A+B Format
  3. Java使用poi操作cexel
  4. Mysql 关键字及保留字
  5. Android 一个app启动另一个app
  6. 在Android应用中使用OpenGL
  7. 全文检索引擎Solr系列—–全文检索基本原理
  8. 用命令行将Java程序打包为jar文件
  9. 理解I/O Completion Port
  10. 解决IE6浏览器下position:fixed固定定位问题
  11. iSwifting社区【www.iSwifting.com】招聘版主
  12. Android Intent 三解决
  13. css左侧固定宽度,右侧自适应的几种实现方法
  14. RocketMQ4.4.0新特性分享
  15. Xilinx Vivado的使用详细介绍(3):使用IP核
  16. DOS 命令 os系统(windows)
  17. 【java提高】---HashSet 与TreeSet和LinkedHashSet的区别
  18. MySQL的lock tables和unlock tables的用法(转载)
  19. RednaxelaFX:软件工程师、主攻高级编程语言虚拟机的设计与实现
  20. SqlServer性能优化 Sql语句优化(十四)

热门文章

  1. request.startAsync()不支持异步操作
  2. OC中数组的使用方法
  3. [Tools] Batch Create Markdown Files from a Template with Node.js and Mustache
  4. AFNetworking 下载文件断点续传操作
  5. 【转】iBatis简单入门教程
  6. user-defined conversion
  7. js重置form表单
  8. arm-linux内核start_kernel之前启动分析(1)-接过bootloader的衣钵
  9. maven 动态版本 aliyun阿里云Maven仓库地址——加速你的maven构建
  10. ip地址库选择