diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3363,8 +3363,19 @@ // 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; + int64_t off = static_cast(isec->getVA() - getVA()); + 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 diff --git a/lld/test/ELF/arm-exidx-range.s b/lld/test/ELF/arm-exidx-range.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/arm-exidx-range.s @@ -0,0 +1,35 @@ +// REQUIRES: arm +// 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 : { *(.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 is a common occurrence as the vector +/// table can only be placed at either 0 or 0xffff0000 in older 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 +// CHECK-NOT: 0x80000010 + + .text + .global _start + .type _start, %function +_start: + .fnstart + bx lr + .cantunwind + .fnend + + .section .vectors, "ax", %progbits + .global vecs + .type vecs, %function +vecs: + bx lr