Skip to content

Commit

Permalink
[ELF] Convert Thunks to use InputSectionDescriptions
Browse files Browse the repository at this point in the history
Thunks are now generated per InputSectionDescription instead of per
OutputSection. This allows created ThunkSections to be inserted directly
into InputSectionDescription.

Changes in this patch:
- Loop over InputSectionDescriptions to find relocations to Thunks
- Generate a ThunkSection per InputSectionDescription
- Remove synchronize() as we no longer need it
- Move fabricateDefaultCommands() before createThunks

Differential Revision: https://reviews.llvm.org/D33835

llvm-svn: 304887
  • Loading branch information
smithp35 committed Jun 7, 2017
1 parent 990c9cb commit 8e79146
Show file tree
Hide file tree
Showing 6 changed files with 297 additions and 67 deletions.
45 changes: 0 additions & 45 deletions lld/ELF/LinkerScript.cpp
Expand Up @@ -870,51 +870,6 @@ void LinkerScript::processNonSectionCommands() {
}
}

// Do a last effort at synchronizing the linker script "AST" and the section
// list. This is needed to account for last minute changes, like adding a
// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections.
//
// FIXME: We should instead create the "AST" earlier and the above changes would
// be done directly in the "AST".
//
// This can only handle new sections being added and sections being reordered.
void LinkerScript::synchronize() {
for (BaseCommand *Base : Opt.Commands) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
std::vector<InputSection **> ScriptSections;
DenseSet<InputSection *> ScriptSectionsSet;
for (BaseCommand *Base : Cmd->Commands) {
auto *ISD = dyn_cast<InputSectionDescription>(Base);
if (!ISD)
continue;
for (InputSection *&IS : ISD->Sections) {
if (IS->Live) {
ScriptSections.push_back(&IS);
ScriptSectionsSet.insert(IS);
}
}
}
std::vector<InputSection *> Missing;
for (InputSection *IS : Sections)
if (!ScriptSectionsSet.count(IS))
Missing.push_back(IS);
if (!Missing.empty()) {
auto ISD = make<InputSectionDescription>("");
ISD->Sections = Missing;
Cmd->Commands.push_back(ISD);
for (InputSection *&IS : ISD->Sections)
if (IS->Live)
ScriptSections.push_back(&IS);
}
assert(ScriptSections.size() == Sections.size());
for (int I = 0, N = Sections.size(); I < N; ++I)
*ScriptSections[I] = Sections[I];
}
}

