Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -269,7 +269,9 @@ void assignOffsets(OutputSectionCommand *Cmd); void placeOrphanSections(); void processNonSectionCommands(); + void sortLinkOrder(); void synchronize(); + void resetAddressState(); void assignAddresses(std::vector &Phdrs); void writeDataBytes(OutputSection *Sec, uint8_t *Buf); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -628,6 +628,19 @@ return nullptr; } +// Reset the members associated with address assigment to their initial values +// this permits addressAssignment to be run again. +void LinkerScript::resetAddressState() { + LMAOffset = 0; + CurOutSec = nullptr; + CurMemRegion = nullptr; + ThreadBssOffset = 0; + for (auto &MRI : Opt.MemoryRegions) { + MemoryRegion &MR = MRI.second; + MR.Offset = MR.Origin; + } +} + // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) { @@ -864,9 +877,61 @@ } } +static bool compareByFilePosition(InputSectionBase *A, InputSectionBase *B) { + // Synthetic doesn't have link order dependency, stable_sort will keep it last + if (A->kind() == InputSectionBase::Synthetic) + return false; + else if (B->kind() == InputSectionBase::Synthetic) + return true; + auto *LA = cast(A->getLinkOrderDep()); + auto *LB = cast(B->getLinkOrderDep()); + OutputSection *AOut = LA->OutSec; + OutputSection *BOut = LB->OutSec; + if (AOut != BOut) + return AOut->SectionIndex < BOut->SectionIndex; + return LA->OutSecOff < LB->OutSecOff; +} + +// InputSections with the SHF_LINK_ORDER flag are sorted in the same relative +// order as the InputSections +void LinkerScript::sortLinkOrder() { + // We need at least a relative order of InputSections within an OutputSection + // these need not be precise. + for (BaseCommand *Base : Opt.Commands) + if (auto *Cmd = dyn_cast(Base)) { + if (Config->Relocatable) + Cmd->Sec->assignOffsets(); + else + assignOffsets(Cmd); + } + + for (BaseCommand *Base : Opt.Commands) { + auto *Cmd = dyn_cast(Base); + if (!Cmd || !(Cmd->Sec->Flags & SHF_LINK_ORDER) || + Cmd->Sec->Sections.empty()) + continue; + + // 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 : Cmd->Commands) { + auto *ISD = dyn_cast(Base); + if (!ISD) + continue; + for (InputSectionBase *&IS : ISD->Sections) + if (IS->Live) { + ScriptSections.push_back(&IS); + Sections.push_back(cast(IS)); + } + } + std::sort(Sections.begin(), Sections.end(), compareByFilePosition); + for (int I = 0, N = Sections.size(); I < N; ++I) + *ScriptSections[I] = Sections[I]; + } +} // 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. +// list. This is needed to account for last minute changes, like adding thunks // // FIXME: We should instead create the "AST" earlier and the above changes would // be done directly in the "AST". @@ -875,7 +940,7 @@ void LinkerScript::synchronize() { for (BaseCommand *Base : Opt.Commands) { auto *Cmd = dyn_cast(Base); - if (!Cmd) + if (!Cmd || (Cmd->Sec->Flags & SHF_LINK_ORDER)) continue; ArrayRef Sections = Cmd->Sec->Sections; std::vector ScriptSections; @@ -954,6 +1019,7 @@ void LinkerScript::assignAddresses(std::vector &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; + resetAddressState(); ErrorOnMissingSection = true; switchTo(Aether); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -71,20 +71,6 @@ /*Link*/ 0), SectionIndex(INT_MAX) {} -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; - auto *LA = cast(A->getLinkOrderDep()); - auto *LB = cast(B->getLinkOrderDep()); - OutputSection *AOut = LA->OutSec; - OutputSection *BOut = LB->OutSec; - if (AOut != BOut) - return AOut->SectionIndex < BOut->SectionIndex; - return LA->OutSecOff < LB->OutSecOff; -} - // Compress section contents if this section contains debug info. template void OutputSection::maybeCompress() { typedef typename ELFT::Chdr Elf_Chdr; @@ -114,9 +100,6 @@ template void OutputSection::finalize() { if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { - std::sort(Sections.begin(), Sections.end(), compareByFilePosition); - assignOffsets(); - // 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/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2196,13 +2196,16 @@ // This section will have been sorted last in the .ARM.exidx table. // This table entry will have the form: // | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | +// The sentinel must have the PREL31 value of an address higher than any +// address described by any other table entry. void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { - // Get the InputSection before us, we are by definition last - auto RI = cast(this->OutSec)->Sections.rbegin(); - InputSection *LE = *(++RI); - InputSection *LC = cast(LE->getLinkOrderDep()); - uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); - uint64_t P = this->getVA(); + uint64_t S = 0; + uint64_t P = getVA(); + for (auto *IS : OutSec->Sections) + if (IS->kind() != InputSectionBase::Synthetic) { + InputSection *LS = cast(IS->getLinkOrderDep()); + S = std::max(S, LS->OutSec->Addr + LS->getOffset(LS->getSize())); + } Target->relocateOne(Buf, R_ARM_PREL31, S - P); write32le(Buf + 4, 0x1); } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -203,6 +203,7 @@ // Create linker-synthesized sections such as .got or .plt. // Such sections are of type input section. createSyntheticSections(); + addPredefinedSections(); combineMergableSections(); if (!Config->Relocatable) @@ -247,10 +248,6 @@ if (Config->Relocatable) { assignFileOffsets(); } else { - if (!Script->Opt.HasSections) { - fixSectionAlignments(); - Script->fabricateDefaultCommands(); - } Script->synchronize(); Script->assignAddresses(Phdrs); @@ -1174,9 +1171,6 @@ if (ErrorCount) return; - // So far we have added sections from input object files. - // This function adds linker-created Out::* sections. - addPredefinedSections(); removeUnusedSyntheticSections(OutputSections); sortSections(); @@ -1201,6 +1195,12 @@ Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } + if (!Script->Opt.HasSections) { + fixSectionAlignments(); + Script->fabricateDefaultCommands(); + } + Script->sortLinkOrder(); + // 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, @@ -1248,9 +1248,12 @@ template void Writer::addPredefinedSections() { // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. - auto *OS = dyn_cast_or_null(findSection(".ARM.exidx")); - if (OS && !OS->Sections.empty() && !Config->Relocatable) - OS->addSection(make()); + if (Config->EMachine == EM_ARM && !Config->Relocatable && + std::find_if(InputSections.begin(), InputSections.end(), + [](InputSectionBase *S) { + return S->Name.startswith(".ARM.exidx"); + }) != InputSections.end()) + InputSections.push_back(make()); } // The linker is expected to define SECNAME_start and SECNAME_end