This is an archive of the discontinued LLVM Phabricator instance.

[ELF2] - Initial lazy loading support (x86_x64 and x86)
ClosedPublic

Authored by grimar on Oct 12 2015, 7:30 AM.

Details

Summary

Main aim of this patch is adding support of lazy loading.

This patch implements basic variant for x86_x64 and for X86 targets. What was done:

  1. .got.plt section is created for functions that requires PLT. .got.plt has 3 predefined empty entries now that are required for dynamic linker.

Also other new items created are configured to have correct jump to PLT[N]

  1. PLT section now has PLT[0] entry, also others ones are configured to support PLT->GOT(.got.plt) calls.
  2. Implemented .rel[a].plt sections (based on patch http://reviews.llvm.org/D13569)
  3. Fixed plt relocations types (based on patch http://reviews.llvm.org/D13589)

NOTES:
The .plt.got zero entry is empty now. According to ELF specification it should hold the address of the dynamic structure, referenced with the symbol
_DYNAMIC. The _DYNAMIC entry points to the .dynamic section which contains information used by the ELF interpreter to setup the binary.
This seems to be separate task and I think following patches should handle it, but not this one.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 37107.Oct 12 2015, 7:30 AM
grimar retitled this revision from to [ELF2] - Initial lazy loading support (x86_x64).
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: grimar, llvm-commits.
grimar updated this object.Oct 12 2015, 7:33 AM
emaste added a subscriber: emaste.Oct 12 2015, 7:55 AM
grimar updated this object.Oct 12 2015, 9:13 AM
ruiu added inline comments.Oct 12 2015, 5:04 PM
ELF/OutputSections.cpp
39–41 ↗(On Diff #37107)
Entries.resize(3);
65–70 ↗(On Diff #37107)
if (B)
  Target->writeGotPltEntry(Buf, Out<ELFT>::Plt->getEntryAddr(*B);
Buf += sizeof(uintX_t);
115 ↗(On Diff #37107)

Start with an uppercase character and end with a period.

116 ↗(On Diff #37107)

Is PLT base is a common terminology? I prefer writePltZeroEntry as the name of the function.

174–208 ↗(On Diff #37107)

This code needs explaining. I'm not actually sure that this code is correct overall.

762–766 ↗(On Diff #37107)

Move this before template class GotSection<ELF32LE>;

ELF/OutputSections.h
305 ↗(On Diff #37107)

Sort.

320 ↗(On Diff #37107)

Sort.

ELF/Target.cpp
127–136 ↗(On Diff #37107)
write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2);  // GOT+8
write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4);  // GOT+16

No assert() needed.

147–161 ↗(On Diff #37107)
write32le(Buf + 2, GotEntryAdrr - PltEntryAddr - 6);
write32le(Buf + 7, Index);
write32le(Buf + 11, ...);
grimar updated this revision to Diff 37243.Oct 13 2015, 6:40 AM
grimar updated this object.
  • Review comments addressed.
  • Added x86 target implementation.
  • Added isInGotPlt() method.
  • Had to set PltZeroEntrySize = 0 for PPC64TargetInfo otherwise it fails the ppc64-toc-restore.s because of changed offsets. PPC64TargetInfo does not seem to implement PLT->GOT dispatchment.
ELF/OutputSections.cpp
39–41 ↗(On Diff #37107)

Done.

65–70 ↗(On Diff #37107)

Done.

115 ↗(On Diff #37107)

Done.

116 ↗(On Diff #37107)

Changed to writePltZeroEntry. Also changed PltBaseSize to PltZeroEntrySize.

174–208 ↗(On Diff #37107)

I added some comments above, under each of 2 code sections of my changes.

192 ↗(On Diff #37107)

Each symbol that needs plt relocation is placed to Plt and GotPlt, otherwise to Got.
Also symbol can be placed both to Got and Plt+GotPlt, for example when we take address of function from DSO and also make a call to it.
So here depending on what type of relocation is we switch from which table to take the offset from.

198 ↗(On Diff #37107)

Relocations of symbols in ".rela.dyn" and ".rela.plt" are different.
Symbols that NeedsPlt placed to .rela.plt and requred to be R_X86_64_JUMP_SLOT.

762–766 ↗(On Diff #37107)

Done.

ELF/OutputSections.h
305 ↗(On Diff #37107)

Done.

320 ↗(On Diff #37107)

Done.

ELF/Target.cpp
127–136 ↗(On Diff #37107)

Done.

147–161 ↗(On Diff #37107)

Done. Just note: Buf + 12, not + 11.

grimar retitled this revision from [ELF2] - Initial lazy loading support (x86_x64) to [ELF2] - Initial lazy loading support (x86_x64 and x86).Oct 13 2015, 6:45 AM
ruiu added inline comments.Oct 13 2015, 7:08 AM
ELF/OutputSections.cpp
183 ↗(On Diff #37243)

Please add this as a comment to this function.

ELF/Target.cpp
66 ↗(On Diff #37243)

It can read relocation minus index. Maybe I'd write <relocation index> instead of reloc-index.

152 ↗(On Diff #37243)

Ditto

grimar updated this revision to Diff 37252.Oct 13 2015, 7:59 AM

Review comments addressed.

ruiu accepted this revision.Oct 13 2015, 8:11 AM
ruiu edited edge metadata.

LGTM with a nit. This is a great feature. Thank you for doing this!

test/elf2/plt-i686.s
23–35 ↗(On Diff #37252)

You want to use CHECK-NEXT instead of CHECK.

This revision is now accepted and ready to land.Oct 13 2015, 8:11 AM
This revision was automatically updated to reflect the committed changes.