aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-08 08:57:23 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-08 08:57:23 +0000
commita7f57508ab146b624f969a7925fa1d4afc5bc710 (patch)
tree3ead4559ca48ebb6662a29d182a44f22a4e20b11
parent4b232f4c010afc8474c3d90b4ee49495c233db61 (diff)
Merging r368041:
------------------------------------------------------------------------ r368041 | psmith | 2019-08-06 16:13:38 +0200 (Tue, 06 Aug 2019) | 16 lines [ELF][ARM] Fix /DISCARD/ of section with .ARM.exidx section The combineEhSections runs, by design, before processSectionCommands so that input exception sections like .ARM.exidx and .eh_frame are not assigned to OutputSections. Unfortunately if /DISCARD/ removes InputSections that have associated .ARM.exidx sections without discarding the .ARM.exidx synthetic section then we will end up crashing when trying to sort the InputSections in ascending address order. We fix this by filtering out the sections that have been discarded prior to processing the InputSections in finalizeContents(). fixes pr42890 Differential Revision: https://reviews.llvm.org/D65759 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/lld/branches/release_90@368270 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--ELF/SyntheticSections.cpp14
-rw-r--r--test/ELF/arm-exidx-partial-discard.s37
2 files changed, 50 insertions, 1 deletions
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index f6d0f190d..35b9b8928 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -3177,11 +3177,23 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
// 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.
diff --git a/test/ELF/arm-exidx-partial-discard.s b/test/ELF/arm-exidx-partial-discard.s
new file mode 100644
index 000000000..770a811c1
--- /dev/null
+++ b/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