[PATCH] D65759: [ELF][ARM] Fix /DISCARD/ of section with .ARM.exidx section

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 6 03:40:16 PDT 2019


peter.smith updated this revision to Diff 213559.
peter.smith edited the summary of this revision.
peter.smith added a comment.

Thanks very much for the comments. I've updated the description, comment, used llvm::erase_if and combined the llvm-readobj into one call.

The full details are in https://static.docs.arm.com/ihi0038/a/IHI0038A_ehabi.pdf although only a small part is relevant to linking. The biggest complications that lead to us using a SyntheticSection were:

- Adjacent table entries with identical unwind entries can be merged.
- The address range covered by table entry N is terminated by table entry N + 1. This means that if the .ARM.exidx information is incomplete (executable sections don't have any unwinding information) then an exception thrown through a function without any unwinding information can match a table entry with unwinding information. We fix this by generating CANT_UNWIND table entries for sections without any unwind information.
- A terminating CANT_UNWIND sentinel entry is required to terminate the address range of the last table entry.

Let me know if you have any questions, I've glossed over a lot of detail.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65759/new/

https://reviews.llvm.org/D65759

Files:
  ELF/SyntheticSections.cpp
  test/ELF/arm-exidx-partial-discard.s


Index: test/ELF/arm-exidx-partial-discard.s
===================================================================
--- /dev/null
+++ 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
Index: ELF/SyntheticSections.cpp
===================================================================
--- ELF/SyntheticSections.cpp
+++ 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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D65759.213559.patch
Type: text/x-patch
Size: 2866 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190806/03c58626/attachment.bin>


More information about the llvm-commits mailing list