Skip to content

Commit bb6a485

Browse files
authored
[BOLT] Fix updating DW_AT_stmt_list for DWARF5 TUs (#79374)
Changed so that we also update DW_AT_stmt_list for DWARF5 TUs. BOLT was doing it for DWARF4, but it wasn't doing it for DWARF5.
1 parent 1ae0448 commit bb6a485

6 files changed

+1087
-25
lines changed

bolt/include/bolt/Rewrite/DWARFRewriter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class DWARFRewriter {
9696
std::unordered_map<uint64_t, uint64_t> DwoRangesBase;
9797

9898
std::unordered_map<DWARFUnit *, uint64_t> LineTablePatchMap;
99-
std::unordered_map<DWARFUnit *, uint64_t> TypeUnitRelocMap;
99+
std::unordered_map<const DWARFUnit *, uint64_t> TypeUnitRelocMap;
100100

101101
/// Entries for GDB Index Types CU List
102102
using GDBIndexTUEntryType = std::vector<GDBIndexTUEntry>;

bolt/lib/Rewrite/DWARFRewriter.cpp

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,41 +1393,60 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
13931393
// ones.
13941394
std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;
13951395

1396-
auto GetStatementListValue = [](DWARFUnit *Unit) {
1397-
std::optional<DWARFFormValue> StmtList =
1398-
Unit->getUnitDIE().find(dwarf::DW_AT_stmt_list);
1396+
auto GetStatementListValue =
1397+
[](const DWARFDie &DIE) -> std::optional<uint64_t> {
1398+
std::optional<DWARFFormValue> StmtList = DIE.find(dwarf::DW_AT_stmt_list);
1399+
if (!StmtList)
1400+
return std::nullopt;
13991401
std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);
14001402
assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");
14011403
return *Offset;
14021404
};
14031405

1404-
for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
1406+
SmallVector<DWARFUnit *, 1> TUs;
1407+
for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1408+
if (CU->isTypeUnit()) {
1409+
TUs.push_back(CU.get());
1410+
continue;
1411+
}
14051412
const unsigned CUID = CU->getOffset();
14061413
MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
14071414
if (!Label)
14081415
continue;
14091416

1410-
std::optional<AttrInfo> AttrVal =
1411-
findAttributeInfo(CU.get()->getUnitDIE(), dwarf::DW_AT_stmt_list);
1412-
if (!AttrVal)
1417+
std::optional<uint64_t> StmtOffset =
1418+
GetStatementListValue(CU.get()->getUnitDIE());
1419+
if (!StmtOffset)
14131420
continue;
14141421

14151422
const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
1416-
DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset;
1423+
DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
14171424
assert(DbgInfoSection && ".debug_info section must exist");
14181425
LineTablePatchMap[CU.get()] = LineTableOffset;
14191426
}
14201427

1421-
for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units()) {
1422-
DWARFUnit *Unit = TU.get();
1423-
std::optional<AttrInfo> AttrVal =
1424-
findAttributeInfo(TU.get()->getUnitDIE(), dwarf::DW_AT_stmt_list);
1425-
if (!AttrVal)
1428+
for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())
1429+
TUs.push_back(TU.get());
1430+
1431+
for (DWARFUnit *TU : TUs) {
1432+
std::optional<uint64_t> StmtOffset =
1433+
GetStatementListValue(TU->getUnitDIE());
1434+
if (!StmtOffset)
1435+
continue;
1436+
auto Iter = DebugLineOffsetMap.find(*StmtOffset);
1437+
if (Iter == DebugLineOffsetMap.end()) {
1438+
// Implementation depends on TU sharing DW_AT_stmt_list with a CU.
1439+
// Only case that it hasn't been true was for manually modified assembly
1440+
// file. Adding this warning in case assumption is false.
1441+
errs()
1442+
<< "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"
1443+
<< Twine::utohexstr(TU->getOffset())
1444+
<< " is not sharing "
1445+
".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "
1446+
"updated.\n";
14261447
continue;
1427-
auto Iter = DebugLineOffsetMap.find(GetStatementListValue(Unit));
1428-
assert(Iter != DebugLineOffsetMap.end() &&
1429-
"Type Unit Updated Line Number Entry does not exist.");
1430-
TypeUnitRelocMap[Unit] = Iter->second;
1448+
}
1449+
TypeUnitRelocMap[TU] = Iter->second;
14311450
}
14321451

14331452
// Set .debug_info as finalized so it won't be skipped over when
@@ -1443,15 +1462,15 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
14431462
CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
14441463
DIEStreamer &Streamer) {
14451464
// update TypeUnit DW_AT_stmt_list with new .debug_line information.
1446-
for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units()) {
1447-
DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*TU.get());
1465+
auto updateLineTable = [&](const DWARFUnit &Unit) -> void {
1466+
DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit);
14481467
DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);
1449-
if (!StmtAttrInfo || !TypeUnitRelocMap.count(TU.get()))
1450-
continue;
1468+
if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit))
1469+
return;
14511470
DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,
14521471
StmtAttrInfo.getForm(),
1453-
DIEInteger(TypeUnitRelocMap[TU.get()]));
1454-
}
1472+
DIEInteger(TypeUnitRelocMap[&Unit]));
1473+
};
14551474

