diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -245,10 +245,13 @@ void expandMemoryRegions(uint64_t size); std::vector - computeInputSections(const InputSectionDescription *); + computeInputSections(const InputSectionDescription *, + ArrayRef); std::vector createInputSectionList(OutputSection &cmd); + void discardSynthetic(OutputSection &); + std::vector getPhdrIndices(OutputSection *sec); MemoryRegion *findMemoryRegion(OutputSection *sec); diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -407,14 +407,15 @@ // Compute and remember which sections the InputSectionDescription matches. std::vector -LinkerScript::computeInputSections(const InputSectionDescription *cmd) { +LinkerScript::computeInputSections(const InputSectionDescription *cmd, + ArrayRef sections) { std::vector ret; // Collects all sections that satisfy constraints of Cmd. for (const SectionPattern &pat : cmd->sectionPatterns) { size_t sizeBefore = ret.size(); - for (InputSectionBase *sec : inputSections) { + for (InputSectionBase *sec : sections) { if (!sec->isLive() || sec->parent) continue; @@ -465,13 +466,29 @@ discard(ds); } +void LinkerScript::discardSynthetic(OutputSection &outCmd) { + for (Partition &part : partitions) { + if (!part.armExidx || !part.armExidx->isLive()) + continue; + std::vector secs(part.armExidx->exidxSections.begin(), + part.armExidx->exidxSections.end()); + for (BaseCommand *base : outCmd.sectionCommands) + if (auto *cmd = dyn_cast(base)) { + std::vector matches = + computeInputSections(cmd, secs); + for (InputSectionBase *s : matches) + discard(s); + } + } +} + std::vector LinkerScript::createInputSectionList(OutputSection &outCmd) { std::vector ret; for (BaseCommand *base : outCmd.sectionCommands) { if (auto *cmd = dyn_cast(base)) { - cmd->sectionBases = computeInputSections(cmd); + cmd->sectionBases = computeInputSections(cmd, inputSections); for (InputSectionBase *s : cmd->sectionBases) s->parent = &outCmd; ret.insert(ret.end(), cmd->sectionBases.begin(), cmd->sectionBases.end()); @@ -492,6 +509,7 @@ if (sec->name == "/DISCARD/") { for (InputSectionBase *s : v) discard(s); + discardSynthetic(*sec); sec->sectionCommands.clear(); continue; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3263,7 +3263,7 @@ static InputSection *findExidxSection(InputSection *isec) { for (InputSection *d : isec->dependentSections) - if (d->type == SHT_ARM_EXIDX) + if (d->type == SHT_ARM_EXIDX && d->isLive()) return d; return nullptr; } diff --git a/lld/test/ELF/arm-exidx-partial-discard-exidx.s b/lld/test/ELF/arm-exidx-partial-discard-exidx.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/arm-exidx-partial-discard-exidx.s @@ -0,0 +1,48 @@ +// REQUIRES: arm +// RUN: llvm-mc --arm-add-build-attributes --triple=armv7a-linux-gnueabihf -filetype=obj %s -o %t.o +// RUN: echo "SECTIONS { \ +// RUN: /DISCARD/ : { *(.ARM.exidx.exit.text) *(.ARM.extab.exit.text)} \ +// RUN: . = 0x90000000; \ +// RUN: .ARM.exidx : { *(.ARM.exidx) } \ +// RUN: .text : { *(.text) } \ +// RUN: .exit.text : { *(.exit.text) } \ +// RUN: .rodata : { *(.rodata) } \ +// RUN: } " > %t.script +// RUN: ld.lld --script %t.script %t.o -o %t +// RUN: llvm-readelf -x .ARM.exidx %t | FileCheck %s + +/// The linker script /DISCARDS/ the .ARM.exidx and .ARM.extab for the +/// .exit.text . If we do not discard both sections we will end up with +/// a dangling reference. We expect no linker error for an out of range +/// relocation/dangling reference and just a single .ARM.exidx entry +/// for _start and an entry for the terminating sentinel. + +// CHECK: Hex dump of section '.ARM.exidx': +// CHECK-NEXT: 0x90000000 10000000 01000000 10000000 01000000 +// CHECK-NOT: 0x90000010 + .text + .global _start + .type _start, %function +_start: + .fnstart + bx lr + .cantunwind + .fnend + + .section .exit.text, "ax", %progbits + .global exit_text + .type exit_text, %function +exit_text: + .fnstart + bx lr + .personality __gxx_personality_v0 + .handlerdata + .long 0 + .fnend + +/// Dummy definition for a reference from the personality routine created by +/// the assembler, use .data to avoid generating a cantunwind table. + .section .rodata + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + .word 0