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/None.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ADT/SmallSet.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
16 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
17 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
18 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
20 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/DataExtractor.h"
23 #include "llvm/Support/Format.h"
24 #include "llvm/Support/FormatAdapters.h"
25 #include "llvm/Support/FormatVariadic.h"
26 #include "llvm/Support/MathExtras.h"
27 #include "llvm/Support/WithColor.h"
28 #include "llvm/Support/raw_ostream.h"
37 using namespace dwarf
;
38 using namespace object
;
40 static void dumpApplePropertyAttribute(raw_ostream
&OS
, uint64_t Val
) {
43 uint64_t Shift
= countTrailingZeros(Val
);
44 assert(Shift
< 64 && "undefined behavior");
45 uint64_t Bit
= 1ULL << Shift
;
46 auto PropName
= ApplePropertyString(Bit
);
47 if (!PropName
.empty())
50 OS
<< format("DW_APPLE_PROPERTY_0x%" PRIx64
, Bit
);
58 static void dumpRanges(const DWARFObject
&Obj
, raw_ostream
&OS
,
59 const DWARFAddressRangesVector
&Ranges
,
60 unsigned AddressSize
, unsigned Indent
,
61 const DIDumpOptions
&DumpOpts
) {
62 if (!DumpOpts
.ShowAddresses
)
65 for (const DWARFAddressRange
&R
: Ranges
) {
68 R
.dump(OS
, AddressSize
, DumpOpts
, &Obj
);
72 static void dumpLocationList(raw_ostream
&OS
, const DWARFFormValue
&FormValue
,
73 DWARFUnit
*U
, unsigned Indent
,
74 DIDumpOptions DumpOpts
) {
75 assert(FormValue
.isFormClass(DWARFFormValue::FC_SectionOffset
) &&
76 "bad FORM for location list");
77 DWARFContext
&Ctx
= U
->getContext();
78 const MCRegisterInfo
*MRI
= Ctx
.getRegisterInfo();
79 uint64_t Offset
= *FormValue
.getAsSectionOffset();
81 if (FormValue
.getForm() == DW_FORM_loclistx
) {
82 FormValue
.dump(OS
, DumpOpts
);
84 if (auto LoclistOffset
= U
->getLoclistOffset(Offset
))
85 Offset
= *LoclistOffset
;
89 U
->getLocationTable().dumpLocationList(&Offset
, OS
, U
->getBaseAddress(), MRI
,
90 Ctx
.getDWARFObj(), U
, DumpOpts
,
95 static void dumpLocationExpr(raw_ostream
&OS
, const DWARFFormValue
&FormValue
,
96 DWARFUnit
*U
, unsigned Indent
,
97 DIDumpOptions DumpOpts
) {
98 assert((FormValue
.isFormClass(DWARFFormValue::FC_Block
) ||
99 FormValue
.isFormClass(DWARFFormValue::FC_Exprloc
)) &&
100 "bad FORM for location expression");
101 DWARFContext
&Ctx
= U
->getContext();
102 const MCRegisterInfo
*MRI
= Ctx
.getRegisterInfo();
103 ArrayRef
<uint8_t> Expr
= *FormValue
.getAsBlock();
104 DataExtractor
Data(StringRef((const char *)Expr
.data(), Expr
.size()),
105 Ctx
.isLittleEndian(), 0);
106 DWARFExpression(Data
, U
->getAddressByteSize(), U
->getFormParams().Format
)
107 .print(OS
, DumpOpts
, MRI
, U
);
111 /// Dump the name encoded in the type tag.
112 static void dumpTypeTagName(raw_ostream
&OS
, dwarf::Tag T
) {
113 StringRef TagStr
= TagString(T
);
114 if (!TagStr
.startswith("DW_TAG_") || !TagStr
.endswith("_type"))
116 OS
<< TagStr
.substr(7, TagStr
.size() - 12) << " ";
119 static void dumpArrayType(raw_ostream
&OS
, const DWARFDie
&D
) {
120 for (const DWARFDie
&C
: D
.children())
121 if (C
.getTag() == DW_TAG_subrange_type
) {
122 Optional
<uint64_t> LB
;
123 Optional
<uint64_t> Count
;
124 Optional
<uint64_t> UB
;
125 Optional
<unsigned> DefaultLB
;
126 if (Optional
<DWARFFormValue
> L
= C
.find(DW_AT_lower_bound
))
127 LB
= L
->getAsUnsignedConstant();
128 if (Optional
<DWARFFormValue
> CountV
= C
.find(DW_AT_count
))
129 Count
= CountV
->getAsUnsignedConstant();
130 if (Optional
<DWARFFormValue
> UpperV
= C
.find(DW_AT_upper_bound
))
131 UB
= UpperV
->getAsUnsignedConstant();
132 if (Optional
<DWARFFormValue
> LV
=
133 D
.getDwarfUnit()->getUnitDIE().find(DW_AT_language
))
134 if (Optional
<uint64_t> LC
= LV
->getAsUnsignedConstant())
136 LanguageLowerBound(static_cast<dwarf::SourceLanguage
>(*LC
))))
137 if (LB
&& *LB
== *DefaultLB
)
139 if (!LB
&& !Count
&& !UB
)
141 else if (!LB
&& (Count
|| UB
) && DefaultLB
)
142 OS
<< '[' << (Count
? *Count
: *UB
- *DefaultLB
+ 1) << ']';
154 OS
<< "? + " << *Count
;
164 /// Recursively dump the DIE type name when applicable.
165 static void dumpTypeName(raw_ostream
&OS
, const DWARFDie
&D
) {
169 if (const char *Name
= D
.getName(DINameKind::LinkageName
)) {
174 // FIXME: We should have pretty printers per language. Currently we print
175 // everything as if it was C++ and fall back to the TAG type name.
176 const dwarf::Tag T
= D
.getTag();
178 case DW_TAG_array_type
:
179 case DW_TAG_pointer_type
:
180 case DW_TAG_ptr_to_member_type
:
181 case DW_TAG_reference_type
:
182 case DW_TAG_rvalue_reference_type
:
183 case DW_TAG_subroutine_type
:
186 dumpTypeTagName(OS
, T
);
189 // Follow the DW_AT_type if possible.
190 DWARFDie TypeDie
= D
.getAttributeValueAsReferencedDie(DW_AT_type
);
191 dumpTypeName(OS
, TypeDie
);
194 case DW_TAG_subroutine_type
: {
199 for (const DWARFDie
&C
: D
.children()) {
200 if (C
.getTag() == DW_TAG_formal_parameter
) {
204 dumpTypeName(OS
, C
.getAttributeValueAsReferencedDie(DW_AT_type
));
210 case DW_TAG_array_type
: {
211 dumpArrayType(OS
, D
);
214 case DW_TAG_pointer_type
:
217 case DW_TAG_ptr_to_member_type
:
219 D
.getAttributeValueAsReferencedDie(DW_AT_containing_type
)) {
220 dumpTypeName(OS
<< ' ', Cont
);
225 case DW_TAG_reference_type
:
228 case DW_TAG_rvalue_reference_type
:
236 static void dumpAttribute(raw_ostream
&OS
, const DWARFDie
&Die
,
237 const DWARFAttribute
&AttrValue
, unsigned Indent
,
238 DIDumpOptions DumpOpts
) {
241 const char BaseIndent
[] = " ";
243 OS
.indent(Indent
+ 2);
244 dwarf::Attribute Attr
= AttrValue
.Attr
;
245 WithColor(OS
, HighlightColor::Attribute
) << formatv("{0}", Attr
);
247 dwarf::Form Form
= AttrValue
.Value
.getForm();
248 if (DumpOpts
.Verbose
|| DumpOpts
.ShowForm
)
249 OS
<< formatv(" [{0}]", Form
);
251 DWARFUnit
*U
= Die
.getDwarfUnit();
252 const DWARFFormValue
&FormValue
= AttrValue
.Value
;
258 auto Color
= HighlightColor::Enumerator
;
259 if (Attr
== DW_AT_decl_file
|| Attr
== DW_AT_call_file
) {
260 Color
= HighlightColor::String
;
261 if (const auto *LT
= U
->getContext().getLineTableForUnit(U
))
262 if (LT
->getFileNameByIndex(
263 FormValue
.getAsUnsignedConstant().getValue(),
264 U
->getCompilationDir(),
265 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
, File
)) {
266 File
= '"' + File
+ '"';
269 } else if (Optional
<uint64_t> Val
= FormValue
.getAsUnsignedConstant())
270 Name
= AttributeValueString(Attr
, *Val
);
273 WithColor(OS
, Color
) << Name
;
274 else if (Attr
== DW_AT_decl_line
|| Attr
== DW_AT_call_line
)
275 OS
<< *FormValue
.getAsUnsignedConstant();
276 else if (Attr
== DW_AT_low_pc
&&
277 (FormValue
.getAsAddress() ==
278 dwarf::computeTombstoneAddress(U
->getAddressByteSize()))) {
279 if (DumpOpts
.Verbose
) {
280 FormValue
.dump(OS
, DumpOpts
);
284 if (DumpOpts
.Verbose
)
286 } else if (Attr
== DW_AT_high_pc
&& !DumpOpts
.ShowForm
&& !DumpOpts
.Verbose
&&
287 FormValue
.getAsUnsignedConstant()) {
288 if (DumpOpts
.ShowAddresses
) {
289 // Print the actual address rather than the offset.
290 uint64_t LowPC
, HighPC
, Index
;
291 if (Die
.getLowAndHighPC(LowPC
, HighPC
, Index
))
292 DWARFFormValue::dumpAddress(OS
, U
->getAddressByteSize(), HighPC
);
294 FormValue
.dump(OS
, DumpOpts
);
296 } else if (DWARFAttribute::mayHaveLocationList(Attr
) &&
297 FormValue
.isFormClass(DWARFFormValue::FC_SectionOffset
))
298 dumpLocationList(OS
, FormValue
, U
, sizeof(BaseIndent
) + Indent
+ 4,
300 else if (FormValue
.isFormClass(DWARFFormValue::FC_Exprloc
) ||
301 (DWARFAttribute::mayHaveLocationExpr(Attr
) &&
302 FormValue
.isFormClass(DWARFFormValue::FC_Block
)))
303 dumpLocationExpr(OS
, FormValue
, U
, sizeof(BaseIndent
) + Indent
+ 4,
306 FormValue
.dump(OS
, DumpOpts
);
308 std::string Space
= DumpOpts
.ShowAddresses
? " " : "";
310 // We have dumped the attribute raw value. For some attributes
311 // having both the raw value and the pretty-printed value is
312 // interesting. These attributes are handled below.
313 if (Attr
== DW_AT_specification
|| Attr
== DW_AT_abstract_origin
) {
314 if (const char *Name
=
315 Die
.getAttributeValueAsReferencedDie(FormValue
).getName(
316 DINameKind::LinkageName
))
317 OS
<< Space
<< "\"" << Name
<< '\"';
318 } else if (Attr
== DW_AT_type
) {
320 dumpTypeName(OS
, Die
.getAttributeValueAsReferencedDie(FormValue
));
322 } else if (Attr
== DW_AT_APPLE_property_attribute
) {
323 if (Optional
<uint64_t> OptVal
= FormValue
.getAsUnsignedConstant())
324 dumpApplePropertyAttribute(OS
, *OptVal
);
325 } else if (Attr
== DW_AT_ranges
) {
326 const DWARFObject
&Obj
= Die
.getDwarfUnit()->getContext().getDWARFObj();
327 // For DW_FORM_rnglistx we need to dump the offset separately, since
328 // we have only dumped the index so far.
329 if (FormValue
.getForm() == DW_FORM_rnglistx
)
330 if (auto RangeListOffset
=
331 U
->getRnglistOffset(*FormValue
.getAsSectionOffset())) {
332 DWARFFormValue FV
= DWARFFormValue::createFromUValue(
333 dwarf::DW_FORM_sec_offset
, *RangeListOffset
);
334 FV
.dump(OS
, DumpOpts
);
336 if (auto RangesOrError
= Die
.getAddressRanges())
337 dumpRanges(Obj
, OS
, RangesOrError
.get(), U
->getAddressByteSize(),
338 sizeof(BaseIndent
) + Indent
+ 4, DumpOpts
);
340 DumpOpts
.RecoverableErrorHandler(createStringError(
341 errc::invalid_argument
, "decoding address ranges: %s",
342 toString(RangesOrError
.takeError()).c_str()));
348 bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram
; }
350 bool DWARFDie::isSubroutineDIE() const {
352 return Tag
== DW_TAG_subprogram
|| Tag
== DW_TAG_inlined_subroutine
;
355 Optional
<DWARFFormValue
> DWARFDie::find(dwarf::Attribute Attr
) const {
358 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
360 return AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
);
364 Optional
<DWARFFormValue
>
365 DWARFDie::find(ArrayRef
<dwarf::Attribute
> Attrs
) const {
368 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
370 for (auto Attr
: Attrs
) {
371 if (auto Value
= AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
))
378 Optional
<DWARFFormValue
>
379 DWARFDie::findRecursively(ArrayRef
<dwarf::Attribute
> Attrs
) const {
380 SmallVector
<DWARFDie
, 3> Worklist
;
381 Worklist
.push_back(*this);
383 // Keep track if DIEs already seen to prevent infinite recursion.
384 // Empirically we rarely see a depth of more than 3 when dealing with valid
385 // DWARF. This corresponds to following the DW_AT_abstract_origin and
386 // DW_AT_specification just once.
387 SmallSet
<DWARFDie
, 3> Seen
;
390 while (!Worklist
.empty()) {
391 DWARFDie Die
= Worklist
.pop_back_val();
396 if (auto Value
= Die
.find(Attrs
))
399 if (auto D
= Die
.getAttributeValueAsReferencedDie(DW_AT_abstract_origin
))
400 if (Seen
.insert(D
).second
)
401 Worklist
.push_back(D
);
403 if (auto D
= Die
.getAttributeValueAsReferencedDie(DW_AT_specification
))
404 if (Seen
.insert(D
).second
)
405 Worklist
.push_back(D
);
412 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr
) const {
413 if (Optional
<DWARFFormValue
> F
= find(Attr
))
414 return getAttributeValueAsReferencedDie(*F
);
419 DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue
&V
) const {
420 if (auto SpecRef
= V
.getAsRelativeReference()) {
422 return SpecRef
->Unit
->getDIEForOffset(SpecRef
->Unit
->getOffset() + SpecRef
->Offset
);
423 if (auto SpecUnit
= U
->getUnitVector().getUnitForOffset(SpecRef
->Offset
))
424 return SpecUnit
->getDIEForOffset(SpecRef
->Offset
);
429 Optional
<uint64_t> DWARFDie::getRangesBaseAttribute() const {
430 return toSectionOffset(find({DW_AT_rnglists_base
, DW_AT_GNU_ranges_base
}));
433 Optional
<uint64_t> DWARFDie::getLocBaseAttribute() const {
434 return toSectionOffset(find(DW_AT_loclists_base
));
437 Optional
<uint64_t> DWARFDie::getHighPC(uint64_t LowPC
) const {
438 uint64_t Tombstone
= dwarf::computeTombstoneAddress(U
->getAddressByteSize());
439 if (LowPC
== Tombstone
)
441 if (auto FormValue
= find(DW_AT_high_pc
)) {
442 if (auto Address
= FormValue
->getAsAddress()) {
443 // High PC is an address.
446 if (auto Offset
= FormValue
->getAsUnsignedConstant()) {
447 // High PC is an offset from LowPC.
448 return LowPC
+ *Offset
;
454 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC
, uint64_t &HighPC
,
455 uint64_t &SectionIndex
) const {
456 auto F
= find(DW_AT_low_pc
);
457 auto LowPcAddr
= toSectionedAddress(F
);
460 if (auto HighPcAddr
= getHighPC(LowPcAddr
->Address
)) {
461 LowPC
= LowPcAddr
->Address
;
462 HighPC
= *HighPcAddr
;
463 SectionIndex
= LowPcAddr
->SectionIndex
;
469 Expected
<DWARFAddressRangesVector
> DWARFDie::getAddressRanges() const {
471 return DWARFAddressRangesVector();
472 // Single range specified by low/high PC.
473 uint64_t LowPC
, HighPC
, Index
;
474 if (getLowAndHighPC(LowPC
, HighPC
, Index
))
475 return DWARFAddressRangesVector
{{LowPC
, HighPC
, Index
}};
477 Optional
<DWARFFormValue
> Value
= find(DW_AT_ranges
);
479 if (Value
->getForm() == DW_FORM_rnglistx
)
480 return U
->findRnglistFromIndex(*Value
->getAsSectionOffset());
481 return U
->findRnglistFromOffset(*Value
->getAsSectionOffset());
483 return DWARFAddressRangesVector();
486 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address
) const {
487 auto RangesOrError
= getAddressRanges();
488 if (!RangesOrError
) {
489 llvm::consumeError(RangesOrError
.takeError());
493 for (const auto &R
: RangesOrError
.get())
494 if (R
.LowPC
<= Address
&& Address
< R
.HighPC
)
499 Expected
<DWARFLocationExpressionsVector
>
500 DWARFDie::getLocations(dwarf::Attribute Attr
) const {
501 Optional
<DWARFFormValue
> Location
= find(Attr
);
503 return createStringError(inconvertibleErrorCode(), "No %s",
504 dwarf::AttributeString(Attr
).data());
506 if (Optional
<uint64_t> Off
= Location
->getAsSectionOffset()) {
507 uint64_t Offset
= *Off
;
509 if (Location
->getForm() == DW_FORM_loclistx
) {
510 if (auto LoclistOffset
= U
->getLoclistOffset(Offset
))
511 Offset
= *LoclistOffset
;
513 return createStringError(inconvertibleErrorCode(),
514 "Loclist table not found");
516 return U
->findLoclistFromOffset(Offset
);
519 if (Optional
<ArrayRef
<uint8_t>> Expr
= Location
->getAsBlock()) {
520 return DWARFLocationExpressionsVector
{
521 DWARFLocationExpression
{None
, to_vector
<4>(*Expr
)}};
524 return createStringError(
525 inconvertibleErrorCode(), "Unsupported %s encoding: %s",
526 dwarf::AttributeString(Attr
).data(),
527 dwarf::FormEncodingString(Location
->getForm()).data());
530 const char *DWARFDie::getSubroutineName(DINameKind Kind
) const {
531 if (!isSubroutineDIE())
533 return getName(Kind
);
536 const char *DWARFDie::getName(DINameKind Kind
) const {
537 if (!isValid() || Kind
== DINameKind::None
)
539 // Try to get mangled name only if it was asked for.
540 if (Kind
== DINameKind::LinkageName
) {
541 if (auto Name
= getLinkageName())
544 return getShortName();
547 const char *DWARFDie::getShortName() const {
551 return dwarf::toString(findRecursively(dwarf::DW_AT_name
), nullptr);
554 const char *DWARFDie::getLinkageName() const {
558 return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name
,
559 dwarf::DW_AT_linkage_name
}),
563 uint64_t DWARFDie::getDeclLine() const {
564 return toUnsigned(findRecursively(DW_AT_decl_line
), 0);
568 DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind
) const {
569 auto D
= getAttributeValueAsReferencedDie(DW_AT_abstract_origin
);
572 std::string FileName
;
573 if (auto DeclFile
= toUnsigned(D
.find(DW_AT_decl_file
))) {
574 if (const auto *LineTable
=
575 getDwarfUnit()->getContext().getLineTableForUnit(
576 D
.getDwarfUnit()->getLinkedUnit()))
577 LineTable
->getFileNameByIndex(
578 *DeclFile
, D
.getDwarfUnit()->getCompilationDir(), Kind
, FileName
);
583 void DWARFDie::getCallerFrame(uint32_t &CallFile
, uint32_t &CallLine
,
584 uint32_t &CallColumn
,
585 uint32_t &CallDiscriminator
) const {
586 CallFile
= toUnsigned(find(DW_AT_call_file
), 0);
587 CallLine
= toUnsigned(find(DW_AT_call_line
), 0);
588 CallColumn
= toUnsigned(find(DW_AT_call_column
), 0);
589 CallDiscriminator
= toUnsigned(find(DW_AT_GNU_discriminator
), 0);
592 /// Helper to dump a DIE with all of its parents, but no siblings.
593 static unsigned dumpParentChain(DWARFDie Die
, raw_ostream
&OS
, unsigned Indent
,
594 DIDumpOptions DumpOpts
, unsigned Depth
= 0) {
597 if (DumpOpts
.ParentRecurseDepth
> 0 && Depth
>= DumpOpts
.ParentRecurseDepth
)
599 Indent
= dumpParentChain(Die
.getParent(), OS
, Indent
, DumpOpts
, Depth
+ 1);
600 Die
.dump(OS
, Indent
, DumpOpts
);
604 void DWARFDie::dump(raw_ostream
&OS
, unsigned Indent
,
605 DIDumpOptions DumpOpts
) const {
608 DWARFDataExtractor debug_info_data
= U
->getDebugInfoExtractor();
609 const uint64_t Offset
= getOffset();
610 uint64_t offset
= Offset
;
611 if (DumpOpts
.ShowParents
) {
612 DIDumpOptions ParentDumpOpts
= DumpOpts
;
613 ParentDumpOpts
.ShowParents
= false;
614 ParentDumpOpts
.ShowChildren
= false;
615 Indent
= dumpParentChain(getParent(), OS
, Indent
, ParentDumpOpts
);
618 if (debug_info_data
.isValidOffset(offset
)) {
619 uint32_t abbrCode
= debug_info_data
.getULEB128(&offset
);
620 if (DumpOpts
.ShowAddresses
)
621 WithColor(OS
, HighlightColor::Address
).get()
622 << format("\n0x%8.8" PRIx64
": ", Offset
);
625 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
627 WithColor(OS
, HighlightColor::Tag
).get().indent(Indent
)
628 << formatv("{0}", getTag());
629 if (DumpOpts
.Verbose
)
630 OS
<< format(" [%u] %c", abbrCode
,
631 AbbrevDecl
->hasChildren() ? '*' : ' ');
634 // Dump all data in the DIE for the attributes.
635 for (const DWARFAttribute
&AttrValue
: attributes())
636 dumpAttribute(OS
, *this, AttrValue
, Indent
, DumpOpts
);
638 if (DumpOpts
.ShowChildren
&& DumpOpts
.ChildRecurseDepth
> 0) {
639 DWARFDie Child
= getFirstChild();
640 DumpOpts
.ChildRecurseDepth
--;
641 DIDumpOptions ChildDumpOpts
= DumpOpts
;
642 ChildDumpOpts
.ShowParents
= false;
644 Child
.dump(OS
, Indent
+ 2, ChildDumpOpts
);
645 Child
= Child
.getSibling();
649 OS
<< "Abbreviation code not found in 'debug_abbrev' class for code: "
653 OS
.indent(Indent
) << "NULL\n";
658 LLVM_DUMP_METHOD
void DWARFDie::dump() const { dump(llvm::errs(), 0); }
660 DWARFDie
DWARFDie::getParent() const {
662 return U
->getParent(Die
);
666 DWARFDie
DWARFDie::getSibling() const {
668 return U
->getSibling(Die
);
672 DWARFDie
DWARFDie::getPreviousSibling() const {
674 return U
->getPreviousSibling(Die
);
678 DWARFDie
DWARFDie::getFirstChild() const {
680 return U
->getFirstChild(Die
);
684 DWARFDie
DWARFDie::getLastChild() const {
686 return U
->getLastChild(Die
);
690 iterator_range
<DWARFDie::attribute_iterator
> DWARFDie::attributes() const {
691 return make_range(attribute_iterator(*this, false),
692 attribute_iterator(*this, true));
695 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D
, bool End
)
697 auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr();
698 assert(AbbrDecl
&& "Must have abbreviation declaration");
700 // This is the end iterator so we set the index to the attribute count.
701 Index
= AbbrDecl
->getNumAttributes();
703 // This is the begin iterator so we extract the value for this->Index.
704 AttrValue
.Offset
= D
.getOffset() + AbbrDecl
->getCodeByteSize();
705 updateForIndex(*AbbrDecl
, 0);
709 void DWARFDie::attribute_iterator::updateForIndex(
710 const DWARFAbbreviationDeclaration
&AbbrDecl
, uint32_t I
) {
712 // AbbrDecl must be valid before calling this function.
713 auto NumAttrs
= AbbrDecl
.getNumAttributes();
714 if (Index
< NumAttrs
) {
715 AttrValue
.Attr
= AbbrDecl
.getAttrByIndex(Index
);
716 // Add the previous byte size of any previous attribute value.
717 AttrValue
.Offset
+= AttrValue
.ByteSize
;
718 uint64_t ParseOffset
= AttrValue
.Offset
;
719 if (AbbrDecl
.getAttrIsImplicitConstByIndex(Index
))
720 AttrValue
.Value
= DWARFFormValue::createFromSValue(
721 AbbrDecl
.getFormByIndex(Index
),
722 AbbrDecl
.getAttrImplicitConstValueByIndex(Index
));
724 auto U
= Die
.getDwarfUnit();
725 assert(U
&& "Die must have valid DWARF unit");
726 AttrValue
.Value
= DWARFFormValue::createFromUnit(
727 AbbrDecl
.getFormByIndex(Index
), U
, &ParseOffset
);
729 AttrValue
.ByteSize
= ParseOffset
- AttrValue
.Offset
;
731 assert(Index
== NumAttrs
&& "Indexes should be [0, NumAttrs) only");
736 DWARFDie::attribute_iterator
&DWARFDie::attribute_iterator::operator++() {
737 if (auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr())
738 updateForIndex(*AbbrDecl
, Index
+ 1);
742 bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr
) {
745 case DW_AT_string_length
:
746 case DW_AT_return_addr
:
747 case DW_AT_data_member_location
:
748 case DW_AT_frame_base
:
749 case DW_AT_static_link
:
751 case DW_AT_use_location
:
752 case DW_AT_vtable_elem_location
:
759 bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr
) {
761 // From the DWARF v5 specification.
763 case DW_AT_byte_size
:
764 case DW_AT_bit_offset
:
766 case DW_AT_string_length
:
767 case DW_AT_lower_bound
:
768 case DW_AT_return_addr
:
769 case DW_AT_bit_stride
:
770 case DW_AT_upper_bound
:
772 case DW_AT_data_member_location
:
773 case DW_AT_frame_base
:
775 case DW_AT_static_link
:
776 case DW_AT_use_location
:
777 case DW_AT_vtable_elem_location
:
778 case DW_AT_allocated
:
779 case DW_AT_associated
:
780 case DW_AT_data_location
:
781 case DW_AT_byte_stride
:
783 case DW_AT_call_value
:
784 case DW_AT_call_origin
:
785 case DW_AT_call_target
:
786 case DW_AT_call_target_clobbered
:
787 case DW_AT_call_data_location
:
788 case DW_AT_call_data_value
:
790 case DW_AT_GNU_call_site_value
:
791 case DW_AT_GNU_call_site_target
: