Skip to content

Commit 7f320d4

Browse files
committed
[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 llvm-svn: 368041
1 parent e49c417 commit 7f320d4

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

lld/ELF/SyntheticSections.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3200,11 +3200,23 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
32003200

32013201
// The .ARM.exidx table must be sorted in ascending order of the address of the
32023202
// functions the table describes. Optionally duplicate adjacent table entries
3203-
// can be removed. At the end of the function the ExecutableSections must be
3203+
// can be removed. At the end of the function the executableSections must be
32043204
// sorted in ascending order of address, Sentinel is set to the InputSection
32053205
// with the highest address and any InputSections that have mergeable
32063206
// .ARM.exidx table entries are removed from it.
32073207
void ARMExidxSyntheticSection::finalizeContents() {
3208+
if (script->hasSectionsCommand) {
3209+
// The executableSections and exidxSections that we use to derive the
3210+
// final contents of this SyntheticSection are populated before the
3211+
// linker script assigns InputSections to OutputSections. The linker script
3212+
// SECTIONS command may have a /DISCARD/ entry that removes executable
3213+
// InputSections and their dependent .ARM.exidx section that we recorded
3214+
// earlier.
3215+
auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); };
3216+
llvm::erase_if(executableSections, isDiscarded);
3217+
llvm::erase_if(exidxSections, isDiscarded);
3218+
}
3219+
32083220
// Sort the executable sections that may or may not have associated
32093221
// .ARM.exidx sections by order of ascending address. This requires the
32103222
// relative positions of InputSections to be known.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// REQUIRES: arm
2+
// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o
3+
// RUN: echo "SECTIONS { . = 0x10000; .text : { *(.text) } /DISCARD/ : { *(.exit.text) } }" > %t.script
4+
// RUN: ld.lld -T %t.script %t.o -o %t.elf
5+
// RUN: llvm-readobj -x .ARM.exidx --sections %t.elf | FileCheck %s
6+
7+
// CHECK-NOT: .exit.text
8+
/// Expect 2 entries both CANTUNWIND as the .ARM.exidx.exit.text
9+
// should have been removed.
10+
// CHECK: Hex dump of section '.ARM.exidx':
11+
// CHECK-NEXT: 0x00010000 10000000 01000000 10000000 01000000
12+
13+
/// The /DISCARD/ is evaluated after sections have been assigned to the
14+
/// .ARM.exidx synthetic section. We must account for the /DISCARD/
15+
.section .exit.text, "ax", %progbits
16+
.globl foo
17+
.type foo, %function
18+
foo:
19+
.fnstart
20+
bx lr
21+
.save {r7, lr}
22+
.setfp r7, sp, #0
23+
.fnend
24+
25+
.text
26+
.globl _start
27+
.type _start, %function
28+
_start:
29+
.fnstart
30+
bx lr
31+
.cantunwind
32+
.fnend
33+
34+
.section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
35+
.global __aeabi_unwind_cpp_pr0
36+
__aeabi_unwind_cpp_pr0:
37+
bx lr

0 commit comments

Comments
 (0)