static bool
allocateHeaders(std::vector<PhdrEntry> &Phdrs,
ArrayRef<OutputSectionCommand *> OutputSectionCommands,
Expand Down
1 change: 0 additions & 1 deletion lld/ELF/LinkerScript.h
Expand Up @@ -281,7 +281,6 @@ class LinkerScript final {
void assignOffsets(OutputSectionCommand *Cmd);
void placeOrphanSections();
void processNonSectionCommands();
void synchronize();
void assignAddresses(std::vector<PhdrEntry> &Phdrs,
ArrayRef<OutputSectionCommand *> OutputSectionCommands);

Expand Down
44 changes: 32 additions & 12 deletions lld/ELF/Relocations.cpp
Expand Up @@ -43,6 +43,7 @@

#include "Relocations.h"
#include "Config.h"
#include "LinkerScript.h"
#include "Memory.h"
#include "OutputSections.h"
#include "Strings.h"
Expand Down Expand Up @@ -995,13 +996,12 @@ void ThunkCreator::mergeThunks() {
};
std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(),
std::back_inserter(Tmp), MergeCmp);
OutputSection *OS = Thunks.front()->getParent();
OS->Sections = std::move(Tmp);
OS->assignOffsets();
*ISR = std::move(Tmp);
}
}

ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS) {
ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS,
std::vector<InputSection *> *ISR) {
if (CurTS == nullptr) {
uint32_t Off = 0;
for (auto *IS : OS->Sections) {
Expand All @@ -1010,7 +1010,7 @@ ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS) {
break;
}
CurTS = make<ThunkSection>(OS, Off);
ThunkSections[&OS->Sections].push_back(CurTS);
ThunkSections[ISR].push_back(CurTS);
}
return CurTS;
}
Expand All @@ -1021,7 +1021,21 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) {
return TS;
auto *TOS = IS->getParent();
TS = make<ThunkSection>(TOS, IS->OutSecOff);
ThunkSections[&TOS->Sections].push_back(TS);

// Find InputSectionRange within TOS that IS is in
OutputSectionCommand *C = Script->getCmd(TOS);
std::vector<InputSection *> *Range = nullptr;
for (BaseCommand *BC : C->Commands)
if (auto *ISD = dyn_cast<InputSectionDescription> (BC)) {
InputSection *first = ISD->Sections.front();
InputSection *last = ISD->Sections.back();
if (IS->OutSecOff >= first->OutSecOff &&
IS->OutSecOff <= last->OutSecOff) {
Range = &ISD->Sections;
break;
}
}
ThunkSections[Range].push_back(TS);
ThunkedSections[IS] = TS;
return TS;
}
Expand All @@ -1038,13 +1052,18 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
// InputSectionDescription::Sections.
void ThunkCreator::forEachExecInputSection(
ArrayRef<OutputSection *> OutputSections,
std::function<void(OutputSection *, InputSection *)> Fn) {
std::function<void(OutputSection *, std::vector<InputSection*> *,
InputSection *)> Fn) {
for (OutputSection *OS : OutputSections) {
if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
continue;
CurTS = nullptr;
for (InputSection *IS : OS->Sections)
Fn(OS, IS);
if (OutputSectionCommand *C = Script->getCmd(OS))
for (BaseCommand *BC : C->Commands)
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
CurTS = nullptr;
for (InputSection* IS : ISD->Sections)
Fn(OS, &ISD->Sections, IS);
}
}
}

Expand All @@ -1066,7 +1085,8 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
// ThunkSections back into the OutputSection as ThunkSections are not always
// inserted into the same OutputSection as the caller.
forEachExecInputSection(
OutputSections, [=](OutputSection *OS, InputSection *IS) {
OutputSections, [=](OutputSection *OS, std::vector<InputSection*> *ISR,
InputSection *IS) {
for (Relocation &Rel : IS->Relocations) {
SymbolBody &Body = *Rel.Sym;
if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
Expand All @@ -1080,7 +1100,7 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
if (auto *TIS = T->getTargetInputSection())
TS = getISThunkSec(TIS, OS);
else
TS = getOSThunkSec(OS);
TS = getOSThunkSec(OS, ISR);
TS->addThunk(T);
}
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
Expand Down
6 changes: 4 additions & 2 deletions lld/ELF/Relocations.h
Expand Up @@ -127,11 +127,13 @@ class ThunkCreator {

private:
void mergeThunks();
ThunkSection *getOSThunkSec(OutputSection *OS);
ThunkSection *getOSThunkSec(OutputSection *OS,
std::vector<InputSection *> *ISR);
ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
void forEachExecInputSection(
ArrayRef<OutputSection *> OutputSections,
std::function<void(OutputSection *, InputSection *)> Fn);
std::function<void(OutputSection *, std::vector<InputSection *> *,
InputSection *)> Fn);
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);

// Track Symbols that already have a Thunk
Expand Down
13 changes: 6 additions & 7 deletions lld/ELF/Writer.cpp
Expand Up @@ -1225,6 +1225,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (SS->getParent() && !SS->empty())
SS->getParent()->assignOffsets();

if (!Script->Opt.HasSections)
Script->fabricateDefaultCommands();
for (BaseCommand *Base : Script->Opt.Commands)
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
OutputSectionCommands.push_back(Cmd);

// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo,
Expand Down Expand Up @@ -1253,13 +1259,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
[](SyntheticSection *SS) { SS->updateAllocSize(); });
}

if (!Script->Opt.HasSections)
Script->fabricateDefaultCommands();
else
Script->synchronize();
for (BaseCommand *Base : Script->Opt.Commands)
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
OutputSectionCommands.push_back(Cmd);
clearOutputSections();

// Fill other section headers. The dynamic table is finalized
Expand Down

0 comments on commit 8e79146

Please sign in to comment.