linux下elf重定位理解

重定位:就是把符号的value进行重新定位,value可是地址也可是其他类型值.要重点理解
编译器、连接器和装载器各个职能,熟悉编译、连接和加载过程、符号(symbol)、段(section)等概念

符号:高级语言经编译处理后,在binary层面上,统一以符号表示各个变量、函数实体。是连接和重定位桥
    梁。不同编译器有不同的地符号影射,比如c语言中,以前有的编译器固定变量前加下划线 int a ==>_a

段:binary层面对指令和数据的组织,方便管理、理解。深入参考汇编中有关段概念。
符号和段都是属于ELF表示范畴,是对binary层面的描述。深入可参考ELF或者coff相关文档


重定位分为两大类:普通和动态。普通就是连接时候重定位,动态是指加载、运行重定位。

重定位过程要用到一些表,来辅助定位,有.rel.text、 .rel.dyn和.rel.plt。下面根据他们来展开说明。

.rel.text
  重定位的地方在.text段内,以offset指定具体要定位位置。在连接时候由连接器完成。注意比较.text段前后变化。指的是比较.o文件和最终的执行文件(或者动态库文件)。就是重定位前后比较,以上是说明了具体比较对象而已。

.rel.dyn
  重定位的地方在.got段内。主要是针对外部数据变量符号。例如全局数据。重定位在程序运行时定位,一般是在.init段内。定位过程:获得符号对应value后,根据rel.dyn表中对应的offset,修改.got表对应位置的value。
 
.rel.plt 
  重定位的地方在.got.plt段内(注意也是.got内,具体区分而已)。 主要是针对外部函数符号。一般是函数首次被调用时候重定位。可看汇编,理解其首次访问是如何重定位的,实际很简单,就是初次重定位函数地址,以后经重定位后,存放的是最终函数地址(参考过程说明)。  所有外部函数调用都是经过一个对应桩函数,这些桩函数都在.got.plt内。
 
 过程说明:调用对应桩函数--->桩函数取出.got表(具体是.got.plt)表内地址--->然后跳转到这个地址.如果是第一次,这个跳转地址默认是桩函数本身跳转处地址的下一个指令地址(目的是通过桩函数集中取地址和加载地址),后续接着把对应函数的真实地址加载进来放到.got表对应处,同时跳转执行该地址指令.以后桩函数从.got取得地址都是真实函数地址了。
  
 
 
.rel.text属于普通重定位辅助段 ,他由编译器编译产生,存在于obj文件内。连接器连接时,他 用于最终可执行文件或者动态库的重定位。通过它修改原obj文件的.text段后,和并      到 最终可执行文件或者动态文件的.text段。

.rel.dyn和.rel.plt是动态定位辅助段。由连接器产生,存在于可执行文件或者动态库文
     件内。用于运行时重定位。.rel.dyn 对应地点在.got表内;.rel.plt  在.got.plt,注意不是在.text,这点和普通不同,也是重要点。要理解,动态连接中访问外部符号是通过.got和.got.plt


例子在此不举了,分析这个重定位过程,最好还是自己动手写个例子来,比单纯看文章好理解。
分析没多久,还有好多问题,大家多多指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值