[PATCH] D65995: [ELF] Don't special case symbolic relocations with 0 addend to ifunc in writable locations

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 12 07:06:53 PDT 2019


peter.smith added a comment.

In D65995#1623285 <https://reviews.llvm.org/D65995#1623285>, @MaskRay wrote:

> > If I've understood correctly, this will make the case "address of an ifunc is taken from RW but there are no other relocations that would create a canonical PLT entry" worse as we would always create the canonical PLT entry even if it isn't strictly needed. The trade off is simpler code and a possible size saving from only needing one irelative relocation?
>
> We have probably overloaded the meaning of "canonical PLT" here:) Let me give a bit more details about the two types of canonical PLT:
>
> 1. STT_FUNC, `Undefined` or `SharedSymbol`. The canonical PLT makes it a `Defined` and exports it (`replaceWithDefined` sets the `exportDynamic` field) in the dynamic symbol table. This fake definition (`st_value=addr(PLT)!=0, st_shndx=0`, ld.so has logic to handle such symbols) can preempt a real definition in a DSO. This can be seen as an address leak (in AArch64 BTI protection such PLT needs `BTI c`).
> 2. STT_IFUNC, `Defined`. The canonical PLT is created because the symbol is referenced by a non-PLT-generating-non-GOT-generating relocation. This case is already a `Defined`, so there is no new `Defined` (`exportDynamic` field is not set). We just change some fields of the symbol (st_value and st_type are important to ld.so. For st_shndx, as long as is non-zero, it doesn't matter what its actual value is). If the STT_GNU_IFUNC symbol was exported before, the converted STT_FUNC is still exported. If the STT_GNU_IFUNC was not (e.g. local/hidden), the new STT_FUNC is not.
>
>   Both are created for pointer equality. This patch deals with 2).
>
>   If the ifunc is referenced by another component.
> 3. Without a canonical PLT, its type is STT_GNU_IFUNC. A reference (symbolic relocation/GLOB_DAT/JUMP_SLOT) has to call the ifunc resolver to get the real address.
> 4. With a canonical PLT, its type is STT_FUNC. A reference does not have to call the ifunc resolver, but every subsequent function call has to go through the canonical PLT. Address taken of a non-preemptable ifunc in a static storage (.rodata, .data, etc) is rare, so when making the trade-off, we can lean toward implementation complexity.


I agree that in hand written code it is not common to take the address of an ifunc in such a way that a canonical PLT entry isn't needed. My concern is that this part of the code is motivated by something like HWASAN, which I believe may make compiler generated use of ifuncs to access shadow memory for example: D50544 <https://reviews.llvm.org/D50544> . I must confess to not knowing too much about the details about HWASAN so I'm hoping that PCC can let us know if this will be a real performance problem or not.


Repository:
  rLLD LLVM Linker

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65995/new/

https://reviews.llvm.org/D65995





More information about the llvm-commits mailing list