14561475
// generate and populate abbrevs here
14571476
DIEBlder.generateAbbrevs();
@@ -1469,6 +1488,7 @@ CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
14691488
for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
14701489
if (!CU->isTypeUnit())
14711490
continue;
1491+
updateLineTable(*CU.get());
14721492
emitUnit(DIEBlder, Streamer, *CU.get());
14731493
uint32_t StartOffset = CUOffset;
14741494
DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get());
@@ -1478,8 +1498,10 @@ CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
14781498
}
14791499

14801500
// Emit Type Unit of DWARF 4 to .debug_type section
1481-
for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector())
1501+
for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {
1502+
updateLineTable(*TU);
14821503
emitUnit(DIEBlder, *TypeStreamer, *TU);
1504+
}
14831505

14841506
TypeStreamer->finish();
14851507

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# clang++ -g2 -fdebug-types-section -gdwarf-4 -ffunction-sections
2+
# int foo(int i) {
3+
# if (i == 1)
4+
# return 2;
5+
# return 1;
6+
# }
7+
# int main(int argc, char* argv[]) {
8+
# int j = argc;
9+
# if (j ==3)
10+
# j+= foo(argc);
11+
# return j;
12+
# }
13+
.text
14+
.file "helper.cpp"
15+
.file 1 "/test" "helper.cpp"
16+
.section .debug_types,"G",@progbits,7448148824980338162,comdat
17+
.Ltu_begin0:
18+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
19+
.Ldebug_info_start0:
20+
.short 4 # DWARF version number
21+
.long .debug_abbrev # Offset Into Abbrev. Section
22+
.byte 8 # Address Size (in bytes)
23+
.quad 7448148824980338162 # Type Signature
24+
.long 30 # Type DIE Offset
25+
.byte 1 # Abbrev [1] 0x17:0x25 DW_TAG_type_unit
26+
.short 33 # DW_AT_language
27+
.long .Lline_table_start0 # DW_AT_stmt_list
28+
.byte 2 # Abbrev [2] 0x1e:0x16 DW_TAG_structure_type
29+
.byte 5 # DW_AT_calling_convention
30+
.long .Linfo_string6 # DW_AT_name
31+
.byte 4 # DW_AT_byte_size
32+
.byte 1 # DW_AT_decl_file
33+
.byte 1 # DW_AT_decl_line
34+
.byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member
35+
.long .Linfo_string4 # DW_AT_name
36+
.long 52 # DW_AT_type
37+
.byte 1 # DW_AT_decl_file
38+
.byte 2 # DW_AT_decl_line
39+
.byte 0 # DW_AT_data_member_location
40+
.byte 0 # End Of Children Mark
41+
.byte 4 # Abbrev [4] 0x34:0x7 DW_TAG_base_type
42+
.long .Linfo_string5 # DW_AT_name
43+
.byte 5 # DW_AT_encoding
44+
.byte 4 # DW_AT_byte_size
45+
.byte 0 # End Of Children Mark
46+
.Ldebug_info_end0:
47+
.type f2,@object # @f2
48+
.bss
49+
.globl f2
50+
.p2align 2, 0x0
51+
f2:
52+
.zero 4
53+
.size f2, 4
54+
55+
.section .debug_abbrev,"",@progbits
56+
.byte 1 # Abbreviation Code
57+
.byte 65 # DW_TAG_type_unit
58+
.byte 1 # DW_CHILDREN_yes
59+
.byte 19 # DW_AT_language
60+
.byte 5 # DW_FORM_data2
61+
.byte 16 # DW_AT_stmt_list
62+
.byte 23 # DW_FORM_sec_offset
63+
.byte 0 # EOM(1)
64+
.byte 0 # EOM(2)
65+
.byte 2 # Abbreviation Code
66+
.byte 19 # DW_TAG_structure_type
67+
.byte 1 # DW_CHILDREN_yes
68+
.byte 54 # DW_AT_calling_convention
69+
.byte 11 # DW_FORM_data1
70+
.byte 3 # DW_AT_name
71+
.byte 14 # DW_FORM_strp
72+
.byte 11 # DW_AT_byte_size
73+
.byte 11 # DW_FORM_data1
74+
.byte 58 # DW_AT_decl_file
75+
.byte 11 # DW_FORM_data1
76+
.byte 59 # DW_AT_decl_line
77+
.byte 11 # DW_FORM_data1
78+
.byte 0 # EOM(1)
79+
.byte 0 # EOM(2)
80+
.byte 3 # Abbreviation Code
81+
.byte 13 # DW_TAG_member
82+
.byte 0 # DW_CHILDREN_no
83+
.byte 3 # DW_AT_name
84+
.byte 14 # DW_FORM_strp
85+
.byte 73 # DW_AT_type
86+
.byte 19 # DW_FORM_ref4
87+
.byte 58 # DW_AT_decl_file
88+
.byte 11 # DW_FORM_data1
89+
.byte 59 # DW_AT_decl_line
90+
.byte 11 # DW_FORM_data1
91+
.byte 56 # DW_AT_data_member_location
92+
.byte 11 # DW_FORM_data1
93+
.byte 0 # EOM(1)
94+
.byte 0 # EOM(2)
95+
.byte 4 # Abbreviation Code
96+
.byte 36 # DW_TAG_base_type
97+
.byte 0 # DW_CHILDREN_no
98+
.byte 3 # DW_AT_name
99+
.byte 14 # DW_FORM_strp
100+
.byte 62 # DW_AT_encoding
101+
.byte 11 # DW_FORM_data1
102+
.byte 11 # DW_AT_byte_size
103+
.byte 11 # DW_FORM_data1
104+
.byte 0 # EOM(1)
105+
.byte 0 # EOM(2)
106+
.byte 5 # Abbreviation Code
107+
.byte 17 # DW_TAG_compile_unit
108+
.byte 1 # DW_CHILDREN_yes
109+
.byte 37 # DW_AT_producer
110+
.byte 14 # DW_FORM_strp
111+
.byte 19 # DW_AT_language
112+
.byte 5 # DW_FORM_data2
113+
.byte 3 # DW_AT_name
114+
.byte 14 # DW_FORM_strp
115+
.byte 16 # DW_AT_stmt_list
116+
.byte 23 # DW_FORM_sec_offset
117+
.byte 27 # DW_AT_comp_dir
118+
.byte 14 # DW_FORM_strp
119+
.byte 0 # EOM(1)
120+
.byte 0 # EOM(2)
121+
.byte 6 # Abbreviation Code
122+
.byte 52 # DW_TAG_variable
123+
.byte 0 # DW_CHILDREN_no
124+
.byte 3 # DW_AT_name
125+
.byte 14 # DW_FORM_strp
126+
.byte 73 # DW_AT_type
127+
.byte 19 # DW_FORM_ref4
128+
.byte 63 # DW_AT_external
129+
.byte 25 # DW_FORM_flag_present
130+
.byte 58 # DW_AT_decl_file
131+
.byte 11 # DW_FORM_data1
132+
.byte 59 # DW_AT_decl_line
133+
.byte 11 # DW_FORM_data1
134+
.byte 2 # DW_AT_location
135+
.byte 24 # DW_FORM_exprloc
136+
.byte 0 # EOM(1)
137+
.byte 0 # EOM(2)
138+
.byte 7 # Abbreviation Code
139+
.byte 19 # DW_TAG_structure_type
140+
.byte 0 # DW_CHILDREN_no
141+
.byte 60 # DW_AT_declaration
142+
.byte 25 # DW_FORM_flag_present
143+
.byte 105 # DW_AT_signature
144+
.byte 32 # DW_FORM_ref_sig8
145+
.byte 0 # EOM(1)
146+
.byte 0 # EOM(2)
147+
.byte 0 # EOM(3)
148+
.section .debug_info,"",@progbits
149+
.Lcu_begin0:
150+
.long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
151+
.Ldebug_info_start1:
152+
.short 4 # DWARF version number
153+
.long .debug_abbrev # Offset Into Abbrev. Section
154+
.byte 8 # Address Size (in bytes)
155+
.byte 5 # Abbrev [5] 0xb:0x32 DW_TAG_compile_unit
156+
.long .Linfo_string0 # DW_AT_producer
157+
.short 33 # DW_AT_language
158+
.long .Linfo_string1 # DW_AT_name
159+
.long .Lline_table_start0 # DW_AT_stmt_list
160+
.long .Linfo_string2 # DW_AT_comp_dir
161+
.byte 6 # Abbrev [6] 0x1e:0x15 DW_TAG_variable
162+
.long .Linfo_string3 # DW_AT_name
163+
.long 51 # DW_AT_type
164+
# DW_AT_external
165+
.byte 1 # DW_AT_decl_file
166+
.byte 4 # DW_AT_decl_line
167+
.byte 9 # DW_AT_location
168+
.byte 3
169+
.quad f2
170+
.byte 7 # Abbrev [7] 0x33:0x9 DW_TAG_structure_type
171+
# DW_AT_declaration
172+
.quad 7448148824980338162 # DW_AT_signature
173+
.byte 0 # End Of Children Mark
174+
.Ldebug_info_end1:
175+
.section .debug_str,"MS",@progbits,1
176+
.Linfo_string0:
177+
.asciz "clang version 18.0.0git" # string offset=0
178+
.Linfo_string1:
179+
.asciz "helper.cpp" # string offset=24
180+
.Linfo_string2:
181+
.asciz "/test" # string offset=35
182+
.Linfo_string3:
183+
.asciz "f2" # string offset=73
184+
.Linfo_string4:
185+
.asciz "i" # string offset=76
186+
.Linfo_string5:
187+
.asciz "int" # string offset=78
188+
.Linfo_string6:
189+
.asciz "Foo" # string offset=82
190+
.ident "clang version 18.0.0git"
191+
.section ".note.GNU-stack","",@progbits
192+
.addrsig
193+
.section .debug_line,"",@progbits
194+
.Lline_table_start0:

0 commit comments

Comments
 (0)