是什么在链接R_386_PC32和R_X86_64_PC32之间的差值(GNU LD)搬迁过程(Wh

2019-09-28 02:56发布

当读本书计算机系统:程序员的角度7.7.1节定位项:本节简要内容是链接器重新定位在不同的目标文件引用。

当编译和objdump的示例源代码:

void swap();
int buf[2] = {1, 2};
int main()
{
  swap();
  return 0;
}

然后GCC -Wall -c -o main.o main.c中,和objdump的-S​​ -r main.o> main.asm中; 并且将看到交换搬迁条目:

6: e8 fc ff ff ff    call 7 <main+0x7> swap();
                     7: R_386_PC32 swap relocation entry

因此,当LD链接main.o和swap.o,所述LD将使用交换的重定位项R(偏移= 7,类型= R_386_PC32),以确定链接地址:

refaddr = ADDR(section .text) + r.offset
*refptr = (unsigned)(ADDR(r.symbol + *refptr - refptr)

和调用指令(FC FF FF FF)-4的操作是完全相适应386指令集。

但是,当我重复这在X86_64 Linux中,我发现了代号为呼叫:

9: e8 00 00 00 00 callq e <main+0xe>
                  a: R_X86_64_PC32 swap relocation entry

那么我的问题是,为什么在386呼叫(E8)的操作数为-4((FC FF FF FF),但在X86_64 main.o操作数是00 00 00 00?难道是因为不同的指令集(称之为VS 。callq),或仅仅是GNU LD使用不同的算法来搬迁R_X86_64_PC32?

希望能为你解答,非常感谢。

Answer 1:

该值无关紧要,它会在搬迁过程中被覆盖。 显然,对于I386的编译器的默认指向的重定位项本身,而对于X86-64它指向下一条指令。 这只是一个虚拟值反正。



文章来源: What's the difference between R_386_PC32 and R_X86_64_PC32 in link(GNU ld) relocation process