LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDie.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 252 269 93.7 %
Date: 2017-09-14 15:23:50 Functions: 26 28 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "SyntaxHighlighting.h"
      12             : #include "llvm/ADT/None.h"
      13             : #include "llvm/ADT/Optional.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/DWARFDebugRangeList.h"
      19             : #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
      20             : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
      21             : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
      22             : #include "llvm/Object/ObjectFile.h"
      23             : #include "llvm/Support/DataExtractor.h"
      24             : #include "llvm/Support/Format.h"
      25             : #include "llvm/Support/MathExtras.h"
      26             : #include "llvm/Support/raw_ostream.h"
      27             : #include <algorithm>
      28             : #include <cassert>
      29             : #include <cinttypes>
      30             : #include <cstdint>
      31             : #include <string>
      32             : #include <utility>
      33             : 
      34             : using namespace llvm;
      35             : using namespace dwarf;
      36             : using namespace object;
      37             : using namespace syntax;
      38             : 
      39          25 : static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
      40          25 :   OS << " (";
      41             :   do {
      42          98 :     uint64_t Shift = countTrailingZeros(Val);
      43             :     assert(Shift < 64 && "undefined behavior");
      44          98 :     uint64_t Bit = 1ULL << Shift;
      45          98 :     auto PropName = ApplePropertyString(Bit);
      46          98 :     if (!PropName.empty())
      47          98 :       OS << PropName;
      48             :     else
      49           0 :       OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
      50          98 :     if (!(Val ^= Bit))
      51             :       break;
      52          73 :     OS << ", ";
      53             :   } while (true);
      54          25 :   OS << ")";
      55          25 : }
      56             : 
      57          47 : static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,
      58             :                        const DWARFAddressRangesVector &Ranges,
      59             :                        unsigned AddressSize, unsigned Indent,
      60             :                        const DIDumpOptions &DumpOpts) {
      61          47 :   ArrayRef<SectionName> SectionNames;
      62          47 :   if (DumpOpts.Verbose)
      63          37 :     SectionNames = Obj.getSectionNames();
      64             : 
      65         328 :   for (size_t I = 0; I < Ranges.size(); ++I) {
      66         234 :     const DWARFAddressRange &R = Ranges[I];
      67             : 
      68         117 :     OS << '\n';
      69         117 :     OS.indent(Indent);
      70         351 :     OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", AddressSize * 2,
      71         117 :                  R.LowPC, AddressSize * 2, R.HighPC);
      72             : 
      73         192 :     if (SectionNames.empty() || R.SectionIndex == -1ULL)
      74          75 :       continue;
      75             : 
      76          84 :     StringRef Name = SectionNames[R.SectionIndex].Name;
      77          84 :     OS << " \"" << Name << '\"';
      78             : 
      79             :     // Print section index if name is not unique.
      80          84 :     if (!SectionNames[R.SectionIndex].IsNameUnique)
      81           4 :       OS << format(" [%" PRIu64 "]", R.SectionIndex);
      82             :   }
      83          47 : }
      84             : 
      85        1922 : static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
      86             :                          DWARFUnit *U, unsigned Indent,
      87             :                          DIDumpOptions DumpOpts) {
      88        1922 :   DWARFContext &Ctx = U->getContext();
      89        1922 :   const DWARFObject &Obj = Ctx.getDWARFObj();
      90        1922 :   const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
      91        3017 :   if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
      92        1095 :       FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) {
      93        4773 :     ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
      94        1591 :     DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
      95        4773 :                        Ctx.isLittleEndian(), 0);
      96        4773 :     DWARFExpression(Data, U->getVersion(), U->getAddressByteSize())
      97        1591 :         .print(OS, MRI);
      98             :     return;
      99             :   }
     100             : 
     101         331 :   FormValue.dump(OS, DumpOpts);
     102         331 :   if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
     103         147 :     const DWARFSection &LocSection = Obj.getLocSection();
     104         147 :     const DWARFSection &LocDWOSection = Obj.getLocDWOSection();
     105         441 :     uint32_t Offset = *FormValue.getAsSectionOffset();
     106             : 
     107         294 :     if (!LocSection.Data.empty()) {
     108         284 :       DWARFDebugLoc DebugLoc;
     109         142 :       DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(),
     110         426 :                               Obj.getAddressSize());
     111         284 :       auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
     112         142 :       if (LL)
     113         284 :         LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent);
     114             :       else
     115           0 :         OS << "error extracting location list.";
     116          10 :     } else if (!LocDWOSection.Data.empty()) {
     117          10 :       DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0);
     118          10 :       auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset);
     119           5 :       if (LL)
     120          10 :         LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent);
     121             :       else
     122           0 :         OS << "error extracting location list.";
     123             :     }
     124             :   }
     125             : }
     126             : 
     127       22372 : static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
     128             :                           uint32_t *OffsetPtr, dwarf::Attribute Attr,
     129             :                           dwarf::Form Form, unsigned Indent,
     130             :                           DIDumpOptions DumpOpts) {
     131       22372 :   if (!Die.isValid())
     132           0 :     return;
     133       22372 :   const char BaseIndent[] = "            ";
     134       22372 :   OS << BaseIndent;
     135       22372 :   OS.indent(Indent+2);
     136       22372 :   auto attrString = AttributeString(Attr);
     137       22372 :   if (!attrString.empty())
     138       89480 :     WithColor(OS, syntax::Attribute) << attrString;
     139             :   else
     140           6 :     WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr);
     141             : 
     142       22372 :   if (DumpOpts.Verbose) {
     143       18337 :     auto formString = FormEncodingString(Form);
     144       18337 :     if (!formString.empty())
     145       18337 :       OS << " [" << formString << ']';
     146             :     else
     147           0 :       OS << format(" [DW_FORM_Unknown_%x]", Form);
     148             :   }
     149             : 
     150       22372 :   DWARFUnit *U = Die.getDwarfUnit();
     151       44744 :   DWARFFormValue formValue(Form);
     152             : 
     153       22372 :   if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U))
     154             :     return;
     155             : 
     156       22372 :   OS << "\t(";
     157             : 
     158       22372 :   StringRef Name;
     159       44744 :   std::string File;
     160       22372 :   auto Color = syntax::Enumerator;
     161       22372 :   if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
     162        2390 :     Color = syntax::String;
     163        2390 :     if (const auto *LT = U->getContext().getLineTableForUnit(U))
     164        6792 :       if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
     165        6792 :         File = '"' + File + '"';
     166        2264 :         Name = File;
     167             :       }
     168       39964 :   } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
     169        8324 :     Name = AttributeValueString(Attr, *Val);
     170             : 
     171       22372 :   if (!Name.empty())
     172       14256 :     WithColor(OS, Color) << Name;
     173       18808 :   else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
     174        7287 :     OS << *formValue.getAsUnsignedConstant();
     175       16379 :   else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
     176             :            Attr == DW_AT_data_member_location)
     177        1922 :     dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
     178             :   else
     179       14457 :     formValue.dump(OS, DumpOpts);
     180             : 
     181             :   // We have dumped the attribute raw value. For some attributes
     182             :   // having both the raw value and the pretty-printed value is
     183             :   // interesting. These attributes are handled below.
     184       22372 :   if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
     185         300 :     if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName))
     186         298 :         OS << " \"" << Name << '\"';
     187       22072 :   } else if (Attr == DW_AT_APPLE_property_attribute) {
     188          50 :     if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
     189          25 :       dumpApplePropertyAttribute(OS, *OptVal);
     190       22047 :   } else if (Attr == DW_AT_ranges) {
     191          94 :     const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
     192          94 :     dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(),
     193             :                sizeof(BaseIndent) + Indent + 4, DumpOpts);
     194             :   }
     195             : 
     196       22372 :   OS << ")\n";
     197             : }
     198             : 
     199      672055 : bool DWARFDie::isSubprogramDIE() const {
     200      672055 :   return getTag() == DW_TAG_subprogram;
     201             : }
     202             : 
     203    17264560 : bool DWARFDie::isSubroutineDIE() const {
     204    17264560 :   auto Tag = getTag();
     205    17264560 :   return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
     206             : }
     207             : 
     208             : Optional<DWARFFormValue>
     209     7400956 : DWARFDie::find(dwarf::Attribute Attr) const {
     210     7400956 :   if (!isValid())
     211             :     return None;
     212    14801912 :   auto AbbrevDecl = getAbbreviationDeclarationPtr();
     213     7400956 :   if (AbbrevDecl)
     214    14801890 :     return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
     215             :   return None;
     216             : }
     217             : 
     218             : Optional<DWARFFormValue>
     219       36323 : DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
     220       36323 :   if (!isValid())
     221             :     return None;
     222       72646 :   auto AbbrevDecl = getAbbreviationDeclarationPtr();
     223       36323 :   if (AbbrevDecl) {
     224       85730 :     for (auto Attr : Attrs) {
     225       97834 :       if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
     226       58564 :         return Value;
     227             :     }
     228             :   }
     229             :   return None;
     230             : }
     231             : 
     232             : Optional<DWARFFormValue>
     233        4919 : DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
     234        4919 :   if (!isValid())
     235             :     return None;
     236        4919 :   auto Die = *this;
     237        7177 :   if (auto Value = Die.find(Attrs))
     238        5322 :     return Value;
     239        2631 :   if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
     240         373 :     Die = D;
     241        4378 :   if (auto Value = Die.find(Attrs))
     242         276 :     return Value;
     243        2665 :   if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))
     244         545 :     Die = D;
     245        3717 :   if (auto Value = Die.find(Attrs))
     246        1046 :     return Value;
     247             :   return None;
     248             : }
     249             : 
     250             : DWARFDie
     251        4678 : DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
     252       18712 :   auto SpecRef = toReference(find(Attr));
     253        4678 :   if (SpecRef) {
     254        2436 :     auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
     255        1218 :     if (SpecUnit)
     256        1218 :       return SpecUnit->getDIEForOffset(*SpecRef);
     257             :   }
     258        3460 :   return DWARFDie();
     259             : }
     260             : 
     261             : Optional<uint64_t>
     262          17 : DWARFDie::getRangesBaseAttribute() const {
     263          68 :   return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
     264             : }
     265             : 
     266      210241 : Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
     267      234986 :   if (auto FormValue = find(DW_AT_high_pc)) {
     268      370680 :     if (auto Address = FormValue->getAsAddress()) {
     269             :       // High PC is an address.
     270         624 :       return Address;
     271             :     }
     272      185184 :     if (auto Offset = FormValue->getAsUnsignedConstant()) {
     273             :       // High PC is an offset from LowPC.
     274      370368 :       return LowPC + *Offset;
     275             :     }
     276             :   }
     277             :   return None;
     278             : }
     279             : 
     280     3638944 : bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
     281             :                                uint64_t &SectionIndex) const {
     282     7277888 :   auto F = find(DW_AT_low_pc);
     283     7277888 :   auto LowPcAddr = toAddress(F);
     284     3638944 :   if (!LowPcAddr)
     285             :     return false;
     286      234793 :   if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
     287      185329 :     LowPC = *LowPcAddr;
     288      185329 :     HighPC = *HighPcAddr;
     289      185329 :     SectionIndex = F->getSectionIndex();
     290      370658 :     return true;
     291             :   }
     292       24732 :   return false;
     293             : }
     294             : 
     295             : DWARFAddressRangesVector
     296     3638920 : DWARFDie::getAddressRanges() const {
     297     3638920 :   if (isNULL())
     298             :     return DWARFAddressRangesVector();
     299             :   // Single range specified by low/high PC.
     300             :   uint64_t LowPC, HighPC, Index;
     301     3638920 :   if (getLowAndHighPC(LowPC, HighPC, Index))
     302      741292 :     return {{LowPC, HighPC, Index}};
     303             : 
     304             :   // Multiple ranges from .debug_ranges section.
     305    10360791 :   auto RangesOffset = toSectionOffset(find(DW_AT_ranges));
     306     3453597 :   if (RangesOffset) {
     307      114871 :     DWARFDebugRangeList RangeList;
     308      229738 :     if (U->extractRangeList(*RangesOffset, RangeList))
     309      344601 :       return RangeList.getAbsoluteRanges(U->getBaseAddress());
     310             :   }
     311             :   return DWARFAddressRangesVector();
     312             : }
     313             : 
     314             : void
     315      672055 : DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const {
     316      672055 :   if (isNULL())
     317             :     return;
     318      672055 :   if (isSubprogramDIE()) {
     319      174433 :     const auto &DIERanges = getAddressRanges();
     320      872165 :     Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
     321             :   }
     322             : 
     323     2015562 :   for (auto Child: children())
     324      671452 :     Child.collectChildrenAddressRanges(Ranges);
     325             : }
     326             : 
     327           0 : bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
     328           0 :   for (const auto& R : getAddressRanges()) {
     329           0 :     if (R.LowPC <= Address && Address < R.HighPC)
     330           0 :       return true;
     331             :   }
     332           0 :   return false;
     333             : }
     334             : 
     335             : const char *
     336         893 : DWARFDie::getSubroutineName(DINameKind Kind) const {
     337         893 :   if (!isSubroutineDIE())
     338             :     return nullptr;
     339         893 :   return getName(Kind);
     340             : }
     341             : 
     342             : const char *
     343        2567 : DWARFDie::getName(DINameKind Kind) const {
     344        2567 :   if (!isValid() || Kind == DINameKind::None)
     345             :     return nullptr;
     346             :   // Try to get mangled name only if it was asked for.
     347        2567 :   if (Kind == DINameKind::LinkageName) {
     348        5562 :     if (auto Name = dwarf::toString(findRecursively({DW_AT_MIPS_linkage_name,
     349        1854 :                                     DW_AT_linkage_name}), nullptr))
     350             :       return Name;
     351             :   }
     352        8080 :   if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
     353             :     return Name;
     354             :   return nullptr;
     355             : }
     356             : 
     357        1041 : uint64_t DWARFDie::getDeclLine() const {
     358        4164 :   return toUnsigned(findRecursively(DW_AT_decl_line), 0);
     359             : }
     360             : 
     361         139 : void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
     362             :                               uint32_t &CallColumn,
     363             :                               uint32_t &CallDiscriminator) const {
     364         417 :   CallFile = toUnsigned(find(DW_AT_call_file), 0);
     365         417 :   CallLine = toUnsigned(find(DW_AT_call_line), 0);
     366         417 :   CallColumn = toUnsigned(find(DW_AT_call_column), 0);
     367         417 :   CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);
     368         139 : }
     369             : 
     370        6406 : void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent,
     371             :                     DIDumpOptions DumpOpts) const {
     372        6406 :   if (!isValid())
     373           0 :     return;
     374        6406 :   DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
     375       12812 :   const uint32_t Offset = getOffset();
     376        6406 :   uint32_t offset = Offset;
     377             : 
     378       12812 :   if (debug_info_data.isValidOffset(offset)) {
     379        6406 :     uint32_t abbrCode = debug_info_data.getULEB128(&offset);
     380       19218 :     WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
     381             : 
     382        6406 :     if (abbrCode) {
     383        9636 :       auto AbbrevDecl = getAbbreviationDeclarationPtr();
     384        4818 :       if (AbbrevDecl) {
     385        4818 :         auto tagString = TagString(getTag());
     386        4818 :         if (!tagString.empty())
     387        9636 :           WithColor(OS, syntax::Tag).get().indent(Indent) << tagString;
     388             :         else
     389           0 :           WithColor(OS, syntax::Tag).get().indent(Indent)
     390           0 :           << format("DW_TAG_Unknown_%x", getTag());
     391             : 
     392        4818 :         if (DumpOpts.Verbose)
     393        7940 :           OS << format(" [%u] %c", abbrCode,
     394        3970 :                        AbbrevDecl->hasChildren() ? '*' : ' ');
     395        4818 :         OS << '\n';
     396             : 
     397             :         // Dump all data in the DIE for the attributes.
     398       27190 :         for (const auto &AttrSpec : AbbrevDecl->attributes()) {
     399       22372 :           if (AttrSpec.Form == DW_FORM_implicit_const) {
     400             :             // We are dumping .debug_info section ,
     401             :             // implicit_const attribute values are not really stored here,
     402             :             // but in .debug_abbrev section. So we just skip such attrs.
     403           0 :             continue;
     404             :           }
     405       22372 :           dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
     406             :                         Indent, DumpOpts);
     407             :         }
     408             : 
     409        4818 :         DWARFDie child = getFirstChild();
     410        4818 :         if (RecurseDepth > 0 && child) {
     411       11544 :           while (child) {
     412        5772 :             child.dump(OS, RecurseDepth-1, Indent+2, DumpOpts);
     413        5772 :             child = child.getSibling();
     414             :           }
     415             :         }
     416             :       } else {
     417           0 :         OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
     418           0 :         << abbrCode << '\n';
     419             :       }
     420             :     } else {
     421        1588 :       OS.indent(Indent) << "NULL\n";
     422             :     }
     423             :   }
     424             : }
     425             : 
     426           0 : LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }
     427             : 
     428        1963 : DWARFDie DWARFDie::getParent() const {
     429        1963 :   if (isValid())
     430        1962 :     return U->getParent(Die);
     431           1 :   return DWARFDie();
     432             : }
     433             : 
     434    17941888 : DWARFDie DWARFDie::getSibling() const {
     435    17941888 :   if (isValid())
     436    17941887 :     return U->getSibling(Die);
     437           1 :   return DWARFDie();
     438             : }
     439             : 
     440             : iterator_range<DWARFDie::attribute_iterator>
     441         136 : DWARFDie::attributes() const {
     442             :   return make_range(attribute_iterator(*this, false),
     443         136 :                     attribute_iterator(*this, true));
     444             : }
     445             : 
     446         272 : DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) :
     447         544 :     Die(D), AttrValue(0), Index(0) {
     448         544 :   auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
     449             :   assert(AbbrDecl && "Must have abbreviation declaration");
     450         272 :   if (End) {
     451             :     // This is the end iterator so we set the index to the attribute count.
     452         136 :     Index = AbbrDecl->getNumAttributes();
     453             :   } else {
     454             :     // This is the begin iterator so we extract the value for this->Index.
     455         272 :     AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();
     456         136 :     updateForIndex(*AbbrDecl, 0);
     457             :   }
     458         272 : }
     459             : 
     460         774 : void DWARFDie::attribute_iterator::updateForIndex(
     461             :     const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {
     462         774 :   Index = I;
     463             :   // AbbrDecl must be valid before calling this function.
     464         774 :   auto NumAttrs = AbbrDecl.getNumAttributes();
     465         774 :   if (Index < NumAttrs) {
     466        1276 :     AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);
     467             :     // Add the previous byte size of any previous attribute value.
     468         638 :     AttrValue.Offset += AttrValue.ByteSize;
     469        1914 :     AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index));
     470         638 :     uint32_t ParseOffset = AttrValue.Offset;
     471         638 :     auto U = Die.getDwarfUnit();
     472             :     assert(U && "Die must have valid DWARF unit");
     473        1276 :     bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(),
     474         638 :                                           &ParseOffset, U);
     475             :     (void)b;
     476             :     assert(b && "extractValue cannot fail on fully parsed DWARF");
     477         638 :     AttrValue.ByteSize = ParseOffset - AttrValue.Offset;
     478             :   } else {
     479             :     assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
     480         136 :     AttrValue.clear();
     481             :   }
     482         774 : }
     483             : 
     484         638 : DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
     485        1276 :   if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
     486         638 :     updateForIndex(*AbbrDecl, Index + 1);
     487         638 :   return *this;
     488             : }

Generated by: LCOV version 1.13