Skip to content

Commit e93df78

Browse files
authored
[llvm/DWARF] Recursively resolve DW_AT_signature references (#97423)
findRecursively follows DW_AT_specification and DW_AT_abstract_origin references, but not DW_AT_signature. As far as I can tell, there is no fundamental difference between these attributes that would make this behavior desirable, and this just seems like a consequence of the fact that this attribute is newer. This patch aims to change that. The motivation is some code in lldb, which assumes that it can construct a qualified name of a type by just walking the parent chain and looking at the name attribute. This works for "regular" debug info, even when some of the DIEs are just forward declarations, but it breaks in the presence of type units, because of the need to explicitly resolve the signature reference. While LLDB does not use the llvm's DWARFDie class (yet?), this seems like a very important change in the overall API, and any divergence here would complicate eventual reunification, which is why I am making the change in the llvm API first. However, putting lldb aside, I think this change is beneficial in llvm on its own, as it allows us to remove the explicit DW_AT_signature resolution in the DWARFTypePrinter.
1 parent a19e5ae commit e93df78

File tree

4 files changed

+54
-55
lines changed

4 files changed

+54
-55
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ class DWARFDie {
181181
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
182182
DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const;
183183

184-
DWARFDie resolveTypeUnitReference() const;
185-
186184
/// Extract the range base attribute from this DIE as absolute section offset.
187185
///
188186
/// This is a utility function that checks for either the DW_AT_rnglists_base

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,6 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
103103
.print(OS, DumpOpts, U);
104104
}
105105

106-
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
107-
return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
108-
}
109-
110106
static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
111107
const DWARFAttribute &AttrValue, unsigned Indent,
112108
DIDumpOptions DumpOpts) {
@@ -198,8 +194,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
198194
DINameKind::LinkageName))
199195
OS << Space << "\"" << Name << '\"';
200196
} else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) {
201-
DWARFDie D = resolveReferencedType(Die, FormValue);
202-
if (D && !D.isNULL()) {
197+
if (DWARFDie D = Die.getAttributeValueAsReferencedDie(FormValue);
198+
D && !D.isNULL()) {
203199
OS << Space << "\"";
204200
dumpTypeQualifiedName(D, OS);
205201
OS << '"';
@@ -291,13 +287,12 @@ DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
291287
if (auto Value = Die.find(Attrs))
292288
return Value;
293289

294-
if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
295-
if (Seen.insert(D).second)
296-
Worklist.push_back(D);
297-
298-
if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))
299-
if (Seen.insert(D).second)
300-
Worklist.push_back(D);
290+
for (dwarf::Attribute Attr :
291+
{DW_AT_abstract_origin, DW_AT_specification, DW_AT_signature}) {
292+
if (auto D = Die.getAttributeValueAsReferencedDie(Attr))
293+
if (Seen.insert(D).second)
294+
Worklist.push_back(D);
295+
}
301296
}
302297

303298
return std::nullopt;
@@ -319,21 +314,14 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
319314
} else if (Offset = V.getAsDebugInfoReference(); Offset) {
320315
if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))
321316
Result = SpecUnit->getDIEForOffset(*Offset);
317+
} else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {
318+
if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
319+
U->getVersion(), *Sig, U->isDWOUnit()))
320+
Result = TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
322321
}
323322
return Result;
324323
}
325324

326-
DWARFDie DWARFDie::resolveTypeUnitReference() const {
327-
if (auto Attr = find(DW_AT_signature)) {
328-
if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
329-
if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
330-
U->getVersion(), *Sig, U->isDWOUnit()))
331-
return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
332-
}
333-
}
334-
return *this;
335-
}
336-
337325
std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
338326
return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
339327
}

llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,10 @@ void DWARFTypePrinter::appendArrayType(const DWARFDie &D) {
6262
EndedWithTemplate = false;
6363
}
6464

65-
static DWARFDie resolveReferencedType(DWARFDie D,
66-
dwarf::Attribute Attr = DW_AT_type) {
67-
return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
68-
}
69-
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
70-
return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
71-
}
7265
DWARFDie DWARFTypePrinter::skipQualifiers(DWARFDie D) {
7366
while (D && (D.getTag() == DW_TAG_const_type ||
7467
D.getTag() == DW_TAG_volatile_type))
75-
D = resolveReferencedType(D);
68+
D = D.getAttributeValueAsReferencedDie(DW_AT_type);
7669
return D;
7770
}
7871

