call x86 优化 重定位,链接(GNU ld)重定位过程中R_386_PC32和R_X86_64_PC32之间的区别是什么...

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 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

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.

解决方案

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值