[lld] [LLD] Tombstone LocalTU entry in .debug_names (PR #70701)
Alexander Yermolovich via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 2 16:48:55 PDT 2023
https://github.com/ayermolo updated https://github.com/llvm/llvm-project/pull/70701
>From d2665cc895bde817e358713e9116855a48d72bf6 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Mon, 16 Oct 2023 10:42:15 -0700
Subject: [PATCH 1/6] [LLD] Tombstone LocalTU entry in .debug_names
By default LLD uses 0x0... as a tombstone value. For Type Units this is a valid
address. Changed so that MAX value is used for tombstone.
This was introduced as a change to DWARF6 spec:
https://dwarfstd.org/issues/231013.1.html
---
lld/ELF/InputFiles.cpp | 5 +-
lld/ELF/InputSection.cpp | 21 +-
...dwarf5-64-debug-names-type-comdat-helper.s | 397 +++++++++++++++++
.../dwarf5-64-debug-names-type-comdat-main.s | 384 ++++++++++++++++
.../dwarf5-debug-names-type-comdat-helper.s | 410 ++++++++++++++++++
.../dwarf5-debug-names-type-comdat-main.s | 397 +++++++++++++++++
...-64-dwarf5-64-debug-names-type-comdat.test | 20 +
...x86-64-dwarf5-debug-names-type-comdat.test | 10 +
8 files changed, 1639 insertions(+), 5 deletions(-)
create mode 100644 lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
create mode 100644 lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
create mode 100644 lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-helper.s
create mode 100644 lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-main.s
create mode 100644 lld/test/ELF/x86-64-dwarf5-64-debug-names-type-comdat.test
create mode 100644 lld/test/ELF/x86-64-dwarf5-debug-names-type-comdat.test
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index a0d4be8ff9885b0..9237cd451f2e568 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1158,10 +1158,11 @@ void ObjFile<ELFT>::initSectionsAndLocalSyms(bool ignoreComdats) {
StringRef name(stringTable.data() + eSym.st_name);
symbols[i] = reinterpret_cast<Symbol *>(locals + i);
- if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded)
+ if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) {
+ StringRef name = CHECK(eSym.getName(stringTable), this);
new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type,
/*discardedSecIdx=*/secIdx);
- else
+ } else
new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type,
eSym.st_value, eSym.st_size, sec);
symbols[i]->partition = 1;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 02394cbae95d557..d839e7274763f85 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -20,8 +20,6 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/xxhash.h"
-#include <algorithm>
-#include <mutex>
#include <vector>
using namespace llvm;
@@ -888,6 +886,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
const bool isDebug = isDebugSection(*this);
const bool isDebugLocOrRanges =
isDebug && (name == ".debug_loc" || name == ".debug_ranges");
+ const bool isDebugNames = isDebug && name == ".debug_names";
const bool isDebugLine = isDebug && name == ".debug_line";
std::optional<uint64_t> tombstone;
for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
@@ -918,7 +917,8 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
continue;
if (tombstone ||
- (isDebug && (type == target.symbolicRel || expr == R_DTPREL))) {
+ ((isDebug && (type == target.symbolicRel || expr == R_DTPREL))) ||
+ isDebugNames) {
// 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
@@ -948,6 +948,21 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> 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<Defined>(&sym);
+ if (isDebugNames && dyn_cast<Undefined>(&sym)) {
+ uint64_t maxVal = 0;
+ switch (type) {
+ case R_X86_64_64:
+ maxVal = llvm::maxUIntN(64);
+ break;
+ case R_X86_64_32:
+ maxVal = llvm::maxUIntN(32);
+ break;
+ default:
+ llvm_unreachable("Unsupported relocation type in .debug_names.");
+ }
+ target.relocateNoSym(bufLoc, type, SignExtend64<bits>(maxVal));
+ continue;
+ }
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)
diff --git a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
new file mode 100644
index 000000000000000..1c046bc1520dc96
--- /dev/null
+++ b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
@@ -0,0 +1,397 @@
+ .text
+ .file "helper.cpp"
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov, at function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .file 0 "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" "helper.cpp" md5 0x305ec66c221c583021f8375b300e2591
+ .loc 0 2 0 # helper.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ .loc 0 4 3 prologue_end # helper.cpp:4:3
+ xorl %eax, %eax
+ .loc 0 4 3 epilogue_begin is_stmt 0 # helper.cpp:4:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0x53699580704254cb1dd2a83230f8a7ea
+ .section .debug_info,"G", at progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .quad .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .quad 59 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x28:0x2d DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .quad .Lline_table_start0 # DW_AT_stmt_list
+ .quad .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x3b:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 9 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x41:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 75 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x4b:0x5 DW_TAG_pointer_type
+ .long 80 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x50:0x4 DW_TAG_base_type
+ .byte 8 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .quad .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0x18:0x4d DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .quad .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .quad .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .quad .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x3b:0x1c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 87 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x4b:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 91 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x57:0x4 DW_TAG_base_type
+ .byte 5 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x5b:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad 84 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)" # string offset=0
+.Linfo_string1:
+ .asciz "helper.cpp" # string offset=105
+.Linfo_string2:
+ .asciz "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" # string offset=116
+.Linfo_string3:
+ .asciz "foo" # string offset=169
+.Linfo_string4:
+ .asciz "_Z3foov" # string offset=173
+.Linfo_string5:
+ .asciz "int" # string offset=181
+.Linfo_string6:
+ .asciz "f" # string offset=185
+.Linfo_string7:
+ .asciz "Foo2a" # string offset=187
+.Linfo_string8:
+ .asciz "c1" # string offset=193
+.Linfo_string9:
+ .asciz "char" # string offset=196
+ .section .debug_str_offsets,"", at progbits
+ .quad .Linfo_string0
+ .quad .Linfo_string1
+ .quad .Linfo_string2
+ .quad .Linfo_string4
+ .quad .Linfo_string3
+ .quad .Linfo_string5
+ .quad .Linfo_string6
+ .quad .Linfo_string8
+ .quad .Linfo_string9
+ .quad .Linfo_string7
+ .section .debug_addr,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # 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 .Lcu_begin0 # Compilation unit 0
+ .quad .Ltu_begin0 # Type unit 0
+ .long 0 # Bucket 0
+ .long 0 # Bucket 1
+ .long 0 # Bucket 2
+ .long 1 # Bucket 3
+ .long 2 # Bucket 4
+ .long 193495088 # Hash in Bucket 3
+ .long 193491849 # Hash in Bucket 4
+ .long 259227804 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 4
+ .long -1257882357 # Hash in Bucket 4
+ .quad .Linfo_string5 # String in Bucket 3: int
+ .quad .Linfo_string3 # String in Bucket 4: foo
+ .quad .Linfo_string7 # String in Bucket 4: Foo2a
+ .quad .Linfo_string9 # String in Bucket 4: char
+ .quad .Linfo_string4 # String in Bucket 4: _Z3foov
+ .quad .Lnames2-.Lnames_entries0 # Offset in Bucket 3
+ .quad .Lnames0-.Lnames_entries0 # Offset in Bucket 4
+ .quad .Lnames3-.Lnames_entries0 # Offset in Bucket 4
+ .quad .Lnames4-.Lnames_entries0 # Offset in Bucket 4
+ .quad .Lnames1-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+ .ascii "\210\t" # Abbreviation code
+ .long 87 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 59 # DW_IDX_die_offset
+ .byte 0 # End of list: foo
+.Lnames3:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 59 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 91 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames4:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 80 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+.Lnames1:
+ .ascii "\310\013" # Abbreviation code
+ .long 59 # DW_IDX_die_offset
+ .byte 0 # End of list: _Z3foov
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
new file mode 100644
index 000000000000000..2686a253fa56b97
--- /dev/null
+++ b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
@@ -0,0 +1,384 @@
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" "main.cpp" md5 0x6e787b94dac2f817bb35cfde8006dc82
+ .loc 0 2 0 # main.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+.Ltmp0:
+ .loc 0 4 2 prologue_end # main.cpp:4:2
+ xorl %eax, %eax
+ .loc 0 4 2 epilogue_begin is_stmt 0 # main.cpp:4:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0x53699580704254cb1dd2a83230f8a7ea
+ .section .debug_info,"G", at progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .quad .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .quad 59 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x28:0x2d DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .quad .Lline_table_start0 # DW_AT_stmt_list
+ .quad .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x3b:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 8 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x41:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 75 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x4b:0x5 DW_TAG_pointer_type
+ .long 80 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x50:0x4 DW_TAG_base_type
+ .byte 7 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .quad .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0x18:0x4c DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .quad .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .quad .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .quad .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x3b:0x1b DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x4a:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 90 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x56:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x5a:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad 76 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=105
+.Linfo_string2:
+ .asciz "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" # string offset=114
+.Linfo_string3:
+ .asciz "main" # string offset=167
+.Linfo_string4:
+ .asciz "int" # string offset=172
+.Linfo_string5:
+ .asciz "f3" # string offset=176
+.Linfo_string6:
+ .asciz "Foo2a" # string offset=179
+.Linfo_string7:
+ .asciz "c1" # string offset=185
+.Linfo_string8:
+ .asciz "char" # string offset=188
+ .section .debug_str_offsets,"", at progbits
+ .quad .Linfo_string0
+ .quad .Linfo_string1
+ .quad .Linfo_string2
+ .quad .Linfo_string3
+ .quad .Linfo_string4
+ .quad .Linfo_string5
+ .quad .Linfo_string7
+ .quad .Linfo_string8
+ .quad .Linfo_string6
+ .section .debug_addr,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long 4294967295 # DWARF64 Mark
+ .quad .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 4 # Header: bucket count
+ .long 4 # 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 .Lcu_begin0 # Compilation unit 0
+ .quad .Ltu_begin0 # Type unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 3 # Bucket 2
+ .long 4 # Bucket 3
+ .long 193495088 # Hash in Bucket 0
+ .long 259227804 # Hash in Bucket 0
+ .long 2090499946 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 3
+ .quad .Linfo_string4 # String in Bucket 0: int
+ .quad .Linfo_string6 # String in Bucket 0: Foo2a
+ .quad .Linfo_string3 # String in Bucket 2: main
+ .quad .Linfo_string8 # String in Bucket 3: char
+ .quad .Lnames1-.Lnames_entries0 # Offset in Bucket 0
+ .quad .Lnames2-.Lnames_entries0 # Offset in Bucket 0
+ .quad .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .quad .Lnames3-.Lnames_entries0 # Offset in Bucket 3
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+ .ascii "\210\t" # Abbreviation code
+ .long 86 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames2:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 59 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 90 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 59 # DW_IDX_die_offset
+ .byte 0 # End of list: main
+.Lnames3:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 80 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-helper.s b/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-helper.s
new file mode 100644
index 000000000000000..501065f9c111f28
--- /dev/null
+++ b/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-helper.s
@@ -0,0 +1,410 @@
+ .text
+ .file "helper.cpp"
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov, at function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .file 0 "/typeDedupSmall" "helper.cpp" md5 0x305ec66c221c583021f8375b300e2591
+ .loc 0 2 0 # helper.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ .loc 0 4 3 prologue_end # helper.cpp:4:3
+ xorl %eax, %eax
+ .loc 0 4 3 epilogue_begin is_stmt 0 # helper.cpp:4:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0xfea7bb1f22c47f129e15695f7137a1e7
+ .section .debug_info,"G", at progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 11 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member
+ .byte 10 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type
+ .long 74 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type
+ .byte 8 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0xc:0x41 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x23:0x1c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 63 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x33:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 104
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 67 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3f:0x4 DW_TAG_base_type
+ .byte 5 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x43:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"", at progbits
+ .long 52 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)" # string offset=0
+.Linfo_string1:
+ .asciz "helper.cpp" # string offset=105
+.Linfo_string2:
+ .asciz "/typeDedupSmall" # string offset=116
+.Linfo_string3:
+ .asciz "foo" # string offset=169
+.Linfo_string4:
+ .asciz "_Z3foov" # string offset=173
+.Linfo_string5:
+ .asciz "int" # string offset=181
+.Linfo_string6:
+ .asciz "f" # string offset=185
+.Linfo_string7:
+ .asciz "Foo2a" # string offset=187
+.Linfo_string8:
+ .asciz "c1" # string offset=193
+.Linfo_string9:
+ .asciz "char" # string offset=196
+.Linfo_string10:
+ .asciz "c2" # string offset=201
+.Linfo_string11:
+ .asciz "c3" # string offset=204
+ .section .debug_str_offsets,"", at progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string4
+ .long .Linfo_string3
+ .long .Linfo_string5
+ .long .Linfo_string6
+ .long .Linfo_string8
+ .long .Linfo_string9
+ .long .Linfo_string10
+ .long .Linfo_string11
+ .long .Linfo_string7
+ .section .debug_addr,"", at progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # 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 .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 0 # Bucket 0
+ .long 0 # Bucket 1
+ .long 0 # Bucket 2
+ .long 1 # Bucket 3
+ .long 2 # Bucket 4
+ .long 193495088 # Hash in Bucket 3
+ .long 193491849 # Hash in Bucket 4
+ .long 259227804 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 4
+ .long -1257882357 # Hash in Bucket 4
+ .long .Linfo_string5 # String in Bucket 3: int
+ .long .Linfo_string3 # String in Bucket 4: foo
+ .long .Linfo_string7 # String in Bucket 4: Foo2a
+ .long .Linfo_string9 # String in Bucket 4: char
+ .long .Linfo_string4 # String in Bucket 4: _Z3foov
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+ .ascii "\210\t" # Abbreviation code
+ .long 63 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: foo
+.Lnames3:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 67 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames4:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 74 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+.Lnames1:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: _Z3foov
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
diff --git a/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-main.s b/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-main.s
new file mode 100644
index 000000000000000..df4091705d656e8
--- /dev/null
+++ b/lld/test/ELF/Inputs/dwarf5-debug-names-type-comdat-main.s
@@ -0,0 +1,397 @@
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "/typeDedupSmall" "main.cpp" md5 0x6e787b94dac2f817bb35cfde8006dc82
+ .loc 0 2 0 # main.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+.Ltmp0:
+ .loc 0 4 2 prologue_end # main.cpp:4:2
+ xorl %eax, %eax
+ .loc 0 4 2 epilogue_begin is_stmt 0 # main.cpp:4:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0xfea7bb1f22c47f129e15695f7137a1e7
+ .section .debug_info,"G", at progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 10 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 69 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type
+ .long 74 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type
+ .byte 7 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0xc:0x40 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x23:0x1b DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 62 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x32:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 96
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 66 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3e:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x42:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"", at progbits
+ .long 48 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=105
+.Linfo_string2:
+ .asciz "/typeDedupSmall" # string offset=114
+.Linfo_string3:
+ .asciz "main" # string offset=167
+.Linfo_string4:
+ .asciz "int" # string offset=172
+.Linfo_string5:
+ .asciz "f3" # string offset=176
+.Linfo_string6:
+ .asciz "Foo2a" # string offset=179
+.Linfo_string7:
+ .asciz "c1" # string offset=185
+.Linfo_string8:
+ .asciz "char" # string offset=188
+.Linfo_string9:
+ .asciz "c2" # string offset=193
+.Linfo_string10:
+ .asciz "c3" # string offset=196
+ .section .debug_str_offsets,"", at progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string4
+ .long .Linfo_string5
+ .long .Linfo_string7
+ .long .Linfo_string8
+ .long .Linfo_string9
+ .long .Linfo_string10
+ .long .Linfo_string6
+ .section .debug_addr,"", at progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"", at progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 4 # Header: bucket count
+ .long 4 # 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 .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 3 # Bucket 2
+ .long 4 # Bucket 3
+ .long 193495088 # Hash in Bucket 0
+ .long 259227804 # Hash in Bucket 0
+ .long 2090499946 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 3
+ .long .Linfo_string4 # String in Bucket 0: int
+ .long .Linfo_string6 # String in Bucket 0: Foo2a
+ .long .Linfo_string3 # String in Bucket 2: main
+ .long .Linfo_string8 # String in Bucket 3: char
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 3
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+ .ascii "\210\t" # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames2:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: main
+.Lnames3:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 74 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0 (git at github.com:ayermolo/llvm-project.git 2a059ae838c2e444f47dc1dcdfefb6fc876a53c1)"
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .section .debug_line,"", at progbits
+.Lline_table_start0:
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 000000000000000..707a90b31d79e0e
--- /dev/null
+++ b/lld/test/ELF/x86-64-dwarf5-64-debug-names-type-comdat.test
@@ -0,0 +1,20 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dwarf5-64-debug-names-type-comdat-main.s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dwarf5-64-debug-names-type-comdat-helper.s -o %t1.o
+// RUN: ld.lld %t.o %t1.o -o %t1
+// RUN: llvm-readelf --relocs %t.o | FileCheck --check-prefix=RELOCMAIN %s
+// RUN: llvm-dwarfdump --debug-names %t1 | FileCheck %s
+
+// Test checks that LLD tombstones TU section that was de-duplicated using COMDAT to the maxium value.
+// For some reason llvm-dwarfdump doesn't print out full 64bitt offset at the moment.
+// Working around it by checking that relocation is 64 bit.
+
+// RELOCMAIN: rela.debug_names
+// RELOCMAIN-NEXT: Offset
+// RELOCMAIN-NEXT: R_X86_64_64
+// RELOCMAIN-SAME: .debug_info + 0
+// RELOCMAIN-NEXT: R_X86_64_64
+// RELOCMAIN-SAME: .debug_info + 0
+
+// CHECK: LocalTU[0]: 0x00000000
+// CHECK: LocalTU[0]: 0xffffffffffffffff
diff --git a/lld/test/ELF/x86-64-dwarf5-debug-names-type-comdat.test b/lld/test/ELF/x86-64-dwarf5-debug-names-type-comdat.test
new file mode 100644
index 000000000000000..1234a83bf7671a5
--- /dev/null
+++ b/lld/test/ELF/x86-64-dwarf5-debug-names-type-comdat.test
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-type-comdat-main.s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-type-comdat-helper.s -o %t1.o
+// RUN: ld.lld %t.o %t1.o -o %t1
+// RUN: llvm-dwarfdump --debug-names %t1 | FileCheck %s
+
+// Test checks that LLD tombstones TU section that was de-duplicated using COMDAT to the maxium value.
+
+// CHECK: LocalTU[0]: 0x00000000
+// CHECK: LocalTU[0]: 0xffffffff
>From 792155d4ae506378212d963e97dba1ea69f65122 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Mon, 30 Oct 2023 11:39:40 -0700
Subject: [PATCH 2/6] fixup! [LLD] Tombstone LocalTU entry in .debug_names
---
lld/ELF/InputFiles.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 9237cd451f2e568..a0d4be8ff9885b0 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1158,11 +1158,10 @@ void ObjFile<ELFT>::initSectionsAndLocalSyms(bool ignoreComdats) {
StringRef name(stringTable.data() + eSym.st_name);
symbols[i] = reinterpret_cast<Symbol *>(locals + i);
- if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) {
- StringRef name = CHECK(eSym.getName(stringTable), this);
+ if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded)
new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type,
/*discardedSecIdx=*/secIdx);
- } else
+ else
new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type,
eSym.st_value, eSym.st_size, sec);
symbols[i]->partition = 1;
>From 854a281473f7ae9ac2213ac0e09c8d2385237d90 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Mon, 30 Oct 2023 11:49:38 -0700
Subject: [PATCH 3/6] fixup! fixup! [LLD] Tombstone LocalTU entry in
.debug_names
---
lld/ELF/InputSection.cpp | 3 ++-
.../ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s | 4 ++--
lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s | 4 ++--
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index d839e7274763f85..8afb7c7ddf2f6e0 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -947,7 +947,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> 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<Defined>(&sym);
+
if (isDebugNames && dyn_cast<Undefined>(&sym)) {
uint64_t maxVal = 0;
switch (type) {
@@ -963,6 +963,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
target.relocateNoSym(bufLoc, type, SignExtend64<bits>(maxVal));
continue;
}
+ auto *ds = dyn_cast<Defined>(&sym);
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)
diff --git a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
index 1c046bc1520dc96..98972a018a5df06 100644
--- a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
+++ b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-helper.s
@@ -5,7 +5,7 @@
.type _Z3foov, at function
_Z3foov: # @_Z3foov
.Lfunc_begin0:
- .file 0 "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" "helper.cpp" md5 0x305ec66c221c583021f8375b300e2591
+ .file 0 "/typeDedupSmall" "helper.cpp" md5 0x305ec66c221c583021f8375b300e2591
.loc 0 2 0 # helper.cpp:2:0
.cfi_startproc
# %bb.0: # %entry
@@ -254,7 +254,7 @@ _Z3foov: # @_Z3foov
.Linfo_string1:
.asciz "helper.cpp" # string offset=105
.Linfo_string2:
- .asciz "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" # string offset=116
+ .asciz "/typeDedupSmall" # string offset=116
.Linfo_string3:
.asciz "foo" # string offset=169
.Linfo_string4:
diff --git a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
index 2686a253fa56b97..4b4f0b39701980b 100644
--- a/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
+++ b/lld/test/ELF/Inputs/dwarf5-64-debug-names-type-comdat-main.s
@@ -5,7 +5,7 @@
.type main, at function
main: # @main
.Lfunc_begin0:
- .file 0 "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" "main.cpp" md5 0x6e787b94dac2f817bb35cfde8006dc82
+ .file 0 "/typeDedupSmall" "main.cpp" md5 0x6e787b94dac2f817bb35cfde8006dc82
.loc 0 2 0 # main.cpp:2:0
.cfi_startproc
# %bb.0: # %entry
@@ -252,7 +252,7 @@ main: # @main
.Linfo_string1:
.asciz "main.cpp" # string offset=105
.Linfo_string2:
- .asciz "/home/ayermolo/local/tasks/T138552329/typeDedupSmall" # string offset=114
+ .asciz "/typeDedupSmall" # string offset=114
.Linfo_string3:
.asciz "main" # string offset=167
.Linfo_string4:
>From b716d70a0d9b8b648c111333a15cf45fa69d210e Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 2 Nov 2023 12:42:13 -0700
Subject: [PATCH 4/6] fixup! fixup! fixup! [LLD] Tombstone LocalTU entry in
.debug_names
---
lld/ELF/InputSection.cpp | 40 +++++++++++++--------------------
lld/test/ELF/debug-dead-reloc.s | 8 +++----
2 files changed, 19 insertions(+), 29 deletions(-)
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 8afb7c7ddf2f6e0..ce95f8137f48db4 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -884,8 +884,6 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> 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 isDebugNames = isDebug && name == ".debug_names";
const bool isDebugLine = isDebug && name == ".debug_line";
std::optional<uint64_t> tombstone;
@@ -895,6 +893,16 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
break;
}
+ const uint64_t debugTombstone = StringSwitch<uint64_t>(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)
+ tombstone = debugTombstone;
+ else if (tombstone)
+ tombstone = SignExtend64<bits>(*tombstone);
for (const RelTy &rel : rels) {
RelType type = rel.getType(config->isMips64EL);
@@ -916,9 +924,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
if (expr == R_NONE)
continue;
- if (tombstone ||
- ((isDebug && (type == target.symbolicRel || expr == R_DTPREL))) ||
- isDebugNames) {
+ if (tombstone) {
// 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
@@ -948,27 +954,13 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
// TODO To reduce disruption, we use 0 instead of -1 as the tombstone
// value. Enable -1 in a future release.
- if (isDebugNames && dyn_cast<Undefined>(&sym)) {
- uint64_t maxVal = 0;
- switch (type) {
- case R_X86_64_64:
- maxVal = llvm::maxUIntN(64);
- break;
- case R_X86_64_32:
- maxVal = llvm::maxUIntN(32);
- break;
- default:
- llvm_unreachable("Unsupported relocation type in .debug_names.");
- }
- target.relocateNoSym(bufLoc, type, SignExtend64<bits>(maxVal));
- continue;
- }
+ // Extend to 64bit MAX for 64 bit relocations, LocalTU, in .debug_names.
+ if (isDebugNames && type == target.symbolicRel)
+ tombstone = SignExtend64<32>(*tombstone);
+
auto *ds = dyn_cast<Defined>(&sym);
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);
- target.relocateNoSym(bufLoc, type, value);
+ target.relocateNoSym(bufLoc, type, *tombstone);
continue;
}
}
diff --git a/lld/test/ELF/debug-dead-reloc.s b/lld/test/ELF/debug-dead-reloc.s
index fcf53205079ed6a..fdfde6ce2c75ca2 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
>From 19fa33e1938b25c74528239912eea85f2962b327 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 2 Nov 2023 16:45:31 -0700
Subject: [PATCH 5/6] fixup! fixup! fixup! fixup! [LLD] Tombstone LocalTU entry
in .debug_names
---
lld/ELF/InputSection.cpp | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index ce95f8137f48db4..b5e9f681c4f5d6a 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -20,6 +20,7 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/xxhash.h"
+#include <cstdint>
#include <vector>
using namespace llvm;
@@ -884,9 +885,9 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
const unsigned bits = sizeof(typename ELFT::uint) * 8;
const TargetInfo &target = *elf::target;
const bool isDebug = isDebugSection(*this);
- const bool isDebugNames = isDebug && name == ".debug_names";
const bool isDebugLine = isDebug && name == ".debug_line";
std::optional<uint64_t> tombstone;
+ uint64_t tombstoneValueToUse = 0;
for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
if (patAndValue.first.match(this->name)) {
tombstone = patAndValue.second;
@@ -900,9 +901,9 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
.Default(0);
// If -z dead-reloc-in-nonalloc= is specified, respect it.
if (!tombstone && isDebug)
- tombstone = debugTombstone;
+ tombstoneValueToUse = debugTombstone;
else if (tombstone)
- tombstone = SignExtend64<bits>(*tombstone);
+ tombstoneValueToUse = SignExtend64<bits>(*tombstone);
for (const RelTy &rel : rels) {
RelType type = rel.getType(config->isMips64EL);
@@ -924,7 +925,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
if (expr == R_NONE)
continue;
- if (tombstone) {
+ if (tombstone || isDebug) {
// 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
@@ -954,13 +955,14 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
// TODO To reduce disruption, we use 0 instead of -1 as the tombstone
// value. Enable -1 in a future release.
- // Extend to 64bit MAX for 64 bit relocations, LocalTU, in .debug_names.
- if (isDebugNames && type == target.symbolicRel)
- tombstone = SignExtend64<32>(*tombstone);
+ // 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);
auto *ds = dyn_cast<Defined>(&sym);
if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
- target.relocateNoSym(bufLoc, type, *tombstone);
+ target.relocateNoSym(bufLoc, type, tombstoneValueToUse);
continue;
}
}
>From a69878bc110721e6cd6e9cc5ffee15c520365a72 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 2 Nov 2023 16:48:06 -0700
Subject: [PATCH 6/6] fixup! fixup! fixup! fixup! fixup! [LLD] Tombstone
LocalTU entry in .debug_names
---
lld/ELF/InputSection.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index b5e9f681c4f5d6a..0ec0e6f52b8392e 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -21,6 +21,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/xxhash.h"
#include <cstdint>
+#include <optional>
#include <vector>
using namespace llvm;
@@ -886,8 +887,8 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
const TargetInfo &target = *elf::target;
const bool isDebug = isDebugSection(*this);
const bool isDebugLine = isDebug && name == ".debug_line";
- std::optional<uint64_t> tombstone;
- uint64_t tombstoneValueToUse = 0;
+ std::optional<uint64_t> tombstone = std::nullopt;
+ std::optional<uint64_t> tombstoneValueToUse = std::nullopt;
for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
if (patAndValue.first.match(this->name)) {
tombstone = patAndValue.second;
@@ -925,7 +926,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
if (expr == R_NONE)
continue;
- if (tombstone || isDebug) {
+ if (tombstoneValueToUse) {
// 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
@@ -958,11 +959,11 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
// 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);
+ tombstoneValueToUse = SignExtend64<32>(*tombstoneValueToUse);
auto *ds = dyn_cast<Defined>(&sym);
if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
- target.relocateNoSym(bufLoc, type, tombstoneValueToUse);
+ target.relocateNoSym(bufLoc, type, *tombstoneValueToUse);
continue;
}
}
More information about the llvm-commits
mailing list