Skip to content

Commit

Permalink
[ELF] Change .debug_names tombstone value to UINT32_MAX/UINT64_MAX (#…
Browse files Browse the repository at this point in the history
…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",@progbits,5657452045627120676,comdat
.Ltu_begin0:
...

.section        .debug_names,"",@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.

Co-authored-by: Alexander Yermolovich <ayermolo@meta.com>
  • Loading branch information
MaskRay and ayermolo committed Dec 22, 2023
1 parent 847a6f8 commit 26ddf4e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
22 changes: 16 additions & 6 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
if (isDebug) {
if (name == ".debug_loc" || name == ".debug_ranges")
tombstone = 1;
else if (name == ".debug_names")
tombstone = UINT64_MAX; // tombstone value
else
tombstone = 0;
}
for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
if (patAndValue.first.match(this->name)) {
tombstone = patAndValue.second;
Expand Down Expand Up @@ -946,8 +952,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
return;
}

if (tombstone ||
(isDebug && (type == target.symbolicRel || expr == R_DTPREL))) {
if (tombstone && (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
Expand Down Expand Up @@ -978,8 +983,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 = SignExtend64<bits>(*tombstone);
// For a 32-bit local TU reference in .debug_names, X86_64::relocate
// requires that the unsigned value for R_X86_64_32 is truncated to
// 32-bit. Other 64-bit targets's don't discern signed/unsigned 32-bit
// absolute relocations and do not need this change.
if (emachine == EM_X86_64 && type == R_X86_64_32)
value = static_cast<uint32_t>(value);
target.relocateNoSym(bufLoc, type, value);
continue;
}
Expand Down
11 changes: 11 additions & 0 deletions lld/test/ELF/debug-dead-reloc-32.s
Original file line number Diff line number Diff line change
Expand Up @@ -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

## -z dead-reloc-in-nonalloc= can override the tombstone value.
# RUN: ld.lld -z dead-reloc-in-nonalloc=.debug_loc=42 -z dead-reloc-in-nonalloc=.debug_addr=0xfffffffffffffffe %t.o -o %t1
Expand All @@ -38,3 +40,12 @@
## Resolved to UINT32_C(0), with the addend ignored.
.section .debug_addr
.long .text.1+8

.section .debug_info,"eG",@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
24 changes: 22 additions & 2 deletions lld/test/ELF/debug-dead-reloc.s
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
# CHECK: Contents of section .debug_addr:
# CHECK-NEXT: 0000 {{.*}}00 00000000 {{.*}}00 00000000
# CHECK-NEXT: 0010 00000000 00000000 {{.*}}00 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 {
Expand All @@ -43,6 +46,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
Expand Down Expand Up @@ -82,6 +91,17 @@ group:
## resolved to the prevailing copy.
.quad group+32

.section .debug_info,"G",@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

Expand Down

0 comments on commit 26ddf4e

Please sign in to comment.