[lld] r316750 - [ELF] Record created ThunkSections in InputSectionDescription [NFC].
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 27 01:56:20 PDT 2017
Author: psmith
Date: Fri Oct 27 01:56:20 2017
New Revision: 316750
URL: http://llvm.org/viewvc/llvm-project?rev=316750&view=rev
Log:
[ELF] Record created ThunkSections in InputSectionDescription [NFC].
Instead of maintaining a map of the std::vector to ThunkSections, record the
ThunkSections directly in InputSectionDescription.
Differential Revision: https://reviews.llvm.org/D37743
Modified:
lld/trunk/ELF/LinkerScript.h
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=316750&r1=316749&r2=316750&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Oct 27 01:56:20 2017
@@ -138,6 +138,7 @@ struct SectionPattern {
SortSectionPolicy SortInner;
};
+class ThunkSection;
struct InputSectionDescription : BaseCommand {
InputSectionDescription(StringRef FilePattern)
: BaseCommand(InputSectionKind), FilePat(FilePattern) {}
@@ -153,6 +154,10 @@ struct InputSectionDescription : BaseCom
std::vector<SectionPattern> SectionPatterns;
std::vector<InputSection *> Sections;
+
+ // Temporary record of synthetic ThunkSection instances that we need to
+ // insert into Sections at the end of a createThunks() pass.
+ std::vector<ThunkSection *> ThunkSections;
};
// Represents an ASSERT().
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=316750&r1=316749&r2=316750&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Fri Oct 27 01:56:20 2017
@@ -1048,40 +1048,40 @@ template <class ELFT> void elf::scanRelo
scanRelocs<ELFT>(S, S.rels<ELFT>());
}
-// Insert the Thunks for OutputSection OS into their designated place
-// in the Sections vector, and recalculate the InputSection output section
-// offsets.
-// This may invalidate any output section offsets stored outside of InputSection
-void ThunkCreator::mergeThunks() {
- for (auto &KV : ThunkSections) {
- std::vector<InputSection *> *ISR = KV.first;
- std::vector<ThunkSection *> &Thunks = KV.second;
-
- // Order Thunks in ascending OutSecOff
- auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
- return A->OutSecOff < B->OutSecOff;
- };
- std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
-
- // Merge sorted vectors of Thunks and InputSections by OutSecOff
- std::vector<InputSection *> Tmp;
- Tmp.reserve(ISR->size() + Thunks.size());
- auto MergeCmp = [](const InputSection *A, const InputSection *B) {
- // std::merge requires a strict weak ordering.
- if (A->OutSecOff < B->OutSecOff)
- return true;
- if (A->OutSecOff == B->OutSecOff)
- // Check if Thunk is immediately before any specific Target InputSection
- // for example Mips LA25 Thunks.
- if (auto *TA = dyn_cast<ThunkSection>(A))
- if (TA && TA->getTargetInputSection() == B)
+// Merge the ThunkSections created this pass into the InputSectionDescriptions.
+void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> OutputSections) {
+ forEachInputSectionDescription(
+ OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
+ if (ISD->ThunkSections.empty())
+ return;
+
+ // Order Thunks in ascending OutSecOff
+ std::stable_sort(ISD->ThunkSections.begin(), ISD->ThunkSections.end(),
+ [](const ThunkSection *A, const ThunkSection *B) {
+ return A->OutSecOff < B->OutSecOff;
+ });
+
+ // Merge sorted vectors of Thunks and InputSections by OutSecOff
+ std::vector<InputSection *> Tmp;
+ Tmp.reserve(ISD->Sections.size() + ISD->ThunkSections.size());
+ auto MergeCmp = [](const InputSection *A, const InputSection *B) {
+ // std::merge requires a strict weak ordering.
+ if (A->OutSecOff < B->OutSecOff)
return true;
- return false;
- };
- std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(),
- std::back_inserter(Tmp), MergeCmp);
- *ISR = std::move(Tmp);
- }
+ if (A->OutSecOff == B->OutSecOff)
+ // Check if Thunk is immediately before any specific Target
+ // InputSection for example Mips LA25 Thunks.
+ if (auto *TA = dyn_cast<ThunkSection>(A))
+ if (TA && TA->getTargetInputSection() == B)
+ return true;
+ return false;
+ };
+ std::merge(ISD->Sections.begin(), ISD->Sections.end(),
+ ISD->ThunkSections.begin(), ISD->ThunkSections.end(),
+ std::back_inserter(Tmp), MergeCmp);
+ ISD->Sections = std::move(Tmp);
+ ISD->ThunkSections.clear();
+ });
}
static uint32_t findEndOfFirstNonExec(OutputSection &Cmd) {
@@ -1094,12 +1094,12 @@ static uint32_t findEndOfFirstNonExec(Ou
}
ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS,
- std::vector<InputSection *> *ISR) {
- if (CurTS == nullptr) {
- uint32_t Off = findEndOfFirstNonExec(*OS);
- CurTS = addThunkSection(OS, ISR, Off);
- }
- return CurTS;
+ InputSectionDescription *ISD) {
+ if (!ISD->ThunkSections.empty())
+ return ISD->ThunkSections.front();
+
+ uint32_t Off = findEndOfFirstNonExec(*OS);
+ return addThunkSection(OS, ISD, Off);
}
// Add a Thunk that needs to be placed in a ThunkSection that immediately
@@ -1112,27 +1112,25 @@ ThunkSection *ThunkCreator::getISThunkSe
// Find InputSectionRange within Target Output Section (TOS) that the
// InputSection (IS) that we need to precede is in.
OutputSection *TOS = IS->getParent();
- std::vector<InputSection *> *Range = nullptr;
for (BaseCommand *BC : TOS->SectionCommands)
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;
+ TS = addThunkSection(TOS, ISD, IS->OutSecOff);
+ ThunkedSections[IS] = TS;
break;
}
}
- TS = addThunkSection(TOS, Range, IS->OutSecOff);
- ThunkedSections[IS] = TS;
return TS;
}
ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
- std::vector<InputSection *> *ISR,
+ InputSectionDescription *ISD,
uint64_t Off) {
auto *TS = make<ThunkSection>(OS, Off);
- ThunkSections[ISR].push_back(TS);
+ ISD->ThunkSections.push_back(TS);
return TS;
}
@@ -1153,73 +1151,66 @@ std::pair<Thunk *, bool> ThunkCreator::g
// Call Fn on every executable InputSection accessed via the linker script
// InputSectionDescription::Sections.
-void ThunkCreator::forEachExecInputSection(
+void ThunkCreator::forEachInputSectionDescription(
ArrayRef<OutputSection *> OutputSections,
- std::function<void(OutputSection *, std::vector<InputSection *> *,
- InputSection *)>
- Fn) {
+ std::function<void(OutputSection *, InputSectionDescription *)> Fn) {
for (OutputSection *OS : OutputSections) {
if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
continue;
for (BaseCommand *BC : OS->SectionCommands)
- if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
- CurTS = nullptr;
- for (InputSection *IS : ISD->Sections)
- Fn(OS, &ISD->Sections, IS);
- }
+ if (auto *ISD = dyn_cast<InputSectionDescription>(BC))
+ Fn(OS, ISD);
}
}
// Process all relocations from the InputSections that have been assigned
-// to OutputSections and redirect through Thunks if needed.
+// to InputSectionDescriptions and redirect through Thunks if needed.
//
// createThunks must be called after scanRelocs has created the Relocations for
// each InputSection. It must be called before the static symbol table is
-// finalized. If any Thunks are added to an OutputSection the output section
-// offsets of the InputSections will change.
+// finalized. If any Thunks are added to an InputSectionDescription the
+// offsets within the OutputSection of the InputSections will change.
//
// FIXME: All Thunks are assumed to be in range of the relocation. Range
// extension Thunks are not yet supported.
bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
- if (Pass > 0)
- ThunkSections.clear();
-
+ bool AddressesChanged = false;
// Create all the Thunks and insert them into synthetic ThunkSections. The
- // ThunkSections are later inserted back into the OutputSection.
-
+ // ThunkSections are later inserted back into InputSectionDescriptions.
// We separate the creation of ThunkSections from the insertion of the
- // ThunkSections back into the OutputSection as ThunkSections are not always
- // inserted into the same OutputSection as the caller.
- forEachExecInputSection(OutputSections, [&](OutputSection *OS,
- std::vector<InputSection *> *ISR,
- InputSection *IS) {
- for (Relocation &Rel : IS->Relocations) {
- SymbolBody &Body = *Rel.Sym;
- if (Thunks.find(&Body) != Thunks.end() ||
- !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
- continue;
- Thunk *T;
- bool IsNew;
- std::tie(T, IsNew) = getThunk(Body, Rel.Type);
- if (IsNew) {
- // Find or create a ThunkSection for the new Thunk
- ThunkSection *TS;
- if (auto *TIS = T->getTargetInputSection())
- TS = getISThunkSec(TIS);
- else
- TS = getOSThunkSec(OS, ISR);
- TS->addThunk(T);
- Thunks[T->ThunkSym] = T;
- }
- // Redirect relocation to Thunk, we never go via the PLT to a Thunk
- Rel.Sym = T->ThunkSym;
- Rel.Expr = fromPlt(Rel.Expr);
- }
- });
+ // ThunkSections as ThunkSections are not always inserted into the same
+ // InputSectionDescription as the caller.
+ forEachInputSectionDescription(
+ OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
+ for (InputSection *IS : ISD->Sections)
+ for (Relocation &Rel : IS->Relocations) {
+ SymbolBody &Body = *Rel.Sym;
+ if (Thunks.find(&Body) != Thunks.end() ||
+ !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+ continue;
+ Thunk *T;
+ bool IsNew;
+ std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+ if (IsNew) {
+ AddressesChanged = true;
+ // Find or create a ThunkSection for the new Thunk
+ ThunkSection *TS;
+ if (auto *TIS = T->getTargetInputSection())
+ TS = getISThunkSec(TIS);
+ else
+ TS = getOSThunkSec(OS, ISD);
+ TS->addThunk(T);
+ Thunks[T->ThunkSym] = T;
+ }
+ // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+ Rel.Sym = T->ThunkSym;
+ Rel.Expr = fromPlt(Rel.Expr);
+ }
+ });
// Merge all created synthetic ThunkSections back into OutputSection
- mergeThunks();
+ mergeThunks(OutputSections);
++Pass;
- return !ThunkSections.empty();
+ return AddressesChanged;
}
template void elf::scanRelocations<ELF32LE>(InputSectionBase &);
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=316750&r1=316749&r2=316750&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Fri Oct 27 01:56:20 2017
@@ -125,6 +125,7 @@ template <class ELFT> void scanRelocatio
class ThunkSection;
class Thunk;
+struct InputSectionDescription;
class ThunkCreator {
public:
@@ -137,18 +138,17 @@ public:
uint32_t Pass = 0;
private:
- void mergeThunks();
- ThunkSection *getOSThunkSec(OutputSection *OS,
- std::vector<InputSection *> *ISR);
+ void mergeThunks(ArrayRef<OutputSection *> OutputSections);
+ ThunkSection *getOSThunkSec(OutputSection *OS, InputSectionDescription *ISD);
ThunkSection *getISThunkSec(InputSection *IS);
- void forEachExecInputSection(
+
+ void forEachInputSectionDescription(
ArrayRef<OutputSection *> OutputSections,
- std::function<void(OutputSection *, std::vector<InputSection *> *,
- InputSection *)>
- Fn);
+ std::function<void(OutputSection *, InputSectionDescription *)> Fn);
+
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, RelType Type);
- ThunkSection *addThunkSection(OutputSection *OS,
- std::vector<InputSection *> *, uint64_t Off);
+ ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *,
+ uint64_t Off);
// Record all the available Thunks for a Symbol
llvm::DenseMap<SymbolBody *, std::vector<Thunk *>> ThunkedSymbols;
@@ -161,16 +161,6 @@ private:
// so we need to make sure that there is only one of them.
// The Mips LA25 Thunk is an example of an inline ThunkSection.
llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
-
- // All the ThunkSections that we have created, organised by OutputSection
- // will contain a mix of ThunkSections that have been created this pass, and
- // ThunkSections that have been merged into the OutputSection on previous
- // passes
- std::map<std::vector<InputSection *> *, std::vector<ThunkSection *>>
- ThunkSections;
-
- // The ThunkSection for this vector of InputSections
- ThunkSection *CurTS;
};
// Return a int64_t to make sure we get the sign extension out of the way as
More information about the llvm-commits
mailing list