[PATCH] D78820: [LLD][ELF] Eliminate symbols of merged .ARM.exidx sections.

Igor Kudrin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 24 11:21:02 PDT 2020


ikudrin created this revision.
ikudrin added reviewers: ruiu, MaskRay, grimar, peter.smith.
ikudrin added projects: lld, LLVM.
Herald added subscribers: danielkiss, kristof.beyls, arichardson, emaste.
Herald added a reviewer: espindola.

GNU tools generate mapping symbols "$d" for `.ARM.exidx` sections. The symbols are added to the symbol table much earlier than the merging takes place, and after that, they become dangling. Before the patch, LLD output those symbols as SHN_ABS with the value of 0. The patch removes such symbols from the symbol table.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D78820

Files:
  lld/ELF/SyntheticSections.cpp
  lld/ELF/SyntheticSections.h
  lld/test/ELF/arm-exidx-mapping-symbols.s


Index: lld/test/ELF/arm-exidx-mapping-symbols.s
===================================================================
--- /dev/null
+++ lld/test/ELF/arm-exidx-mapping-symbols.s
@@ -0,0 +1,41 @@
+// REQUIRES: arm
+// Test that symbols which point to merged .ARM.exidx sections are eliminated.
+// These symbols might be produced, for example, by GNU tools.
+
+// 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.bar
+
+    .syntax unified
+    .section .text.foo,"axG",%progbits,foo,comdat
+foo:
+    bx lr
+
+// GNU as adds a mapping symbol "$d" for .ARM.exidx sections it generate.
+// llvm-mc does not do that, so reproduce such sections manually.
+// Use an explicit name of the symbol for the test purpose and because all
+// symbols in the assembly file should have unique names.
+    .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.bar,"axG",%progbits,bar,comdat
+bar:
+    bx lr
+
+// This section is the same as the one for foo so it is a subject to merge.
+    .section .ARM.exidx.text.bar,"ao?",%0x70000001,.text.bar
+$d.exidx.bar:
+    .reloc 0, R_ARM_NONE, __aeabi_unwind_cpp_pr0
+    .long .text.bar(PREL31)
+    .long 0x80b0b0b0
+
+    .section .text.h
+    .global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
+    nop
+    bx lr
Index: lld/ELF/SyntheticSections.h
===================================================================
--- lld/ELF/SyntheticSections.h
+++ lld/ELF/SyntheticSections.h
@@ -585,6 +585,7 @@
   unsigned getNumSymbols() const { return symbols.size() + 1; }
   size_t getSymbolIndex(Symbol *sym);
   ArrayRef<SymbolTableEntry> getSymbols() const { return symbols; }
+  void removeDeadLocalSymbols();
 
 protected:
   void sortSymTabSymbols();
Index: lld/ELF/SyntheticSections.cpp
===================================================================
--- lld/ELF/SyntheticSections.cpp
+++ lld/ELF/SyntheticSections.cpp
@@ -2021,6 +2021,21 @@
   }
 }
 
+// Remove local symbols which belong to dead sections.
+// The method is used to clean up the table after merging .ARM.exidx sections.
+// The symbols are added earlier than the merging takes place, and it is not
+// known at that time which of them will become dangling. Thus, we first add
+// all the symbols, and eliminate them when the dead sections are known.
+void SymbolTableBaseSection::removeDeadLocalSymbols() {
+  llvm::erase_if(symbols, [](const SymbolTableEntry &s) {
+    if (!s.sym->isLocal())
+      return false;
+    auto *d = dyn_cast<Defined>(s.sym);
+    assert(d);
+    return d->section && !d->section->repl->isLive();
+  });
+}
+
 // The ELF spec requires that all local symbols precede global symbols, so we
 // sort symbol entries in this function. (For .dynsym, we don't do that because
 // symbols for dynamic linking are inherently all globals.)
@@ -3405,6 +3420,15 @@
   }
   // Size includes Sentinel.
   size = offset + 8;
+
+  // Mark merged input .ARM.exidx sections as dead.
+  if (config->mergeArmExidx) {
+    for (InputSection *isec : exidxSections)
+      if (!isec->getParent())
+        isec->markDead();
+    if (in.symTab)
+      in.symTab->removeDeadLocalSymbols();
+  }
 }
 
 InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D78820.259934.patch
Type: text/x-patch
Size: 3441 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200424/1f78c3f9/attachment.bin>


More information about the llvm-commits mailing list