@@ -103,7 +96,9 @@ DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D,
10396
return DWARFDie();
10497
}
10598
DWARFDie InnerDIE;
106-
auto Inner = [&] { return InnerDIE = resolveReferencedType(D); };
99+
auto Inner = [&] {
100+
return InnerDIE = D.getAttributeValueAsReferencedDie(DW_AT_type);
101+
};
107102
const dwarf::Tag T = D.getTag();
108103
switch (T) {
109104
case DW_TAG_pointer_type: {
@@ -134,7 +129,8 @@ DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D,
134129
OS << '(';
135130
else if (Word)
136131
OS << ' ';
137-
if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
132+
if (DWARFDie Cont =
133+
D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) {
138134
appendQualifiedName(Cont);
139135
EndedWithTemplate = false;
140136
OS << "::";
@@ -173,7 +169,8 @@ DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D,
173169
case DW_TAG_base_type:
174170
*/
175171
default: {
176-
const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr);
172+
const char *NamePtr =
173+
dwarf::toString(D.findRecursively(DW_AT_name), nullptr);
177174
if (!NamePtr) {
178175
appendTypeTagName(D.getTag());
179176
return DWARFDie();
@@ -235,9 +232,9 @@ void DWARFTypePrinter::appendUnqualifiedNameAfter(
235232
case DW_TAG_pointer_type: {
236233
if (needsParens(Inner))
237234
OS << ')';
238-
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner),
239-
/*SkipFirstParamIfArtificial=*/D.getTag() ==
240-
DW_TAG_ptr_to_member_type);
235+
appendUnqualifiedNameAfter(
236+
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type),
237+
/*SkipFirstParamIfArtificial=*/D.getTag() == DW_TAG_ptr_to_member_type);
241238
break;
242239
}
243240
case DW_TAG_LLVM_ptrauth_type: {
@@ -341,7 +338,7 @@ bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D,
341338
appendTemplateParameters(C, FirstParameter);
342339
}
343340
if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
344-
DWARFDie T = resolveReferencedType(C);
341+
DWARFDie T = C.getAttributeValueAsReferencedDie(DW_AT_type);
345342
Sep();
346343
if (T.getTag() == DW_TAG_enumeration_type) {
347344
OS << '(';
@@ -461,7 +458,7 @@ bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D,
461458
continue;
462459
auto TypeAttr = C.find(DW_AT_type);
463460
Sep();
464-
appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr)
461+
appendQualifiedName(TypeAttr ? C.getAttributeValueAsReferencedDie(*TypeAttr)
465462
: DWARFDie());
466463
}
467464
if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
@@ -473,15 +470,15 @@ bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D,
473470
void DWARFTypePrinter::decomposeConstVolatile(DWARFDie &N, DWARFDie &T,
474471
DWARFDie &C, DWARFDie &V) {
475472
(N.getTag() == DW_TAG_const_type ? C : V) = N;
476-
T = resolveReferencedType(N);
473+
T = N.getAttributeValueAsReferencedDie(DW_AT_type);
477474
if (T) {
478475
auto Tag = T.getTag();
479476
if (Tag == DW_TAG_const_type) {
480477
C = T;
481-
T = resolveReferencedType(T);
478+
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
482479
} else if (Tag == DW_TAG_volatile_type) {
483480
V = T;
484-
T = resolveReferencedType(T);
481+
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
485482
}
486483
}
487484
}
@@ -491,10 +488,11 @@ void DWARFTypePrinter::appendConstVolatileQualifierAfter(DWARFDie N) {
491488
DWARFDie T;
492489
decomposeConstVolatile(N, T, C, V);
493490
if (T && T.getTag() == DW_TAG_subroutine_type)
494-
appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(),
495-
V.isValid());
491+
appendSubroutineNameAfter(T, T.getAttributeValueAsReferencedDie(DW_AT_type),
492+
false, C.isValid(), V.isValid());
496493
else
497-
appendUnqualifiedNameAfter(T, resolveReferencedType(T));
494+
appendUnqualifiedNameAfter(T,
495+
T.getAttributeValueAsReferencedDie(DW_AT_type));
498496
}
499497
void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) {
500498
DWARFDie C;
@@ -504,7 +502,7 @@ void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) {
504502
bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
505503
DWARFDie A = T;
506504
while (A && A.getTag() == DW_TAG_array_type)
507-
A = resolveReferencedType(A);
505+
A = A.getAttributeValueAsReferencedDie(DW_AT_type);
508506
bool Leading =
509507
(!A || (A.getTag() != DW_TAG_pointer_type &&
510508
A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
@@ -546,7 +544,7 @@ void DWARFTypePrinter::appendSubroutineNameAfter(
546544
if (P.getTag() != DW_TAG_formal_parameter &&
547545
P.getTag() != DW_TAG_unspecified_parameters)
548546
return;
549-
DWARFDie T = resolveReferencedType(P);
547+
DWARFDie T = P.getAttributeValueAsReferencedDie(DW_AT_type);
550548
if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
551549
FirstParamIfArtificial = T;
552550
RealFirst = false;
@@ -567,7 +565,7 @@ void DWARFTypePrinter::appendSubroutineNameAfter(
567565
if (DWARFDie P = FirstParamIfArtificial) {
568566
if (P.getTag() == DW_TAG_pointer_type) {
569567
auto CVStep = [&](DWARFDie CV) {
570-
if (DWARFDie U = resolveReferencedType(CV)) {
568+
if (DWARFDie U = CV.getAttributeValueAsReferencedDie(DW_AT_type)) {
571569
Const |= U.getTag() == DW_TAG_const_type;
572570
Volatile |= U.getTag() == DW_TAG_volatile_type;
573571
return U;
@@ -653,7 +651,8 @@ void DWARFTypePrinter::appendSubroutineNameAfter(
653651
if (D.find(DW_AT_rvalue_reference))
654652
OS << " &&";
655653

656-
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner));
654+
appendUnqualifiedNameAfter(
655+
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type));
657656
}
658657
void DWARFTypePrinter::appendScopes(DWARFDie D) {
659658
if (D.getTag() == DW_TAG_compile_unit)
@@ -666,7 +665,6 @@ void DWARFTypePrinter::appendScopes(DWARFDie D) {
666665
return;
667666
if (D.getTag() == DW_TAG_lexical_block)
668667
return;
669-
D = D.resolveTypeUnitReference();
670668
if (DWARFDie P = D.getParent())
671669
appendScopes(P);
672670
appendUnqualifiedName(D);

llvm/test/tools/llvm-dwarfdump/X86/prettyprint_type_units.s

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
# doesn't really need templates - two local variables would've sufficed
1919
# (anything that references the type units) but I was working on something else
2020
# and this seemed minimal enough.
21+
# A gcc-style type signature reference was also inserted.
2122

2223

2324
# CHECK: DW_TAG_template_type_parameter
2425
# CHECK: DW_AT_type ({{.*}} "t1")
2526
# CHECK: DW_TAG_template_type_parameter
2627
# CHECK: DW_AT_type ({{.*}} "t2")
28+
# CHECK: DW_TAG_template_type_parameter
29+
# CHECK: DW_AT_type (0xc6694e51369161f2 "t1")
2730

2831
.text
2932
.file "test.cpp"
@@ -270,6 +273,13 @@ _Z2f1IJ2t12t2EEvv: # @_Z2f1IJ2t12t2EEvv
270273
.byte 11 # DW_FORM_data1
271274
.byte 0 # EOM(1)
272275
.byte 0 # EOM(2)
276+
.byte 12 # Abbreviation Code
277+
.byte 47 # DW_TAG_template_type_parameter
278+
.byte 0 # DW_CHILDREN_no
279+
.byte 73 # DW_AT_type
280+
.byte 32 # DW_FORM_ref_sig8
281+
.byte 0 # EOM(1)
282+
.byte 0 # EOM(2)
273283
.byte 0 # EOM(3)
274284
.section .debug_info,"",@progbits
275285
.Lcu_begin0:
@@ -313,18 +323,23 @@ _Z2f1IJ2t12t2EEvv: # @_Z2f1IJ2t12t2EEvv
313323
.byte 6 # Abbrev [6] 0x46:0xd DW_TAG_GNU_template_parameter_pack
314324
.byte 5 # DW_AT_name
315325
.byte 7 # Abbrev [7] 0x48:0x5 DW_TAG_template_type_parameter
316-
.long 88 # DW_AT_type
326+
.long .Lt1_decl-.Lcu_begin0 # DW_AT_type
317327
.byte 7 # Abbrev [7] 0x4d:0x5 DW_TAG_template_type_parameter
318-
.long 97 # DW_AT_type
328+
# Simulate DWARF emitted by GCC where the signature is directly in the type attribute.
329+
.long .Lt2_decl-.Lcu_begin0 # DW_AT_type
330+
.byte 12 # Abbrev [12] DW_TAG_template_type_parameter
331+
.quad -4149699470930386446 # DW_AT_type
319332
.byte 0 # End Of Children Mark
320333
.byte 0 # End Of Children Mark
321334
.byte 8 # Abbrev [8] 0x54:0x4 DW_TAG_base_type
322335
.byte 4 # DW_AT_name
323336
.byte 5 # DW_AT_encoding
324337
.byte 4 # DW_AT_byte_size
338+
.Lt1_decl:
325339
.byte 9 # Abbrev [9] 0x58:0x9 DW_TAG_structure_type
326340
# DW_AT_declaration
327341
.quad -4149699470930386446 # DW_AT_signature
342+
.Lt2_decl:
328343
.byte 9 # Abbrev [9] 0x61:0x9 DW_TAG_structure_type
329344
# DW_AT_declaration
330345
.quad 5649318945901130368 # DW_AT_signature

0 commit comments

Comments
 (0)