zoukankan      html  css  js  c++  java
  • 可执行文件格式elf和bin

    区别

    常用的可执行文件包含两类:原始二进制文件(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 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
    sub.o:     ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
    test.o:    ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
    libsub.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
    test:      ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, 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, 1, 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.ELF格式文件和BIN文件的区别
    2.可执行文件(ELF)格式的理解
    3. 嵌入式系统可执行文件格式
    4. Linux中ELF格式文件介绍
    5. ELF文件和BIN文件
  • 相关阅读:
    对MVC模型的自悟,详尽解释,为了更多非计算机人员可以理解
    openSUSE leap 42.3 实现有线 无线同时用
    Fedora27 源配置
    Ubuntu16.04添加HP Laserjet Pro M128fn打印机和驱动
    openSUSE leap 42.3 添加HP Laserjet Pro M128fn打印机和驱动
    OpenSUSE Leap 42.3下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    OpenSUSE Leap 42.3 安装java(Oracle jre)
    linux下支持托盘的邮件客户端Sylpheed
    Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    Firefox 浏览器添加Linux jre插件
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/7237189.html
Copyright © 2011-2022 走看看