[lld] e00ac48 - [ELF] Use tombstone values for discarded symbols in relocatable output

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 12 21:32:39 PST 2022


Author: Igor Kudrin
Date: 2022-01-13T11:38:26+07:00
New Revision: e00ac48df3a6d5e3fa23fdb898c5179a75fd855f

URL: https://github.com/llvm/llvm-project/commit/e00ac48df3a6d5e3fa23fdb898c5179a75fd855f
DIFF: https://github.com/llvm/llvm-project/commit/e00ac48df3a6d5e3fa23fdb898c5179a75fd855f.diff

LOG: [ELF] Use tombstone values for discarded symbols in relocatable output

This extends D81784. Sections can be discarded when linking a
relocatable output. Before the patch, LLD did not update the content
of debug sections and only replaced the corresponding relocations with
R_*_NONE, which could break the debug information.

Differential Revision: https://reviews.llvm.org/D116946

Added: 
    lld/test/ELF/debug-dead-reloc-relocatable.s

Modified: 
    lld/ELF/InputSection.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index ae7ddb50793b2..f767f9e94c2b7 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -890,38 +890,6 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
     if (expr == R_NONE)
       continue;
 
-    if (expr == R_SIZE) {
-      target.relocateNoSym(bufLoc, type,
-                           SignExtend64<bits>(sym.getSize() + addend));
-      continue;
-    }
-
-    // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
-    // sections.
-    if (expr != R_ABS && expr != R_DTPREL && expr != R_GOTPLTREL &&
-        expr != R_RISCV_ADD) {
-      std::string msg = getLocation<ELFT>(offset) +
-                        ": has non-ABS relocation " + toString(type) +
-                        " against symbol '" + toString(sym) + "'";
-      if (expr != R_PC && expr != R_ARM_PCA) {
-        error(msg);
-        return;
-      }
-
-      // If the control reaches here, we found a PC-relative relocation in a
-      // non-ALLOC section. Since non-ALLOC section is not loaded into memory
-      // at runtime, the notion of PC-relative doesn't make sense here. So,
-      // this is a usage error. However, GNU linkers historically accept such
-      // relocations without any errors and relocate them as if they were at
-      // address 0. For bug-compatibilty, we accept them with warnings. We
-      // know Steel Bank Common Lisp as of 2018 have this bug.
-      warn(msg);
-      target.relocateNoSym(
-          bufLoc, type,
-          SignExtend64<bits>(sym.getVA(addend - offset - outSecOff)));
-      continue;
-    }
-
     if (tombstone ||
         (isDebug && (type == target.symbolicRel || expr == R_DTPREL))) {
       // Resolve relocations in .debug_* referencing (discarded symbols or ICF
@@ -961,7 +929,44 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
         continue;
       }
     }
-    target.relocateNoSym(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
+
+    // For a relocatable link, only tombstone values are applied.
+    if (config->relocatable)
+      continue;
+
+    if (expr == R_SIZE) {
+      target.relocateNoSym(bufLoc, type,
+                           SignExtend64<bits>(sym.getSize() + addend));
+      continue;
+    }
+
+    // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
+    // sections.
+    if (expr == R_ABS || expr == R_DTPREL || expr == R_GOTPLTREL ||
+        expr == R_RISCV_ADD) {
+      target.relocateNoSym(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
+      continue;
+    }
+
+    std::string msg = getLocation<ELFT>(offset) + ": has non-ABS relocation " +
+                      toString(type) + " against symbol '" + toString(sym) +
+                      "'";
+    if (expr != R_PC && expr != R_ARM_PCA) {
+      error(msg);
+      return;
+    }
+
+    // If the control reaches here, we found a PC-relative relocation in a
+    // non-ALLOC section. Since non-ALLOC section is not loaded into memory
+    // at runtime, the notion of PC-relative doesn't make sense here. So,
+    // this is a usage error. However, GNU linkers historically accept such
+    // relocations without any errors and relocate them as if they were at
+    // address 0. For bug-compatibilty, we accept them with warnings. We
+    // know Steel Bank Common Lisp as of 2018 have this bug.
+    warn(msg);
+    target.relocateNoSym(
+        bufLoc, type,
+        SignExtend64<bits>(sym.getVA(addend - offset - outSecOff)));
   }
 }
 
@@ -993,15 +998,15 @@ void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) {
   }
 
   auto *sec = cast<InputSection>(this);
-  if (config->relocatable) {
+  if (config->relocatable)
     relocateNonAllocForRelocatable(sec, buf);
-  } else {
-    const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
-    if (rels.areRelocsRel())
-      sec->relocateNonAlloc<ELFT>(buf, rels.rels);
-    else
-      sec->relocateNonAlloc<ELFT>(buf, rels.relas);
-  }
+  // For a relocatable link, also call relocateNonAlloc() to rewrite applicable
+  // locations with tombstone values.
+  const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
+  if (rels.areRelocsRel())
+    sec->relocateNonAlloc<ELFT>(buf, rels.rels);
+  else
+    sec->relocateNonAlloc<ELFT>(buf, rels.relas);
 }
 
 void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {

diff  --git a/lld/test/ELF/debug-dead-reloc-relocatable.s b/lld/test/ELF/debug-dead-reloc-relocatable.s
new file mode 100644
index 0000000000000..e8886f096a8f3
--- /dev/null
+++ b/lld/test/ELF/debug-dead-reloc-relocatable.s
@@ -0,0 +1,36 @@
+# REQUIRES: x86
+## Test we resolve symbolic relocations in .debug_* sections to a tombstone
+## value if the referenced symbol is discarded when linking a relocatable object.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
+# RUN: ld.lld -r %t1.o %t1.o -o %t2.o
+# RUN: llvm-readelf -r -x .debug_ranges %t2.o | FileCheck %s
+
+## Relocations for a discarded section are changed to R_*_NONE.
+# CHECK:      Relocation section '.rela.debug_ranges' at offset [[#%#x,]] contains 4 entries:
+# CHECK-NEXT:     Offset          Info        Type       Symbol's Value  Symbol's Name + Addend
+# CHECK-NEXT: 0000000000000000  [[#%x,]] R_X86_64_64    0000000000000000 .text.foo + 0
+# CHECK-NEXT: 0000000000000008  [[#%x,]] R_X86_64_64    0000000000000000 .text.foo + 1
+# CHECK-NEXT: 0000000000000020  [[#%x,]] R_X86_64_NONE
+# CHECK-NEXT: 0000000000000028  [[#%x,]] R_X86_64_NONE
+
+## References to a discarded section are changed to tombstone values.
+# CHECK:      Hex dump of section '.debug_ranges':
+# CHECK-NEXT: 0x00000000 00000000 00000000 00000000 00000000
+# CHECK-NEXT: 0x00000010 00000000 00000000 00000000 00000000
+# CHECK-NEXT: 0x00000020 01000000 00000000 01000000 00000000
+# CHECK-NEXT: 0x00000030 00000000 00000000 00000000 00000000
+
+.weak foo
+
+  .section .text.foo,"axG", at progbits,foo,comdat
+.Lfoo:
+foo:
+  ret
+.Lfoo_end:
+
+  .section .debug_ranges,"", at progbits
+  .quad .Lfoo
+  .quad .Lfoo_end
+  .quad	0
+  .quad	0


        


More information about the llvm-commits mailing list