Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -126,6 +126,8 @@ // Return true if Thunks have been added to OutputSections bool createThunks(ArrayRef OutputSections); + uint32_t Pass = 0; + private: void mergeThunks(); ThunkSection *getOSThunkSec(OutputSection *OS, @@ -137,14 +139,22 @@ InputSection *)> Fn); std::pair getThunk(SymbolBody &Body, uint32_t Type); - + ThunkSection *addThunkSection(OutputSection *OS, + std::vector *, uint64_t Off); // Track Symbols that already have a Thunk llvm::DenseMap ThunkedSymbols; + // Find a Thunk from the Thunks symbol definition, we can use this to find + // the Thunk from a relocation to the Thunks symbol definition. + llvm::DenseMap Thunks; + // Track InputSections that have a ThunkSection placed in front llvm::DenseMap ThunkedSections; - // Track the ThunksSections that need to be inserted into an OutputSection + // 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> ThunkSections; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -1009,8 +1009,7 @@ if ((IS->Flags & SHF_EXECINSTR) == 0) break; } - CurTS = make(OS, Off); - ThunkSections[ISR].push_back(CurTS); + CurTS = addThunkSection(OS, ISR, Off); } return CurTS; } @@ -1035,11 +1034,20 @@ break; } } - ThunkSections[Range].push_back(TS); + TS = addThunkSection(TOS, Range, IS->OutSecOff); ThunkedSections[IS] = TS; return TS; } +ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, + std::vector *ISR, + uint64_t Off) { + auto *TS = make(OS, Off); + ThunkSections[ISR].push_back(TS); + return TS; +} + + std::pair ThunkCreator::getThunk(SymbolBody &Body, uint32_t Type) { auto res = ThunkedSymbols.insert({&Body, nullptr}); @@ -1081,6 +1089,15 @@ // extension Thunks are not yet supported. bool ThunkCreator::createThunks( ArrayRef OutputSections) { + bool AddressesChanged = false; + if (Pass > 0) { + ThunkSections.clear(); + if (Pass == 2) + // With supported Thunks pass 0 will create all Thunks, pass 1 will + // create no more Thunks so something must have gone wrong. + fatal("Thunk creation not converged in sufficient number of passes"); + } + // Create all the Thunks and insert them into synthetic ThunkSections. The // ThunkSections are later inserted back into the OutputSection. @@ -1088,16 +1105,21 @@ // ThunkSections back into the OutputSection as ThunkSections are not always // inserted into the same OutputSection as the caller. forEachExecInputSection( - OutputSections, [=](OutputSection *OS, std::vector *ISR, + OutputSections, [&](OutputSection *OS, std::vector *ISR, InputSection *IS) { + if (isa(IS)) + // Do not create Thunks for relocations from existing Thunks + return; for (Relocation &Rel : IS->Relocations) { SymbolBody &Body = *Rel.Sym; - if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) + 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()) @@ -1105,16 +1127,19 @@ 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); } }); - - // Merge all created synthetic ThunkSections back into OutputSection - mergeThunks(); - return !ThunkSections.empty(); + if (AddressesChanged) { + // Merge all created synthetic ThunkSections back into OutputSection + mergeThunks(); + ++Pass; + } + return AddressesChanged; } template void elf::scanRelocations(InputSectionBase &); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1253,7 +1253,7 @@ // are out of range. This will need to turn into a loop that converges // when no more Thunks are added ThunkCreator TC; - if (TC.createThunks(OutputSectionCommands)) + while (TC.createThunks(OutputSectionCommands)) applySynthetic({InX::MipsGot}, [](SyntheticSection *SS) { SS->updateAllocSize(); }); }