4.2.2 重定位表
链接器怎么知道那些指令是要被调整?而这些指令的中那些部分需要被调整?记得在ELF文件中
有一个重定位表,专门保存这些与重定位相关的信息,重定位表往往是一个或者多个重定位段。
对于每个要被重定位的段在ELF中都会有一个对应的重定位段。比如代码段“.text”有要被重定位的地方,
那么会有一个相对应的“.rel.text”段保存代码段中的重定位表。可以用objdump -r a.o
来查看ELF文件的重定位表。如图4.2.4所示:
***图4.2.4***
上图显示了目标文件a.o中所引用到的外部符号的地址。每个要被重定位的地方叫重定位入口
(Relocation Entry),可以看到a.o中有两个重定位入口。重定位入口的偏移表示该入口在要
被重定位的段中的位置,而RELOCATION RECORDS FOR[.text]表示这个重定位表是代码段的重定位
表,所以偏移表示代码段中需要被调整的位置。用objdump -d a.o查看a.o的反汇编代码,如图
4.2.5所示:
***图4.2.5***
对照前面的重定位表,可以得知图4.2.4中偏移为0x15和0x21正好是图4.2.5中mov指令和call
指令的地址部分。
重定位表是由Elf32_Rel结构提构成的数组,每个数组元素对应一个重定位入口。Elf32_Rel的
定义如下:
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
}Elf32_Rel;
其中,r_offset是重定位入口的偏移。对于可重定位文件来说,这个值是该重定位入口所要
修正的位置的第一个字节相对与起始段的偏移;对于可执行文件或者共享文件来说,这个值
是该重定位入口所要修正的位置的第一个字节的虚拟地址。r_info是重定位的类型和符号,
这个成员的低8位值表示重定位的类型,高24位表示重定位入口的符号在符号表中的下标。