This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Lazy relocations support for x86 target.
ClosedPublic

Authored by grimar on Nov 24 2015, 8:07 AM.

Details

Summary

Patch implements lazy relocations for x86.
One of features of x86 is that executable files and shared object files have separate procedure linkage tables. So patch implements both cases.
As a noticable difference with other targets can mention that relocation offset is required for writePltEntry. I added it as parameter. Also it needs offset in Got, so added addr of Got either.

Detailed information about instructions used can be found in http://docs.oracle.com/cd/E19620-01/805-3050/chapter6-1235/index.html (search: x86: Procedure Linkage Table).

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 41050.Nov 24 2015, 8:07 AM
grimar retitled this revision from to [ELF] - Lazy relocations support for x86 target..
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: llvm-commits, grimar.
ikudrin added inline comments.
ELF/Target.cpp
196 ↗(On Diff #41050)

The address of the .dynamic section has to be stored at the location which is pointed to by the _GLOBAL_OFFSET_TABLE_ symbol. Although we don't use this symbol explicitly, the same effect is achieved in the method InputSectionBase<ELFT>::relocate() in the branch "if (Target->relocPointsToGot(Type))". But in that branch, the address of .got section is used, not .got.plt's.

ruiu added inline comments.Nov 24 2015, 3:41 PM
ELF/Writer.cpp
248–250 ↗(On Diff #41050)

This piece of code does not depends on any local context of Writer.cpp, so I think you can move this into a function that handles i386 PLT entries instead of propagating this unsigned value all the way to the consumer.

grimar added inline comments.Nov 25 2015, 4:04 AM
ELF/Target.cpp
196 ↗(On Diff #41050)

According to gold source code _GLOBAL_OFFSET_TABLE_ points to got.plt for x86. So if address of .dynamic section should be placed there then .. its already there :)

Just note about relocPointsToGot() - I will review this one. It is not clear for me why we need it as separate method if we have relocNeedsGot(). relocPointsToGot() is used only for x86 now and I think we can combine it with relocNeedsGot().

ELF/Writer.cpp
248–250 ↗(On Diff #41050)

What I need is a accordance of PLT entry and the offset in relocation table for its relocation. It can be calculated only here I think.

That its only needed for x86 now, thats true. But what is the way to move it from here ? Function that handles i386 PLT entries is

writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff).

It does not know anything about conformity of relocations and PLT entries.
I added RelOff for it since I dont know the easier/shorter way to do what is needed.

ruiu added inline comments.Nov 25 2015, 10:17 AM
ELF/Writer.cpp
248–250 ↗(On Diff #41050)

I think I don't understand what you mean. What I wanted to say is since no local variables are used in the following expression, you can move this code to somewhere else.

unsigned RelOff = Target->supportsLazyRelocations()
                      ? Out<ELFT>::RelaPlt->getRelocOffset()
                      : Out<ELFT>::RelaDyn->getRelocOffset();
grimar added inline comments.Nov 25 2015, 12:17 PM
ELF/Writer.cpp
248–250 ↗(On Diff #41050)

I understood what you want.
But I think it is only can be moved to

template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym)

from here. It is anyways common code and not just i386 specific.

Point is that getRelocOffset() returns current offset in relocation table, so it needs to be remembered for each added Plt entry. Because
each Out<ELFT>::RelaPlt->addReloc({&C, &RI}); call below changes it.

ruiu added inline comments.Nov 25 2015, 12:31 PM
ELF/OutputSections.cpp
154 ↗(On Diff #41050)

I'd give names to both pair elements.

SymbolBody *E = I.first;
unsigned RelOff = I.second;
288 ↗(On Diff #41050)

remove const as it is obvious.

ELF/Writer.cpp
248–250 ↗(On Diff #41050)

Yeah, so why don't you move this into addEntry?

grimar updated this revision to Diff 41174.Nov 25 2015, 1:03 PM

Review comments addressed.

ELF/OutputSections.cpp
154 ↗(On Diff #41050)

Done.

288 ↗(On Diff #41050)

Well, I removed. But I just saw the same in

template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
  const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
ELF/Writer.cpp
248–250 ↗(On Diff #41050)

Done.

ruiu accepted this revision.Nov 25 2015, 1:06 PM
ruiu edited edge metadata.

LGTM

ELF/OutputSections.cpp
292 ↗(On Diff #41174)

Oh OK then you can keep it. Consistency matters.

ELF/Target.cpp
225 ↗(On Diff #41174)

Let's use shorter name as the scope is very narrow.

DsoPltData -> V

This revision is now accepted and ready to land.Nov 25 2015, 1:06 PM
This revision was automatically updated to reflect the committed changes.
grimar added inline comments.Nov 25 2015, 1:41 PM
ELF/OutputSections.cpp
292 ↗(On Diff #41174)

Done.

ELF/Target.cpp
225 ↗(On Diff #41174)

Done.