Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -271,22 +271,6 @@ writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); } -static bool compareByFilePosition(InputSection *A, InputSection *B) { - // Synthetic doesn't have link order dependecy, stable_sort will keep it last - if (A->kind() == InputSectionBase::Synthetic || - B->kind() == InputSectionBase::Synthetic) - return false; - InputSection *LA = A->getLinkOrderDep(); - InputSection *LB = B->getLinkOrderDep(); - OutputSection *AOut = LA->getParent(); - OutputSection *BOut = LB->getParent(); - if (AOut != BOut) - return AOut->SectionIndex < BOut->SectionIndex; - assert(LA->OutSecPos && LB->OutSecPos && - "Cannot compare late-inserted section positions."); - return LA->OutSecPos < LB->OutSecPos; -} - template static void finalizeShtGroup(OutputSection *OS, ArrayRef Sections) { @@ -304,24 +288,15 @@ } template void OutputSection::finalize() { - // Link order may be distributed across several InputSectionDescriptions - // but sort must consider them all at once. - std::vector ScriptSections; std::vector Sections; for (BaseCommand *Base : SectionCommands) { if (auto *ISD = dyn_cast(Base)) { - for (InputSection *&IS : ISD->Sections) { - ScriptSections.push_back(&IS); + for (InputSection *&IS : ISD->Sections) Sections.push_back(IS); - } } } if (Flags & SHF_LINK_ORDER) { - std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); - for (int I = 0, N = Sections.size(); I < N; ++I) - *ScriptSections[I] = Sections[I]; - // We must preserve the link order dependency of sections with the // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -52,6 +52,7 @@ void addReservedSymbols(); void forEachRelSec(std::function Fn); void sortSections(); + void resolveShfLinkOrder(); void sortInputSections(); void finalizeSections(); void addPredefinedSections(); @@ -1142,6 +1143,44 @@ Script->adjustSectionsAfterSorting(); } +static bool compareByFilePosition(InputSection *A, InputSection *B) { + // Synthetic doesn't have link order dependecy, stable_sort will keep it last + if (A->kind() == InputSectionBase::Synthetic || + B->kind() == InputSectionBase::Synthetic) + return false; + InputSection *LA = A->getLinkOrderDep(); + InputSection *LB = B->getLinkOrderDep(); + OutputSection *AOut = LA->getParent(); + OutputSection *BOut = LB->getParent(); + if (AOut != BOut) + return AOut->SectionIndex < BOut->SectionIndex; + assert(LA->OutSecPos && LB->OutSecPos && + "Cannot compare late-inserted section positions."); + return LA->OutSecPos < LB->OutSecPos; +} + +template void Writer::resolveShfLinkOrder() { + // Link order may be distributed across several InputSectionDescriptions + // but sort must consider them all at once. + for (OutputSection *Sec : OutputSections) { + if (!(Sec->Flags & SHF_LINK_ORDER)) + continue; + std::vector ScriptSections; + std::vector Sections; + for (BaseCommand *Base : Sec->SectionCommands) { + if (auto *ISD = dyn_cast(Base)) { + for (InputSection *&IS : ISD->Sections) { + ScriptSections.push_back(&IS); + Sections.push_back(IS); + } + } + } + std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); + for (int I = 0, N = Sections.size(); I < N; ++I) + *ScriptSections[I] = Sections[I]; + } +} + static void applySynthetic(const std::vector &Sections, std::function Fn) { for (SyntheticSection *SS : Sections) @@ -1350,6 +1389,10 @@ if (!Script->HasSectionsCommand && !Config->Relocatable) fixSectionAlignments(); + // After link order processing .ARM.exidx sections can be deduplicated, which + // needs to be resolved before any other address dependent operation. + resolveShfLinkOrder(); + // Some architectures need to generate content that depends on the address // of InputSections. For example some architectures use small displacements // for jump instructions that is is the linker's responsibility for creating