Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -784,9 +784,13 @@ class ARMExidxSentinelSection : public SyntheticSection { public: + static ARMExidxSentinelSection *create(); + ARMExidxSentinelSection(); size_t getSize() const override { return 8; } void writeTo(uint8_t *Buf) override; + + InputSection *Highest = 0; }; // A container for one or more linker generated thunks. Instances of these Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2556,6 +2556,20 @@ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} +ARMExidxSentinelSection *ARMExidxSentinelSection::create() { + if (Config->Relocatable) + return nullptr; + + // Find if there are live ARM exidx input sections. + if (InputSections.end() == + llvm::find_if(InputSections, [](InputSectionBase *Sec) { + return Sec->Type == SHT_ARM_EXIDX && Sec->Live; + })) + return nullptr; + + return make(); +} + ARMExidxSentinelSection::ARMExidxSentinelSection() : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, Config->Wordsize, ".ARM.exidx") {} @@ -2567,23 +2581,6 @@ // 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) { - // The Sections are sorted in order of ascending PREL31 address with the - // sentinel last. We need to find the InputSection that precedes the - // sentinel. - OutputSection *C = getParent(); - InputSection *Highest = nullptr; - unsigned Skip = 1; - for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) { - if (!isa(Base)) - continue; - auto L = cast(Base); - if (Skip >= L->Sections.size()) { - Skip -= L->Sections.size(); - continue; - } - Highest = L->Sections[L->Sections.size() - Skip - 1]; - break; - } assert(Highest); InputSection *LS = Highest->getLinkOrderDep(); uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -54,7 +54,6 @@ void resolveShfLinkOrder(); void sortInputSections(); void finalizeSections(); - void addPredefinedSections(); void setReservedSymbolSections(); std::vector createPhdrs(); @@ -390,6 +389,12 @@ Add(InX::ShStrTab); if (InX::StrTab) Add(InX::StrTab); + + if (Config->EMachine == EM_ARM) + // Add a sentinel to terminate .ARM.exidx. It helps an unwinder + // to find the exact address range of the last entry. + if (auto *Sec = ARMExidxSentinelSection::create()) + Add(Sec); } // The main function of the writer. @@ -1145,10 +1150,10 @@ } static bool compareByFilePosition(InputSection *A, InputSection *B) { - // Synthetic doesn't have link order dependecy, stable_sort will keep it last + // Synthetic, i. e. a sentinel section, should go last. if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) - return false; + return A->kind() != InputSectionBase::Synthetic; InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); @@ -1175,9 +1180,21 @@ } } } + if (Sections.empty()) + continue; + std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); for (int I = 0, N = Sections.size(); I < N; ++I) *ScriptSections[I] = Sections[I]; + + // The last actual entry is required to fill the sentinel. + // Remember it here so that we don't have to find it again. + if (auto *Sentinel = dyn_cast(Sections.back())) { + assert(Sections.size() >= 2 && + "We should create a sentinel section only if there are " + "alive regular exidx sections."); + Sentinel->Highest = Sections[Sections.size() - 2]; + } } } @@ -1331,7 +1348,6 @@ if (errorCount()) return; - addPredefinedSections(); removeUnusedSyntheticSections(); sortSections(); @@ -1427,17 +1443,6 @@ [](SyntheticSection *SS) { SS->postThunkContents(); }); } -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. - OutputSection *Cmd = findSection(".ARM.exidx"); - if (!Cmd || !Cmd->Live || Config->Relocatable) - return; - - auto *Sentinel = make(); - Cmd->addSection(Sentinel); -} - // The linker is expected to define SECNAME_start and SECNAME_end // symbols for a few sections. This function defines them. template void Writer::addStartEndSymbols() { Index: test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s =================================================================== --- test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s +++ test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s @@ -7,7 +7,8 @@ ## We used to crash if the last output section command for .ARM.exidx ## was anything but an input section description. # RUN: ld.lld -T %t.script %t.o -shared -o %t.so -# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s +# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s --check-prefix=DUMP +# RUN: llvm-readobj -s -t %t.so | FileCheck %s .syntax unified .text @@ -18,7 +19,23 @@ bx lr .fnend -// CHECK: Contents of section .ARM.exidx: -// 1000 + 1000 = 0x2000 = _start -// 1008 + 0ffc = 0x2004 = _start + sizeof(_start) -// CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000 +# DUMP: Contents of section .ARM.exidx: +# 1000 + 1000 = 0x2000 = _start +# 1008 + 0ffc = 0x2004 = _start + sizeof(_start) +# DUMP-NEXT: 1000 00100000 01000000 fc0f0000 01000000 + +# CHECK: Section { +# CHECK: Name: .ARM.exidx +# CHECK-NEXT: Type: SHT_ARM_EXIDX +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_LINK_ORDER +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x1000 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 16 + +# Symbol 'foo' is expected to point at the end of the section. +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: 0x1010