ELF的.rela.dyn节

.rela.dyn节是什么节呢?该节保存的是重定位信息,数据内容是包含带有显式加数的重定位条目,每个条目固定大小(24个字节)。话又说回来,什么是重定位?

这里引用oracle网站的解答:重定位是连接符号引用与符号定义的过程。例如,程序调用函数时,关联的调用指令必须在执行时将控制权转移到正确的目标地址。可重定位文件必须包含说明如何修改其节内容的信息。通过此信息,可执行文件和共享目标文件可包含进程的程序映像的正确信息。重定位项即是这些数据。

插一句,个人觉得oracle官方文档对重定位节的介绍通俗易懂(虽然是solaris系统,但也是Linux内核)。

了解了重定位,现在回到开头的问题,.rela.dyn节是什么节?.rela.dyn在动态链接的目标文件中保存的是需要被重定位的变量数据。

下面来看看重定位节的位置在哪儿,已知示例文件中节头表显示.rela.dyn节的偏移量是0x488,十进制是1160,大小是0xc0,十进制是192

%title插图%num

已知每个条目固定大小24个字节,那么我们可以计算出一共有8个条目,即192/24=8,现在我们看看每个条目的构成,即每个条目的结构组成

%title插图%num

每个条目分别由3个部分组成:r_offset、r_info和r_addend,每个部分占8个字节,正好3*8=24个字节(每个条目的大小)

r_offset。

本字段保存的是重定位所作用的位置。对于重定位文件来说,此值是受重定
位作用的存储单元在节中的字节偏移量;对于可执行文件或共享目标文件来说,此
值是受重定位作用的存储单元的虚拟地址。

r_info。

该字段指定必须对其进行重定位的符号表索引以及要应用的重定位类型。例如,调用指令的重定位项包含所调用的函数的符号表索引。如果索引是未定义的符号索引 STN_UNDEF,则重定位将使用零作为符号值。

重定位类型特定于处理器。重定位项的重定位类型或符号表索引是将 ELF64_R_TYPE 或 ELF64_R_SYM 分别应用于项的 r_info 成员所得的结果,计算过程如下图:

%title插图%num

r_addend。

该字段是一个常量加数,用于计算存储在可重定位字段中的值。

第1个条目。

我们先看看.rela.dyn节的第一个条目,已知偏移量是1160,那么我们从1160的地方开始取24个字节,如下图:

%title插图%num

r_offset。r_offset是0x3de8,十进制是15848,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x8,十进制是8,info是8,类型是R_X86_64_RELATIVE,有的文章里叫做R_AMD64_RELATIVE。

%title插图%num

根据类型可以进行计算存储在重定位字段中的值,由于是RELATIVE类型,所以计算方法是B+A,B表示执行过程中将共享目标文件装入内存的基本地址。通常,生成的共享目标文件的基本虚拟地址为 0,A表示常量加数,用于计算存储在可重定位字段中的值。

r_addend。r_addend是0x1130,十进制是4400,该字段即上面说的B+A中的A。

现在我们可以看出B是0,A是0x1130,B+A=0x1130,符号名是0x1130,说明第一个条目是符号名称为0x1130的重定位条目。

第2个条目。

已知文件偏移量为1160个字节开始的24个字节是第1个条目,那么第2个条目的偏移量是1160+24=1184,即从文件偏移量1184处取24个字节就是第2个条目。

%title插图%num

r_offset。r_offset是0x3df0,十进制是15856,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x8,十进制是8,info是8,类型也是R_X86_64_RELATIVE,因此计算方式是B+A

r_addend。r_addend是0x10f0,十进制是4336,该字段及上面说的B+A中的A。B表示执行过程中将共享目标文件装入内存的基本地址。通常,生成的共享目标文件的基本虚拟地址为 0

B+A=0+0x10f0=0x10f0,因此第2个条目是符号名称为0x10f0的重定位条目。

第3个条目。

已知文件偏移量为1184个字节开始的24个字节是第2个条目,那么第3个条目的偏移量是1184+24=1208,即从文件偏移量1208处取24个字节就是第3个条目。

%title插图%num

r_offset。r_offset是0x4028,十进制是16424,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x8,十进制是8,info是8,类型也是R_X86_64_RELATIVE,因此计算方式是B+A

r_addend。r_addend是0x4028,十进制是16424,该字段及上面说的B+A中的A。B表示执行过程中将共享目标文件装入内存的基本地址。通常,生成的共享目标文件的基本虚拟地址为 0

B+A=0+0x4028=0x10f0,因此第3个条目是符号名称为0x4028的重定位条目。

第4个条目。

已知文件偏移量为1208个字节开始的24个字节是第3个条目,那么第4个条目的偏移量是1208+24=1232,即从文件偏移量1232处取24个字节就是第4个条目。

%title插图%num

r_offset。r_offset是0x3fd8,十进制是15864,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x100000006,根据计算得出类型是6,对应R_X86_64_GLOB_DAT,因此最终运行时重定位计算方式是S,S表示索引位于重定位项中的符号的值,计算方式就是直接取这个地址值。

r_addend。r_addend是0,常量加数是0。

第5个条目。

已知文件偏移量为1232个字节开始的24个字节是第4个条目,那么第5个条目的偏移量是1232+24=1256,即从文件偏移量1256处取24个字节就是第5个条目。

%title插图%num

r_offset。r_offset是0x3fe0,十进制是16352,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x300000006,根据计算得出类型是6,对应R_X86_64_GLOB_DAT,因此最终运行时重定位计算方式是S,S表示索引位于重定位项中的符号的值,计算方式就是直接取这个值。

r_addend。r_addend是0,常量加数是0。

第6个条目。

已知文件偏移量为1256个字节开始的24个字节是第5个条目,那么第6个条目的偏移量是1256+24=1280,即从文件偏移量1280处取24个字节就是第6个条目。

%title插图%num

r_offset。r_offset是0x3fe8,十进制是16360,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x400000006,根据计算得出类型是6,对应R_X86_64_GLOB_DAT,因此最终运行时重定位计算方式是S,S表示索引位于重定位项中的符号的值,计算方式就是直接取这个值。

r_addend。r_addend是0,常量加数是0。

第7个条目。

已知文件偏移量为1280个字节开始的24个字节是第6个条目,那么第7个条目的偏移量是1280+24=1304,即从文件偏移量1304处取24个字节就是第7个条目。

%title插图%num

r_offset。r_offset是0x3ff0,十进制是16368,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x500000006,根据计算得出类型是6,对应R_X86_64_GLOB_DAT,因此最终运行时重定位计算方式是S,S表示索引位于重定位项中的符号的值,计算方式就是直接取这个值。

r_addend。r_addend是0,常量加数是0。

第8个条目。

已知文件偏移量为1304个字节开始的24个字节是第7个条目,那么第8个条目的偏移量是1304+24=1328,即从文件偏移量1328处取24个字节就是第8个条目。

%title插图%num

r_offset。r_offset是0x3ff8,十进制是16376,该处的代码或者数据会被(修改)重定位,需要进行什么类型的重定位得看r_info。

r_info。r_info是0x600000006,根据计算得出类型是6,对应R_X86_64_GLOB_DAT,因此最终运行时重定位计算方式是S,S表示索引位于重定位项中的符号的值,计算方式就是直接取这个值。

r_addend。r_addend是0,常量加数是0。

以上就是整个.rela.dyn节的内容。

发表回复