Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -129,7 +129,7 @@ ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS, InputSectionDescription *ISD, uint32_t Type, - uint64_t Src); + uint64_t Src, unsigned &ThunkSecIdx); ThunkSection *getISThunkSec(InputSection *IS); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -1240,10 +1240,9 @@ for (auto I = Rels.begin(), End = Rels.end(); I != End;) scanReloc(Sec, GetOffset, I, End); - // Sort relocations by offset for more efficient searching for - // R_RISCV_PCREL_HI20 and R_PPC64_ADDR64. - if (Config->EMachine == EM_RISCV || - (Config->EMachine == EM_PPC64 && Sec.Name == ".toc")) + // Efficient searching for R_RISCV_PCREL_HI20 and R_PPC64_ADDR64, and targets + // need thunks require relocations sorted by offset. + if (Target->NeedsThunks || Config->EMachine == EM_RISCV) llvm::stable_sort(Sec.Relocations, [](const Relocation &LHS, const Relocation &RHS) { return LHS.Offset < RHS.Offset; @@ -1441,13 +1440,20 @@ // linker script section pattern such as { .text .text.* }. ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS, InputSectionDescription *ISD, - uint32_t Type, uint64_t Src) { - for (std::pair TP : ISD->ThunkSections) { - ThunkSection *TS = TP.first; + uint32_t Type, uint64_t Src, + unsigned &ThunkSecIdx) { + for (unsigned E = ISD->ThunkSections.size(); ThunkSecIdx != E; + ++ThunkSecIdx) { + ThunkSection *TS = ISD->ThunkSections[ThunkSecIdx].first; uint64_t TSBase = OS->Addr + TS->OutSecOff; uint64_t TSLimit = TSBase + TS->getSize(); if (Target->inBranchRange(Type, Src, (Src > TSLimit) ? TSBase : TSLimit)) return TS; + if (Src < TSLimit) + break; + + // If we reach here, we know ThunkSecIdx cannot satisfy any subsequent + // relocation, which has a larger offset. Thus we skip it (++ThunkSecIdx). } // No suitable ThunkSection exists. This can happen when there is a branch @@ -1634,6 +1640,7 @@ // InputSectionDescription as the caller. forEachInputSectionDescription( OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { + unsigned ThunkSecIdx = 0; for (InputSection *IS : ISD->Sections) for (Relocation &Rel : IS->Relocations) { uint64_t Src = IS->getVA(Rel.Offset); @@ -1658,7 +1665,7 @@ if (auto *TIS = T->getTargetInputSection()) TS = getISThunkSec(TIS); else - TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src); + TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src, ThunkSecIdx); TS->addThunk(T); Thunks[T->getThunkTargetSym()] = T; }