From 3ed33eade06d583f2a93fe253975bc07a39fbd9e Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 3 Oct 2018 22:20:26 +0000 Subject: [PATCH] Minor refacotring of Relocations.cpp. NFC. This patch splits ThunkCreator::mergeThunks into two smaller functions. Also adds blank lines to various places so that the code doesn't look too dense. llvm-svn: 343732 --- lld/ELF/Relocations.cpp | 111 +++++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 8e4ea1d..8f42340 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1065,6 +1065,29 @@ template void elf::scanRelocations(InputSectionBase &S) { scanRelocs(S, S.rels()); } +static bool 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) { + auto *TA = dyn_cast(A); + auto *TB = dyn_cast(B); + + // Check if Thunk is immediately before any specific Target + // InputSection for example Mips LA25 Thunks. + if (TA && TA->getTargetInputSection() == B) + return true; + + // Place Thunk Sections without specific targets before + // non-Thunk Sections. + if (TA && !TB && !TA->getTargetInputSection()) + return true; + } + + return false; +} + // Thunk Implementation // // Thunks (sometimes called stubs, veneers or branch islands) are small pieces @@ -1167,6 +1190,7 @@ void ThunkCreator::mergeThunks(ArrayRef OutputSections) { [](const std::pair &TS) { return TS.first->getSize() == 0; }); + // ISD->ThunkSections contains all created ThunkSections, including // those inserted in previous passes. Extract the Thunks created this // pass and order them in ascending OutSecOff. @@ -1182,27 +1206,11 @@ void ThunkCreator::mergeThunks(ArrayRef OutputSections) { // Merge sorted vectors of Thunks and InputSections by OutSecOff std::vector Tmp; Tmp.reserve(ISD->Sections.size() + NewThunks.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) { - auto *TA = dyn_cast(A); - auto *TB = dyn_cast(B); - // Check if Thunk is immediately before any specific Target - // InputSection for example Mips LA25 Thunks. - if (TA && TA->getTargetInputSection() == B) - return true; - if (TA && !TB && !TA->getTargetInputSection()) - // Place Thunk Sections without specific targets before - // non-Thunk Sections. - return true; - } - return false; - }; + std::merge(ISD->Sections.begin(), ISD->Sections.end(), NewThunks.begin(), NewThunks.end(), std::back_inserter(Tmp), - MergeCmp); + mergeCmp); + ISD->Sections = std::move(Tmp); }); } @@ -1246,20 +1254,23 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { // Find InputSectionRange within Target Output Section (TOS) that the // InputSection (IS) that we need to precede is in. OutputSection *TOS = IS->getParent(); - for (BaseCommand *BC : TOS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) { - if (ISD->Sections.empty()) - continue; - InputSection *first = ISD->Sections.front(); - InputSection *last = ISD->Sections.back(); - if (IS->OutSecOff >= first->OutSecOff && - IS->OutSecOff <= last->OutSecOff) { - TS = addThunkSection(TOS, ISD, IS->OutSecOff); - ThunkedSections[IS] = TS; - break; - } - } - return TS; + for (BaseCommand *BC : TOS->SectionCommands) { + auto *ISD = dyn_cast(BC); + if (!ISD || ISD->Sections.empty()) + continue; + + InputSection *First = ISD->Sections.front(); + InputSection *Last = ISD->Sections.back(); + + if (IS->OutSecOff < First->OutSecOff || Last->OutSecOff < IS->OutSecOff) + continue; + + TS = addThunkSection(TOS, ISD, IS->OutSecOff); + ThunkedSections[IS] = TS; + return TS; + } + + return nullptr; } // Create one or more ThunkSections per OS that can be used to place Thunks. @@ -1281,10 +1292,12 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { void ThunkCreator::createInitialThunkSections( ArrayRef OutputSections) { uint32_t ThunkSectionSpacing = Target->getThunkSectionSpacing(); + forEachInputSectionDescription( OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { if (ISD->Sections.empty()) return; + uint32_t ISDBegin = ISD->Sections.front()->OutSecOff; uint32_t ISDEnd = ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize(); @@ -1314,13 +1327,14 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, InputSectionDescription *ISD, uint64_t Off) { auto *TS = make(OS, Off); - ISD->ThunkSections.push_back(std::make_pair(TS, Pass)); + ISD->ThunkSections.push_back({TS, Pass}); return TS; } std::pair ThunkCreator::getThunk(Symbol &Sym, RelType Type, uint64_t Src) { std::vector *ThunkVec = nullptr; + // We use (section, offset) pair to find the thunk position if possible so // that we create only one thunk for aliased symbols or ICFed sections. if (auto *D = dyn_cast(&Sym)) @@ -1328,15 +1342,17 @@ std::pair ThunkCreator::getThunk(Symbol &Sym, RelType Type, ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}]; if (!ThunkVec) ThunkVec = &ThunkedSymbols[&Sym]; + // Check existing Thunks for Sym to see if they can be reused - for (Thunk *ET : *ThunkVec) - if (ET->isCompatibleWith(Type) && - Target->inBranchRange(Type, Src, ET->getThunkTargetSym()->getVA())) - return std::make_pair(ET, false); + for (Thunk *T : *ThunkVec) + if (T->isCompatibleWith(Type) && + Target->inBranchRange(Type, Src, T->getThunkTargetSym()->getVA())) + return {T, false}; + // No existing compatible Thunk in range, create a new one Thunk *T = addThunk(Type, Sym); ThunkVec->push_back(T); - return std::make_pair(T, true); + return {T, true}; } // Call Fn on every executable InputSection accessed via the linker script @@ -1358,10 +1374,10 @@ void ThunkCreator::forEachInputSectionDescription( // was originally to a Thunk, but is no longer in range we revert the // relocation back to its original non-Thunk target. bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { - if (Thunk *ET = Thunks.lookup(Rel.Sym)) { + if (Thunk *T = Thunks.lookup(Rel.Sym)) { if (Target->inBranchRange(Rel.Type, Src, Rel.Sym->getVA())) return true; - Rel.Sym = &ET->Destination; + Rel.Sym = &T->Destination; if (Rel.Sym->isInPlt()) Rel.Expr = toPlt(Rel.Expr); } @@ -1395,11 +1411,13 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { // relocation out of range error. bool ThunkCreator::createThunks(ArrayRef OutputSections) { bool AddressesChanged = false; + if (Pass == 0 && Target->getThunkSectionSpacing()) createInitialThunkSections(OutputSections); - else if (Pass == 10) - // With Thunk Size much smaller than branch range we expect to - // converge quickly; if we get to 10 something has gone wrong. + + // With Thunk Size much smaller than branch range we expect to + // converge quickly; if we get to 10 something has gone wrong. + if (Pass == 10) fatal("thunk creation not converged"); // Create all the Thunks and insert them into synthetic ThunkSections. The @@ -1422,9 +1440,11 @@ bool ThunkCreator::createThunks(ArrayRef OutputSections) { if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src, *Rel.Sym)) continue; + Thunk *T; bool IsNew; std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src); + if (IsNew) { // Find or create a ThunkSection for the new Thunk ThunkSection *TS; @@ -1435,13 +1455,16 @@ bool ThunkCreator::createThunks(ArrayRef OutputSections) { TS->addThunk(T); Thunks[T->getThunkTargetSym()] = T; } + // Redirect relocation to Thunk, we never go via the PLT to a Thunk Rel.Sym = T->getThunkTargetSym(); Rel.Expr = fromPlt(Rel.Expr); } + for (auto &P : ISD->ThunkSections) AddressesChanged |= P.first->assignOffsets(); }); + for (auto &P : ThunkedSections) AddressesChanged |= P.second->assignOffsets(); -- 2.7.4