Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -11,6 +11,9 @@ #define LLD_ELF_RELOCATIONS_H #include "lld/Core/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include +#include namespace lld { namespace elf { @@ -113,8 +116,29 @@ template void scanRelocations(InputSectionBase &); -template -bool createThunks(ArrayRef OutputSections); +class ThunkSection; +class Thunk; + +template class ThunkCreator { +public: + // Return true if Thunks have been added to OutputSections + bool createThunks(ArrayRef OutputSections); + +private: + void mergeThunks(OutputSection *OS, std::vector &Thunks); + ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS); + ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); + std::pair getThunk(SymbolBody &Body, uint32_t Type); + + // Track Symbols that already have a Thunk + llvm::DenseMap ThunkedSymbols; + + // Track InputSections that have a ThunkSection placed in front + llvm::DenseMap ThunkedSections; + + // Track the ThunksSections that need to be inserted into an OutputSection + std::map> ThunkSections; +}; // Return a int64_t to make sure we get the sign extension out of the way as // early as possible. Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -932,8 +932,9 @@ // in the Sections vector, and recalculate the InputSection output section // offsets. // This may invalidate any output section offsets stored outside of InputSection -static void mergeThunks(OutputSection *OS, - std::vector &Thunks) { +template +void ThunkCreator::mergeThunks(OutputSection *OS, + std::vector &Thunks) { // Order Thunks in ascending OutSecOff auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) { return A->OutSecOff < B->OutSecOff; @@ -961,6 +962,44 @@ OS->assignOffsets(); } +template +ThunkSection *ThunkCreator::getOSThunkSec(ThunkSection *&TS, + OutputSection *OS) { + if (TS == nullptr) { + uint32_t Off = 0; + for (auto *IS : OS->Sections) { + Off = IS->OutSecOff + IS->getSize(); + if ((IS->Flags & SHF_EXECINSTR) == 0) + break; + } + TS = make(OS, Off); + ThunkSections[OS].push_back(TS); + } + return TS; +} + +template +ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, + OutputSection *OS) { + ThunkSection *TS = ThunkedSections.lookup(IS); + if (TS) + return TS; + auto *TOS = cast(IS->OutSec); + TS = make(TOS, IS->OutSecOff); + ThunkSections[TOS].push_back(TS); + ThunkedSections[IS] = TS; + return TS; +} + +template +std::pair ThunkCreator::getThunk(SymbolBody &Body, + uint32_t Type) { + auto res = ThunkedSymbols.insert({&Body, nullptr}); + if (res.second) + res.first->second = addThunk(Type, Body); + return std::make_pair(res.first->second, res.second); +} + // Process all relocations from the InputSections that have been assigned // to OutputSections and redirect through Thunks if needed. // @@ -972,48 +1011,8 @@ // FIXME: All Thunks are assumed to be in range of the relocation. Range // extension Thunks are not yet supported. template -bool elf::createThunks(ArrayRef OutputSections) { - // Track Symbols that already have a Thunk - DenseMap ThunkedSymbols; - // Track InputSections that have a ThunkSection placed in front - DenseMap ThunkedSections; - // Track the ThunksSections that need to be inserted into an OutputSection - std::map> ThunkSections; - - // Find or create a Thunk for Body for relocation Type - auto GetThunk = [&](SymbolBody &Body, uint32_t Type) { - auto res = ThunkedSymbols.insert({&Body, nullptr}); - if (res.second == true) - res.first->second = addThunk(Type, Body); - return std::make_pair(res.first->second, res.second); - }; - - // Find or create a ThunkSection to be placed immediately before IS - auto GetISThunkSec = [&](InputSection *IS, OutputSection *OS) { - ThunkSection *TS = ThunkedSections.lookup(IS); - if (TS) - return TS; - auto *TOS = cast(IS->OutSec); - TS = make(TOS, IS->OutSecOff); - ThunkSections[TOS].push_back(TS); - ThunkedSections[IS] = TS; - return TS; - }; - // Find or create a ThunkSection to be placed as last executable section in - // OS. - auto GetOSThunkSec = [&](ThunkSection *&TS, OutputSection *OS) { - if (TS == nullptr) { - uint32_t Off = 0; - for (auto *IS : OS->Sections) { - Off = IS->OutSecOff + IS->getSize(); - if ((IS->Flags & SHF_EXECINSTR) == 0) - break; - } - TS = make(OS, Off); - ThunkSections[OS].push_back(TS); - } - return TS; - }; +bool ThunkCreator::createThunks( + ArrayRef OutputSections) { // Create all the Thunks and insert them into synthetic ThunkSections. The // ThunkSections are later inserted back into the OutputSection. @@ -1025,23 +1024,23 @@ for (InputSection *IS : OS->Sections) { for (Relocation &Rel : IS->Relocations) { SymbolBody &Body = *Rel.Sym; - if (Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) { - 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, OS); - else - TS = GetOSThunkSec(OSTS, OS); - TS->addThunk(T); - } - // Redirect relocation to Thunk, we never go via the PLT to a Thunk - Rel.Sym = T->ThunkSym; - Rel.Expr = fromPlt(Rel.Expr); + if (!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, OS); + else + TS = getOSThunkSec(OSTS, OS); + TS->addThunk(T); } + // Redirect relocation to Thunk, we never go via the PLT to a Thunk + Rel.Sym = T->ThunkSym; + Rel.Expr = fromPlt(Rel.Expr); } } } @@ -1057,7 +1056,7 @@ template void elf::scanRelocations(InputSectionBase &); template void elf::scanRelocations(InputSectionBase &); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); +template class elf::ThunkCreator; +template class elf::ThunkCreator; +template class elf::ThunkCreator; +template class elf::ThunkCreator; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1180,7 +1180,8 @@ // we need to assign addresses so that we can tell if jump instructions // are out of range. This will need to turn into a loop that converges // when no more Thunks are added - if (createThunks(OutputSections)) + ThunkCreator TC; + if (TC.createThunks(OutputSections)) applySynthetic({In::MipsGot}, [](SyntheticSection *SS) { SS->updateAllocSize(); }); }