Index: ELF/ICF.cpp =================================================================== --- ELF/ICF.cpp +++ ELF/ICF.cpp @@ -436,8 +436,8 @@ if (Config->EMachine == EM_ARM) for (InputSectionBase *Sec : InputSections) if (auto *S = dyn_cast(Sec)) - if (S->Flags & SHF_LINK_ORDER) - S->Live = S->getLinkOrderDep()->Live; + if (S->LinkOrderSection) + S->Live = S->LinkOrderSection->Live; } // ICF entry point function. Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -163,8 +163,6 @@ return getFile()->getObj(); } - InputSection *getLinkOrderDep() const; - void uncompress(); // Returns a source location string. Used to construct an error message. @@ -184,6 +182,10 @@ return llvm::makeArrayRef((const T *)Data.data(), S / sizeof(T)); } + // A value of an SHF_LINK_ORDER flag. If a section doesn't have an + // SHF_LINK_ORDER, it's nullptr. + InputSection *LinkOrderSection = nullptr; + private: // A pointer that owns uncompressed data if a section is compressed by zlib. // Since the feature is not used often, this is usually a nullptr. Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -105,6 +105,18 @@ NumRelocations = 0; AreRelocsRela = false; + if (this->Flags & SHF_LINK_ORDER) { + InputSectionBase *Sec = File->getSections()[Link]; + if (isa(Sec)) + LinkOrderSection = cast(Sec); + else + error("a section with SHF_LINK_ORDER should not refer a non-regular " + "section: " + + toString(Sec)); + if (!Config->Relocatable) + this->Flags &= ~(uint64_t)SHF_LINK_ORDER; + } + // The ELF spec states that a value of 0 means the section has // no alignment constraits. uint32_t V = std::max(Alignment, 1); @@ -230,18 +242,6 @@ return getOffset(Sym.Value); } -InputSection *InputSectionBase::getLinkOrderDep() const { - if ((Flags & SHF_LINK_ORDER) && Link != 0) { - InputSectionBase *L = File->getSections()[Link]; - if (auto *IS = dyn_cast(L)) - return IS; - error("a section with SHF_LINK_ORDER should not refer a non-regular " - "section: " + - toString(L)); - } - return nullptr; -} - // Returns a source location string. Used to construct an error message. template std::string InputSectionBase::getLocation(uint64_t Offset) { Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -246,7 +246,7 @@ // referred by .eh_frame here. if (auto *EH = dyn_cast_or_null(Sec)) scanEhFrameSection(*EH, Enqueue); - if (Sec->Flags & SHF_LINK_ORDER) + if (Sec->LinkOrderSection) continue; if (isReserved(Sec) || Script->shouldKeep(Sec)) Enqueue(Sec, 0); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -421,13 +421,11 @@ 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(); + OutputSection *AOut = A->LinkOrderSection->getParent(); + OutputSection *BOut = B->LinkOrderSection->getParent(); if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; - return LA->OutSecOff < LB->OutSecOff; + return A->LinkOrderSection->OutSecOff < B->LinkOrderSection->OutSecOff; } template @@ -446,6 +444,13 @@ OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info]); } +static uint32_t getLinkOrder(ArrayRef V) { + for (InputSection *IS : V) + if (IS->LinkOrderSection) + return IS->LinkOrderSection->getParent()->SectionIndex; + return 0; +} + template void OutputSection::finalize() { // Link order may be distributed across several InputSectionDescriptions // but sort must consider them all at once. @@ -460,17 +465,20 @@ } } - if (Flags & SHF_LINK_ORDER) { + bool HasLinkOrder = llvm::any_of( + Sections, [](InputSection *Sec) { return Sec->LinkOrderSection; }); + if (HasLinkOrder) { 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, - // all InputSections in the OutputSection have the same dependency. - if (auto *D = Sections.front()->getLinkOrderDep()) - Link = D->getParent()->SectionIndex; + // If -r is given we preserve SHF_LINK_ORDER flag. In that case we must + // preserve the link order dependency. The dependency is indicated by the + // sh_link field. We need to translate the InputSection sh_link to the + // OutputSection sh_link, all InputSections in the OutputSection have the + // same dependency. + if (this->Flags & SHF_LINK_ORDER) + this->Link = getLinkOrder(Sections); } if (Type == SHT_GROUP) { Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2346,8 +2346,8 @@ ".rld_map") {} ARMExidxSentinelSection::ARMExidxSentinelSection() - : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, - Config->Wordsize, ".ARM.exidx") {} + : SyntheticSection(SHF_ALLOC, SHT_ARM_EXIDX, Config->Wordsize, + ".ARM.exidx") {} // Write a terminating sentinel entry to the end of the .ARM.exidx table. // This section will have been sorted last in the .ARM.exidx table. @@ -2367,7 +2367,7 @@ }); auto L = cast(*ISD); InputSection *Highest = L->Sections[L->Sections.size() - 2]; - InputSection *LS = Highest->getLinkOrderDep(); + InputSection *LS = Highest->LinkOrderSection; uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); uint64_t P = getVA(); Target->relocateOne(Buf, R_ARM_PREL31, S - P); Index: test/ELF/arm-exidx-canunwind.s =================================================================== --- test/ELF/arm-exidx-canunwind.s +++ test/ELF/arm-exidx-canunwind.s @@ -80,7 +80,6 @@ // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Flags [ // CHECK-PT-NEXT: SHF_ALLOC -// CHECK-PT-NEXT: SHF_LINK_ORDER // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 Index: test/ELF/arm-exidx-link.s =================================================================== --- test/ELF/arm-exidx-link.s +++ test/ELF/arm-exidx-link.s @@ -7,16 +7,26 @@ // CHECK-NEXT: Type: SHT_ARM_EXIDX // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_LINK_ORDER // CHECK-NEXT: ] // CHECK-NEXT: Address: // CHECK-NEXT: Offset: // CHECK-NEXT: Size: -// CHECK-NEXT: Link: [[INDEX:.*]] - -// CHECK: Index: [[INDEX]] -// CHECK-NEXT: Name: .text +// CHECK-NEXT: Link: 0 +// RUN: ld.lld %t.o -o %t2.o -r +// RUN: llvm-readobj -s %t2.o | FileCheck %s --check-prefix=RELOC +// RELOC: Index: 1 +// RELOC-NEXT: Name: .text +// RELOC: Name: .ARM.exidx +// RELOC-NEXT: Type: SHT_ARM_EXIDX +// RELOC-NEXT: Flags [ +// RELOC-NEXT: SHF_ALLOC +// RELOC-NEXT: SHF_LINK_ORDER +// RELOC-NEXT: ] +// RELOC-NEXT: Address: +// RELOC-NEXT: Offset: +// RELOC-NEXT: Size: +// RELOC-NEXT: Link: 1 f: .fnstart Index: test/ELF/arm-exidx-order.s =================================================================== --- test/ELF/arm-exidx-order.s +++ test/ELF/arm-exidx-order.s @@ -105,7 +105,6 @@ // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Flags [ // CHECK-PT-NEXT: SHF_ALLOC -// CHECK-PT-NEXT: SHF_LINK_ORDER // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 Index: test/ELF/arm-exidx-output.s =================================================================== --- test/ELF/arm-exidx-output.s +++ test/ELF/arm-exidx-output.s @@ -37,7 +37,6 @@ // CHECK-NEXT: Type: SHT_ARM_EXIDX (0x70000001) // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_LINK_ORDER // CHECK-NEXT: ] // CHECK-NOT: Name: .ARM.exidx.text.f1