Index: lld/ELF/SyntheticSections.h =================================================================== --- lld/ELF/SyntheticSections.h +++ lld/ELF/SyntheticSections.h @@ -994,7 +994,7 @@ size_t getSize() const override { return size; } void writeTo(uint8_t *buf) override; - bool isNeeded() const override { return !empty; } + bool isNeeded() const override; // Sort and remove duplicate entries. void finalizeContents() override; InputSection *getLinkOrderDep() const; @@ -1008,9 +1008,6 @@ private: size_t size; - // Empty if ExecutableSections contains no dependent .ARM.exidx sections. - bool empty = true; - // Instead of storing pointers to the .ARM.exidx InputSections from // InputObjects, we store pointers to the executable sections that need // .ARM.exidx sections. We can then use the dependentSections of these to Index: lld/ELF/SyntheticSections.cpp =================================================================== --- lld/ELF/SyntheticSections.cpp +++ lld/ELF/SyntheticSections.cpp @@ -3218,17 +3218,23 @@ return nullptr; } +static bool isValidExidxSectionDep(InputSection *isec) { + return (isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) && + isec->getSize() > 0; +} + bool ARMExidxSyntheticSection::addSection(InputSection *isec) { if (isec->type == SHT_ARM_EXIDX) { - exidxSections.push_back(isec); - return true; + if (InputSection* dep = isec->getLinkOrderDep()) + if (isValidExidxSectionDep(dep)) { + exidxSections.push_back(isec); + return true; + } + return false; } - if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) && - isec->getSize() > 0) { + if (isValidExidxSectionDep(isec)) { executableSections.push_back(isec); - if (empty && findExidxSection(isec)) - empty = false; return false; } @@ -3395,6 +3401,12 @@ assert(size == offset + 8); } +bool ARMExidxSyntheticSection::isNeeded() const { + return llvm::find_if(exidxSections, [](InputSection *isec) { + return isec->isLive(); + }) != exidxSections.end(); +} + bool ARMExidxSyntheticSection::classof(const SectionBase *d) { return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX; } Index: lld/test/ELF/linkerscript/arm-exidx-discard-all.s =================================================================== --- /dev/null +++ lld/test/ELF/linkerscript/arm-exidx-discard-all.s @@ -0,0 +1,19 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o +// RUN: echo "ENTRY(__entrypoint) SECTIONS { /DISCARD/ : { *(.text.1) } }" > %t.script +// RUN: ld.lld -T %t.script %t.o -o %t.elf +// RUN: llvm-readobj --sections %t.elf | FileCheck %s + +/// Test that when we /DISCARD/ all the input sections with associated +/// .ARM.exidx sections then we also discard all the .ARM.exidx sections. + + .section .text.1, "ax", %progbits + .global foo + .type foo, %function + .fnstart +foo: + bx lr + .cantunwind + .fnend + +// CHECK-NOT: .ARM.exidx