This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: What is R_X86_64_GOTPLT64 used for?
- From: Michael Matz <matz at suse dot de>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: "x86-64-abi at googlegroups dot com" <x86-64-abi at googlegroups dot com>, GCC Development <gcc at gcc dot gnu dot org>, Binutils <binutils at sourceware dot org>, GNU C Library <libc-alpha at sourceware dot org>
- Date: Thu, 20 Nov 2014 14:42:27 +0100 (CET)
- Subject: Re: What is R_X86_64_GOTPLT64 used for?
- Authentication-results: sourceware.org; auth=none
- References: <CAMe9rOqb0g2asAe6UZ0hxh8jFf-+eBiaez0pLrPjd0oqVdP0Rg at mail dot gmail dot com> <alpine dot LNX dot 2 dot 00 dot 1411131717220 dot 405 at wotan dot suse dot de> <CAMe9rOrTg=YtVZ1EqN7ha8qUPSXzms20eMU51txVAmL3+cUsQQ at mail dot gmail dot com> <CAMe9rOrnQRo3XXowAEcd_h=i_i5v04=i=kLWjm2ANduv8MwhYQ at mail dot gmail dot com> <alpine dot LNX dot 2 dot 00 dot 1411171425020 dot 405 at wotan dot suse dot de> <CAMe9rOppfTEwtRROsAhFf+7tFjv7pRZ8qho-3NOC7BxvfSBaKg at mail dot gmail dot com>
Hi,
On Wed, 19 Nov 2014, H.J. Lu wrote:
> > The first one (to 600ff8) is the normal GOT slot, the second one the GOT
> > slot for the PLT entry. Both are actually used:
> >
> > 00000000004005f0 <foo@plt>:
> > 4005f0: ff 25 32 0a 20 00 jmpq *0x200a32(%rip) # 601028 <_GLOBAL_OFFSET_TABLE_+0x28>
>
> They are not:
Huh? I said both GOT slots are used and I proved it in the disasm dumps.
> => 0x00000000004005aa <+29>: movabs $0xfffffffffffffff8,%rax
> 0x00000000004005b4 <+39>: mov (%rbx,%rax,1),%rax
Here it's using one of the GOT slots (namely the one not associated with
the PLT entry) ...
> Breakpoint 2, 0x00000000004005c0 in main () at main.c:6
> 6 f();
> (gdb) p $rax
> $5 = 140737352012384
> (gdb) disass $rax
> Dump of assembler code for function foo:
... which is why %rax contains the final address of foo, being loaded from
the appropriate GOT slot that was just relocated with a GLOB_DAT reloc.
> Breakpoint 3, 0x00000000004005cf in main () at main.c:7
> 7 foo();
> (gdb) p $rax
> $6 = 4195472
> (gdb) disass $rax
> Dump of assembler code for function foo@plt:
> 0x0000000000400490 <+0>: jmpq *0x200552(%rip) # 0x6009e8
> <foo@got.plt>
And here it's using the other GOT slot (associated with this PLT entry),
unequal to the one used above and initially pointing to the first PLT
stub. So why do you say that not both are used, you clearly see they are?
> One way to optimize it is to make PLT entry to use the normal GOT
> slot:
Exactly. As a symbol lookup needs to be done anyway for the GLOB_DAT
reloc going through the dynamic linker for the lazy lookup later when a
call occurs doesn't make sense.
> jmp *name@GOTPCREL(%rip)
> 8 byte nop
You mean replacing the PLT slot with the above? Yep, something like that.
Even better of course would be to not use the PLT slot at all, it's just a
useless indirection. It would be even cooler to rewrite the call insn
from
call foo@PLT
into
call *foo@GOTPCREL(%rip)
(in the small model here) Unfortunately the latter is one byte larger
than the former. But perhaps GCC could already emit the latter form
when it knows a certain function symbol has its address taken (or more
precisely if a GLOB_DAT reloc is going to be emitted for it).
> where name@GOTPCREL points to the normal GOT slot
> updated by R_X86_64_GLOB_DAT relocation at run-time.
> Should I give it a try?
Frankly, I have no idea if it's worth it. Address takings of function
symbols doesn't occur very often, except in vtables, and that's not using
GOT slots. Vtables should be handled in a completely different way
anyway: as the entries aren't usually used for address comparisons they
should point to the PLT slots, so that it's only RELATIVE relocs, not
symbol based ones, so that also virtual calls can be resolved lazily.
Ciao,
Michael.