What is R_X86_64_GOTPLT64 used for?

Michael Matz matz@suse.de
Thu Nov 20 13:42:00 GMT 2014


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 
  call foo@PLT
  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.


More information about the Binutils mailing list