diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 02394cbae95d5..154fabbf9b414 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -20,8 +20,7 @@ #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/xxhash.h" -#include -#include +#include #include using namespace llvm; @@ -886,16 +885,25 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { const unsigned bits = sizeof(typename ELFT::uint) * 8; const TargetInfo &target = *elf::target; const bool isDebug = isDebugSection(*this); - const bool isDebugLocOrRanges = - isDebug && (name == ".debug_loc" || name == ".debug_ranges"); const bool isDebugLine = isDebug && name == ".debug_line"; - std::optional tombstone; + std::optional tombstone = std::nullopt; + std::optional tombstoneValueToUse = std::nullopt; for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc)) if (patAndValue.first.match(this->name)) { tombstone = patAndValue.second; break; } + const uint64_t debugTombstone = StringSwitch(name) + .Case(".debug_ranges", 1) + .Case(".debug_loc", 1) + .Case(".debug_names", llvm::maxUIntN(32)) + .Default(0); + // If -z dead-reloc-in-nonalloc= is specified, respect it. + if (!tombstone && isDebug) + tombstoneValueToUse = debugTombstone; + else if (tombstone) + tombstoneValueToUse = SignExtend64(*tombstone); for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); @@ -917,8 +925,9 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (expr == R_NONE) continue; - if (tombstone || - (isDebug && (type == target.symbolicRel || expr == R_DTPREL))) { + auto *ds = dyn_cast(&sym); + if (tombstoneValueToUse && + (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine))) { // 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 @@ -947,14 +956,13 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { // // TODO To reduce disruption, we use 0 instead of -1 as the tombstone // value. Enable -1 in a future release. - auto *ds = dyn_cast(&sym); - if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) { - // If -z dead-reloc-in-nonalloc= is specified, respect it. - const uint64_t value = tombstone ? SignExtend64(*tombstone) - : (isDebugLocOrRanges ? 1 : 0); - target.relocateNoSym(bufLoc, type, value); - continue; - } + + // Extending 32bit MAX value to 64bit MAX value.. + // One usage example is in .debug_names LocatTU tombstoning. + if (!tombstone && type == target.symbolicRel) + tombstoneValueToUse = SignExtend64<32>(*tombstoneValueToUse); + target.relocateNoSym(bufLoc, type, *tombstoneValueToUse); + continue; } // For a relocatable link, content relocated by RELA remains unchanged and diff --git a/lld/test/ELF/debug-dead-reloc.s b/lld/test/ELF/debug-dead-reloc.s index fcf53205079ed..fdfde6ce2c75c 100644 --- a/lld/test/ELF/debug-dead-reloc.s +++ b/lld/test/ELF/debug-dead-reloc.s @@ -17,8 +17,8 @@ # CHECK-NEXT: 0000 {{.*}}000 00000000 {{.*}}000 00000000 # CHECK-NEXT: 0010 00000000 00000000 {{.*}}000 00000000 # 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 { @@ -80,8 +80,6 @@ group: .section .debug_foo .quad .text.1+8 -## We only deal with DW_FORM_addr. Don't special case short-range absolute -## relocations. Treat them like regular absolute relocations referencing -## discarded symbols, which are resolved to the addend. +## Treat short-range absolute relocations the same as DW_FORM_addr. .long .text.1+8 .long 0 diff --git a/lld/test/ELF/x86-64-dwarf5-64-debug-names-type-comdat.test b/lld/test/ELF/x86-64-dwarf5-64-debug-names-type-comdat.test new file mode 100644 index 0000000000000..25e820f19e7bc --- /dev/null +++ b/lld/test/ELF/x86-64-dwarf5-64-debug-names-type-comdat.test @@ -0,0 +1,97 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux --defsym DWARF32=1 %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux --defsym DWARF32=1 %s -o %t1.o +# RUN: ld.lld %t.o %t1.o -o %t1 +# RUN: llvm-objdump -s %t1 | FileCheck %s --check-prefix=CHECK32 + +# Test checks that LLD tombstones TU section that was de-duplicated using COMDAT to the maxium value. + +# CHECK32:Contents of section .debug_names: +# CHECK32-NEXT: 0000 37000000 05000000 00000000 01000000 7............... +# CHECK32-NEXT: 0010 00000000 00000000 00000000 03000000 ................ +# CHECK32-NEXT: 0020 08000000 4c4c564d 30373030 00000000 ....LLVM0700.... +# CHECK32-NEXT: 0030 00000000 00000000 00000037 00000005 ...........7.... +# CHECK32-NEXT: 0040 00000000 00000001 00000000 00000000 ................ +# CHECK32-NEXT: 0050 00000000 00000003 00000008 0000004c ...............L +# CHECK32-NEXT: 0060 4c564d30 37303000 000000ff ffffff00 LVM0700......... + + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux --defsym DWARF64=1 %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux --defsym DWARF64=1 %s -o %t1.o +# RUN: ld.lld %t.o %t1.o -o %t1 +# RUN: llvm-objdump -s %t1 | FileCheck %s --check-prefix=CHECK64 + +# Test checks that LLD tombstones TU section that was de-duplicated using COMDAT to the maxium value. + +# CHECK64: Contents of section .debug_names: +# CHECK64-NEXT: 0000 ffffffff 3f000000 00000000 05000000 ....?........... +# CHECK64-NEXT: 0010 00000000 01000000 00000000 00000000 ................ +# CHECK64-NEXT: 0020 00000000 03000000 08000000 4c4c564d ............LLVM +# CHECK64-NEXT: 0030 30373030 00000000 00000000 00000000 0700............ +# CHECK64-NEXT: 0040 00000000 00000000 000000ff ffffff3f ...............? +# CHECK64-NEXT: 0050 00000000 00000005 00000000 00000001 ................ +# CHECK64-NEXT: 0060 00000000 00000000 00000000 00000003 ................ +# CHECK64-NEXT: 0070 00000008 0000004c 4c564d30 37303000 .......LLVM0700. +# CHECK64-NEXT: 0080 00000000 000000ff ffffffff ffffff00 ................ + +# Test generated with clang++ -g2 -gdwarf-5 -gpubnames -fdebug-types-section -S and then manually reduced. +.ifdef DWARF32 + .section .debug_info,"G",@progbits,1175092228111723119,comdat +.Ltu_begin0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 0 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 0 # Header: bucket count + .long 0 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long 0 # Compilation unit 0 + .long .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + +.Lnames_abbrev_start0: + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames_end0: +.endif + +# Test generated with clang++ -g2 -gdwarf-5 -gdwarf64 -gpubnames -fdebug-types-section -S and then manually reduced. +.ifdef DWARF64 + .section .debug_info,"G",@progbits,1175092228111723119,comdat +.Ltu_begin0: + .section .debug_names,"",@progbits + .long 4294967295 # DWARF64 Mark + .quad .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 0 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 0 # Header: bucket count + .long 0 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .quad 0 # Compilation unit 0 + .quad .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + +.Lnames_abbrev_start0: + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames_end0: +.endif