1 //===- DWARFDie.cpp -------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
10 #include "llvm/ADT/SmallPtrSet.h"
11 #include "llvm/ADT/SmallSet.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
15 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
17 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
18 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
20 #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
21 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
22 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/DataExtractor.h"
25 #include "llvm/Support/Format.h"
26 #include "llvm/Support/FormatVariadic.h"
27 #include "llvm/Support/WithColor.h"
28 #include "llvm/Support/raw_ostream.h"
36 using namespace dwarf
;
37 using namespace object
;
39 static void dumpApplePropertyAttribute(raw_ostream
&OS
, uint64_t Val
) {
42 uint64_t Shift
= llvm::countr_zero(Val
);
43 assert(Shift
< 64 && "undefined behavior");
44 uint64_t Bit
= 1ULL << Shift
;
45 auto PropName
= ApplePropertyString(Bit
);
46 if (!PropName
.empty())
49 OS
<< format("DW_APPLE_PROPERTY_0x%" PRIx64
, Bit
);
57 static void dumpRanges(const DWARFObject
&Obj
, raw_ostream
&OS
,
58 const DWARFAddressRangesVector
&Ranges
,
59 unsigned AddressSize
, unsigned Indent
,
60 const DIDumpOptions
&DumpOpts
) {
61 if (!DumpOpts
.ShowAddresses
)
64 for (const DWARFAddressRange
&R
: Ranges
) {
67 R
.dump(OS
, AddressSize
, DumpOpts
, &Obj
);
71 static void dumpLocationList(raw_ostream
&OS
, const DWARFFormValue
&FormValue
,
72 DWARFUnit
*U
, unsigned Indent
,
73 DIDumpOptions DumpOpts
) {
74 assert(FormValue
.isFormClass(DWARFFormValue::FC_SectionOffset
) &&
75 "bad FORM for location list");
76 DWARFContext
&Ctx
= U
->getContext();
77 uint64_t Offset
= *FormValue
.getAsSectionOffset();
79 if (FormValue
.getForm() == DW_FORM_loclistx
) {
80 FormValue
.dump(OS
, DumpOpts
);
82 if (auto LoclistOffset
= U
->getLoclistOffset(Offset
))
83 Offset
= *LoclistOffset
;
87 U
->getLocationTable().dumpLocationList(
88 &Offset
, OS
, U
->getBaseAddress(), Ctx
.getDWARFObj(), U
, DumpOpts
, Indent
);
91 static void dumpLocationExpr(raw_ostream
&OS
, const DWARFFormValue
&FormValue
,
92 DWARFUnit
*U
, unsigned Indent
,
93 DIDumpOptions DumpOpts
) {
94 assert((FormValue
.isFormClass(DWARFFormValue::FC_Block
) ||
95 FormValue
.isFormClass(DWARFFormValue::FC_Exprloc
)) &&
96 "bad FORM for location expression");
97 DWARFContext
&Ctx
= U
->getContext();
98 ArrayRef
<uint8_t> Expr
= *FormValue
.getAsBlock();
99 DataExtractor
Data(StringRef((const char *)Expr
.data(), Expr
.size()),
100 Ctx
.isLittleEndian(), 0);
101 DWARFExpression(Data
, U
->getAddressByteSize(), U
->getFormParams().Format
)
102 .print(OS
, DumpOpts
, U
);
105 static DWARFDie
resolveReferencedType(DWARFDie D
, DWARFFormValue F
) {
106 return D
.getAttributeValueAsReferencedDie(F
).resolveTypeUnitReference();
109 static void dumpAttribute(raw_ostream
&OS
, const DWARFDie
&Die
,
110 const DWARFAttribute
&AttrValue
, unsigned Indent
,
111 DIDumpOptions DumpOpts
) {
114 const char BaseIndent
[] = " ";
116 OS
.indent(Indent
+ 2);
117 dwarf::Attribute Attr
= AttrValue
.Attr
;
118 WithColor(OS
, HighlightColor::Attribute
) << formatv("{0}", Attr
);
120 dwarf::Form Form
= AttrValue
.Value
.getForm();
121 if (DumpOpts
.Verbose
|| DumpOpts
.ShowForm
)
122 OS
<< formatv(" [{0}]", Form
);
124 DWARFUnit
*U
= Die
.getDwarfUnit();
125 const DWARFFormValue
&FormValue
= AttrValue
.Value
;
131 auto Color
= HighlightColor::Enumerator
;
132 if (Attr
== DW_AT_decl_file
|| Attr
== DW_AT_call_file
) {
133 Color
= HighlightColor::String
;
134 if (const auto *LT
= U
->getContext().getLineTableForUnit(U
)) {
135 if (std::optional
<uint64_t> Val
= FormValue
.getAsUnsignedConstant()) {
136 if (LT
->getFileNameByIndex(
137 *Val
, U
->getCompilationDir(),
138 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
,
140 File
= '"' + File
+ '"';
145 } else if (std::optional
<uint64_t> Val
= FormValue
.getAsUnsignedConstant())
146 Name
= AttributeValueString(Attr
, *Val
);
149 WithColor(OS
, Color
) << Name
;
150 else if (Attr
== DW_AT_decl_line
|| Attr
== DW_AT_decl_column
||
151 Attr
== DW_AT_call_line
|| Attr
== DW_AT_call_column
) {
152 if (std::optional
<uint64_t> Val
= FormValue
.getAsUnsignedConstant())
155 FormValue
.dump(OS
, DumpOpts
);
156 } else if (Attr
== DW_AT_low_pc
&&
157 (FormValue
.getAsAddress() ==
158 dwarf::computeTombstoneAddress(U
->getAddressByteSize()))) {
159 if (DumpOpts
.Verbose
) {
160 FormValue
.dump(OS
, DumpOpts
);
164 if (DumpOpts
.Verbose
)
166 } else if (Attr
== DW_AT_high_pc
&& !DumpOpts
.ShowForm
&& !DumpOpts
.Verbose
&&
167 FormValue
.getAsUnsignedConstant()) {
168 if (DumpOpts
.ShowAddresses
) {
169 // Print the actual address rather than the offset.
170 uint64_t LowPC
, HighPC
, Index
;
171 if (Die
.getLowAndHighPC(LowPC
, HighPC
, Index
))
172 DWARFFormValue::dumpAddress(OS
, U
->getAddressByteSize(), HighPC
);
174 FormValue
.dump(OS
, DumpOpts
);
176 } else if (DWARFAttribute::mayHaveLocationList(Attr
) &&
177 FormValue
.isFormClass(DWARFFormValue::FC_SectionOffset
))
178 dumpLocationList(OS
, FormValue
, U
, sizeof(BaseIndent
) + Indent
+ 4,
180 else if (FormValue
.isFormClass(DWARFFormValue::FC_Exprloc
) ||
181 (DWARFAttribute::mayHaveLocationExpr(Attr
) &&
182 FormValue
.isFormClass(DWARFFormValue::FC_Block
)))
183 dumpLocationExpr(OS
, FormValue
, U
, sizeof(BaseIndent
) + Indent
+ 4,
186 FormValue
.dump(OS
, DumpOpts
);
188 std::string Space
= DumpOpts
.ShowAddresses
? " " : "";
190 // We have dumped the attribute raw value. For some attributes
191 // having both the raw value and the pretty-printed value is
192 // interesting. These attributes are handled below.
193 if (Attr
== DW_AT_specification
|| Attr
== DW_AT_abstract_origin
||
194 Attr
== DW_AT_call_origin
) {
195 if (const char *Name
=
196 Die
.getAttributeValueAsReferencedDie(FormValue
).getName(
197 DINameKind::LinkageName
))
198 OS
<< Space
<< "\"" << Name
<< '\"';
199 } else if (Attr
== DW_AT_type
|| Attr
== DW_AT_containing_type
) {
200 DWARFDie D
= resolveReferencedType(Die
, FormValue
);
201 if (D
&& !D
.isNULL()) {
203 dumpTypeQualifiedName(D
, OS
);
206 } else if (Attr
== DW_AT_APPLE_property_attribute
) {
207 if (std::optional
<uint64_t> OptVal
= FormValue
.getAsUnsignedConstant())
208 dumpApplePropertyAttribute(OS
, *OptVal
);
209 } else if (Attr
== DW_AT_ranges
) {
210 const DWARFObject
&Obj
= Die
.getDwarfUnit()->getContext().getDWARFObj();
211 // For DW_FORM_rnglistx we need to dump the offset separately, since
212 // we have only dumped the index so far.
213 if (FormValue
.getForm() == DW_FORM_rnglistx
)
214 if (auto RangeListOffset
=
215 U
->getRnglistOffset(*FormValue
.getAsSectionOffset())) {
216 DWARFFormValue FV
= DWARFFormValue::createFromUValue(
217 dwarf::DW_FORM_sec_offset
, *RangeListOffset
);
218 FV
.dump(OS
, DumpOpts
);
220 if (auto RangesOrError
= Die
.getAddressRanges())
221 dumpRanges(Obj
, OS
, RangesOrError
.get(), U
->getAddressByteSize(),
222 sizeof(BaseIndent
) + Indent
+ 4, DumpOpts
);
224 DumpOpts
.RecoverableErrorHandler(createStringError(
225 errc::invalid_argument
, "decoding address ranges: %s",
226 toString(RangesOrError
.takeError()).c_str()));
232 void DWARFDie::getFullName(raw_string_ostream
&OS
,
233 std::string
*OriginalFullName
) const {
234 const char *NamePtr
= getShortName();
237 if (getTag() == DW_TAG_GNU_template_parameter_pack
)
239 dumpTypeUnqualifiedName(*this, OS
, OriginalFullName
);
242 bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram
; }
244 bool DWARFDie::isSubroutineDIE() const {
246 return Tag
== DW_TAG_subprogram
|| Tag
== DW_TAG_inlined_subroutine
;
249 std::optional
<DWARFFormValue
> DWARFDie::find(dwarf::Attribute Attr
) const {
252 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
254 return AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
);
258 std::optional
<DWARFFormValue
>
259 DWARFDie::find(ArrayRef
<dwarf::Attribute
> Attrs
) const {
262 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
264 for (auto Attr
: Attrs
) {
265 if (auto Value
= AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
))
272 std::optional
<DWARFFormValue
>
273 DWARFDie::findRecursively(ArrayRef
<dwarf::Attribute
> Attrs
) const {
274 SmallVector
<DWARFDie
, 3> Worklist
;
275 Worklist
.push_back(*this);
277 // Keep track if DIEs already seen to prevent infinite recursion.
278 // Empirically we rarely see a depth of more than 3 when dealing with valid
279 // DWARF. This corresponds to following the DW_AT_abstract_origin and
280 // DW_AT_specification just once.
281 SmallSet
<DWARFDie
, 3> Seen
;
284 while (!Worklist
.empty()) {
285 DWARFDie Die
= Worklist
.pop_back_val();
290 if (auto Value
= Die
.find(Attrs
))
293 for (dwarf::Attribute Attr
:
294 {DW_AT_abstract_origin
, DW_AT_specification
, DW_AT_signature
}) {
295 if (auto D
= Die
.getAttributeValueAsReferencedDie(Attr
))
296 if (Seen
.insert(D
).second
)
297 Worklist
.push_back(D
);
305 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr
) const {
306 if (std::optional
<DWARFFormValue
> F
= find(Attr
))
307 return getAttributeValueAsReferencedDie(*F
);
312 DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue
&V
) const {
314 if (std::optional
<uint64_t> Offset
= V
.getAsRelativeReference()) {
315 Result
= const_cast<DWARFUnit
*>(V
.getUnit())
316 ->getDIEForOffset(V
.getUnit()->getOffset() + *Offset
);
317 } else if (Offset
= V
.getAsDebugInfoReference(); Offset
) {
318 if (DWARFUnit
*SpecUnit
= U
->getUnitVector().getUnitForOffset(*Offset
))
319 Result
= SpecUnit
->getDIEForOffset(*Offset
);
320 } else if (std::optional
<uint64_t> Sig
= V
.getAsSignatureReference()) {
321 if (DWARFTypeUnit
*TU
=
322 U
->getContext().getTypeUnitForHash(*Sig
, U
->isDWOUnit()))
323 Result
= TU
->getDIEForOffset(TU
->getTypeOffset() + TU
->getOffset());
328 DWARFDie
DWARFDie::resolveTypeUnitReference() const {
329 if (auto Attr
= find(DW_AT_signature
)) {
330 if (std::optional
<uint64_t> Sig
= Attr
->getAsReferenceUVal()) {
331 if (DWARFTypeUnit
*TU
=
332 U
->getContext().getTypeUnitForHash(*Sig
, U
->isDWOUnit()))
333 return TU
->getDIEForOffset(TU
->getTypeOffset() + TU
->getOffset());
339 DWARFDie
DWARFDie::resolveReferencedType(dwarf::Attribute Attr
) const {
340 return getAttributeValueAsReferencedDie(Attr
).resolveTypeUnitReference();
342 DWARFDie
DWARFDie::resolveReferencedType(const DWARFFormValue
&V
) const {
343 return getAttributeValueAsReferencedDie(V
).resolveTypeUnitReference();
346 std::optional
<uint64_t> DWARFDie::getRangesBaseAttribute() const {
347 return toSectionOffset(find({DW_AT_rnglists_base
, DW_AT_GNU_ranges_base
}));
350 std::optional
<uint64_t> DWARFDie::getLocBaseAttribute() const {
351 return toSectionOffset(find(DW_AT_loclists_base
));
354 std::optional
<uint64_t> DWARFDie::getHighPC(uint64_t LowPC
) const {
355 uint64_t Tombstone
= dwarf::computeTombstoneAddress(U
->getAddressByteSize());
356 if (LowPC
== Tombstone
)
358 if (auto FormValue
= find(DW_AT_high_pc
)) {
359 if (auto Address
= FormValue
->getAsAddress()) {
360 // High PC is an address.
363 if (auto Offset
= FormValue
->getAsUnsignedConstant()) {
364 // High PC is an offset from LowPC.
365 return LowPC
+ *Offset
;
371 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC
, uint64_t &HighPC
,
372 uint64_t &SectionIndex
) const {
373 auto F
= find(DW_AT_low_pc
);
374 auto LowPcAddr
= toSectionedAddress(F
);
377 if (auto HighPcAddr
= getHighPC(LowPcAddr
->Address
)) {
378 LowPC
= LowPcAddr
->Address
;
379 HighPC
= *HighPcAddr
;
380 SectionIndex
= LowPcAddr
->SectionIndex
;
386 Expected
<DWARFAddressRangesVector
> DWARFDie::getAddressRanges() const {
388 return DWARFAddressRangesVector();
389 // Single range specified by low/high PC.
390 uint64_t LowPC
, HighPC
, Index
;
391 if (getLowAndHighPC(LowPC
, HighPC
, Index
))
392 return DWARFAddressRangesVector
{{LowPC
, HighPC
, Index
}};
394 std::optional
<DWARFFormValue
> Value
= find(DW_AT_ranges
);
396 if (Value
->getForm() == DW_FORM_rnglistx
)
397 return U
->findRnglistFromIndex(*Value
->getAsSectionOffset());
398 return U
->findRnglistFromOffset(*Value
->getAsSectionOffset());
400 return DWARFAddressRangesVector();
403 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address
) const {
404 auto RangesOrError
= getAddressRanges();
405 if (!RangesOrError
) {
406 llvm::consumeError(RangesOrError
.takeError());
410 for (const auto &R
: RangesOrError
.get())
411 if (R
.LowPC
<= Address
&& Address
< R
.HighPC
)
416 std::optional
<uint64_t> DWARFDie::getLanguage() const {
418 if (std::optional
<DWARFFormValue
> LV
=
419 U
->getUnitDIE().find(dwarf::DW_AT_language
))
420 return LV
->getAsUnsignedConstant();
425 Expected
<DWARFLocationExpressionsVector
>
426 DWARFDie::getLocations(dwarf::Attribute Attr
) const {
427 std::optional
<DWARFFormValue
> Location
= find(Attr
);
429 return createStringError(inconvertibleErrorCode(), "No %s",
430 dwarf::AttributeString(Attr
).data());
432 if (std::optional
<uint64_t> Off
= Location
->getAsSectionOffset()) {
433 uint64_t Offset
= *Off
;
435 if (Location
->getForm() == DW_FORM_loclistx
) {
436 if (auto LoclistOffset
= U
->getLoclistOffset(Offset
))
437 Offset
= *LoclistOffset
;
439 return createStringError(inconvertibleErrorCode(),
440 "Loclist table not found");
442 return U
->findLoclistFromOffset(Offset
);
445 if (std::optional
<ArrayRef
<uint8_t>> Expr
= Location
->getAsBlock()) {
446 return DWARFLocationExpressionsVector
{
447 DWARFLocationExpression
{std::nullopt
, to_vector
<4>(*Expr
)}};
450 return createStringError(
451 inconvertibleErrorCode(), "Unsupported %s encoding: %s",
452 dwarf::AttributeString(Attr
).data(),
453 dwarf::FormEncodingString(Location
->getForm()).data());
456 const char *DWARFDie::getSubroutineName(DINameKind Kind
) const {
457 if (!isSubroutineDIE())
459 return getName(Kind
);
462 const char *DWARFDie::getName(DINameKind Kind
) const {
463 if (!isValid() || Kind
== DINameKind::None
)
465 // Try to get mangled name only if it was asked for.
466 if (Kind
== DINameKind::LinkageName
) {
467 if (auto Name
= getLinkageName())
470 return getShortName();
473 const char *DWARFDie::getShortName() const {
477 return dwarf::toString(findRecursively(dwarf::DW_AT_name
), nullptr);
480 const char *DWARFDie::getLinkageName() const {
484 return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name
,
485 dwarf::DW_AT_linkage_name
}),
489 uint64_t DWARFDie::getDeclLine() const {
490 return toUnsigned(findRecursively(DW_AT_decl_line
), 0);
494 DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind
) const {
495 if (auto FormValue
= findRecursively(DW_AT_decl_file
))
496 if (auto OptString
= FormValue
->getAsFile(Kind
))
501 void DWARFDie::getCallerFrame(uint32_t &CallFile
, uint32_t &CallLine
,
502 uint32_t &CallColumn
,
503 uint32_t &CallDiscriminator
) const {
504 CallFile
= toUnsigned(find(DW_AT_call_file
), 0);
505 CallLine
= toUnsigned(find(DW_AT_call_line
), 0);
506 CallColumn
= toUnsigned(find(DW_AT_call_column
), 0);
507 CallDiscriminator
= toUnsigned(find(DW_AT_GNU_discriminator
), 0);
510 static std::optional
<uint64_t>
511 getTypeSizeImpl(DWARFDie Die
, uint64_t PointerSize
,
512 SmallPtrSetImpl
<const DWARFDebugInfoEntry
*> &Visited
) {
514 if (!Visited
.insert(Die
.getDebugInfoEntry()).second
)
516 if (auto SizeAttr
= Die
.find(DW_AT_byte_size
))
517 if (std::optional
<uint64_t> Size
= SizeAttr
->getAsUnsignedConstant())
520 switch (Die
.getTag()) {
521 case DW_TAG_pointer_type
:
522 case DW_TAG_reference_type
:
523 case DW_TAG_rvalue_reference_type
:
525 case DW_TAG_ptr_to_member_type
: {
526 if (DWARFDie BaseType
= Die
.getAttributeValueAsReferencedDie(DW_AT_type
))
527 if (BaseType
.getTag() == DW_TAG_subroutine_type
)
528 return 2 * PointerSize
;
531 case DW_TAG_const_type
:
532 case DW_TAG_immutable_type
:
533 case DW_TAG_volatile_type
:
534 case DW_TAG_restrict_type
:
535 case DW_TAG_template_alias
:
536 case DW_TAG_typedef
: {
537 if (DWARFDie BaseType
= Die
.getAttributeValueAsReferencedDie(DW_AT_type
))
538 return getTypeSizeImpl(BaseType
, PointerSize
, Visited
);
541 case DW_TAG_array_type
: {
542 DWARFDie BaseType
= Die
.getAttributeValueAsReferencedDie(DW_AT_type
);
545 std::optional
<uint64_t> BaseSize
=
546 getTypeSizeImpl(BaseType
, PointerSize
, Visited
);
549 uint64_t Size
= *BaseSize
;
550 for (DWARFDie Child
: Die
) {
551 if (Child
.getTag() != DW_TAG_subrange_type
)
554 if (auto ElemCountAttr
= Child
.find(DW_AT_count
))
555 if (std::optional
<uint64_t> ElemCount
=
556 ElemCountAttr
->getAsUnsignedConstant())
558 if (auto UpperBoundAttr
= Child
.find(DW_AT_upper_bound
))
559 if (std::optional
<int64_t> UpperBound
=
560 UpperBoundAttr
->getAsSignedConstant()) {
561 int64_t LowerBound
= 0;
562 if (auto LowerBoundAttr
= Child
.find(DW_AT_lower_bound
))
563 LowerBound
= LowerBoundAttr
->getAsSignedConstant().value_or(0);
564 Size
*= *UpperBound
- LowerBound
+ 1;
570 if (DWARFDie BaseType
= Die
.getAttributeValueAsReferencedDie(DW_AT_type
))
571 return getTypeSizeImpl(BaseType
, PointerSize
, Visited
);
577 std::optional
<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize
) {
578 SmallPtrSet
<const DWARFDebugInfoEntry
*, 4> Visited
;
579 return getTypeSizeImpl(*this, PointerSize
, Visited
);
582 /// Helper to dump a DIE with all of its parents, but no siblings.
583 static unsigned dumpParentChain(DWARFDie Die
, raw_ostream
&OS
, unsigned Indent
,
584 DIDumpOptions DumpOpts
, unsigned Depth
= 0) {
587 if (DumpOpts
.ParentRecurseDepth
> 0 && Depth
>= DumpOpts
.ParentRecurseDepth
)
589 Indent
= dumpParentChain(Die
.getParent(), OS
, Indent
, DumpOpts
, Depth
+ 1);
590 Die
.dump(OS
, Indent
, DumpOpts
);
594 void DWARFDie::dump(raw_ostream
&OS
, unsigned Indent
,
595 DIDumpOptions DumpOpts
) const {
598 DWARFDataExtractor debug_info_data
= U
->getDebugInfoExtractor();
599 const uint64_t Offset
= getOffset();
600 uint64_t offset
= Offset
;
601 if (DumpOpts
.ShowParents
) {
602 DIDumpOptions ParentDumpOpts
= DumpOpts
;
603 ParentDumpOpts
.ShowParents
= false;
604 ParentDumpOpts
.ShowChildren
= false;
605 Indent
= dumpParentChain(getParent(), OS
, Indent
, ParentDumpOpts
);
608 if (debug_info_data
.isValidOffset(offset
)) {
609 uint32_t abbrCode
= debug_info_data
.getULEB128(&offset
);
610 if (DumpOpts
.ShowAddresses
)
611 WithColor(OS
, HighlightColor::Address
).get()
612 << format("\n0x%8.8" PRIx64
": ", Offset
);
615 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
617 WithColor(OS
, HighlightColor::Tag
).get().indent(Indent
)
618 << formatv("{0}", getTag());
619 if (DumpOpts
.Verbose
) {
620 OS
<< format(" [%u] %c", abbrCode
,
621 AbbrevDecl
->hasChildren() ? '*' : ' ');
622 if (std::optional
<uint32_t> ParentIdx
= Die
->getParentIdx())
623 OS
<< format(" (0x%8.8" PRIx64
")",
624 U
->getDIEAtIndex(*ParentIdx
).getOffset());
628 // Dump all data in the DIE for the attributes.
629 for (const DWARFAttribute
&AttrValue
: attributes())
630 dumpAttribute(OS
, *this, AttrValue
, Indent
, DumpOpts
);
632 if (DumpOpts
.ShowChildren
&& DumpOpts
.ChildRecurseDepth
> 0) {
633 DWARFDie Child
= getFirstChild();
634 DumpOpts
.ChildRecurseDepth
--;
635 DIDumpOptions ChildDumpOpts
= DumpOpts
;
636 ChildDumpOpts
.ShowParents
= false;
638 Child
.dump(OS
, Indent
+ 2, ChildDumpOpts
);
639 Child
= Child
.getSibling();
643 OS
<< "Abbreviation code not found in 'debug_abbrev' class for code: "
647 OS
.indent(Indent
) << "NULL\n";
652 LLVM_DUMP_METHOD
void DWARFDie::dump() const { dump(llvm::errs(), 0); }
654 DWARFDie
DWARFDie::getParent() const {
656 return U
->getParent(Die
);
660 DWARFDie
DWARFDie::getSibling() const {
662 return U
->getSibling(Die
);
666 DWARFDie
DWARFDie::getPreviousSibling() const {
668 return U
->getPreviousSibling(Die
);
672 DWARFDie
DWARFDie::getFirstChild() const {
674 return U
->getFirstChild(Die
);
678 DWARFDie
DWARFDie::getLastChild() const {
680 return U
->getLastChild(Die
);
684 iterator_range
<DWARFDie::attribute_iterator
> DWARFDie::attributes() const {
685 return make_range(attribute_iterator(*this, false),
686 attribute_iterator(*this, true));
689 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D
, bool End
)
691 auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr();
692 assert(AbbrDecl
&& "Must have abbreviation declaration");
694 // This is the end iterator so we set the index to the attribute count.
695 Index
= AbbrDecl
->getNumAttributes();
697 // This is the begin iterator so we extract the value for this->Index.
698 AttrValue
.Offset
= D
.getOffset() + AbbrDecl
->getCodeByteSize();
699 updateForIndex(*AbbrDecl
, 0);
703 void DWARFDie::attribute_iterator::updateForIndex(
704 const DWARFAbbreviationDeclaration
&AbbrDecl
, uint32_t I
) {
706 // AbbrDecl must be valid before calling this function.
707 auto NumAttrs
= AbbrDecl
.getNumAttributes();
708 if (Index
< NumAttrs
) {
709 AttrValue
.Attr
= AbbrDecl
.getAttrByIndex(Index
);
710 // Add the previous byte size of any previous attribute value.
711 AttrValue
.Offset
+= AttrValue
.ByteSize
;
712 uint64_t ParseOffset
= AttrValue
.Offset
;
713 if (AbbrDecl
.getAttrIsImplicitConstByIndex(Index
))
714 AttrValue
.Value
= DWARFFormValue::createFromSValue(
715 AbbrDecl
.getFormByIndex(Index
),
716 AbbrDecl
.getAttrImplicitConstValueByIndex(Index
));
718 auto U
= Die
.getDwarfUnit();
719 assert(U
&& "Die must have valid DWARF unit");
720 AttrValue
.Value
= DWARFFormValue::createFromUnit(
721 AbbrDecl
.getFormByIndex(Index
), U
, &ParseOffset
);
723 AttrValue
.ByteSize
= ParseOffset
- AttrValue
.Offset
;
725 assert(Index
== NumAttrs
&& "Indexes should be [0, NumAttrs) only");
730 DWARFDie::attribute_iterator
&DWARFDie::attribute_iterator::operator++() {
731 if (auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr())
732 updateForIndex(*AbbrDecl
, Index
+ 1);
736 bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr
) {
739 case DW_AT_string_length
:
740 case DW_AT_return_addr
:
741 case DW_AT_data_member_location
:
742 case DW_AT_frame_base
:
743 case DW_AT_static_link
:
745 case DW_AT_use_location
:
746 case DW_AT_vtable_elem_location
:
753 bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr
) {
755 // From the DWARF v5 specification.
757 case DW_AT_byte_size
:
758 case DW_AT_bit_offset
:
760 case DW_AT_string_length
:
761 case DW_AT_lower_bound
:
762 case DW_AT_return_addr
:
763 case DW_AT_bit_stride
:
764 case DW_AT_upper_bound
:
766 case DW_AT_data_member_location
:
767 case DW_AT_frame_base
:
769 case DW_AT_static_link
:
770 case DW_AT_use_location
:
771 case DW_AT_vtable_elem_location
:
772 case DW_AT_allocated
:
773 case DW_AT_associated
:
774 case DW_AT_data_location
:
775 case DW_AT_byte_stride
:
777 case DW_AT_call_value
:
778 case DW_AT_call_origin
:
779 case DW_AT_call_target
:
780 case DW_AT_call_target_clobbered
:
781 case DW_AT_call_data_location
:
782 case DW_AT_call_data_value
:
784 case DW_AT_GNU_call_site_value
:
785 case DW_AT_GNU_call_site_target
:
794 void dumpTypeQualifiedName(const DWARFDie
&DIE
, raw_ostream
&OS
) {
795 DWARFTypePrinter
<DWARFDie
>(OS
).appendQualifiedName(DIE
);
798 void dumpTypeUnqualifiedName(const DWARFDie
&DIE
, raw_ostream
&OS
,
799 std::string
*OriginalFullName
) {
800 DWARFTypePrinter
<DWARFDie
>(OS
).appendUnqualifiedName(DIE
, OriginalFullName
);