diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -681,6 +681,15 @@ if (config->copyRelocs && sym.used) return true; + // Exclude local symbols pointing to .ARM.exidx sections. + // They are probably mapping symbols "$d", which are optional for these + // sections. After merging the .ARM.exidx sections, some of these symbols + // may become dangling. The easiest way to avoid the issue is not to add + // them to the symbol table from the beginning. + if (config->emachine == EM_ARM && sym.section && + sym.section->type == SHT_ARM_EXIDX) + return false; + if (config->discard == DiscardPolicy::None) return true; if (config->discard == DiscardPolicy::All) diff --git a/lld/test/ELF/arm-exidx-mapping-symbols.s b/lld/test/ELF/arm-exidx-mapping-symbols.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/arm-exidx-mapping-symbols.s @@ -0,0 +1,26 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: ld.lld %t -o %t2 +// RUN: llvm-readelf -s %t2 | FileCheck %s +// CHECK-NOT: $d.exidx.foo + +/// Test that symbols which point to input .ARM.exidx sections are eliminated. +/// These symbols might be produced, for example, by GNU tools. + + .syntax unified + .section .text.foo,"axG",%progbits,foo,comdat +foo: + bx lr + +/// GNU as adds mapping symbols "$d" for .ARM.exidx sections it generates. +/// llvm-mc does not do that, so reproduce that manually. + .section .ARM.exidx.text.foo,"ao?",%0x70000001,.text.foo +$d.exidx.foo: + .reloc 0, R_ARM_NONE, __aeabi_unwind_cpp_pr0 + .long .text.foo(PREL31) + .long 0x80b0b0b0 + + .section .text.h,"ax" + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr