Skip to content

Commit 8ee5c40

Browse files
authored
[DebugInfo] Support to get TU for hash from .debug_types.dwo section in DWARF4. (#161067)
Using the DWP's cu_index/tu_index only loads the DWO units from the .debug_info.dwo section for hash, which works fine in DWARF5. However, tu_index points to .debug_types.dwo section in DWARF4, which can cause the type unit to be lost due to the incorrect loading target. (Related discussion in [811b60f](811b60f)) This patch supports to get the type unit for hash from .debug_types.dwo section in DWARF4.
1 parent 7de1a17 commit 8ee5c40

File tree

5 files changed

+280
-13
lines changed

5 files changed

+280
-13
lines changed

bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# UNSUPPORTED: system-linux
21
; RUN: rm -rf %t
32
; RUN: mkdir %t
43
; RUN: cd %t

llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,11 @@ class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1>
143143
decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
144144

145145
LLVM_ABI DWARFUnit *getUnitForOffset(uint64_t Offset) const;
146-
LLVM_ABI DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
146+
/// Returns the Unit from the .debug_info or .debug_types section by the index
147+
/// entry.
148+
LLVM_ABI DWARFUnit *
149+
getUnitForIndexEntry(const DWARFUnitIndex::Entry &E, DWARFSectionKind Sec,
150+
const DWARFSection *Section = nullptr);
147151

148152
/// Read units from a .debug_info or .debug_types section. Calls made
149153
/// before finishedInfoUnits() are assumed to be for .debug_info sections,

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,9 +1344,20 @@ void DWARFContext::dump(
13441344
DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint64_t Hash, bool IsDWO) {
13451345
DWARFUnitVector &DWOUnits = State->getDWOUnits();
13461346
if (const auto &TUI = getTUIndex()) {
1347-
if (const auto *R = TUI.getFromHash(Hash))
1348-
return dyn_cast_or_null<DWARFTypeUnit>(
1349-
DWOUnits.getUnitForIndexEntry(*R));
1347+
if (const auto *R = TUI.getFromHash(Hash)) {
1348+
if (TUI.getVersion() >= 5) {
1349+
return dyn_cast_or_null<DWARFTypeUnit>(
1350+
DWOUnits.getUnitForIndexEntry(*R, DW_SECT_INFO));
1351+
} else {
1352+
DWARFUnit *TypesUnit = nullptr;
1353+
getDWARFObj().forEachTypesDWOSections([&](const DWARFSection &S) {
1354+
if (!TypesUnit)
1355+
TypesUnit =
1356+
DWOUnits.getUnitForIndexEntry(*R, DW_SECT_EXT_TYPES, &S);
1357+
});
1358+
return dyn_cast_or_null<DWARFTypeUnit>(TypesUnit);
1359+
}
1360+
}
13501361
return nullptr;
13511362
}
13521363
return State->getTypeUnitMap(IsDWO).lookup(Hash);
@@ -1358,7 +1369,7 @@ DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
13581369
if (const auto &CUI = getCUIndex()) {
13591370
if (const auto *R = CUI.getFromHash(Hash))
13601371
return dyn_cast_or_null<DWARFCompileUnit>(
1361-
DWOUnits.getUnitForIndexEntry(*R));
1372+
DWOUnits.getUnitForIndexEntry(*R, DW_SECT_INFO));
13621373
return nullptr;
13631374
}
13641375

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,24 @@ DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const {
161161
return nullptr;
162162
}
163163

164-
DWARFUnit *
165-
DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
166-
const auto *CUOff = E.getContribution(DW_SECT_INFO);
164+
DWARFUnit *DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E,
165+
DWARFSectionKind Sec,
166+
const DWARFSection *Section) {
167+
const auto *CUOff = E.getContribution(Sec);
167168
if (!CUOff)
168169
return nullptr;
169170

170171
uint64_t Offset = CUOff->getOffset();
171-
auto end = begin() + getNumInfoUnits();
172+
auto begin = this->begin();
173+
auto end = begin + getNumInfoUnits();
174+
175+
if (Sec == DW_SECT_EXT_TYPES) {
176+
begin = end;
177+
end = this->end();
178+
}
172179

173180
auto *CU =
174-
std::upper_bound(begin(), end, CUOff->getOffset(),
181+
std::upper_bound(begin, end, CUOff->getOffset(),
175182
[](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
176183
return LHS < RHS->getNextUnitOffset();
177184
});
@@ -181,13 +188,14 @@ DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
181188
if (!Parser)
182189
return nullptr;
183190

184-
auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E);
191+
auto U = Parser(Offset, Sec, Section, &E);
185192
if (!U)
186193
return nullptr;
187194

188195
auto *NewCU = U.get();
189196
this->insert(CU, std::move(U));
190-
++NumInfoUnits;
197+
if (Sec == DW_SECT_INFO)
198+
++NumInfoUnits;
191199
return NewCU;
192200
}
193201

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
## This test uses TU index for type parsing in dwp and makes sure the DWARF4 type is
2+
## successfully retrieved.
3+
4+
# RUN: llvm-mc %s --split-dwarf-file=test.dwo -filetype obj -triple x86_64 -o test.o
5+
# RUN: llvm-dwp -e test.o -o test.dwp
6+
# RUN: llvm-dwarfdump test.dwp | FileCheck %s
7+
8+
# Generated from:
9+
#
10+
# struct t1 { };
11+
# t1 v1;
12+
#
13+
# $ clang++ -S -g -fdebug-types-section -gsplit-dwarf -o test.4.split.dwp.s -gdwarf-4
14+
15+
# CHECK: DW_TAG_variable
16+
# CHECK: DW_AT_type ({{.*}} "t1")
17+
.file "test.cpp"
18+
.section .debug_types.dwo,"e",@progbits
19+
.long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
20+
.Ldebug_info_dwo_start0:
21+
.short 4 # DWARF version number
22+
.long 0 # Offset Into Abbrev. Section
23+
.byte 8 # Address Size (in bytes)
24+
.quad -4149699470930386446 # Type Signature
25+
.long 30 # Type DIE Offset
26+
.byte 1 # Abbrev [1] 0x17:0xe DW_TAG_type_unit
27+
.short 33 # DW_AT_language
28+
.long 0 # DW_AT_stmt_list
29+
.byte 2 # Abbrev [2] 0x1e:0x6 DW_TAG_structure_type
30+
.byte 5 # DW_AT_calling_convention
31+
.byte 1 # DW_AT_name
32+
.byte 1 # DW_AT_byte_size
33+
.byte 1 # DW_AT_decl_file
34+
.byte 1 # DW_AT_decl_line
35+
.byte 0 # End Of Children Mark
36+
.Ldebug_info_dwo_end0:
37+
.file 1 "." "test.cpp"
38+
.type v1,@object # @v1
39+
.bss
40+
.globl v1
41+
v1:
42+
.zero 1
43+
.size v1, 1
44+
45+
.section .debug_abbrev,"",@progbits
46+
.byte 1 # Abbreviation Code
47+
.byte 17 # DW_TAG_compile_unit
48+
.byte 0 # DW_CHILDREN_no
49+
.byte 16 # DW_AT_stmt_list
50+
.byte 23 # DW_FORM_sec_offset
51+
.byte 27 # DW_AT_comp_dir
52+
.byte 14 # DW_FORM_strp
53+
.ascii "\264B" # DW_AT_GNU_pubnames
54+
.byte 25 # DW_FORM_flag_present
55+
.ascii "\260B" # DW_AT_GNU_dwo_name
56+
.byte 14 # DW_FORM_strp
57+
.ascii "\261B" # DW_AT_GNU_dwo_id
58+
.byte 7 # DW_FORM_data8
59+
.ascii "\263B" # DW_AT_GNU_addr_base
60+
.byte 23 # DW_FORM_sec_offset
61+
.byte 0 # EOM(1)
62+
.byte 0 # EOM(2)
63+
.byte 0 # EOM(3)
64+
.section .debug_info,"",@progbits
65+
.Lcu_begin0:
66+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
67+
.Ldebug_info_start0:
68+
.short 4 # DWARF version number
69+
.long .debug_abbrev # Offset Into Abbrev. Section
70+
.byte 8 # Address Size (in bytes)
71+
.byte 1 # Abbrev [1] 0xb:0x19 DW_TAG_compile_unit
72+
.long .Lline_table_start0 # DW_AT_stmt_list
73+
.long .Lskel_string0 # DW_AT_comp_dir
74+
# DW_AT_GNU_pubnames
75+
.long .Lskel_string1 # DW_AT_GNU_dwo_name
76+
.quad 1388839634901268525 # DW_AT_GNU_dwo_id
77+
.long .Laddr_table_base0 # DW_AT_GNU_addr_base
78+
.Ldebug_info_end0:
79+
.section .debug_str,"MS",@progbits,1
80+
.Lskel_string0:
81+
.asciz "." # string offset=0
82+
.Lskel_string1:
83+
.asciz "test.dwo" # string offset=2
84+
.section .debug_str.dwo,"eMS",@progbits,1
85+
.Linfo_string0:
86+
.asciz "v1" # string offset=0
87+
.Linfo_string1:
88+
.asciz "t1" # string offset=3
89+
.Linfo_string2:
90+
.asciz "clang version 22.0.0" # string offset=6
91+
.Linfo_string3:
92+
.asciz "test.cpp" # string offset=27
93+
.Linfo_string4:
94+
.asciz "test.dwo" # string offset=36
95+
.section .debug_str_offsets.dwo,"e",@progbits
96+
.long 0
97+
.long 3
98+
.long 6
99+
.long 27
100+
.long 36
101+
.section .debug_info.dwo,"e",@progbits
102+
.long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
103+
.Ldebug_info_dwo_start1:
104+
.short 4 # DWARF version number
105+
.long 0 # Offset Into Abbrev. Section
106+
.byte 8 # Address Size (in bytes)
107+
.byte 3 # Abbrev [3] 0xb:0x23 DW_TAG_compile_unit
108+
.byte 2 # DW_AT_producer
109+
.short 33 # DW_AT_language
110+
.byte 3 # DW_AT_name
111+
.byte 4 # DW_AT_GNU_dwo_name
112+
.quad 1388839634901268525 # DW_AT_GNU_dwo_id
113+
.byte 4 # Abbrev [4] 0x19:0xb DW_TAG_variable
114+
.byte 0 # DW_AT_name
115+
.long 36 # DW_AT_type
116+
# DW_AT_external
117+
.byte 1 # DW_AT_decl_file
118+
.byte 2 # DW_AT_decl_line
119+
.byte 2 # DW_AT_location
120+
.byte 251
121+
.byte 0
122+
.byte 5 # Abbrev [5] 0x24:0x9 DW_TAG_structure_type
123+
# DW_AT_declaration
124+
.quad -4149699470930386446 # DW_AT_signature
125+
.byte 0 # End Of Children Mark
126+
.Ldebug_info_dwo_end1:
127+
.section .debug_abbrev.dwo,"e",@progbits
128+
.byte 1 # Abbreviation Code
129+
.byte 65 # DW_TAG_type_unit
130+
.byte 1 # DW_CHILDREN_yes
131+
.byte 19 # DW_AT_language
132+
.byte 5 # DW_FORM_data2
133+
.byte 16 # DW_AT_stmt_list
134+
.byte 23 # DW_FORM_sec_offset
135+
.byte 0 # EOM(1)
136+
.byte 0 # EOM(2)
137+
.byte 2 # Abbreviation Code
138+
.byte 19 # DW_TAG_structure_type
139+
.byte 0 # DW_CHILDREN_no
140+
.byte 54 # DW_AT_calling_convention
141+
.byte 11 # DW_FORM_data1
142+
.byte 3 # DW_AT_name
143+
.ascii "\202>" # DW_FORM_GNU_str_index
144+
.byte 11 # DW_AT_byte_size
145+
.byte 11 # DW_FORM_data1
146+
.byte 58 # DW_AT_decl_file
147+
.byte 11 # DW_FORM_data1
148+
.byte 59 # DW_AT_decl_line
149+
.byte 11 # DW_FORM_data1
150+
.byte 0 # EOM(1)
151+
.byte 0 # EOM(2)
152+
.byte 3 # Abbreviation Code
153+
.byte 17 # DW_TAG_compile_unit
154+
.byte 1 # DW_CHILDREN_yes
155+
.byte 37 # DW_AT_producer
156+
.ascii "\202>" # DW_FORM_GNU_str_index
157+
.byte 19 # DW_AT_language
158+
.byte 5 # DW_FORM_data2
159+
.byte 3 # DW_AT_name
160+
.ascii "\202>" # DW_FORM_GNU_str_index
161+
.ascii "\260B" # DW_AT_GNU_dwo_name
162+
.ascii "\202>" # DW_FORM_GNU_str_index
163+
.ascii "\261B" # DW_AT_GNU_dwo_id
164+
.byte 7 # DW_FORM_data8
165+
.byte 0 # EOM(1)
166+
.byte 0 # EOM(2)
167+
.byte 4 # Abbreviation Code
168+
.byte 52 # DW_TAG_variable
169+
.byte 0 # DW_CHILDREN_no
170+
.byte 3 # DW_AT_name
171+
.ascii "\202>" # DW_FORM_GNU_str_index
172+
.byte 73 # DW_AT_type
173+
.byte 19 # DW_FORM_ref4
174+
.byte 63 # DW_AT_external
175+
.byte 25 # DW_FORM_flag_present
176+
.byte 58 # DW_AT_decl_file
177+
.byte 11 # DW_FORM_data1
178+
.byte 59 # DW_AT_decl_line
179+
.byte 11 # DW_FORM_data1
180+
.byte 2 # DW_AT_location
181+
.byte 24 # DW_FORM_exprloc
182+
.byte 0 # EOM(1)
183+
.byte 0 # EOM(2)
184+
.byte 5 # Abbreviation Code
185+
.byte 19 # DW_TAG_structure_type
186+
.byte 0 # DW_CHILDREN_no
187+
.byte 60 # DW_AT_declaration
188+
.byte 25 # DW_FORM_flag_present
189+
.byte 105 # DW_AT_signature
190+
.byte 32 # DW_FORM_ref_sig8
191+
.byte 0 # EOM(1)
192+
.byte 0 # EOM(2)
193+
.byte 0 # EOM(3)
194+
.section .debug_line.dwo,"e",@progbits
195+
.Ltmp0:
196+
.long .Ldebug_line_end0-.Ldebug_line_start0 # unit length
197+
.Ldebug_line_start0:
198+
.short 4
199+
.long .Lprologue_end0-.Lprologue_start0
200+
.Lprologue_start0:
201+
.byte 1
202+
.byte 1
203+
.byte 1
204+
.byte -5
205+
.byte 14
206+
.byte 1
207+
.byte 0
208+
.ascii "test.cpp"
209+
.byte 0
210+
.byte 0
211+
.byte 0
212+
.byte 0
213+
.byte 0
214+
.Lprologue_end0:
215+
.Ldebug_line_end0:
216+
.section .debug_addr,"",@progbits
217+
.Laddr_table_base0:
218+
.quad v1
219+
.section .debug_gnu_pubnames,"",@progbits
220+
.long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info
221+
.LpubNames_start0:
222+
.short 2 # DWARF Version
223+
.long .Lcu_begin0 # Offset of Compilation Unit Info
224+
.long 36 # Compilation Unit Length
225+
.long 25 # DIE offset
226+
.byte 32 # Attributes: VARIABLE, EXTERNAL
227+
.asciz "v1" # External Name
228+
.long 0 # End Mark
229+
.LpubNames_end0:
230+
.section .debug_gnu_pubtypes,"",@progbits
231+
.long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info
232+
.LpubTypes_start0:
233+
.short 2 # DWARF Version
234+
.long .Lcu_begin0 # Offset of Compilation Unit Info
235+
.long 36 # Compilation Unit Length
236+
.long 36 # DIE offset
237+
.byte 16 # Attributes: TYPE, EXTERNAL
238+
.asciz "t1" # External Name
239+
.long 0 # End Mark
240+
.LpubTypes_end0:
241+
.ident "clang version 22.0.0"
242+
.section ".note.GNU-stack","",@progbits
243+
.addrsig
244+
.section .debug_line,"",@progbits
245+
.Lline_table_start0:

0 commit comments

Comments
 (0)