[lld] [ELF] Change .debug_names tombstone value to UINT32_MAX/UINT64_MAX (PR #74686)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 6 17:01:48 PST 2023


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/74686

`clang -g -gpubnames -fdebug-types-section` now emits .debug_names
section with references to local type unit entries defined in COMDAT
.debug_info sections.

```
.section        .debug_info,"G", at progbits,5657452045627120676,comdat
.Ltu_begin0:
...

.section        .debug_names,"", at progbits
...
// DWARF32
.long   .Ltu_begin0                     # Type unit 0
// DWARF64
// .long   .Ltu_begin0                     # Type unit 0
```

When `.Ltu_begin0` is relative to a non-prevailing .debug_info section,
the relocation resolves to 0, which is a valid offset within the
.debug_info section.

```
cat > a.cc <<e
struct A { int x; };
inline A foo() { return {1}; }
int main() { foo(); }
e
cat > b.cc <<e
struct A { int x; };
inline A foo() { return {1}; }
void use() { foo(); }
e
clang++ -g -gpubnames -fdebug-types-section -fuse-ld=lld a.cc b.cc -o old
```
```
% llvm-dwarfdump old
...
  Local Type Unit offsets [
    LocalTU[0]: 0x00000000
  ]
...
  Local Type Unit offsets [
    LocalTU[0]: 0x00000000  // indistinguishable from a valid offset within .debug_info
  ]
```

https://dwarfstd.org/issues/231013.1.html proposes that we use a
tombstone value instead to inform consumers. This patch implements the
idea. The second LocalTU entry will now use 0xffffffff.

https://reviews.llvm.org/D84825 has a TODO that we should switch the
tombstone value for most `.debug_*` sections to UINT64_MAX. We have
postponed the change for more than three years for consumers to migrate.
At some point we shall make the change, so that .debug_names is no long
different from other debug section that is not .debug_loc/.debug_ranges.


>From a3b9c53af9a91c7896b8e29538d100bbe5d05c02 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 6 Dec 2023 15:02:14 -0800
Subject: [PATCH] [ELF] Change .debug_names tombstone value to
 UINT32_MAX/UINT64_MAX

`clang -g -gpubnames -fdebug-types-section` now emits .debug_names
section with references to local type unit entries defined in COMDAT
.debug_info sections.

```
.section        .debug_info,"G", at progbits,5657452045627120676,comdat
.Ltu_begin0:
...

.section        .debug_names,"", at progbits
...
// DWARF32
.long   .Ltu_begin0                     # Type unit 0
// DWARF64
// .long   .Ltu_begin0                     # Type unit 0
```

When `.Ltu_begin0` is relative to a non-prevailing .debug_info section,
the relocation resolves to 0, which is a valid offset within the
.debug_info section.

```
cat > a.cc <<e
struct A { int x; };
inline A foo() { return {1}; }
int main() { foo(); }
e
cat > b.cc <<e
struct A { int x; };
inline A foo() { return {1}; }
void use() { foo(); }
e
clang++ -g -gpubnames -fdebug-types-section -fuse-ld=lld a.cc b.cc -o old
```
```
% llvm-dwarfdump old
...
  Local Type Unit offsets [
    LocalTU[0]: 0x00000000
  ]
...
  Local Type Unit offsets [
    LocalTU[0]: 0x00000000  // indistinguishable from a valid offset within .debug_info
  ]
```

https://dwarfstd.org/issues/231013.1.html proposes that we use a
tombstone value instead to inform consumers. This patch implements the
idea. The second LocalTU entry will now use 0xffffffff.

https://reviews.llvm.org/D84825 has a TODO that we should switch the
tombstone value for most `.debug_*` sections to UINT64_MAX. We have
postponed the change for more than three years for consumers to migrate.
At some point we shall make the change, so that .debug_names is no long
different from other debug section that is not .debug_loc/.debug_ranges.
---
 lld/ELF/InputSection.cpp           | 24 +++++++++++++++++-------
 lld/test/ELF/debug-dead-reloc-32.s | 11 +++++++++++
 lld/test/ELF/debug-dead-reloc.s    | 24 ++++++++++++++++++++++--
 3 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 145d55d9a0a4b..5a62b14f4c973 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -898,10 +898,16 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
   const TargetInfo &target = *elf::target;
   const auto emachine = config->emachine;
   const bool isDebug = isDebugSection(*this);
-  const bool isDebugLocOrRanges =
-      isDebug && (name == ".debug_loc" || name == ".debug_ranges");
   const bool isDebugLine = isDebug && name == ".debug_line";
-  std::optional<uint64_t> tombstone;
+  std::optional<uint64_t> tombstone, debugTombstone;
+  if (isDebug) {
+    if (name == ".debug_loc" || name == ".debug_ranges")
+      debugTombstone = 1;
+    else if (name == ".debug_names")
+      debugTombstone = UINT64_MAX; // DWARF Issue 231013.1
+    else
+      debugTombstone = 0;
+  }
   for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
     if (patAndValue.first.match(this->name)) {
       tombstone = patAndValue.second;
@@ -954,8 +960,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
       return;
     }
 
-    if (tombstone ||
-        (isDebug && (type == target.symbolicRel || expr == R_DTPREL))) {
+    if (tombstone || (isDebug && (expr == R_ABS || expr == R_DTPREL))) {
       // Resolve relocations in .debug_* referencing (discarded symbols or ICF
       // folded section symbols) to a tombstone value. Resolving to addend is
       // unsatisfactory because the result address range may collide with a
@@ -986,8 +991,13 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
       // value. Enable -1 in a future release.
       if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
         // If -z dead-reloc-in-nonalloc= is specified, respect it.
-        const uint64_t value = tombstone ? SignExtend64<bits>(*tombstone)
-                                         : (isDebugLocOrRanges ? 1 : 0);
+        uint64_t value;
+        if (tombstone)
+          value = SignExtend64<bits>(*tombstone);
+        else if (type == target.symbolicRel)
+          value = *debugTombstone;
+        else // .debug_names uses 32-bit local TU offsets for DWARF32
+          value = static_cast<uint32_t>(*debugTombstone);
         target.relocateNoSym(bufLoc, type, value);
         continue;
       }
diff --git a/lld/test/ELF/debug-dead-reloc-32.s b/lld/test/ELF/debug-dead-reloc-32.s
index b2708a744f288..7bf30b98e6890 100644
--- a/lld/test/ELF/debug-dead-reloc-32.s
+++ b/lld/test/ELF/debug-dead-reloc-32.s
@@ -13,6 +13,8 @@
 # CHECK-NEXT:  0000 01000000
 # CHECK-NEXT: Contents of section .debug_addr:
 # CHECK-NEXT:  0000 00000000
+# CHECK-NEXT: Contents of section .debug_names:
+# CHECK-NEXT:  0000 ffffffff
 
 .section .text.1,"axe"
   .byte 0
@@ -27,3 +29,12 @@
 ## Resolved to UINT32_C(0), with the addend ignored.
 .section .debug_addr
   .long .text.1+8
+
+.section  .debug_info,"eG", at progbits,5657452045627120676,comdat
+.Ltu_begin0:
+
+.section .debug_names
+## .debug_names may reference a local type unit defined in a COMDAT .debug_info
+## section (-g -gpubnames -fdebug-types-section). If the referenced section is
+## non-prevailing, resolve to UINT32_MAX.
+.long .Ltu_begin0
diff --git a/lld/test/ELF/debug-dead-reloc.s b/lld/test/ELF/debug-dead-reloc.s
index fcf53205079ed..627513c2672c4 100644
--- a/lld/test/ELF/debug-dead-reloc.s
+++ b/lld/test/ELF/debug-dead-reloc.s
@@ -16,9 +16,12 @@
 # CHECK:      Contents of section .debug_addr:
 # CHECK-NEXT:  0000 {{.*}}000 00000000 {{.*}}000 00000000
 # CHECK-NEXT:  0010 00000000  00000000 {{.*}}000 00000000
+# CHECK:      Contents of section .debug_names:
+# CHECK-NEXT:  0000 00000000 00000000 00000000 ffffffff .
+# CHECK-NEXT:  0010 ffffffff ffffffff                   .
 # CHECK:      Contents of section .debug_foo:
-# CHECK-NEXT:  0000 00000000 00000000 08000000 00000000
-# CHECK-NEXT:  0010 00000000 00000000 08000000 00000000
+# CHECK-NEXT:  0000 00000000 00000000 00000000 00000000
+# CHECK-NEXT:  0010 00000000 00000000 00000000 00000000
 
 # REL:      Relocations [
 # REL-NEXT:   .rela.text {
@@ -38,6 +41,12 @@
 # REL-NEXT:     0x10 R_X86_64_NONE - 0x18
 # REL-NEXT:     0x18 R_X86_64_64 group 0x20
 # REL-NEXT:   }
+# REL-NEXT:   .rela.debug_names {
+# REL-NEXT:     0x0 R_X86_64_32 .debug_info 0x0
+# REL-NEXT:     0x4 R_X86_64_64 .debug_info 0x0
+# REL-NEXT:     0xC R_X86_64_NONE - 0x0
+# REL-NEXT:     0x10 R_X86_64_NONE - 0x0
+# REL-NEXT:   }
 # REL-NEXT:   .rela.debug_foo {
 # REL-NEXT:     0x0 R_X86_64_NONE - 0x8
 # REL-NEXT:     0x8 R_X86_64_NONE - 0x8
@@ -77,6 +86,17 @@ group:
 ## resolved to the prevailing copy.
   .quad group+32
 
+.section  .debug_info,"G", at progbits,5657452045627120676,comdat
+.Ltu_begin0:
+
+.section .debug_names
+## .debug_names may reference a local type unit defined in a COMDAT .debug_info
+## section (-g -gpubnames -fdebug-types-section). If the referenced section is
+## non-prevailing, resolve to UINT32_MAX.
+.long .Ltu_begin0
+## ... or UINT64_MAX for DWARF64.
+.quad .Ltu_begin0
+
 .section .debug_foo
   .quad .text.1+8
 



More information about the llvm-commits mailing list