Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -281,7 +281,6 @@ void assignOffsets(OutputSectionCommand *Cmd); void placeOrphanSections(); void processNonSectionCommands(); - void synchronize(); void assignAddresses(std::vector &Phdrs, ArrayRef OutputSectionCommands); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -870,51 +870,6 @@ } } -// Do a last effort at synchronizing the linker script "AST" and the section -// list. This is needed to account for last minute changes, like adding a -// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections. -// -// FIXME: We should instead create the "AST" earlier and the above changes would -// be done directly in the "AST". -// -// This can only handle new sections being added and sections being reordered. -void LinkerScript::synchronize() { - for (BaseCommand *Base : Opt.Commands) { - auto *Cmd = dyn_cast(Base); - if (!Cmd) - continue; - ArrayRef Sections = Cmd->Sec->Sections; - std::vector ScriptSections; - DenseSet ScriptSectionsSet; - for (BaseCommand *Base : Cmd->Commands) { - auto *ISD = dyn_cast(Base); - if (!ISD) - continue; - for (InputSection *&IS : ISD->Sections) { - if (IS->Live) { - ScriptSections.push_back(&IS); - ScriptSectionsSet.insert(IS); - } - } - } - std::vector Missing; - for (InputSection *IS : Sections) - if (!ScriptSectionsSet.count(IS)) - Missing.push_back(IS); - if (!Missing.empty()) { - auto ISD = make(""); - ISD->Sections = Missing; - Cmd->Commands.push_back(ISD); - for (InputSection *&IS : ISD->Sections) - if (IS->Live) - ScriptSections.push_back(&IS); - } - assert(ScriptSections.size() == Sections.size()); - for (int I = 0, N = Sections.size(); I < N; ++I) - *ScriptSections[I] = Sections[I]; - } -} - static bool allocateHeaders(std::vector &Phdrs, ArrayRef OutputSectionCommands, Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -127,11 +127,13 @@ private: void mergeThunks(); - ThunkSection *getOSThunkSec(OutputSection *OS); + ThunkSection *getOSThunkSec(OutputSection *OS, + std::vector *ISR); ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); void forEachExecInputSection( ArrayRef OutputSections, - std::function Fn); + std::function *, + InputSection *)> Fn); std::pair getThunk(SymbolBody &Body, uint32_t Type); // Track Symbols that already have a Thunk Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -43,6 +43,7 @@ #include "Relocations.h" #include "Config.h" +#include "LinkerScript.h" #include "Memory.h" #include "OutputSections.h" #include "Strings.h" @@ -995,13 +996,16 @@ }; std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(), std::back_inserter(Tmp), MergeCmp); - OutputSection *OS = Thunks.front()->getParent(); - OS->Sections = std::move(Tmp); - OS->assignOffsets(); + *ISR = std::move(Tmp); + + // Add Thunks to OS->Sections + for (InputSection *TS : Thunks) + TS->getParent()->Sections.push_back(TS); } } -ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS) { +ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS, + std::vector *ISR) { if (CurTS == nullptr) { uint32_t Off = 0; for (auto *IS : OS->Sections) { @@ -1010,7 +1014,7 @@ break; } CurTS = make(OS, Off); - ThunkSections[&OS->Sections].push_back(CurTS); + ThunkSections[ISR].push_back(CurTS); } return CurTS; } @@ -1021,7 +1025,21 @@ return TS; auto *TOS = IS->getParent(); TS = make(TOS, IS->OutSecOff); - ThunkSections[&TOS->Sections].push_back(TS); + + // Find InputSectionRange within TOS that IS is in + OutputSectionCommand *C = Script->getCmd(TOS); + std::vector *Range = nullptr; + for (BaseCommand *BC : C->Commands) + if (auto *ISD = dyn_cast (BC)) { + InputSection *first = ISD->Sections.front(); + InputSection *last = ISD->Sections.back(); + if (IS->OutSecOff >= first->OutSecOff && + IS->OutSecOff <= last->OutSecOff) { + Range = &ISD->Sections; + break; + } + } + ThunkSections[Range].push_back(TS); ThunkedSections[IS] = TS; return TS; } @@ -1038,13 +1056,18 @@ // InputSectionDescription::Sections. void ThunkCreator::forEachExecInputSection( ArrayRef OutputSections, - std::function Fn) { + std::function *, + InputSection *)> Fn) { for (OutputSection *OS : OutputSections) { if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) continue; - CurTS = nullptr; - for (InputSection *IS : OS->Sections) - Fn(OS, IS); + if (OutputSectionCommand *C = Script->getCmd(OS)) + for (BaseCommand *BC : C->Commands) + if (auto *ISD = dyn_cast(BC)) { + CurTS = nullptr; + for (InputSection* IS : ISD->Sections) + Fn(OS, &ISD->Sections, IS); + } } } @@ -1066,7 +1089,8 @@ // ThunkSections back into the OutputSection as ThunkSections are not always // inserted into the same OutputSection as the caller. forEachExecInputSection( - OutputSections, [=](OutputSection *OS, InputSection *IS) { + OutputSections, [=](OutputSection *OS, std::vector *ISR, + InputSection *IS) { for (Relocation &Rel : IS->Relocations) { SymbolBody &Body = *Rel.Sym; if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) @@ -1080,7 +1104,7 @@ if (auto *TIS = T->getTargetInputSection()) TS = getISThunkSec(TIS, OS); else - TS = getOSThunkSec(OS); + TS = getOSThunkSec(OS, ISR); TS->addThunk(T); } // Redirect relocation to Thunk, we never go via the PLT to a Thunk Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1225,6 +1225,12 @@ Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } + if (!Script->Opt.HasSections) { + Script->fabricateDefaultCommands(); + if (!Config->Relocatable) + fixSectionAlignments(); + } + // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo, @@ -1253,14 +1259,6 @@ [](SyntheticSection *SS) { SS->updateAllocSize(); }); } - if (!Script->Opt.HasSections) { - Script->fabricateDefaultCommands(); - if (!Config->Relocatable) - fixSectionAlignments(); - } else { - Script->synchronize(); - } - // Fill other section headers. The dynamic table is finalized // at the end because some tags like RELSZ depend on result // of finalizing other sections.