ELF - 了解 R_386_PC32 重定位

Tre*_*rey 3 x86 elf

我正在尝试理解 ELF 中的重定位,但是我在处理这方面的文档时遇到了一些麻烦,因为它相当神秘。例如,重定位方程描述了 3 个参数:S、A 和 P。现在我知道 A 只是加数,它是用于帮助重定位计算的一些数字,而 S 是“索引位于的符号的值”搬迁条目”(与函数名称相同,对吧?)但是 P 呢?手册将其描述为“存储单元被重新安置的位置”,但这到底是什么意思呢?

\n\n

我刚刚找到一个例子来说明这一点:假设我们有 2 个目标文件,obj1.oobj2.o。第一个引用了一个名为 foo() 的函数,该函数位于obj2.o内部。

\n\n

objdump -d obj1.o产生:

\n\n
Disassembly of section .text:\n00000000 <func>:\n0:   55                      push   %ebp\n1:   89 e5                   mov    %esp,%ebp\n3:   83 ec 08                sub    $0x8,%esp\n6:   e8 fc ff ff ff          call 7 <func+0x7>\nb:   c9                      leave  \nc:   c3                      ret   \n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,readelf表明这是一个R_386_PC32重定位,其方程为:S + A - P

\n\n

将这两个文件组合起来生成完整的可执行文件re located后,重定位条目显然已被修补:

\n\n
objdump -d relocated\ntest:     file format elf32-i386\nDisassembly of section .text:\n080480d8 <func>:\n80480d8:   55                      push   %ebp\n80480d9:   89 e5                   mov    %esp,%ebp\n80480db:   83 ec 08                sub    $0x8,%esp\n80480de:   e8 05 00 00 00          call   80480e8 <foo>\n80480e3:   c9                      leave  \n80480e4:   c3                      ret    \n80480e5:   90                      nop\n80480e6:   90                      nop\n80480e7:   90                      nop\n080480e8 <foo>:\n80480e8:   55                      push   %ebp\n80480e9:   89 e5                   mov    %esp,%ebp\n80480eb:   5d                      pop    %ebp\n80480ec:   c3                      ret\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,链接器似乎执行了以下计算:S + A \xe2\x80\x93 P: 0x80480e8 + 0xfffffffc \xe2\x80\x93 0x80480df

\n\n

我的问题是:

\n\n
    \n
  • P的值从哪里来?
  • \n
  • 加数有什么意义?
  • \n
\n

Pet*_*des 5

P 是程序计数器,因此这是与 PC 相关的重定位。我没有具体检查 ELF32 使用什么作为参考点。从fc ff ff ff = -4un-linked中的来看call rel32,很可能是4字节位移的开始。在机器代码中,相对跳转以指令的call rel32结尾(即下一条指令的开始)为基数,这样就可以解释4字节的偏移量。

这是加数的一个用例。

另一个是对静态数据的 PC 相对寻址,以生成与位置无关的代码。您的 PC 引用可能就在附近,但甚至不在您使用它的指令内,或者您想要索引全局数组。

所以你可能有类似的东西

call get_eip_into_ebx
mov $table - this_instruction + 40(%ebx), %ecx
Run Code Online (Sandbox Code Playgroud)

或者举一个真实的例子,看看 gcc 和 clang 是如何加载-m32 -PIE全局变量的。(但是全局偏移表符号名称会得到特殊处理,因此我不会重现编译器 asm 输出。)