This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Implemented R_*_IRELATIVE relocations for x86, x64 targets.
ClosedPublic

Authored by grimar on Dec 4 2015, 9:12 AM.

Details

Summary

This relocation is similar to R_*_RELATIVE except that the value used in this relocation is the program address returned by the function, which takes no arguments, at the address of
the result of the corresponding R_*_RELATIVE relocation as specified in the processor-specific ABI. The purpose of this relocation to avoid name lookup for locally defined STT_GNU_IFUNC symbols at load-time.

More info can be found in ifunc.txt from https://sites.google.com/site/x32abi/documents.

Testing can be performed using following sample:

#include <stdio.h>
int myfunc1() { return 1; }
int myfunc2() { return 2; }

// Prototype for the common entry point
extern "C" int myfunc();
__asm__ (".type myfunc, @gnu_indirect_function");
// Make the dispatcher function. This returns a pointer to the desired function version
typeof(myfunc) * myfunc_dispatch (void) __asm__ ("myfunc");
typeof(myfunc) * myfunc_dispatch (void)  {
if (0) 
  return &myfunc1;
else
  return &myfunc2;
}

int main() {
   printf("\nCalled function number %i\n", myfunc());
   return 0;
}

~/LLVM/build/bin/clang -fuse-ld=lld -O0 -g test.cpp -o test
./test
Depending on if() condition 1 or 2 should appear in output.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 41888.Dec 4 2015, 9:12 AM
grimar retitled this revision from to [ELF] - Implemented R_*_IRELATIVE relocations for x86, x64 targets..
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: llvm-commits, grimar.
grimar abandoned this revision.Dec 4 2015, 10:19 AM

I need to review it again.

grimar reclaimed this revision.Dec 7 2015, 2:02 AM
grimar updated this revision to Diff 42037.Dec 7 2015, 2:10 AM
  • Fixed compilation error under linux.
grimar updated this object.Dec 7 2015, 2:15 AM
ruiu edited edge metadata.Dec 7 2015, 11:21 AM

Is this only for x32 ABI? If so, is x32 ABI still being actively developed? (I guess the answer is yes, but just to make sure.)

In D15235#304116, @ruiu wrote:

Is this only for x32 ABI? If so, is x32 ABI still being actively developed? (I guess the answer is yes, but just to make sure.)

I know nothing about active development of x32 unfortunately. But it is not only for it, it is generic one.
https://groups.google.com/forum/#!topic/generic-abi/de1Hvq_FAn8

That patch is for both x86 and x64 (R_I386_IRELATIVE vs R_X86_64_IRELATIVE) but that feature exists for other targets such as aarch64 (R_AARCH64_IRELATIVE), powerpc (R_POWERPC_IRELATIVE). gold has support it for.

As far I understand the main use case now is linking against libc.a with multi-arch enabled:
https://lists.gnu.org/archive/html/bug-binutils/2009-11/msg00008.html

ruiu added a comment.Dec 8 2015, 10:21 AM

I'm not still sure if these relocations have to be handled by the linker. These relocations use runtime addresses, so only the dynamic linker has to handle them, no?

grimar added a comment.Dec 9 2015, 2:15 AM
In D15235#305015, @ruiu wrote:

I'm not still sure if these relocations have to be handled by the linker. These relocations use runtime addresses, so only the dynamic linker has to handle them, no?

Yes, and I dont handle them in this patch. Patch only creates it:
If we see the call to function of type STT_GNU_IFUNC then R_*_IRELATIVE relocation should be created and added to RelaPlt. These relocations always uses PLT entry which is also created. Without that logic even sample app from patch summary would not work correctly.

Also rel_iplt_end/rel_iplt_star symbols are added to point on start/end of section holding these relocations. The multi-arch libc will use these symbols to locate these relocations at program startup time.

Just in case both gold and bfd implements the same logic.

ruiu added inline comments.Dec 9 2015, 3:20 PM
ELF/OutputSections.cpp
279–283 ↗(On Diff #42037)
} else if (Body && isGnuIfunc<ELFT>(*Body)) {
  P->setSymbolAndType(0, Target->getIRelativeReloc(), Config->Mips64EL);
} else {
  P->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
}
325–326 ↗(On Diff #42037)

Is this change related to IRELATIVE relocations?

ELF/Symbols.h
194 ↗(On Diff #42037)
static Elf_Sym RelaIpltStart;
static Elf_Sym RelaIpltEnd;
ELF/Target.h
103 ↗(On Diff #42037)

isGnuIfunc -> isGnuIFunc

ELF/Writer.cpp
701 ↗(On Diff #42037)

Can you factor this new code out as a new function?

704 ↗(On Diff #42037)

IpltS -> Start

705 ↗(On Diff #42037)

Remove{}

709 ↗(On Diff #42037)

IpltE -> End

710 ↗(On Diff #42037)

Remove{}

771 ↗(On Diff #42037)

Is that only when static linking?

993 ↗(On Diff #42037)

Is this relative? If not, please remove "R" from "RVA".

grimar updated this revision to Diff 42405.Dec 10 2015, 2:53 AM
grimar edited edge metadata.

Review comments addressed.

ELF/OutputSections.cpp
279–283 ↗(On Diff #42037)

Done.

325–326 ↗(On Diff #42037)

Its helps to generate correct output for static linking. Before this patch RelaPlt was not added to static output. Now it is, but there is no DynSymTab still. And SymTab is used instead. If I remove that then llvm-readobj will complain about binary.
Another possible way probably would be to use DynSymTab and add it to the output, but thats too heavy for that I think.

ELF/Symbols.h
194 ↗(On Diff #42037)

Done.

ELF/Writer.cpp
701 ↗(On Diff #42037)

Done and rewrote it fully to look better.

771 ↗(On Diff #42037)

No, updated the comment. Point is that we always need rel[a].plt in output if it has entries.

993 ↗(On Diff #42037)

R here was first letter of RelaPlt. I didnt want to name it VA because outside of this scope variable VA already exist. I know that VA inside scope would override the outer one, but its confusing to see.
I renamed it to Start.

grimar updated this revision to Diff 43112.Dec 17 2015, 2:21 AM
  • Rebased.
ruiu accepted this revision.Dec 19 2015, 12:10 AM
ruiu edited edge metadata.

LGTM

ELF/Target.cpp
369–372 ↗(On Diff #43112)

This can be

return isGnuIFunc<ELF32LE>(S) ||
       (Type == R_386_PLT32 && ...
This revision is now accepted and ready to land.Dec 19 2015, 12:10 AM
This revision was automatically updated to reflect the committed changes.