[PATCH] D47098: [ELF] Make R_GOTONLY_PC_FROM_END R_GOTREL_FROM_END relative to _GLOBAL_OFFSET_TABLE_ instead of end of .got

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 29 07:54:15 PDT 2018


grimar added a comment.

In https://reviews.llvm.org/D47098#1114628, @peter.smith wrote:

> > I am not sure that the second way should work (if I understand everything correctly). 
> >  For x86 as you know we define _GLOBAL_OFFSET_TABLE_  in the .got.plt[0] now. 
> >  Then for example if we have the following TLS code:
> > 
> >   addl $_GLOBAL_OFFSET_TABLE_, %ebx #add    $0x199f,%ebx, R_386_GOTPC
> >   subl $8, %esp                                         #sub    $0x8,%esp
> >   leal gd at tlsgd(%ebx), %eax                    #lea    -0x10(%ebx),%eax, R_386_TLS_GD
> > 
> > 
> > it expects the first line to be resolved to the end of .got (to the GOT base in ABI terminology).
> >  If we redefine the relocations that use _FROM_END to use the location of the _GLOBAL_OFFSET_TABLE_ (I think that is what this patch tried to do),
> >  then it will not help us I think as we will end up with the address of .got.plt at the first line. And the code will fail to find a proper TLS slot as a result since .got.plt
> >  can be far away from .got in LLD.
>
> I think that the raw calculation would work if R_386_TLS_GD (RelExpr R_TLSGD) were defined to be something like InX::Got->getGlobalDynAddr(Sym) + A - ("VA of where _GLOBAL_OFFSET_TABLE_ is defined"). Instead of InX::Got->getGlobalDynOffset(Sym) + A - InX::Got->getSize();.


Looks a bit tricky for me honestly.

> I think that you are right that this distance will be larger if _GLOBAL_OFFSET_TABLE_ is defined to be base of .got.plt, however isn't the immediate 32-bits in size? I don't know of too many programs that would have that large a separation of .got or .got.plt >but I suppose it is possible. Hope I haven't misunderstood as my x86 asm isn't good.
> 
>      

I do not know.

I wonder if the next would be the correct way to solve this:

As far I understand, _GLOBAL_OFFSET_TABLE_ seems intended to be used with special types of relocations (this needs clarification).
R_X86_64_GOTPC64/R_X86_64_GOTPC32 and you mentioned R_ARM_BASE_PREL for arm, for example (your https://reviews.llvm.org/D46319 seems to make sense to me)

It seems that if we could know that symbol is _GLOBAL_OFFSET_TABLE_, we could always resolve it relative to the end of .got.
For x86 seems llvm-mc emits R_X86_64_PC32/R_X86_64_GOTPC64  and gas emits R_X86_64_GOTPC32/R_X86_64_GOTPC64 if _GLOBAL_OFFSET_TABLE_ is used.

If llvm-mc would emit R_X86_64_GOTPC32 too that we probably could do nothing here and continue resolving such relocations relative to the .got end.
I am not sure about the other targets, but if they also have special relocations for _GLOBAL_OFFSET_TABLE_, that could help to resolve this.

Or probably we could special case relocating _GLOBAL_OFFSET_TABLE_ symbol for now.


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D47098





More information about the llvm-commits mailing list