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 ArrayRef
<SectionName
> SectionNames
;
67 SectionNames
= Obj
.getSectionNames();
69 for (const DWARFAddressRange
&R
: Ranges
) {
72 R
.dump(OS
, AddressSize
);
74 DWARFFormValue::dumpAddressSection(Obj
, OS
, DumpOpts
, R
.SectionIndex
);
78 static void dumpLocation(raw_ostream
&OS
, DWARFFormValue
&FormValue
,
79 DWARFUnit
*U
, unsigned Indent
,
80 DIDumpOptions DumpOpts
) {
81 DWARFContext
&Ctx
= U
->getContext();
82 const DWARFObject
&Obj
= Ctx
.getDWARFObj();
83 const MCRegisterInfo
*MRI
= Ctx
.getRegisterInfo();
84 if (FormValue
.isFormClass(DWARFFormValue::FC_Block
) ||
85 FormValue
.isFormClass(DWARFFormValue::FC_Exprloc
)) {
86 ArrayRef
<uint8_t> Expr
= *FormValue
.getAsBlock();
87 DataExtractor
Data(StringRef((const char *)Expr
.data(), Expr
.size()),
88 Ctx
.isLittleEndian(), 0);
89 DWARFExpression(Data
, U
->getVersion(), U
->getAddressByteSize())
94 FormValue
.dump(OS
, DumpOpts
);
95 const auto &DumpLL
= [&](auto ExpectedLL
) {
97 uint64_t BaseAddr
= 0;
98 if (Optional
<object::SectionedAddress
> BA
= U
->getBaseAddress())
99 BaseAddr
= BA
->Address
;
100 ExpectedLL
->dump(OS
, BaseAddr
, Ctx
.isLittleEndian(), Obj
.getAddressSize(),
105 OS
<< formatv("error extracting location list: {0}",
106 fmt_consume(ExpectedLL
.takeError()));
109 if (FormValue
.isFormClass(DWARFFormValue::FC_SectionOffset
)) {
110 uint64_t Offset
= *FormValue
.getAsSectionOffset();
111 if (!U
->isDWOUnit() && !U
->getLocSection()->Data
.empty()) {
112 DWARFDebugLoc DebugLoc
;
113 DWARFDataExtractor
Data(Obj
, *U
->getLocSection(), Ctx
.isLittleEndian(),
114 Obj
.getAddressSize());
115 DumpLL(DebugLoc
.parseOneLocationList(Data
, &Offset
));
119 bool UseLocLists
= !U
->isDWOUnit();
120 StringRef LoclistsSectionData
=
121 UseLocLists
? Obj
.getLoclistsSection().Data
: U
->getLocSectionData();
123 if (!LoclistsSectionData
.empty()) {
124 DataExtractor
Data(LoclistsSectionData
, Ctx
.isLittleEndian(),
125 Obj
.getAddressSize());
127 // Old-style location list were used in DWARF v4 (.debug_loc.dwo section).
128 // Modern locations list (.debug_loclists) are used starting from v5.
129 // Ideally we should take the version from the .debug_loclists section
130 // header, but using CU's version for simplicity.
131 DumpLL(DWARFDebugLoclists::parseOneLocationList(
132 Data
, &Offset
, UseLocLists
? U
->getVersion() : 4));
137 /// Dump the name encoded in the type tag.
138 static void dumpTypeTagName(raw_ostream
&OS
, dwarf::Tag T
) {
139 StringRef TagStr
= TagString(T
);
140 if (!TagStr
.startswith("DW_TAG_") || !TagStr
.endswith("_type"))
142 OS
<< TagStr
.substr(7, TagStr
.size() - 12) << " ";
145 static void dumpArrayType(raw_ostream
&OS
, const DWARFDie
&D
) {
146 Optional
<uint64_t> Bound
;
147 for (const DWARFDie
&C
: D
.children())
148 if (C
.getTag() == DW_TAG_subrange_type
) {
149 Optional
<uint64_t> LB
;
150 Optional
<uint64_t> Count
;
151 Optional
<uint64_t> UB
;
152 Optional
<unsigned> DefaultLB
;
153 if (Optional
<DWARFFormValue
> L
= C
.find(DW_AT_lower_bound
))
154 LB
= L
->getAsUnsignedConstant();
155 if (Optional
<DWARFFormValue
> CountV
= C
.find(DW_AT_count
))
156 Count
= CountV
->getAsUnsignedConstant();
157 if (Optional
<DWARFFormValue
> UpperV
= C
.find(DW_AT_upper_bound
))
158 UB
= UpperV
->getAsUnsignedConstant();
159 if (Optional
<DWARFFormValue
> LV
=
160 D
.getDwarfUnit()->getUnitDIE().find(DW_AT_language
))
161 if (Optional
<uint64_t> LC
= LV
->getAsUnsignedConstant())
163 LanguageLowerBound(static_cast<dwarf::SourceLanguage
>(*LC
))))
164 if (LB
&& *LB
== *DefaultLB
)
166 if (!LB
&& !Count
&& !UB
)
168 else if (!LB
&& (Count
|| UB
) && DefaultLB
)
169 OS
<< '[' << (Count
? *Count
: *UB
- *DefaultLB
+ 1) << ']';
181 OS
<< "? + " << *Count
;
191 /// Recursively dump the DIE type name when applicable.
192 static void dumpTypeName(raw_ostream
&OS
, const DWARFDie
&D
) {
196 if (const char *Name
= D
.getName(DINameKind::LinkageName
)) {
201 // FIXME: We should have pretty printers per language. Currently we print
202 // everything as if it was C++ and fall back to the TAG type name.
203 const dwarf::Tag T
= D
.getTag();
205 case DW_TAG_array_type
:
206 case DW_TAG_pointer_type
:
207 case DW_TAG_ptr_to_member_type
:
208 case DW_TAG_reference_type
:
209 case DW_TAG_rvalue_reference_type
:
210 case DW_TAG_subroutine_type
:
213 dumpTypeTagName(OS
, T
);
216 // Follow the DW_AT_type if possible.
217 DWARFDie TypeDie
= D
.getAttributeValueAsReferencedDie(DW_AT_type
);
218 dumpTypeName(OS
, TypeDie
);
221 case DW_TAG_subroutine_type
: {
226 for (const DWARFDie
&C
: D
.children()) {
227 if (C
.getTag() == DW_TAG_formal_parameter
) {
231 dumpTypeName(OS
, C
.getAttributeValueAsReferencedDie(DW_AT_type
));
237 case DW_TAG_array_type
: {
238 dumpArrayType(OS
, D
);
241 case DW_TAG_pointer_type
:
244 case DW_TAG_ptr_to_member_type
:
246 D
.getAttributeValueAsReferencedDie(DW_AT_containing_type
)) {
247 dumpTypeName(OS
<< ' ', Cont
);
252 case DW_TAG_reference_type
:
255 case DW_TAG_rvalue_reference_type
:
263 static void dumpAttribute(raw_ostream
&OS
, const DWARFDie
&Die
,
264 uint64_t *OffsetPtr
, dwarf::Attribute Attr
,
265 dwarf::Form Form
, unsigned Indent
,
266 DIDumpOptions DumpOpts
) {
269 const char BaseIndent
[] = " ";
271 OS
.indent(Indent
+ 2);
272 WithColor(OS
, HighlightColor::Attribute
) << formatv("{0}", Attr
);
274 if (DumpOpts
.Verbose
|| DumpOpts
.ShowForm
)
275 OS
<< formatv(" [{0}]", Form
);
277 DWARFUnit
*U
= Die
.getDwarfUnit();
278 DWARFFormValue FormValue
= DWARFFormValue::createFromUnit(Form
, U
, OffsetPtr
);
284 auto Color
= HighlightColor::Enumerator
;
285 if (Attr
== DW_AT_decl_file
|| Attr
== DW_AT_call_file
) {
286 Color
= HighlightColor::String
;
287 if (const auto *LT
= U
->getContext().getLineTableForUnit(U
))
288 if (LT
->getFileNameByIndex(
289 FormValue
.getAsUnsignedConstant().getValue(),
290 U
->getCompilationDir(),
291 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath
, File
)) {
292 File
= '"' + File
+ '"';
295 } else if (Optional
<uint64_t> Val
= FormValue
.getAsUnsignedConstant())
296 Name
= AttributeValueString(Attr
, *Val
);
299 WithColor(OS
, Color
) << Name
;
300 else if (Attr
== DW_AT_decl_line
|| Attr
== DW_AT_call_line
)
301 OS
<< *FormValue
.getAsUnsignedConstant();
302 else if (Attr
== DW_AT_high_pc
&& !DumpOpts
.ShowForm
&& !DumpOpts
.Verbose
&&
303 FormValue
.getAsUnsignedConstant()) {
304 if (DumpOpts
.ShowAddresses
) {
305 // Print the actual address rather than the offset.
306 uint64_t LowPC
, HighPC
, Index
;
307 if (Die
.getLowAndHighPC(LowPC
, HighPC
, Index
))
308 OS
<< format("0x%016" PRIx64
, HighPC
);
310 FormValue
.dump(OS
, DumpOpts
);
312 } else if (DWARFAttribute::mayHaveLocationDescription(Attr
))
313 dumpLocation(OS
, FormValue
, U
, sizeof(BaseIndent
) + Indent
+ 4, DumpOpts
);
315 FormValue
.dump(OS
, DumpOpts
);
317 std::string Space
= DumpOpts
.ShowAddresses
? " " : "";
319 // We have dumped the attribute raw value. For some attributes
320 // having both the raw value and the pretty-printed value is
321 // interesting. These attributes are handled below.
322 if (Attr
== DW_AT_specification
|| Attr
== DW_AT_abstract_origin
) {
323 if (const char *Name
=
324 Die
.getAttributeValueAsReferencedDie(FormValue
).getName(
325 DINameKind::LinkageName
))
326 OS
<< Space
<< "\"" << Name
<< '\"';
327 } else if (Attr
== DW_AT_type
) {
329 dumpTypeName(OS
, Die
.getAttributeValueAsReferencedDie(FormValue
));
331 } else if (Attr
== DW_AT_APPLE_property_attribute
) {
332 if (Optional
<uint64_t> OptVal
= FormValue
.getAsUnsignedConstant())
333 dumpApplePropertyAttribute(OS
, *OptVal
);
334 } else if (Attr
== DW_AT_ranges
) {
335 const DWARFObject
&Obj
= Die
.getDwarfUnit()->getContext().getDWARFObj();
336 // For DW_FORM_rnglistx we need to dump the offset separately, since
337 // we have only dumped the index so far.
338 if (FormValue
.getForm() == DW_FORM_rnglistx
)
339 if (auto RangeListOffset
=
340 U
->getRnglistOffset(*FormValue
.getAsSectionOffset())) {
341 DWARFFormValue FV
= DWARFFormValue::createFromUValue(
342 dwarf::DW_FORM_sec_offset
, *RangeListOffset
);
343 FV
.dump(OS
, DumpOpts
);
345 if (auto RangesOrError
= Die
.getAddressRanges())
346 dumpRanges(Obj
, OS
, RangesOrError
.get(), U
->getAddressByteSize(),
347 sizeof(BaseIndent
) + Indent
+ 4, DumpOpts
);
349 WithColor::error() << "decoding address ranges: "
350 << toString(RangesOrError
.takeError()) << '\n';
356 bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram
; }
358 bool DWARFDie::isSubroutineDIE() const {
360 return Tag
== DW_TAG_subprogram
|| Tag
== DW_TAG_inlined_subroutine
;
363 Optional
<DWARFFormValue
> DWARFDie::find(dwarf::Attribute Attr
) const {
366 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
368 return AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
);
372 Optional
<DWARFFormValue
>
373 DWARFDie::find(ArrayRef
<dwarf::Attribute
> Attrs
) const {
376 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
378 for (auto Attr
: Attrs
) {
379 if (auto Value
= AbbrevDecl
->getAttributeValue(getOffset(), Attr
, *U
))
386 Optional
<DWARFFormValue
>
387 DWARFDie::findRecursively(ArrayRef
<dwarf::Attribute
> Attrs
) const {
388 std::vector
<DWARFDie
> Worklist
;
389 Worklist
.push_back(*this);
391 // Keep track if DIEs already seen to prevent infinite recursion.
392 // Empirically we rarely see a depth of more than 3 when dealing with valid
393 // DWARF. This corresponds to following the DW_AT_abstract_origin and
394 // DW_AT_specification just once.
395 SmallSet
<DWARFDie
, 3> Seen
;
398 while (!Worklist
.empty()) {
399 DWARFDie Die
= Worklist
.back();
405 if (auto Value
= Die
.find(Attrs
))
408 if (auto D
= Die
.getAttributeValueAsReferencedDie(DW_AT_abstract_origin
))
409 if (Seen
.insert(D
).second
)
410 Worklist
.push_back(D
);
412 if (auto D
= Die
.getAttributeValueAsReferencedDie(DW_AT_specification
))
413 if (Seen
.insert(D
).second
)
414 Worklist
.push_back(D
);
421 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr
) const {
422 if (Optional
<DWARFFormValue
> F
= find(Attr
))
423 return getAttributeValueAsReferencedDie(*F
);
428 DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue
&V
) const {
429 if (auto SpecRef
= V
.getAsRelativeReference()) {
431 return SpecRef
->Unit
->getDIEForOffset(SpecRef
->Unit
->getOffset() + SpecRef
->Offset
);
432 if (auto SpecUnit
= U
->getUnitVector().getUnitForOffset(SpecRef
->Offset
))
433 return SpecUnit
->getDIEForOffset(SpecRef
->Offset
);
438 Optional
<uint64_t> DWARFDie::getRangesBaseAttribute() const {
439 return toSectionOffset(find({DW_AT_rnglists_base
, DW_AT_GNU_ranges_base
}));
442 Optional
<uint64_t> DWARFDie::getHighPC(uint64_t LowPC
) const {
443 if (auto FormValue
= find(DW_AT_high_pc
)) {
444 if (auto Address
= FormValue
->getAsAddress()) {
445 // High PC is an address.
448 if (auto Offset
= FormValue
->getAsUnsignedConstant()) {
449 // High PC is an offset from LowPC.
450 return LowPC
+ *Offset
;
456 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC
, uint64_t &HighPC
,
457 uint64_t &SectionIndex
) const {
458 auto F
= find(DW_AT_low_pc
);
459 auto LowPcAddr
= toSectionedAddress(F
);
462 if (auto HighPcAddr
= getHighPC(LowPcAddr
->Address
)) {
463 LowPC
= LowPcAddr
->Address
;
464 HighPC
= *HighPcAddr
;
465 SectionIndex
= LowPcAddr
->SectionIndex
;
471 Expected
<DWARFAddressRangesVector
> DWARFDie::getAddressRanges() const {
473 return DWARFAddressRangesVector();
474 // Single range specified by low/high PC.
475 uint64_t LowPC
, HighPC
, Index
;
476 if (getLowAndHighPC(LowPC
, HighPC
, Index
))
477 return DWARFAddressRangesVector
{{LowPC
, HighPC
, Index
}};
479 Optional
<DWARFFormValue
> Value
= find(DW_AT_ranges
);
481 if (Value
->getForm() == DW_FORM_rnglistx
)
482 return U
->findRnglistFromIndex(*Value
->getAsSectionOffset());
483 return U
->findRnglistFromOffset(*Value
->getAsSectionOffset());
485 return DWARFAddressRangesVector();
488 void DWARFDie::collectChildrenAddressRanges(
489 DWARFAddressRangesVector
&Ranges
) const {
492 if (isSubprogramDIE()) {
493 if (auto DIERangesOrError
= getAddressRanges())
494 Ranges
.insert(Ranges
.end(), DIERangesOrError
.get().begin(),
495 DIERangesOrError
.get().end());
497 llvm::consumeError(DIERangesOrError
.takeError());
500 for (auto Child
: children())
501 Child
.collectChildrenAddressRanges(Ranges
);
504 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address
) const {
505 auto RangesOrError
= getAddressRanges();
506 if (!RangesOrError
) {
507 llvm::consumeError(RangesOrError
.takeError());
511 for (const auto &R
: RangesOrError
.get())
512 if (R
.LowPC
<= Address
&& Address
< R
.HighPC
)
517 const char *DWARFDie::getSubroutineName(DINameKind Kind
) const {
518 if (!isSubroutineDIE())
520 return getName(Kind
);
523 const char *DWARFDie::getName(DINameKind Kind
) const {
524 if (!isValid() || Kind
== DINameKind::None
)
526 // Try to get mangled name only if it was asked for.
527 if (Kind
== DINameKind::LinkageName
) {
528 if (auto Name
= dwarf::toString(
529 findRecursively({DW_AT_MIPS_linkage_name
, DW_AT_linkage_name
}),
533 if (auto Name
= dwarf::toString(findRecursively(DW_AT_name
), nullptr))
538 uint64_t DWARFDie::getDeclLine() const {
539 return toUnsigned(findRecursively(DW_AT_decl_line
), 0);
542 void DWARFDie::getCallerFrame(uint32_t &CallFile
, uint32_t &CallLine
,
543 uint32_t &CallColumn
,
544 uint32_t &CallDiscriminator
) const {
545 CallFile
= toUnsigned(find(DW_AT_call_file
), 0);
546 CallLine
= toUnsigned(find(DW_AT_call_line
), 0);
547 CallColumn
= toUnsigned(find(DW_AT_call_column
), 0);
548 CallDiscriminator
= toUnsigned(find(DW_AT_GNU_discriminator
), 0);
551 /// Helper to dump a DIE with all of its parents, but no siblings.
552 static unsigned dumpParentChain(DWARFDie Die
, raw_ostream
&OS
, unsigned Indent
,
553 DIDumpOptions DumpOpts
, unsigned Depth
= 0) {
556 if (DumpOpts
.ParentRecurseDepth
> 0 && Depth
>= DumpOpts
.ParentRecurseDepth
)
558 Indent
= dumpParentChain(Die
.getParent(), OS
, Indent
, DumpOpts
, Depth
+ 1);
559 Die
.dump(OS
, Indent
, DumpOpts
);
563 void DWARFDie::dump(raw_ostream
&OS
, unsigned Indent
,
564 DIDumpOptions DumpOpts
) const {
567 DWARFDataExtractor debug_info_data
= U
->getDebugInfoExtractor();
568 const uint64_t Offset
= getOffset();
569 uint64_t offset
= Offset
;
570 if (DumpOpts
.ShowParents
) {
571 DIDumpOptions ParentDumpOpts
= DumpOpts
;
572 ParentDumpOpts
.ShowParents
= false;
573 ParentDumpOpts
.ShowChildren
= false;
574 Indent
= dumpParentChain(getParent(), OS
, Indent
, ParentDumpOpts
);
577 if (debug_info_data
.isValidOffset(offset
)) {
578 uint32_t abbrCode
= debug_info_data
.getULEB128(&offset
);
579 if (DumpOpts
.ShowAddresses
)
580 WithColor(OS
, HighlightColor::Address
).get()
581 << format("\n0x%8.8" PRIx64
": ", Offset
);
584 auto AbbrevDecl
= getAbbreviationDeclarationPtr();
586 WithColor(OS
, HighlightColor::Tag
).get().indent(Indent
)
587 << formatv("{0}", getTag());
588 if (DumpOpts
.Verbose
)
589 OS
<< format(" [%u] %c", abbrCode
,
590 AbbrevDecl
->hasChildren() ? '*' : ' ');
593 // Dump all data in the DIE for the attributes.
594 for (const auto &AttrSpec
: AbbrevDecl
->attributes()) {
595 if (AttrSpec
.Form
== DW_FORM_implicit_const
) {
596 // We are dumping .debug_info section ,
597 // implicit_const attribute values are not really stored here,
598 // but in .debug_abbrev section. So we just skip such attrs.
601 dumpAttribute(OS
, *this, &offset
, AttrSpec
.Attr
, AttrSpec
.Form
,
605 DWARFDie child
= getFirstChild();
606 if (DumpOpts
.ShowChildren
&& DumpOpts
.ChildRecurseDepth
> 0 && child
) {
607 DumpOpts
.ChildRecurseDepth
--;
608 DIDumpOptions ChildDumpOpts
= DumpOpts
;
609 ChildDumpOpts
.ShowParents
= false;
611 child
.dump(OS
, Indent
+ 2, ChildDumpOpts
);
612 child
= child
.getSibling();
616 OS
<< "Abbreviation code not found in 'debug_abbrev' class for code: "
620 OS
.indent(Indent
) << "NULL\n";
625 LLVM_DUMP_METHOD
void DWARFDie::dump() const { dump(llvm::errs(), 0); }
627 DWARFDie
DWARFDie::getParent() const {
629 return U
->getParent(Die
);
633 DWARFDie
DWARFDie::getSibling() const {
635 return U
->getSibling(Die
);
639 DWARFDie
DWARFDie::getPreviousSibling() const {
641 return U
->getPreviousSibling(Die
);
645 DWARFDie
DWARFDie::getFirstChild() const {
647 return U
->getFirstChild(Die
);
651 DWARFDie
DWARFDie::getLastChild() const {
653 return U
->getLastChild(Die
);
657 iterator_range
<DWARFDie::attribute_iterator
> DWARFDie::attributes() const {
658 return make_range(attribute_iterator(*this, false),
659 attribute_iterator(*this, true));
662 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D
, bool End
)
664 auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr();
665 assert(AbbrDecl
&& "Must have abbreviation declaration");
667 // This is the end iterator so we set the index to the attribute count.
668 Index
= AbbrDecl
->getNumAttributes();
670 // This is the begin iterator so we extract the value for this->Index.
671 AttrValue
.Offset
= D
.getOffset() + AbbrDecl
->getCodeByteSize();
672 updateForIndex(*AbbrDecl
, 0);
676 void DWARFDie::attribute_iterator::updateForIndex(
677 const DWARFAbbreviationDeclaration
&AbbrDecl
, uint32_t I
) {
679 // AbbrDecl must be valid before calling this function.
680 auto NumAttrs
= AbbrDecl
.getNumAttributes();
681 if (Index
< NumAttrs
) {
682 AttrValue
.Attr
= AbbrDecl
.getAttrByIndex(Index
);
683 // Add the previous byte size of any previous attribute value.
684 AttrValue
.Offset
+= AttrValue
.ByteSize
;
685 uint64_t ParseOffset
= AttrValue
.Offset
;
686 auto U
= Die
.getDwarfUnit();
687 assert(U
&& "Die must have valid DWARF unit");
688 AttrValue
.Value
= DWARFFormValue::createFromUnit(
689 AbbrDecl
.getFormByIndex(Index
), U
, &ParseOffset
);
690 AttrValue
.ByteSize
= ParseOffset
- AttrValue
.Offset
;
692 assert(Index
== NumAttrs
&& "Indexes should be [0, NumAttrs) only");
697 DWARFDie::attribute_iterator
&DWARFDie::attribute_iterator::operator++() {
698 if (auto AbbrDecl
= Die
.getAbbreviationDeclarationPtr())
699 updateForIndex(*AbbrDecl
, Index
+ 1);
703 bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr
) {
705 // From the DWARF v5 specification.
707 case DW_AT_byte_size
:
709 case DW_AT_string_length
:
710 case DW_AT_lower_bound
:
711 case DW_AT_return_addr
:
712 case DW_AT_bit_stride
:
713 case DW_AT_upper_bound
:
715 case DW_AT_data_member_location
:
716 case DW_AT_frame_base
:
718 case DW_AT_static_link
:
719 case DW_AT_use_location
:
720 case DW_AT_vtable_elem_location
:
721 case DW_AT_allocated
:
722 case DW_AT_associated
:
723 case DW_AT_byte_stride
:
725 case DW_AT_call_value
:
726 case DW_AT_call_origin
:
727 case DW_AT_call_target
:
728 case DW_AT_call_target_clobbered
:
729 case DW_AT_call_data_location
:
730 case DW_AT_call_data_value
:
732 case DW_AT_GNU_call_site_value
:
733 case DW_AT_GNU_call_site_target
: