Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -3200,11 +3200,23 @@ // The .ARM.exidx table must be sorted in ascending order of the address of the // functions the table describes. Optionally duplicate adjacent table entries -// can be removed. At the end of the function the ExecutableSections must be +// can be removed. At the end of the function the executableSections must be // sorted in ascending order of address, Sentinel is set to the InputSection // with the highest address and any InputSections that have mergeable // .ARM.exidx table entries are removed from it. void ARMExidxSyntheticSection::finalizeContents() { + if (script->hasSectionsCommand) { + // The executableSections and exidxSections that we use to derive the + // final contents of this SyntheticSection are populated before the + // linker script assigns InputSections to OutputSections. The linker script + // SECTIONS command may have a /DISCARD/ entry that removes executable + // InputSections and their dependent .ARM.exidx section that we recorded + // earlier. + auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); }; + llvm::erase_if(executableSections, isDiscarded); + llvm::erase_if(exidxSections, isDiscarded); + } + // Sort the executable sections that may or may not have associated // .ARM.exidx sections by order of ascending address. This requires the // relative positions of InputSections to be known. Index: lld/trunk/test/ELF/arm-exidx-partial-discard.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-partial-discard.s +++ lld/trunk/test/ELF/arm-exidx-partial-discard.s @@ -0,0 +1,37 @@ +// 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 "SECTIONS { . = 0x10000; .text : { *(.text) } /DISCARD/ : { *(.exit.text) } }" > %t.script +// RUN: ld.lld -T %t.script %t.o -o %t.elf +// RUN: llvm-readobj -x .ARM.exidx --sections %t.elf | FileCheck %s + +// CHECK-NOT: .exit.text +/// Expect 2 entries both CANTUNWIND as the .ARM.exidx.exit.text +// should have been removed. +// CHECK: Hex dump of section '.ARM.exidx': +// CHECK-NEXT: 0x00010000 10000000 01000000 10000000 01000000 + +/// The /DISCARD/ is evaluated after sections have been assigned to the +/// .ARM.exidx synthetic section. We must account for the /DISCARD/ + .section .exit.text, "ax", %progbits + .globl foo + .type foo, %function +foo: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .text + .globl _start + .type _start, %function +_start: + .fnstart + bx lr + .cantunwind + .fnend + + .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr