链接、装载与库:Linux下的ELF文件

简介


    ELF(Execuable Linkable Format)文件,即可执行可链接格式的文件。


    在Linux系统中,目标文件(即源码编译后的但是未进行链接的中间文件)、可执行文件、动态链接库均按照可执行文件格式存储,静态链接库稍有不同,但是它也是由多个目标文件捆绑在一起,再加上一些索引等而形成的文件。

    根据ELF文件标准,将Linux系统中采用ELF格式的文件分为四类:

    可执行文件:如*.sh文件等,主要包含可直接执行的程序;

    可重定位文件:如*.o文件,主要包含代码、数据,用来链接成执行文件、动态或静态链接库;

    共享目标文件:如*.so文件,主要包含代码、数据,主要在两种情况下使用:
                  1) 跟其他可重定位文件和共享目标文件链接,产生新的目标文件;
                  2) 与可执行文件结合,作为进程映象的一部分;
    核心转储文件:如core dump文件,在进程意外终止时产生,主要包含该进程的地址空间内容及终止时的堆栈调用等信息;


ELF文件结构


    常见的ELF文件结构如图示:



    File Header:文件头,描述整个文件的属性,包括是否可执行、静态或动态链接及入口地址、目标硬件及操作系统信息,以及段表(段表描述文件中各个段在文件中的偏移位置及段的属性);

    .text:代码段,经编译后的二进制机器代码;

    .data:数据段,保存已初始化的全局变量和局部静态变量;

    .rodata:只读数据段,保存只读数据,比如const变量、字符串常量。有时,因为编译器的不同,字符串产量也会放到.data段;

    .bss段:BSS段(Block Started by Symbol), 保存未初始化的全局变量和局部静态变量,实质是为它们预留位置,并没有内容,在文件中不占据空间,当程序运行时,才开始分配内存空间;

    .debug*:以debug开头的段基本上属于保存的调试信息。软件开发过程中,Debug版本与Release版本内存占用大小相差很大,主要就是Debug版本多了这些调试信息。

    总体来说,程序源码被编译后主要分成两部分:程序指令(.text段等)、程序数据(.data和.bss段等)。

    (其他段的信息,详细资料可以查看《程序员的自我修养》第三章)


    补充:

    为什么程序指令跟程序数据分开?

    1) 程序被装载,指令和数据分别映射到两个不同部分,两个部分权限可以不同设置,指令部分只读、数据部分则可读写,这样可以防止程序指令被改写;

    2) 指令和数据分离,有利于提高CPU的缓存命中率;

    3) (最重要)当系统中运行多个该程序的副本时,内存只须保存一份该程序的指令部分,节省内存空间;


    Section Header Table:段表,ELF文件除了文件头以外最重要的结构,描述了上述各个段的信息,比如段的名称、长度、在文件的偏移、读写权限等;

    String Tables:字符串表,ELF文件中用到的字符串,比如段名、变量名等,保存在该字符串表中;

    Relocation Tables:重定位表,如果目标文件中的代码段和数据段中存在有绝对地址的引用部分,那么这部分信息都会记录在重定位表中。对于每个需要重定位的代码段或数据段,都会有相应的重定位表;

    Symbol Tables:符号表,记录了目标文件中所用到的所有符号。在链接中,所有函数和变量统称为符号;函数名或变量名就是符号名,将符号表中所有符号进行分类:

    1) 定义在本目标文件的全局符号

    2) 在本目标文件中引用的其他文件定义的全局符号,即外部符号

    3) 各种段名,如“.text”,“.data”

    4) 局部符号(链接器会忽视这些)

    5) 行号信息(可选)


    补充:

    以C/C++代码为例,符号表涉及最常见的知识有extern "C",C++的符号修饰等等。


参考资料

     

     《程序员的自我修养》



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值