[x86] fix assert with horizontal math + broadcast of vector (PR43402)
[llvm-core.git] / lib / DebugInfo / DWARF / DWARFDie.cpp
blobc1b5dfdb61c76f327f9fdde3d1a7d840da98a52f
1 //===- DWARFDie.cpp -------------------------------------------------------===//
2 //
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
6 //
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"
29 #include <algorithm>
30 #include <cassert>
31 #include <cinttypes>
32 #include <cstdint>
33 #include <string>
34 #include <utility>
36 using namespace llvm;
37 using namespace dwarf;
38 using namespace object;
40 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
41 OS << " (";
42 do {
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())
48 OS << PropName;
49 else
50 OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
51 if (!(Val ^= Bit))
52 break;
53 OS << ", ";
54 } while (true);
55 OS << ")";
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)
63 return;
65 ArrayRef<SectionName> SectionNames;
66 if (DumpOpts.Verbose)
67 SectionNames = Obj.getSectionNames();
69 for (const DWARFAddressRange &R : Ranges) {
70 OS << '\n';
71 OS.indent(Indent);
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())
90 .print(OS, MRI, U);
91 return;
94 FormValue.dump(OS, DumpOpts);
95 const auto &DumpLL = [&](auto ExpectedLL) {
96 if (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(),
101 MRI, U, Indent);
102 } else {
103 OS << '\n';
104 OS.indent(Indent);
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));
116 return;
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"))
141 return;
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())
162 if ((DefaultLB =
163 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
164 if (LB && *LB == *DefaultLB)
165 LB = None;
166 if (!LB && !Count && !UB)
167 OS << "[]";
168 else if (!LB && (Count || UB) && DefaultLB)
169 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
170 else {
171 OS << "[[";
172 if (LB)
173 OS << *LB;
174 else
175 OS << '?';
176 OS << ", ";
177 if (Count)
178 if (LB)
179 OS << *LB + *Count;
180 else
181 OS << "? + " << *Count;
182 else if (UB)
183 OS << *UB + 1;
184 else
185 OS << '?';
186 OS << ")]";
191 /// Recursively dump the DIE type name when applicable.
192 static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) {
193 if (!D.isValid())
194 return;
196 if (const char *Name = D.getName(DINameKind::LinkageName)) {
197 OS << Name;
198 return;
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();
204 switch (T) {
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:
211 break;
212 default:
213 dumpTypeTagName(OS, T);
216 // Follow the DW_AT_type if possible.
217 DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type);
218 dumpTypeName(OS, TypeDie);
220 switch (T) {
221 case DW_TAG_subroutine_type: {
222 if (!TypeDie)
223 OS << "void";
224 OS << '(';
225 bool First = true;
226 for (const DWARFDie &C : D.children()) {
227 if (C.getTag() == DW_TAG_formal_parameter) {
228 if (!First)
229 OS << ", ";
230 First = false;
231 dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type));
234 OS << ')';
235 break;
237 case DW_TAG_array_type: {
238 dumpArrayType(OS, D);
239 break;
241 case DW_TAG_pointer_type:
242 OS << '*';
243 break;
244 case DW_TAG_ptr_to_member_type:
245 if (DWARFDie Cont =
246 D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) {
247 dumpTypeName(OS << ' ', Cont);
248 OS << "::";
250 OS << '*';
251 break;
252 case DW_TAG_reference_type:
253 OS << '&';
254 break;
255 case DW_TAG_rvalue_reference_type:
256 OS << "&&";
257 break;
258 default:
259 break;
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) {
267 if (!Die.isValid())
268 return;
269 const char BaseIndent[] = " ";
270 OS << 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);
280 OS << "\t(";
282 StringRef Name;
283 std::string File;
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 + '"';
293 Name = File;
295 } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
296 Name = AttributeValueString(Attr, *Val);
298 if (!Name.empty())
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);
309 else
310 FormValue.dump(OS, DumpOpts);
312 } else if (DWARFAttribute::mayHaveLocationDescription(Attr))
313 dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
314 else
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) {
328 OS << Space << "\"";
329 dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue));
330 OS << '"';
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);
348 else
349 WithColor::error() << "decoding address ranges: "
350 << toString(RangesOrError.takeError()) << '\n';
353 OS << ")\n";
356 bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }
358 bool DWARFDie::isSubroutineDIE() const {
359 auto Tag = getTag();
360 return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
363 Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {
364 if (!isValid())
365 return None;
366 auto AbbrevDecl = getAbbreviationDeclarationPtr();
367 if (AbbrevDecl)
368 return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
369 return None;
372 Optional<DWARFFormValue>
373 DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
374 if (!isValid())
375 return None;
376 auto AbbrevDecl = getAbbreviationDeclarationPtr();
377 if (AbbrevDecl) {
378 for (auto Attr : Attrs) {
379 if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
380 return Value;
383 return None;
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;
396 Seen.insert(*this);
398 while (!Worklist.empty()) {
399 DWARFDie Die = Worklist.back();
400 Worklist.pop_back();
402 if (!Die.isValid())
403 continue;
405 if (auto Value = Die.find(Attrs))
406 return Value;
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);
417 return None;
420 DWARFDie
421 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
422 if (Optional<DWARFFormValue> F = find(Attr))
423 return getAttributeValueAsReferencedDie(*F);
424 return DWARFDie();
427 DWARFDie
428 DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
429 if (auto SpecRef = V.getAsRelativeReference()) {
430 if (SpecRef->Unit)
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);
435 return DWARFDie();
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.
446 return Address;
448 if (auto Offset = FormValue->getAsUnsignedConstant()) {
449 // High PC is an offset from LowPC.
450 return LowPC + *Offset;
453 return None;
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);
460 if (!LowPcAddr)
461 return false;
462 if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) {
463 LowPC = LowPcAddr->Address;
464 HighPC = *HighPcAddr;
465 SectionIndex = LowPcAddr->SectionIndex;
466 return true;
468 return false;
471 Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {
472 if (isNULL())
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);
480 if (Value) {
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 {
490 if (isNULL())
491 return;
492 if (isSubprogramDIE()) {
493 if (auto DIERangesOrError = getAddressRanges())
494 Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(),
495 DIERangesOrError.get().end());
496 else
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());
508 return false;
511 for (const auto &R : RangesOrError.get())
512 if (R.LowPC <= Address && Address < R.HighPC)
513 return true;
514 return false;
517 const char *DWARFDie::getSubroutineName(DINameKind Kind) const {
518 if (!isSubroutineDIE())
519 return nullptr;
520 return getName(Kind);
523 const char *DWARFDie::getName(DINameKind Kind) const {
524 if (!isValid() || Kind == DINameKind::None)
525 return nullptr;
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}),
530 nullptr))
531 return Name;
533 if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
534 return Name;
535 return 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) {
554 if (!Die)
555 return Indent;
556 if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth)
557 return Indent;
558 Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1);
559 Die.dump(OS, Indent, DumpOpts);
560 return Indent + 2;
563 void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
564 DIDumpOptions DumpOpts) const {
565 if (!isValid())
566 return;
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);
583 if (abbrCode) {
584 auto AbbrevDecl = getAbbreviationDeclarationPtr();
585 if (AbbrevDecl) {
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() ? '*' : ' ');
591 OS << '\n';
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.
599 continue;
601 dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
602 Indent, DumpOpts);
605 DWARFDie child = getFirstChild();
606 if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) {
607 DumpOpts.ChildRecurseDepth--;
608 DIDumpOptions ChildDumpOpts = DumpOpts;
609 ChildDumpOpts.ShowParents = false;
610 while (child) {
611 child.dump(OS, Indent + 2, ChildDumpOpts);
612 child = child.getSibling();
615 } else {
616 OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
617 << abbrCode << '\n';
619 } else {
620 OS.indent(Indent) << "NULL\n";
625 LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }
627 DWARFDie DWARFDie::getParent() const {
628 if (isValid())
629 return U->getParent(Die);
630 return DWARFDie();
633 DWARFDie DWARFDie::getSibling() const {
634 if (isValid())
635 return U->getSibling(Die);
636 return DWARFDie();
639 DWARFDie DWARFDie::getPreviousSibling() const {
640 if (isValid())
641 return U->getPreviousSibling(Die);
642 return DWARFDie();
645 DWARFDie DWARFDie::getFirstChild() const {
646 if (isValid())
647 return U->getFirstChild(Die);
648 return DWARFDie();
651 DWARFDie DWARFDie::getLastChild() const {
652 if (isValid())
653 return U->getLastChild(Die);
654 return DWARFDie();
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)
663 : Die(D), Index(0) {
664 auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
665 assert(AbbrDecl && "Must have abbreviation declaration");
666 if (End) {
667 // This is the end iterator so we set the index to the attribute count.
668 Index = AbbrDecl->getNumAttributes();
669 } else {
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) {
678 Index = 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;
691 } else {
692 assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
693 AttrValue = {};
697 DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
698 if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
699 updateForIndex(*AbbrDecl, Index + 1);
700 return *this;
703 bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) {
704 switch (Attr) {
705 // From the DWARF v5 specification.
706 case DW_AT_location:
707 case DW_AT_byte_size:
708 case DW_AT_bit_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:
714 case DW_AT_count:
715 case DW_AT_data_member_location:
716 case DW_AT_frame_base:
717 case DW_AT_segment:
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:
724 case DW_AT_rank:
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:
731 // Extensions.
732 case DW_AT_GNU_call_site_value:
733 case DW_AT_GNU_call_site_target:
734 return true;
735 default:
736 return false;