ELF - 了解R_386_PC32重定位

时间:2018-05-15 18:47:38

标签: x86 elf

我正在尝试理解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

我的问题是:

  • P的价值来自哪里?
  • 加数是什么意思?

2 个答案:

答案 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。