elf 记录

链接器对编译生成的目标文件进行链接时,A.
首先进行符号解析,找出外部符号在哪定义。如果外部符号在一个静态库中定义,则直接将对应的定义代码复制到最终生成的目标文件中。B.
接着链接器进行符号重定位。编译器在生成目标文件时,通常使用从零开始的相对地址,而在链接过程中,链接器从一个指定的地址开始,根据输入目标文件的顺
序,以段(segment)为单位将它们拼装起来。其中每个段可以包括很多个节(section)。除了目标文件的拼装,重定位过程中还完成了下面两个任
务:一是生成最终的符号表,二是对代码段(.text)中的某些位置进行修改,要修改的位置由编译器生成的重定位表指出

链接过程中还会生成两个表:got表和plt表。

 

got表中每一项都是本运行模块要引用的全局变量或函数的地址,可以用got表来间
接引用全局变量。函数也可以把got表的首地址作为一个基准,用相对该基准的偏移量来(直接)引用静态函数。由于动态链接器(ld-linux.so)不
会把运行模块(*.so)加载到固定地址,在不同进程的地址空间中各运行模块的绝对地址、相对地址都不同。这种不同反映到got表上,就是每个进程的每个
运行模块都有独立的got表,所以进程间不能共享got表(内容)。

 

plt表中每一项都是一小段汇编代码,对应于本运行模块要引用的每一个全局函数。当链接器发现某个符号引用是位于其它共享目标文件(动态连接库*.so)中的一个全局函数时,就在文件的plt表里创建一个项目,以便将来重定位

一个elf头,描绘了整个文件的组织结构,这个文件中会有多个段(segment),每个段都由相应的节(section)拼装而成。

 

对由链接器链接生成的可执行目标文件进行加载运行时,内核首先读取elf文件头。根
据头部数据指示分别读入各种数据结构,找出可加载的段并调用mmap()函数将其加载到内存。内核找到标记为PT_INTERP的段,这个段对应着动态链
接器的名称,然后加载动态链接器(linux中通常是/lib/ld-linux.so.2)。接着内核将控制权交给动态链接器。动态链接器检查程序对外
部文件(共享库)的依赖性,并在需要时对其进行加载。之后动态链接器开始对程序中的外部引用(即全局变量/函数)进行重定位,即定位出程序其引用的外部变
量/函数的真实内存地址。R_386_GLOB_DAT类型的重定位项目涉及到got表。R_386_JMP_SLOT类型的重定位项目涉及到plt表。
动态链接还有一个延迟(lazy)特性,即真正引用时才进行重定位(环境变量LD_BIND_NOW为空值NULL时)。接下来动态链接器执行elf文件
中标记为.init节的代码,进行程序运行的初始化。最后动态链接器把控制权交给程序,从elf文件头中定义的入口处开始执行程序。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值