What's the difference between R_386_PC32 and R_X86_64_PC32 in link(GNU ld) relocation process

大兔子大兔子 提交于 2020-01-25 03:46:31

问题


When reading the book Computer System: A Programmer's Perspective Section 7.7.1 Relocation Entries: the brief content of this section is how a linker relocate reference in a different object file.

When compile and objdump the example source code:

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

Then gcc -Wall -c -o main.o main.c, and objdump -S -r main.o > main.asm; and will see the relocation entry for swap:

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

So when ld link the main.o and swap.o, the ld will use the relocation entry r of swap(offset=7, type=R_386_PC32) to determine the link address:

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

And the operand of call instruction (fc ff ff ff) -4 is perfectly suiting for 386 instruction set.

But when I repeat this in a X86_64 Linux, I found the code for the call is:

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

Then My question is why the operand of call(e8) in 386 is -4((fc ff ff ff), but the operand in X86_64 main.o is 00 00 00 00? Is it because of the different instruction set(call vs. callq), or just the GNU ld use different algorithm to relocation R_X86_64_PC32?

Hope for you answer, Many thanks.


回答1:


The value doesn't matter, it will be overwritten during the relocation process. Apparently, for i386 the compiler defaults to pointing to the relocation entry itself, while for x86-64 it points to the next instruction. It's just a dummy value anyway.



来源:https://stackoverflow.com/questions/8367587/whats-the-difference-between-r-386-pc32-and-r-x86-64-pc32-in-linkgnu-ld-reloc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!