1 //===- DWARFDie.cpp -------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
11 #include "llvm/ADT/None.h"
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/SmallSet.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/BinaryFormat/Dwarf.h"
16 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
17 #include "llvm/DebugInfo/DWARF/DWARFContext.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/FormatVariadic.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/WithColor.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include <algorithm>
29 #include <cassert>
30 #include <cinttypes>
31 #include <cstdint>
32 #include <string>
33 #include <utility>
34 
35 using namespace llvm;
36 using namespace dwarf;
37 using namespace object;
38 
39 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
40   OS << " (";
41   do {
42     uint64_t Shift = countTrailingZeros(Val);
43     assert(Shift < 64 && "undefined behavior");
44     uint64_t Bit = 1ULL << Shift;
45     auto PropName = ApplePropertyString(Bit);
46     if (!PropName.empty())
47       OS << PropName;
48     else
49       OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
50     if (!(Val ^= Bit))
51       break;
52     OS << ", ";
53   } while (true);
54   OS << ")";
55 }
56 
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)
62     return;
63 
64   ArrayRef<SectionName> SectionNames;
65   if (DumpOpts.Verbose)
66     SectionNames = Obj.getSectionNames();
67 
68   for (const DWARFAddressRange &R : Ranges) {
69     OS << '\n';
70     OS.indent(Indent);
71     R.dump(OS, AddressSize);
72 
73     if (SectionNames.empty() || R.SectionIndex == -1ULL)
74       continue;
75 
76     StringRef Name = SectionNames[R.SectionIndex].Name;
77     OS << " \"" << Name << '\"';
78 
79     // Print section index if name is not unique.
80     if (!SectionNames[R.SectionIndex].IsNameUnique)
81       OS << format(" [%" PRIu64 "]", R.SectionIndex);
82   }
83 }
84 
85 static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
86                          DWARFUnit *U, unsigned Indent,
87                          DIDumpOptions DumpOpts) {
88   DWARFContext &Ctx = U->getContext();
89   const DWARFObject &Obj = Ctx.getDWARFObj();
90   const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
91   if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
92       FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) {
93     ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
94     DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
95                        Ctx.isLittleEndian(), 0);
96     DWARFExpression(Data, U->getVersion(), U->getAddressByteSize())
97         .print(OS, MRI);
98     return;
99   }
100 
101   FormValue.dump(OS, DumpOpts);
102   if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
103     uint32_t Offset = *FormValue.getAsSectionOffset();
104     if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
105       DWARFDebugLoc DebugLoc;
106       DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
107                               Obj.getAddressSize());
108       auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
109       if (LL) {
110         uint64_t BaseAddr = 0;
111         if (Optional<SectionedAddress> BA = U->getBaseAddress())
112           BaseAddr = BA->Address;
113         LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr,
114                  Indent);
115       } else
116         OS << "error extracting location list.";
117       return;
118     }
119 
120     bool UseLocLists = !U->isDWOUnit();
121     StringRef LoclistsSectionData =
122         UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData();
123 
124     if (!LoclistsSectionData.empty()) {
125       DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
126                          Obj.getAddressSize());
127 
128       // Old-style location list were used in DWARF v4 (.debug_loc.dwo section).
129       // Modern locations list (.debug_loclists) are used starting from v5.
130       // Ideally we should take the version from the .debug_loclists section
131       // header, but using CU's version for simplicity.
132       auto LL = DWARFDebugLoclists::parseOneLocationList(
133           Data, &Offset, UseLocLists ? U->getVersion() : 4);
134 
135       uint64_t BaseAddr = 0;
136       if (Optional<SectionedAddress> BA = U->getBaseAddress())
137         BaseAddr = BA->Address;
138 
139       if (LL)
140         LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
141                  Indent);
142       else
143         OS << "error extracting location list.";
144     }
145   }
146 }
147 
148 /// Dump the name encoded in the type tag.
149 static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) {
150   StringRef TagStr = TagString(T);
151   if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type"))
152     return;
153   OS << TagStr.substr(7, TagStr.size() - 12) << " ";
154 }
155 
156 /// Recursively dump the DIE type name when applicable.
157 static void dumpTypeName(raw_ostream &OS, const DWARFDie &Die) {
158   DWARFDie D = Die.getAttributeValueAsReferencedDie(DW_AT_type);
159 
160   if (!D.isValid())
161     return;
162 
163   if (const char *Name = D.getName(DINameKind::LinkageName)) {
164     OS << Name;
165     return;
166   }
167 
168   // FIXME: We should have pretty printers per language. Currently we print
169   // everything as if it was C++ and fall back to the TAG type name.
170   const dwarf::Tag T = D.getTag();
171   switch (T) {
172   case DW_TAG_array_type:
173   case DW_TAG_pointer_type:
174   case DW_TAG_ptr_to_member_type:
175   case DW_TAG_reference_type:
176   case DW_TAG_rvalue_reference_type:
177     break;
178   default:
179     dumpTypeTagName(OS, T);
180   }
181 
182   // Follow the DW_AT_type if possible.
183   dumpTypeName(OS, D);
184 
185   switch (T) {
186   case DW_TAG_array_type:
187     OS << "[]";
188     break;
189   case DW_TAG_pointer_type:
190     OS << '*';
191     break;
192   case DW_TAG_ptr_to_member_type:
193     OS << '*';
194     break;
195   case DW_TAG_reference_type:
196     OS << '&';
197     break;
198   case DW_TAG_rvalue_reference_type:
199     OS << "&&";
200     break;
201   default:
202     break;
203   }
204 }
205 
206 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
207                           uint32_t *OffsetPtr, dwarf::Attribute Attr,
208                           dwarf::Form Form, unsigned Indent,
209                           DIDumpOptions DumpOpts) {
210   if (!Die.isValid())
211     return;
212   const char BaseIndent[] = "            ";
213   OS << BaseIndent;
214   OS.indent(Indent + 2);
215   WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);
216 
217   if (DumpOpts.Verbose || DumpOpts.ShowForm)
218     OS << formatv(" [{0}]", Form);
219 
220   DWARFUnit *U = Die.getDwarfUnit();
221   DWARFFormValue formValue(Form);
222 
223   if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
224                               U->getFormParams(), U))
225     return;
226 
227   OS << "\t(";
228 
229   StringRef Name;
230   std::string File;
231   auto Color = HighlightColor::Enumerator;
232   if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
233     Color = HighlightColor::String;
234     if (const auto *LT = U->getContext().getLineTableForUnit(U))
235       if (LT->getFileNameByIndex(
236               formValue.getAsUnsignedConstant().getValue(),
237               U->getCompilationDir(),
238               DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
239         File = '"' + File + '"';
240         Name = File;
241       }
242   } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
243     Name = AttributeValueString(Attr, *Val);
244 
245   if (!Name.empty())
246     WithColor(OS, Color) << Name;
247   else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
248     OS << *formValue.getAsUnsignedConstant();
249   else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&
250            formValue.getAsUnsignedConstant()) {
251     if (DumpOpts.ShowAddresses) {
252       // Print the actual address rather than the offset.
253       uint64_t LowPC, HighPC, Index;
254       if (Die.getLowAndHighPC(LowPC, HighPC, Index))
255         OS << format("0x%016" PRIx64, HighPC);
256       else
257         formValue.dump(OS, DumpOpts);
258     }
259   } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
260              Attr == DW_AT_data_member_location ||
261              Attr == DW_AT_GNU_call_site_value)
262     dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
263   else
264     formValue.dump(OS, DumpOpts);
265 
266   std::string Space = DumpOpts.ShowAddresses ? " " : "";
267 
268   // We have dumped the attribute raw value. For some attributes
269   // having both the raw value and the pretty-printed value is
270   // interesting. These attributes are handled below.
271   if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
272     if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(
273             DINameKind::LinkageName))
274       OS << Space << "\"" << Name << '\"';
275   } else if (Attr == DW_AT_type) {
276     OS << Space << "\"";
277     dumpTypeName(OS, Die);
278     OS << '"';
279   } else if (Attr == DW_AT_APPLE_property_attribute) {
280     if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
281       dumpApplePropertyAttribute(OS, *OptVal);
282   } else if (Attr == DW_AT_ranges) {
283     const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
284     // For DW_FORM_rnglistx we need to dump the offset separately, since
285     // we have only dumped the index so far.
286     Optional<DWARFFormValue> Value = Die.find(DW_AT_ranges);
287     if (Value && Value->getForm() == DW_FORM_rnglistx)
288       if (auto RangeListOffset =
289               U->getRnglistOffset(*Value->getAsSectionOffset())) {
290         DWARFFormValue FV(dwarf::DW_FORM_sec_offset);
291         FV.setUValue(*RangeListOffset);
292         FV.dump(OS, DumpOpts);
293       }
294     if (auto RangesOrError = Die.getAddressRanges())
295       dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(),
296                  sizeof(BaseIndent) + Indent + 4, DumpOpts);
297     else
298       WithColor::error() << "decoding address ranges: "
299                          << toString(RangesOrError.takeError()) << '\n';
300   }
301 
302   OS << ")\n";
303 }
304 
305 bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }
306 
307 bool DWARFDie::isSubroutineDIE() const {
308   auto Tag = getTag();
309   return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
310 }
311 
312 Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {
313   if (!isValid())
314     return None;
315   auto AbbrevDecl = getAbbreviationDeclarationPtr();
316   if (AbbrevDecl)
317     return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
318   return None;
319 }
320 
321 Optional<DWARFFormValue>
322 DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
323   if (!isValid())
324     return None;
325   auto AbbrevDecl = getAbbreviationDeclarationPtr();
326   if (AbbrevDecl) {
327     for (auto Attr : Attrs) {
328       if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
329         return Value;
330     }
331   }
332   return None;
333 }
334 
335 Optional<DWARFFormValue>
336 DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
337   std::vector<DWARFDie> Worklist;
338   Worklist.push_back(*this);
339 
340   // Keep track if DIEs already seen to prevent infinite recursion.
341   // Empirically we rarely see a depth of more than 3 when dealing with valid
342   // DWARF. This corresponds to following the DW_AT_abstract_origin and
343   // DW_AT_specification just once.
344   SmallSet<DWARFDie, 3> Seen;
345 
346   while (!Worklist.empty()) {
347     DWARFDie Die = Worklist.back();
348     Worklist.pop_back();
349 
350     if (!Die.isValid())
351       continue;
352 
353     if (Seen.count(Die))
354       continue;
355 
356     Seen.insert(Die);
357 
358     if (auto Value = Die.find(Attrs))
359       return Value;
360 
361     if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
362       Worklist.push_back(D);
363 
364     if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))
365       Worklist.push_back(D);
366   }
367 
368   return None;
369 }
370 
371 DWARFDie
372 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
373   if (auto SpecRef = toReference(find(Attr))) {
374     if (auto SpecUnit = U->getUnitVector().getUnitForOffset(*SpecRef))
375       return SpecUnit->getDIEForOffset(*SpecRef);
376   }
377   return DWARFDie();
378 }
379 
380 Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
381   return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
382 }
383 
384 Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
385   if (auto FormValue = find(DW_AT_high_pc)) {
386     if (auto Address = FormValue->getAsAddress()) {
387       // High PC is an address.
388       return Address;
389     }
390     if (auto Offset = FormValue->getAsUnsignedConstant()) {
391       // High PC is an offset from LowPC.
392       return LowPC + *Offset;
393     }
394   }
395   return None;
396 }
397 
398 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
399                                uint64_t &SectionIndex) const {
400   auto F = find(DW_AT_low_pc);
401   auto LowPcAddr = toAddress(F);
402   if (!LowPcAddr)
403     return false;
404   if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
405     LowPC = *LowPcAddr;
406     HighPC = *HighPcAddr;
407     SectionIndex = F->getSectionIndex();
408     return true;
409   }
410   return false;
411 }
412 
413 Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {
414   if (isNULL())
415     return DWARFAddressRangesVector();
416   // Single range specified by low/high PC.
417   uint64_t LowPC, HighPC, Index;
418   if (getLowAndHighPC(LowPC, HighPC, Index))
419     return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
420 
421   Optional<DWARFFormValue> Value = find(DW_AT_ranges);
422   if (Value) {
423     if (Value->getForm() == DW_FORM_rnglistx)
424       return U->findRnglistFromIndex(*Value->getAsSectionOffset());
425     return U->findRnglistFromOffset(*Value->getAsSectionOffset());
426   }
427   return DWARFAddressRangesVector();
428 }
429 
430 void DWARFDie::collectChildrenAddressRanges(
431     DWARFAddressRangesVector &Ranges) const {
432   if (isNULL())
433     return;
434   if (isSubprogramDIE()) {
435     if (auto DIERangesOrError = getAddressRanges())
436       Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(),
437                     DIERangesOrError.get().end());
438     else
439       llvm::consumeError(DIERangesOrError.takeError());
440   }
441 
442   for (auto Child : children())
443     Child.collectChildrenAddressRanges(Ranges);
444 }
445 
446 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
447   auto RangesOrError = getAddressRanges();
448   if (!RangesOrError) {
449     llvm::consumeError(RangesOrError.takeError());
450     return false;
451   }
452 
453   for (const auto &R : RangesOrError.get())
454     if (R.LowPC <= Address && Address < R.HighPC)
455       return true;
456   return false;
457 }
458 
459 const char *DWARFDie::getSubroutineName(DINameKind Kind) const {
460   if (!isSubroutineDIE())
461     return nullptr;
462   return getName(Kind);
463 }
464 
465 const char *DWARFDie::getName(DINameKind Kind) const {
466   if (!isValid() || Kind == DINameKind::None)
467     return nullptr;
468   // Try to get mangled name only if it was asked for.
469   if (Kind == DINameKind::LinkageName) {
470     if (auto Name = dwarf::toString(
471             findRecursively({DW_AT_MIPS_linkage_name, DW_AT_linkage_name}),
472             nullptr))
473       return Name;
474   }
475   if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
476     return Name;
477   return nullptr;
478 }
479 
480 uint64_t DWARFDie::getDeclLine() const {
481   return toUnsigned(findRecursively(DW_AT_decl_line), 0);
482 }
483 
484 void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
485                               uint32_t &CallColumn,
486                               uint32_t &CallDiscriminator) const {
487   CallFile = toUnsigned(find(DW_AT_call_file), 0);
488   CallLine = toUnsigned(find(DW_AT_call_line), 0);
489   CallColumn = toUnsigned(find(DW_AT_call_column), 0);
490   CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);
491 }
492 
493 /// Helper to dump a DIE with all of its parents, but no siblings.
494 static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,
495                                 DIDumpOptions DumpOpts) {
496   if (!Die)
497     return Indent;
498   Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts);
499   Die.dump(OS, Indent, DumpOpts);
500   return Indent + 2;
501 }
502 
503 void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
504                     DIDumpOptions DumpOpts) const {
505   if (!isValid())
506     return;
507   DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
508   const uint32_t Offset = getOffset();
509   uint32_t offset = Offset;
510   if (DumpOpts.ShowParents) {
511     DIDumpOptions ParentDumpOpts = DumpOpts;
512     ParentDumpOpts.ShowParents = false;
513     ParentDumpOpts.ShowChildren = false;
514     Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts);
515   }
516 
517   if (debug_info_data.isValidOffset(offset)) {
518     uint32_t abbrCode = debug_info_data.getULEB128(&offset);
519     if (DumpOpts.ShowAddresses)
520       WithColor(OS, HighlightColor::Address).get()
521           << format("\n0x%8.8x: ", Offset);
522 
523     if (abbrCode) {
524       auto AbbrevDecl = getAbbreviationDeclarationPtr();
525       if (AbbrevDecl) {
526         WithColor(OS, HighlightColor::Tag).get().indent(Indent)
527             << formatv("{0}", getTag());
528         if (DumpOpts.Verbose)
529           OS << format(" [%u] %c", abbrCode,
530                        AbbrevDecl->hasChildren() ? '*' : ' ');
531         OS << '\n';
532 
533         // Dump all data in the DIE for the attributes.
534         for (const auto &AttrSpec : AbbrevDecl->attributes()) {
535           if (AttrSpec.Form == DW_FORM_implicit_const) {
536             // We are dumping .debug_info section ,
537             // implicit_const attribute values are not really stored here,
538             // but in .debug_abbrev section. So we just skip such attrs.
539             continue;
540           }
541           dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
542                         Indent, DumpOpts);
543         }
544 
545         DWARFDie child = getFirstChild();
546         if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) {
547           DumpOpts.RecurseDepth--;
548           DIDumpOptions ChildDumpOpts = DumpOpts;
549           ChildDumpOpts.ShowParents = false;
550           while (child) {
551             child.dump(OS, Indent + 2, ChildDumpOpts);
552             child = child.getSibling();
553           }
554         }
555       } else {
556         OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
557            << abbrCode << '\n';
558       }
559     } else {
560       OS.indent(Indent) << "NULL\n";
561     }
562   }
563 }
564 
565 LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }
566 
567 DWARFDie DWARFDie::getParent() const {
568   if (isValid())
569     return U->getParent(Die);
570   return DWARFDie();
571 }
572 
573 DWARFDie DWARFDie::getSibling() const {
574   if (isValid())
575     return U->getSibling(Die);
576   return DWARFDie();
577 }
578 
579 DWARFDie DWARFDie::getPreviousSibling() const {
580   if (isValid())
581     return U->getPreviousSibling(Die);
582   return DWARFDie();
583 }
584 
585 DWARFDie DWARFDie::getFirstChild() const {
586   if (isValid())
587     return U->getFirstChild(Die);
588   return DWARFDie();
589 }
590 
591 DWARFDie DWARFDie::getLastChild() const {
592   if (isValid())
593     return U->getLastChild(Die);
594   return DWARFDie();
595 }
596 
597 iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const {
598   return make_range(attribute_iterator(*this, false),
599                     attribute_iterator(*this, true));
600 }
601 
602 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End)
603     : Die(D), AttrValue(0), Index(0) {
604   auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
605   assert(AbbrDecl && "Must have abbreviation declaration");
606   if (End) {
607     // This is the end iterator so we set the index to the attribute count.
608     Index = AbbrDecl->getNumAttributes();
609   } else {
610     // This is the begin iterator so we extract the value for this->Index.
611     AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();
612     updateForIndex(*AbbrDecl, 0);
613   }
614 }
615 
616 void DWARFDie::attribute_iterator::updateForIndex(
617     const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {
618   Index = I;
619   // AbbrDecl must be valid before calling this function.
620   auto NumAttrs = AbbrDecl.getNumAttributes();
621   if (Index < NumAttrs) {
622     AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);
623     // Add the previous byte size of any previous attribute value.
624     AttrValue.Offset += AttrValue.ByteSize;
625     AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index));
626     uint32_t ParseOffset = AttrValue.Offset;
627     auto U = Die.getDwarfUnit();
628     assert(U && "Die must have valid DWARF unit");
629     bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(),
630                                           &ParseOffset, U->getFormParams(), U);
631     (void)b;
632     assert(b && "extractValue cannot fail on fully parsed DWARF");
633     AttrValue.ByteSize = ParseOffset - AttrValue.Offset;
634   } else {
635     assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
636     AttrValue.clear();
637   }
638 }
639 
640 DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
641   if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
642     updateForIndex(*AbbrDecl, Index + 1);
643   return *this;
644 }
645