我正在尝试理解ELF中的重定位,但是我对这方面的文档有些麻烦,这是相当神秘的。例如,重定位方程描述了3个参数,S,A和P.现在我知道A只是加数,它是用于辅助重定位计算的一些数字,S是“符号的值” index位于重定位条目“(与函数名称相同吗?)但是P怎么样?该手册将其描述为“存储单元被重新安置的位置”,但这甚至意味着什么?
我刚刚找到一个例子来说明这一点:假设我们有2个目标文件, obj1.o 和 obj2.o 。第一个引用一个名为foo()的函数,该函数位于 obj2.o 中。
objdump -d obj1.o 产量:
Disassembly of section .text:
00000000 <func>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: e8 fc ff ff ff call 7 <func+0x7>
b: c9 leave
c: c3 ret
现在, readelf 显示这是 R_386_PC32 重定位,其等式为: S + A - P 。
在合并这两个文件以生成完整的可执行文件重定位之后,重定位条目显然已修补:
objdump -d relocated
test: file format elf32-i386
Disassembly of section .text:
080480d8 <func>:
80480d8: 55 push %ebp
80480d9: 89 e5 mov %esp,%ebp
80480db: 83 ec 08 sub $0x8,%esp
80480de: e8 05 00 00 00 call 80480e8 <foo>
80480e3: c9 leave
80480e4: c3 ret
80480e5: 90 nop
80480e6: 90 nop
80480e7: 90 nop
080480e8 <foo>:
80480e8: 55 push %ebp
80480e9: 89 e5 mov %esp,%ebp
80480eb: 5d pop %ebp
80480ec: c3 ret
所以链接器似乎执行了以下计算: S + A - P:0x80480e8 + 0xfffffffc - 0x80480df
我的问题是:
答案 0 :(得分:0)
P是程序计数器,因此这是PC相对重定位。我没有确切地检查ELF32用作参考点的确切内容。从未链接fc ff ff ff = -4
中的call rel32
判断,它可能是4字节位移的开始。在机器代码中,相对跳转如指令的call rel32
end (即下一条指令的开始)作为基数,这样就可以解释4字节的偏移量。
这是加数的一个用例。
另一种是与静态数据进行PC相关寻址,以制作与位置无关的代码。您的PC引用可能在附近,但甚至不在您使用它的指令内,或者您想索引全局数组。
所以你可能有像
这样的东西call get_eip_into_ebx
mov $table - this_instruction + 40(%ebx), %ecx
或者对于真实的示例,-m32 -PIE
SELECT COUNT(*)
加载全局。 (但全局偏移表符号名称得到特殊处理,所以我不打算重现编译器asm输出。)
答案 1 :(得分:0)
S = 0x80480e8是符号起始地址(foo()的入口地址) P = 0x80480df是需要修改其值(正在重定位)的地址
所以S-P是这两个地址之间的距离(以字节为单位)
但是,调用rel32指令会计算从下一条指令开始的距离(rel32),并且与P的偏移量为4个字节,因此为-4。