免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 969 | 回复: 0
打印 上一主题 下一主题

elf格式学习总结 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-09 09:29 |只看该作者 |倒序浏览

当编译一个源文件生成目标文件时,会在目标文件中生成符号表和重定位表。

符号表包含在文件中定义的全局符号以及在文件中引用的外部符号(外部函数或变量)。

重定位表告诉链接器在哪些位置要进行重定位操作。

编译生成的目标文件在文件的开始处会有一个elf头,描绘了整个文件的组织结构。它还包括很多节(section)。这些节有的是系统定义好的,有些是用户在文件在通过.section命令自定义的,链接器会将各输入目标文件中的相同的节合并。

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

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

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

plt表中第一项都是一小段代码,对应于本运行模块要引用的一个全局函数。当链接器发现某个符号引用是共享目标文件中的一个函数时,就在pltk 创建一个入口。

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

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


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/63991/showart_1820079.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP