[PATCH] D79289: [LLD][ELF][ARM] Do not create .ARM.exidx sections for out of range inputs

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat May 2 05:16:12 PDT 2020


psmith created this revision.
psmith added reviewers: ruiu, MaskRay, grimar.
Herald added subscribers: danielkiss, kristof.beyls, arichardson, emaste.
Herald added a reviewer: espindola.

A linker will create .ARM.exidx sections for InputSections that don't have them. This can cause a relocation out of range error If the InputSection happens to be extremely far away from the other sections. This is often the case for the vector table on older ARM CPUs as the only two places that the table can be placed is 0 or 0xffff0000. We fix this by removing InputSections that need a linker generated .ARM.exidx section if that would cause an error.

Fixes part of pr44824 (https://bugs.llvm.org/show_bug.cgi?id=44824)


https://reviews.llvm.org/D79289

Files:
  lld/ELF/SyntheticSections.cpp
  lld/test/ELF/arm-exidx-range.s


Index: lld/test/ELF/arm-exidx-range.s
===================================================================
--- /dev/null
+++ lld/test/ELF/arm-exidx-range.s
@@ -0,0 +1,33 @@
+// RUN: llvm-mc --arm-add-build-attributes --triple=armv7a-linux-gnueabihf -filetype=obj %s -o %t.o
+// RUN: echo "SECTIONS { \
+// RUN:         . = 0x80000000; \
+// RUN:         .text : { *(.text) } \
+// RUN:         .vectors 0xffff0000 : AT(0xffff0000) { *(.vectors) } \
+// RUN: } " > %t.script
+// RUN: ld.lld --script %t.script %t.o -o %t
+// RUN: llvm-readobj -x .ARM.exidx %t | FileCheck %s
+/// Adapted from Linux kernel linker script failing due to out of range
+/// relocation. The .vectors at 0xffff0000 (one of two places the vector table
+/// can go, the other is 0x0) in earlier Arm CPUs.
+/// In the example the .vectors won't have an exception table so if LLD creates
+/// one then we'll get a relocation out of range error. Check that we don't
+/// synthesise a table entry or place a sentinel out of range.
+
+/// Expect only .ARM.exidx from _start and sentinel
+// CHECK: Hex dump of section '.ARM.exidx':
+// CHECK-NEXT: 0x80000000 10000000 01000000 0c000000 01000000
+
+ .text
+ .global _start
+ .type _start, %function
+_start:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .vectors, "ax", %progbits
+ .global vecs
+ .type vecs, %function
+vecs:
+ bx lr
Index: lld/ELF/SyntheticSections.cpp
===================================================================
--- lld/ELF/SyntheticSections.cpp
+++ lld/ELF/SyntheticSections.cpp
@@ -3363,8 +3363,21 @@
   // ICF may remove 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);
+  // We need to remove discarded InputSections and InputSections without
+  // .ARM.exidx sections that if we generated the .ARM.exidx it would be out
+  // of range.
+  auto isDiscardedOrOutOfRange = [this](InputSection *isec) {
+    if (!isec->isLive())
+      return true;
+    if (findExidxSection(isec))
+      return false;
+    uint64_t s = isec->getVA();
+    uint64_t p = getVA();
+    int64_t off = s - p;
+    return off != llvm::SignExtend64(off, 31);
+  };
+  llvm::erase_if(executableSections, isDiscardedOrOutOfRange);
 
   // Sort the executable sections that may or may not have associated
   // .ARM.exidx sections by order of ascending address. This requires the


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79289.261633.patch
Type: text/x-patch
Size: 2535 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200502/bf100fa0/attachment.bin>


More information about the llvm-commits mailing list