10b57cec5SDimitry Andric //===- DWARFDie.cpp -------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 100b57cec5SDimitry Andric #include "llvm/ADT/None.h" 110b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 120b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 130b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 140b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 160b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 190b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 200b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 210b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 220b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 230b57cec5SDimitry Andric #include "llvm/Support/Format.h" 248bcb0991SDimitry Andric #include "llvm/Support/FormatAdapters.h" 250b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 260b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 270b57cec5SDimitry Andric #include "llvm/Support/WithColor.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric #include <algorithm> 300b57cec5SDimitry Andric #include <cassert> 310b57cec5SDimitry Andric #include <cinttypes> 320b57cec5SDimitry Andric #include <cstdint> 330b57cec5SDimitry Andric #include <string> 340b57cec5SDimitry Andric #include <utility> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric using namespace dwarf; 380b57cec5SDimitry Andric using namespace object; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { 410b57cec5SDimitry Andric OS << " ("; 420b57cec5SDimitry Andric do { 430b57cec5SDimitry Andric uint64_t Shift = countTrailingZeros(Val); 440b57cec5SDimitry Andric assert(Shift < 64 && "undefined behavior"); 450b57cec5SDimitry Andric uint64_t Bit = 1ULL << Shift; 460b57cec5SDimitry Andric auto PropName = ApplePropertyString(Bit); 470b57cec5SDimitry Andric if (!PropName.empty()) 480b57cec5SDimitry Andric OS << PropName; 490b57cec5SDimitry Andric else 500b57cec5SDimitry Andric OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); 510b57cec5SDimitry Andric if (!(Val ^= Bit)) 520b57cec5SDimitry Andric break; 530b57cec5SDimitry Andric OS << ", "; 540b57cec5SDimitry Andric } while (true); 550b57cec5SDimitry Andric OS << ")"; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, 590b57cec5SDimitry Andric const DWARFAddressRangesVector &Ranges, 600b57cec5SDimitry Andric unsigned AddressSize, unsigned Indent, 610b57cec5SDimitry Andric const DIDumpOptions &DumpOpts) { 620b57cec5SDimitry Andric if (!DumpOpts.ShowAddresses) 630b57cec5SDimitry Andric return; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric for (const DWARFAddressRange &R : Ranges) { 660b57cec5SDimitry Andric OS << '\n'; 670b57cec5SDimitry Andric OS.indent(Indent); 68480093f4SDimitry Andric R.dump(OS, AddressSize, DumpOpts, &Obj); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 72*4652422eSDimitry Andric static void dumpLocation(raw_ostream &OS, const DWARFFormValue &FormValue, 730b57cec5SDimitry Andric DWARFUnit *U, unsigned Indent, 740b57cec5SDimitry Andric DIDumpOptions DumpOpts) { 750b57cec5SDimitry Andric DWARFContext &Ctx = U->getContext(); 760b57cec5SDimitry Andric const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 770b57cec5SDimitry Andric if (FormValue.isFormClass(DWARFFormValue::FC_Block) || 780b57cec5SDimitry Andric FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { 790b57cec5SDimitry Andric ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); 800b57cec5SDimitry Andric DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), 810b57cec5SDimitry Andric Ctx.isLittleEndian(), 0); 825ffd83dbSDimitry Andric DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) 83e8d8bef9SDimitry Andric .print(OS, DumpOpts, MRI, U); 840b57cec5SDimitry Andric return; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { 888bcb0991SDimitry Andric uint64_t Offset = *FormValue.getAsSectionOffset(); 89480093f4SDimitry Andric 90480093f4SDimitry Andric if (FormValue.getForm() == DW_FORM_loclistx) { 91480093f4SDimitry Andric FormValue.dump(OS, DumpOpts); 92480093f4SDimitry Andric 93480093f4SDimitry Andric if (auto LoclistOffset = U->getLoclistOffset(Offset)) 94480093f4SDimitry Andric Offset = *LoclistOffset; 95480093f4SDimitry Andric else 96480093f4SDimitry Andric return; 97480093f4SDimitry Andric } 98480093f4SDimitry Andric U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), 99480093f4SDimitry Andric MRI, Ctx.getDWARFObj(), U, DumpOpts, 100480093f4SDimitry Andric Indent); 1010b57cec5SDimitry Andric return; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 104480093f4SDimitry Andric FormValue.dump(OS, DumpOpts); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Dump the name encoded in the type tag. 1080b57cec5SDimitry Andric static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) { 1090b57cec5SDimitry Andric StringRef TagStr = TagString(T); 1100b57cec5SDimitry Andric if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type")) 1110b57cec5SDimitry Andric return; 1120b57cec5SDimitry Andric OS << TagStr.substr(7, TagStr.size() - 12) << " "; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { 1160b57cec5SDimitry Andric for (const DWARFDie &C : D.children()) 1170b57cec5SDimitry Andric if (C.getTag() == DW_TAG_subrange_type) { 1180b57cec5SDimitry Andric Optional<uint64_t> LB; 1190b57cec5SDimitry Andric Optional<uint64_t> Count; 1200b57cec5SDimitry Andric Optional<uint64_t> UB; 1210b57cec5SDimitry Andric Optional<unsigned> DefaultLB; 1220b57cec5SDimitry Andric if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) 1230b57cec5SDimitry Andric LB = L->getAsUnsignedConstant(); 1240b57cec5SDimitry Andric if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) 1250b57cec5SDimitry Andric Count = CountV->getAsUnsignedConstant(); 1260b57cec5SDimitry Andric if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) 1270b57cec5SDimitry Andric UB = UpperV->getAsUnsignedConstant(); 1280b57cec5SDimitry Andric if (Optional<DWARFFormValue> LV = 1290b57cec5SDimitry Andric D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) 1300b57cec5SDimitry Andric if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) 1310b57cec5SDimitry Andric if ((DefaultLB = 1320b57cec5SDimitry Andric LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) 1330b57cec5SDimitry Andric if (LB && *LB == *DefaultLB) 1340b57cec5SDimitry Andric LB = None; 1350b57cec5SDimitry Andric if (!LB && !Count && !UB) 1360b57cec5SDimitry Andric OS << "[]"; 1370b57cec5SDimitry Andric else if (!LB && (Count || UB) && DefaultLB) 1380b57cec5SDimitry Andric OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']'; 1390b57cec5SDimitry Andric else { 1400b57cec5SDimitry Andric OS << "[["; 1410b57cec5SDimitry Andric if (LB) 1420b57cec5SDimitry Andric OS << *LB; 1430b57cec5SDimitry Andric else 1440b57cec5SDimitry Andric OS << '?'; 1450b57cec5SDimitry Andric OS << ", "; 1460b57cec5SDimitry Andric if (Count) 1470b57cec5SDimitry Andric if (LB) 1480b57cec5SDimitry Andric OS << *LB + *Count; 1490b57cec5SDimitry Andric else 1500b57cec5SDimitry Andric OS << "? + " << *Count; 1510b57cec5SDimitry Andric else if (UB) 1520b57cec5SDimitry Andric OS << *UB + 1; 1530b57cec5SDimitry Andric else 1540b57cec5SDimitry Andric OS << '?'; 1550b57cec5SDimitry Andric OS << ")]"; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// Recursively dump the DIE type name when applicable. 1610b57cec5SDimitry Andric static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { 1620b57cec5SDimitry Andric if (!D.isValid()) 1630b57cec5SDimitry Andric return; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric if (const char *Name = D.getName(DINameKind::LinkageName)) { 1660b57cec5SDimitry Andric OS << Name; 1670b57cec5SDimitry Andric return; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // FIXME: We should have pretty printers per language. Currently we print 1710b57cec5SDimitry Andric // everything as if it was C++ and fall back to the TAG type name. 1720b57cec5SDimitry Andric const dwarf::Tag T = D.getTag(); 1730b57cec5SDimitry Andric switch (T) { 1740b57cec5SDimitry Andric case DW_TAG_array_type: 1750b57cec5SDimitry Andric case DW_TAG_pointer_type: 1760b57cec5SDimitry Andric case DW_TAG_ptr_to_member_type: 1770b57cec5SDimitry Andric case DW_TAG_reference_type: 1780b57cec5SDimitry Andric case DW_TAG_rvalue_reference_type: 1790b57cec5SDimitry Andric case DW_TAG_subroutine_type: 1800b57cec5SDimitry Andric break; 1810b57cec5SDimitry Andric default: 1820b57cec5SDimitry Andric dumpTypeTagName(OS, T); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Follow the DW_AT_type if possible. 1860b57cec5SDimitry Andric DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type); 1870b57cec5SDimitry Andric dumpTypeName(OS, TypeDie); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric switch (T) { 1900b57cec5SDimitry Andric case DW_TAG_subroutine_type: { 1910b57cec5SDimitry Andric if (!TypeDie) 1920b57cec5SDimitry Andric OS << "void"; 1930b57cec5SDimitry Andric OS << '('; 1940b57cec5SDimitry Andric bool First = true; 1950b57cec5SDimitry Andric for (const DWARFDie &C : D.children()) { 1960b57cec5SDimitry Andric if (C.getTag() == DW_TAG_formal_parameter) { 1970b57cec5SDimitry Andric if (!First) 1980b57cec5SDimitry Andric OS << ", "; 1990b57cec5SDimitry Andric First = false; 2000b57cec5SDimitry Andric dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type)); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric OS << ')'; 2040b57cec5SDimitry Andric break; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric case DW_TAG_array_type: { 2070b57cec5SDimitry Andric dumpArrayType(OS, D); 2080b57cec5SDimitry Andric break; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric case DW_TAG_pointer_type: 2110b57cec5SDimitry Andric OS << '*'; 2120b57cec5SDimitry Andric break; 2130b57cec5SDimitry Andric case DW_TAG_ptr_to_member_type: 2140b57cec5SDimitry Andric if (DWARFDie Cont = 2150b57cec5SDimitry Andric D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) { 2160b57cec5SDimitry Andric dumpTypeName(OS << ' ', Cont); 2170b57cec5SDimitry Andric OS << "::"; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric OS << '*'; 2200b57cec5SDimitry Andric break; 2210b57cec5SDimitry Andric case DW_TAG_reference_type: 2220b57cec5SDimitry Andric OS << '&'; 2230b57cec5SDimitry Andric break; 2240b57cec5SDimitry Andric case DW_TAG_rvalue_reference_type: 2250b57cec5SDimitry Andric OS << "&&"; 2260b57cec5SDimitry Andric break; 2270b57cec5SDimitry Andric default: 2280b57cec5SDimitry Andric break; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, 233*4652422eSDimitry Andric const DWARFAttribute &AttrValue, unsigned Indent, 2340b57cec5SDimitry Andric DIDumpOptions DumpOpts) { 2350b57cec5SDimitry Andric if (!Die.isValid()) 2360b57cec5SDimitry Andric return; 2370b57cec5SDimitry Andric const char BaseIndent[] = " "; 2380b57cec5SDimitry Andric OS << BaseIndent; 2390b57cec5SDimitry Andric OS.indent(Indent + 2); 240*4652422eSDimitry Andric dwarf::Attribute Attr = AttrValue.Attr; 2410b57cec5SDimitry Andric WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); 2420b57cec5SDimitry Andric 243*4652422eSDimitry Andric dwarf::Form Form = AttrValue.Value.getForm(); 2440b57cec5SDimitry Andric if (DumpOpts.Verbose || DumpOpts.ShowForm) 2450b57cec5SDimitry Andric OS << formatv(" [{0}]", Form); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric DWARFUnit *U = Die.getDwarfUnit(); 248*4652422eSDimitry Andric const DWARFFormValue &FormValue = AttrValue.Value; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric OS << "\t("; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric StringRef Name; 2530b57cec5SDimitry Andric std::string File; 2540b57cec5SDimitry Andric auto Color = HighlightColor::Enumerator; 2550b57cec5SDimitry Andric if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { 2560b57cec5SDimitry Andric Color = HighlightColor::String; 2570b57cec5SDimitry Andric if (const auto *LT = U->getContext().getLineTableForUnit(U)) 2580b57cec5SDimitry Andric if (LT->getFileNameByIndex( 2590b57cec5SDimitry Andric FormValue.getAsUnsignedConstant().getValue(), 2600b57cec5SDimitry Andric U->getCompilationDir(), 2610b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { 2620b57cec5SDimitry Andric File = '"' + File + '"'; 2630b57cec5SDimitry Andric Name = File; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) 2660b57cec5SDimitry Andric Name = AttributeValueString(Attr, *Val); 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric if (!Name.empty()) 2690b57cec5SDimitry Andric WithColor(OS, Color) << Name; 2700b57cec5SDimitry Andric else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) 2710b57cec5SDimitry Andric OS << *FormValue.getAsUnsignedConstant(); 272e8d8bef9SDimitry Andric else if (Attr == DW_AT_low_pc && 273e8d8bef9SDimitry Andric (FormValue.getAsAddress() == 274e8d8bef9SDimitry Andric dwarf::computeTombstoneAddress(U->getAddressByteSize()))) { 275e8d8bef9SDimitry Andric if (DumpOpts.Verbose) { 276e8d8bef9SDimitry Andric FormValue.dump(OS, DumpOpts); 277e8d8bef9SDimitry Andric OS << " ("; 278e8d8bef9SDimitry Andric } 279e8d8bef9SDimitry Andric OS << "dead code"; 280e8d8bef9SDimitry Andric if (DumpOpts.Verbose) 281e8d8bef9SDimitry Andric OS << ')'; 282e8d8bef9SDimitry Andric } else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && 2830b57cec5SDimitry Andric FormValue.getAsUnsignedConstant()) { 2840b57cec5SDimitry Andric if (DumpOpts.ShowAddresses) { 2850b57cec5SDimitry Andric // Print the actual address rather than the offset. 2860b57cec5SDimitry Andric uint64_t LowPC, HighPC, Index; 2870b57cec5SDimitry Andric if (Die.getLowAndHighPC(LowPC, HighPC, Index)) 288e8d8bef9SDimitry Andric DWARFFormValue::dumpAddress(OS, U->getAddressByteSize(), HighPC); 2890b57cec5SDimitry Andric else 2900b57cec5SDimitry Andric FormValue.dump(OS, DumpOpts); 2910b57cec5SDimitry Andric } 292480093f4SDimitry Andric } else if (Form == dwarf::Form::DW_FORM_exprloc || 293480093f4SDimitry Andric DWARFAttribute::mayHaveLocationDescription(Attr)) 2940b57cec5SDimitry Andric dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); 2950b57cec5SDimitry Andric else 2960b57cec5SDimitry Andric FormValue.dump(OS, DumpOpts); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric std::string Space = DumpOpts.ShowAddresses ? " " : ""; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // We have dumped the attribute raw value. For some attributes 3010b57cec5SDimitry Andric // having both the raw value and the pretty-printed value is 3020b57cec5SDimitry Andric // interesting. These attributes are handled below. 3030b57cec5SDimitry Andric if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { 3040b57cec5SDimitry Andric if (const char *Name = 3050b57cec5SDimitry Andric Die.getAttributeValueAsReferencedDie(FormValue).getName( 3060b57cec5SDimitry Andric DINameKind::LinkageName)) 3070b57cec5SDimitry Andric OS << Space << "\"" << Name << '\"'; 3080b57cec5SDimitry Andric } else if (Attr == DW_AT_type) { 3090b57cec5SDimitry Andric OS << Space << "\""; 3100b57cec5SDimitry Andric dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue)); 3110b57cec5SDimitry Andric OS << '"'; 3120b57cec5SDimitry Andric } else if (Attr == DW_AT_APPLE_property_attribute) { 3130b57cec5SDimitry Andric if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) 3140b57cec5SDimitry Andric dumpApplePropertyAttribute(OS, *OptVal); 3150b57cec5SDimitry Andric } else if (Attr == DW_AT_ranges) { 3160b57cec5SDimitry Andric const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); 3170b57cec5SDimitry Andric // For DW_FORM_rnglistx we need to dump the offset separately, since 3180b57cec5SDimitry Andric // we have only dumped the index so far. 3190b57cec5SDimitry Andric if (FormValue.getForm() == DW_FORM_rnglistx) 3200b57cec5SDimitry Andric if (auto RangeListOffset = 3210b57cec5SDimitry Andric U->getRnglistOffset(*FormValue.getAsSectionOffset())) { 3220b57cec5SDimitry Andric DWARFFormValue FV = DWARFFormValue::createFromUValue( 3230b57cec5SDimitry Andric dwarf::DW_FORM_sec_offset, *RangeListOffset); 3240b57cec5SDimitry Andric FV.dump(OS, DumpOpts); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric if (auto RangesOrError = Die.getAddressRanges()) 3270b57cec5SDimitry Andric dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), 3280b57cec5SDimitry Andric sizeof(BaseIndent) + Indent + 4, DumpOpts); 3290b57cec5SDimitry Andric else 3305ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(createStringError( 3315ffd83dbSDimitry Andric errc::invalid_argument, "decoding address ranges: %s", 3325ffd83dbSDimitry Andric toString(RangesOrError.takeError()).c_str())); 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric OS << ")\n"; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric bool DWARFDie::isSubroutineDIE() const { 3410b57cec5SDimitry Andric auto Tag = getTag(); 3420b57cec5SDimitry Andric return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const { 3460b57cec5SDimitry Andric if (!isValid()) 3470b57cec5SDimitry Andric return None; 3480b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 3490b57cec5SDimitry Andric if (AbbrevDecl) 3500b57cec5SDimitry Andric return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); 3510b57cec5SDimitry Andric return None; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric Optional<DWARFFormValue> 3550b57cec5SDimitry Andric DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { 3560b57cec5SDimitry Andric if (!isValid()) 3570b57cec5SDimitry Andric return None; 3580b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 3590b57cec5SDimitry Andric if (AbbrevDecl) { 3600b57cec5SDimitry Andric for (auto Attr : Attrs) { 3610b57cec5SDimitry Andric if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) 3620b57cec5SDimitry Andric return Value; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric return None; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric Optional<DWARFFormValue> 3690b57cec5SDimitry Andric DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { 3705ffd83dbSDimitry Andric SmallVector<DWARFDie, 3> Worklist; 3710b57cec5SDimitry Andric Worklist.push_back(*this); 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric // Keep track if DIEs already seen to prevent infinite recursion. 3740b57cec5SDimitry Andric // Empirically we rarely see a depth of more than 3 when dealing with valid 3750b57cec5SDimitry Andric // DWARF. This corresponds to following the DW_AT_abstract_origin and 3760b57cec5SDimitry Andric // DW_AT_specification just once. 3770b57cec5SDimitry Andric SmallSet<DWARFDie, 3> Seen; 3780b57cec5SDimitry Andric Seen.insert(*this); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric while (!Worklist.empty()) { 381e8d8bef9SDimitry Andric DWARFDie Die = Worklist.pop_back_val(); 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric if (!Die.isValid()) 3840b57cec5SDimitry Andric continue; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric if (auto Value = Die.find(Attrs)) 3870b57cec5SDimitry Andric return Value; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 3900b57cec5SDimitry Andric if (Seen.insert(D).second) 3910b57cec5SDimitry Andric Worklist.push_back(D); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) 3940b57cec5SDimitry Andric if (Seen.insert(D).second) 3950b57cec5SDimitry Andric Worklist.push_back(D); 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric return None; 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric DWARFDie 4020b57cec5SDimitry Andric DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { 4030b57cec5SDimitry Andric if (Optional<DWARFFormValue> F = find(Attr)) 4040b57cec5SDimitry Andric return getAttributeValueAsReferencedDie(*F); 4050b57cec5SDimitry Andric return DWARFDie(); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric DWARFDie 4090b57cec5SDimitry Andric DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { 4100b57cec5SDimitry Andric if (auto SpecRef = V.getAsRelativeReference()) { 4110b57cec5SDimitry Andric if (SpecRef->Unit) 4120b57cec5SDimitry Andric return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset); 4130b57cec5SDimitry Andric if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset)) 4140b57cec5SDimitry Andric return SpecUnit->getDIEForOffset(SpecRef->Offset); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric return DWARFDie(); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { 4200b57cec5SDimitry Andric return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 423480093f4SDimitry Andric Optional<uint64_t> DWARFDie::getLocBaseAttribute() const { 424480093f4SDimitry Andric return toSectionOffset(find(DW_AT_loclists_base)); 425480093f4SDimitry Andric } 426480093f4SDimitry Andric 4270b57cec5SDimitry Andric Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { 428e8d8bef9SDimitry Andric uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize()); 429e8d8bef9SDimitry Andric if (LowPC == Tombstone) 430e8d8bef9SDimitry Andric return None; 4310b57cec5SDimitry Andric if (auto FormValue = find(DW_AT_high_pc)) { 4320b57cec5SDimitry Andric if (auto Address = FormValue->getAsAddress()) { 4330b57cec5SDimitry Andric // High PC is an address. 4340b57cec5SDimitry Andric return Address; 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric if (auto Offset = FormValue->getAsUnsignedConstant()) { 4370b57cec5SDimitry Andric // High PC is an offset from LowPC. 4380b57cec5SDimitry Andric return LowPC + *Offset; 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric return None; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 4450b57cec5SDimitry Andric uint64_t &SectionIndex) const { 4460b57cec5SDimitry Andric auto F = find(DW_AT_low_pc); 4470b57cec5SDimitry Andric auto LowPcAddr = toSectionedAddress(F); 4480b57cec5SDimitry Andric if (!LowPcAddr) 4490b57cec5SDimitry Andric return false; 4500b57cec5SDimitry Andric if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { 4510b57cec5SDimitry Andric LowPC = LowPcAddr->Address; 4520b57cec5SDimitry Andric HighPC = *HighPcAddr; 4530b57cec5SDimitry Andric SectionIndex = LowPcAddr->SectionIndex; 4540b57cec5SDimitry Andric return true; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { 4600b57cec5SDimitry Andric if (isNULL()) 4610b57cec5SDimitry Andric return DWARFAddressRangesVector(); 4620b57cec5SDimitry Andric // Single range specified by low/high PC. 4630b57cec5SDimitry Andric uint64_t LowPC, HighPC, Index; 4640b57cec5SDimitry Andric if (getLowAndHighPC(LowPC, HighPC, Index)) 4650b57cec5SDimitry Andric return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric Optional<DWARFFormValue> Value = find(DW_AT_ranges); 4680b57cec5SDimitry Andric if (Value) { 4690b57cec5SDimitry Andric if (Value->getForm() == DW_FORM_rnglistx) 4700b57cec5SDimitry Andric return U->findRnglistFromIndex(*Value->getAsSectionOffset()); 4710b57cec5SDimitry Andric return U->findRnglistFromOffset(*Value->getAsSectionOffset()); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric return DWARFAddressRangesVector(); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric void DWARFDie::collectChildrenAddressRanges( 4770b57cec5SDimitry Andric DWARFAddressRangesVector &Ranges) const { 4780b57cec5SDimitry Andric if (isNULL()) 4790b57cec5SDimitry Andric return; 4800b57cec5SDimitry Andric if (isSubprogramDIE()) { 4810b57cec5SDimitry Andric if (auto DIERangesOrError = getAddressRanges()) 482e8d8bef9SDimitry Andric llvm::append_range(Ranges, DIERangesOrError.get()); 4830b57cec5SDimitry Andric else 4840b57cec5SDimitry Andric llvm::consumeError(DIERangesOrError.takeError()); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric for (auto Child : children()) 4880b57cec5SDimitry Andric Child.collectChildrenAddressRanges(Ranges); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { 4920b57cec5SDimitry Andric auto RangesOrError = getAddressRanges(); 4930b57cec5SDimitry Andric if (!RangesOrError) { 4940b57cec5SDimitry Andric llvm::consumeError(RangesOrError.takeError()); 4950b57cec5SDimitry Andric return false; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric for (const auto &R : RangesOrError.get()) 4990b57cec5SDimitry Andric if (R.LowPC <= Address && Address < R.HighPC) 5000b57cec5SDimitry Andric return true; 5010b57cec5SDimitry Andric return false; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 504480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector> 505480093f4SDimitry Andric DWARFDie::getLocations(dwarf::Attribute Attr) const { 506480093f4SDimitry Andric Optional<DWARFFormValue> Location = find(Attr); 507480093f4SDimitry Andric if (!Location) 508480093f4SDimitry Andric return createStringError(inconvertibleErrorCode(), "No %s", 509480093f4SDimitry Andric dwarf::AttributeString(Attr).data()); 510480093f4SDimitry Andric 511480093f4SDimitry Andric if (Optional<uint64_t> Off = Location->getAsSectionOffset()) { 512480093f4SDimitry Andric uint64_t Offset = *Off; 513480093f4SDimitry Andric 514480093f4SDimitry Andric if (Location->getForm() == DW_FORM_loclistx) { 515480093f4SDimitry Andric if (auto LoclistOffset = U->getLoclistOffset(Offset)) 516480093f4SDimitry Andric Offset = *LoclistOffset; 517480093f4SDimitry Andric else 518480093f4SDimitry Andric return createStringError(inconvertibleErrorCode(), 519480093f4SDimitry Andric "Loclist table not found"); 520480093f4SDimitry Andric } 521480093f4SDimitry Andric return U->findLoclistFromOffset(Offset); 522480093f4SDimitry Andric } 523480093f4SDimitry Andric 524480093f4SDimitry Andric if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { 525480093f4SDimitry Andric return DWARFLocationExpressionsVector{ 526480093f4SDimitry Andric DWARFLocationExpression{None, to_vector<4>(*Expr)}}; 527480093f4SDimitry Andric } 528480093f4SDimitry Andric 529480093f4SDimitry Andric return createStringError( 530480093f4SDimitry Andric inconvertibleErrorCode(), "Unsupported %s encoding: %s", 531480093f4SDimitry Andric dwarf::AttributeString(Attr).data(), 532480093f4SDimitry Andric dwarf::FormEncodingString(Location->getForm()).data()); 533480093f4SDimitry Andric } 534480093f4SDimitry Andric 5350b57cec5SDimitry Andric const char *DWARFDie::getSubroutineName(DINameKind Kind) const { 5360b57cec5SDimitry Andric if (!isSubroutineDIE()) 5370b57cec5SDimitry Andric return nullptr; 5380b57cec5SDimitry Andric return getName(Kind); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric const char *DWARFDie::getName(DINameKind Kind) const { 5420b57cec5SDimitry Andric if (!isValid() || Kind == DINameKind::None) 5430b57cec5SDimitry Andric return nullptr; 5440b57cec5SDimitry Andric // Try to get mangled name only if it was asked for. 5450b57cec5SDimitry Andric if (Kind == DINameKind::LinkageName) { 5465ffd83dbSDimitry Andric if (auto Name = getLinkageName()) 5470b57cec5SDimitry Andric return Name; 5480b57cec5SDimitry Andric } 5495ffd83dbSDimitry Andric return getShortName(); 5505ffd83dbSDimitry Andric } 5515ffd83dbSDimitry Andric 5525ffd83dbSDimitry Andric const char *DWARFDie::getShortName() const { 5535ffd83dbSDimitry Andric if (!isValid()) 5540b57cec5SDimitry Andric return nullptr; 5555ffd83dbSDimitry Andric 5565ffd83dbSDimitry Andric return dwarf::toString(findRecursively(dwarf::DW_AT_name), nullptr); 5575ffd83dbSDimitry Andric } 5585ffd83dbSDimitry Andric 5595ffd83dbSDimitry Andric const char *DWARFDie::getLinkageName() const { 5605ffd83dbSDimitry Andric if (!isValid()) 5615ffd83dbSDimitry Andric return nullptr; 5625ffd83dbSDimitry Andric 5635ffd83dbSDimitry Andric return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name, 5645ffd83dbSDimitry Andric dwarf::DW_AT_linkage_name}), 5655ffd83dbSDimitry Andric nullptr); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric uint64_t DWARFDie::getDeclLine() const { 5690b57cec5SDimitry Andric return toUnsigned(findRecursively(DW_AT_decl_line), 0); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 572e8d8bef9SDimitry Andric std::string 573e8d8bef9SDimitry Andric DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { 574e8d8bef9SDimitry Andric std::string FileName; 575e8d8bef9SDimitry Andric if (auto DeclFile = toUnsigned(findRecursively(DW_AT_decl_file))) { 576e8d8bef9SDimitry Andric if (const auto *LT = U->getContext().getLineTableForUnit(U)) { 577e8d8bef9SDimitry Andric LT->getFileNameByIndex(*DeclFile, U->getCompilationDir(), Kind, FileName); 578e8d8bef9SDimitry Andric } 579e8d8bef9SDimitry Andric } 580e8d8bef9SDimitry Andric return FileName; 581e8d8bef9SDimitry Andric } 582e8d8bef9SDimitry Andric 5830b57cec5SDimitry Andric void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 5840b57cec5SDimitry Andric uint32_t &CallColumn, 5850b57cec5SDimitry Andric uint32_t &CallDiscriminator) const { 5860b57cec5SDimitry Andric CallFile = toUnsigned(find(DW_AT_call_file), 0); 5870b57cec5SDimitry Andric CallLine = toUnsigned(find(DW_AT_call_line), 0); 5880b57cec5SDimitry Andric CallColumn = toUnsigned(find(DW_AT_call_column), 0); 5890b57cec5SDimitry Andric CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric /// Helper to dump a DIE with all of its parents, but no siblings. 5930b57cec5SDimitry Andric static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, 5940b57cec5SDimitry Andric DIDumpOptions DumpOpts, unsigned Depth = 0) { 5950b57cec5SDimitry Andric if (!Die) 5960b57cec5SDimitry Andric return Indent; 5970b57cec5SDimitry Andric if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) 5980b57cec5SDimitry Andric return Indent; 5990b57cec5SDimitry Andric Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); 6000b57cec5SDimitry Andric Die.dump(OS, Indent, DumpOpts); 6010b57cec5SDimitry Andric return Indent + 2; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric void DWARFDie::dump(raw_ostream &OS, unsigned Indent, 6050b57cec5SDimitry Andric DIDumpOptions DumpOpts) const { 6060b57cec5SDimitry Andric if (!isValid()) 6070b57cec5SDimitry Andric return; 6080b57cec5SDimitry Andric DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); 6098bcb0991SDimitry Andric const uint64_t Offset = getOffset(); 6108bcb0991SDimitry Andric uint64_t offset = Offset; 6110b57cec5SDimitry Andric if (DumpOpts.ShowParents) { 6120b57cec5SDimitry Andric DIDumpOptions ParentDumpOpts = DumpOpts; 6130b57cec5SDimitry Andric ParentDumpOpts.ShowParents = false; 6140b57cec5SDimitry Andric ParentDumpOpts.ShowChildren = false; 6150b57cec5SDimitry Andric Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric if (debug_info_data.isValidOffset(offset)) { 6190b57cec5SDimitry Andric uint32_t abbrCode = debug_info_data.getULEB128(&offset); 6200b57cec5SDimitry Andric if (DumpOpts.ShowAddresses) 6210b57cec5SDimitry Andric WithColor(OS, HighlightColor::Address).get() 6228bcb0991SDimitry Andric << format("\n0x%8.8" PRIx64 ": ", Offset); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric if (abbrCode) { 6250b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 6260b57cec5SDimitry Andric if (AbbrevDecl) { 6270b57cec5SDimitry Andric WithColor(OS, HighlightColor::Tag).get().indent(Indent) 6280b57cec5SDimitry Andric << formatv("{0}", getTag()); 6290b57cec5SDimitry Andric if (DumpOpts.Verbose) 6300b57cec5SDimitry Andric OS << format(" [%u] %c", abbrCode, 6310b57cec5SDimitry Andric AbbrevDecl->hasChildren() ? '*' : ' '); 6320b57cec5SDimitry Andric OS << '\n'; 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // Dump all data in the DIE for the attributes. 635*4652422eSDimitry Andric for (const DWARFAttribute &AttrValue : attributes()) 636*4652422eSDimitry Andric dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric DWARFDie child = getFirstChild(); 6390b57cec5SDimitry Andric if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { 6400b57cec5SDimitry Andric DumpOpts.ChildRecurseDepth--; 6410b57cec5SDimitry Andric DIDumpOptions ChildDumpOpts = DumpOpts; 6420b57cec5SDimitry Andric ChildDumpOpts.ShowParents = false; 6430b57cec5SDimitry Andric while (child) { 6440b57cec5SDimitry Andric child.dump(OS, Indent + 2, ChildDumpOpts); 6450b57cec5SDimitry Andric child = child.getSibling(); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric } else { 6490b57cec5SDimitry Andric OS << "Abbreviation code not found in 'debug_abbrev' class for code: " 6500b57cec5SDimitry Andric << abbrCode << '\n'; 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric } else { 6530b57cec5SDimitry Andric OS.indent(Indent) << "NULL\n"; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric DWARFDie DWARFDie::getParent() const { 6610b57cec5SDimitry Andric if (isValid()) 6620b57cec5SDimitry Andric return U->getParent(Die); 6630b57cec5SDimitry Andric return DWARFDie(); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric DWARFDie DWARFDie::getSibling() const { 6670b57cec5SDimitry Andric if (isValid()) 6680b57cec5SDimitry Andric return U->getSibling(Die); 6690b57cec5SDimitry Andric return DWARFDie(); 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric DWARFDie DWARFDie::getPreviousSibling() const { 6730b57cec5SDimitry Andric if (isValid()) 6740b57cec5SDimitry Andric return U->getPreviousSibling(Die); 6750b57cec5SDimitry Andric return DWARFDie(); 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric DWARFDie DWARFDie::getFirstChild() const { 6790b57cec5SDimitry Andric if (isValid()) 6800b57cec5SDimitry Andric return U->getFirstChild(Die); 6810b57cec5SDimitry Andric return DWARFDie(); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric DWARFDie DWARFDie::getLastChild() const { 6850b57cec5SDimitry Andric if (isValid()) 6860b57cec5SDimitry Andric return U->getLastChild(Die); 6870b57cec5SDimitry Andric return DWARFDie(); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { 6910b57cec5SDimitry Andric return make_range(attribute_iterator(*this, false), 6920b57cec5SDimitry Andric attribute_iterator(*this, true)); 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) 6960b57cec5SDimitry Andric : Die(D), Index(0) { 6970b57cec5SDimitry Andric auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); 6980b57cec5SDimitry Andric assert(AbbrDecl && "Must have abbreviation declaration"); 6990b57cec5SDimitry Andric if (End) { 7000b57cec5SDimitry Andric // This is the end iterator so we set the index to the attribute count. 7010b57cec5SDimitry Andric Index = AbbrDecl->getNumAttributes(); 7020b57cec5SDimitry Andric } else { 7030b57cec5SDimitry Andric // This is the begin iterator so we extract the value for this->Index. 7040b57cec5SDimitry Andric AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); 7050b57cec5SDimitry Andric updateForIndex(*AbbrDecl, 0); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric void DWARFDie::attribute_iterator::updateForIndex( 7100b57cec5SDimitry Andric const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { 7110b57cec5SDimitry Andric Index = I; 7120b57cec5SDimitry Andric // AbbrDecl must be valid before calling this function. 7130b57cec5SDimitry Andric auto NumAttrs = AbbrDecl.getNumAttributes(); 7140b57cec5SDimitry Andric if (Index < NumAttrs) { 7150b57cec5SDimitry Andric AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); 7160b57cec5SDimitry Andric // Add the previous byte size of any previous attribute value. 7170b57cec5SDimitry Andric AttrValue.Offset += AttrValue.ByteSize; 7188bcb0991SDimitry Andric uint64_t ParseOffset = AttrValue.Offset; 719*4652422eSDimitry Andric if (AbbrDecl.getAttrIsImplicitConstByIndex(Index)) 720*4652422eSDimitry Andric AttrValue.Value = DWARFFormValue::createFromSValue( 721*4652422eSDimitry Andric AbbrDecl.getFormByIndex(Index), 722*4652422eSDimitry Andric AbbrDecl.getAttrImplicitConstValueByIndex(Index)); 723*4652422eSDimitry Andric else { 7240b57cec5SDimitry Andric auto U = Die.getDwarfUnit(); 7250b57cec5SDimitry Andric assert(U && "Die must have valid DWARF unit"); 7260b57cec5SDimitry Andric AttrValue.Value = DWARFFormValue::createFromUnit( 7270b57cec5SDimitry Andric AbbrDecl.getFormByIndex(Index), U, &ParseOffset); 728*4652422eSDimitry Andric } 7290b57cec5SDimitry Andric AttrValue.ByteSize = ParseOffset - AttrValue.Offset; 7300b57cec5SDimitry Andric } else { 7310b57cec5SDimitry Andric assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); 7320b57cec5SDimitry Andric AttrValue = {}; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { 7370b57cec5SDimitry Andric if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) 7380b57cec5SDimitry Andric updateForIndex(*AbbrDecl, Index + 1); 7390b57cec5SDimitry Andric return *this; 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { 7430b57cec5SDimitry Andric switch (Attr) { 7440b57cec5SDimitry Andric // From the DWARF v5 specification. 7450b57cec5SDimitry Andric case DW_AT_location: 7460b57cec5SDimitry Andric case DW_AT_byte_size: 7470b57cec5SDimitry Andric case DW_AT_bit_size: 7480b57cec5SDimitry Andric case DW_AT_string_length: 7490b57cec5SDimitry Andric case DW_AT_lower_bound: 7500b57cec5SDimitry Andric case DW_AT_return_addr: 7510b57cec5SDimitry Andric case DW_AT_bit_stride: 7520b57cec5SDimitry Andric case DW_AT_upper_bound: 7530b57cec5SDimitry Andric case DW_AT_count: 7540b57cec5SDimitry Andric case DW_AT_data_member_location: 7550b57cec5SDimitry Andric case DW_AT_frame_base: 7560b57cec5SDimitry Andric case DW_AT_segment: 7570b57cec5SDimitry Andric case DW_AT_static_link: 7580b57cec5SDimitry Andric case DW_AT_use_location: 7590b57cec5SDimitry Andric case DW_AT_vtable_elem_location: 7600b57cec5SDimitry Andric case DW_AT_allocated: 7610b57cec5SDimitry Andric case DW_AT_associated: 7620b57cec5SDimitry Andric case DW_AT_byte_stride: 7630b57cec5SDimitry Andric case DW_AT_rank: 7640b57cec5SDimitry Andric case DW_AT_call_value: 7650b57cec5SDimitry Andric case DW_AT_call_origin: 7660b57cec5SDimitry Andric case DW_AT_call_target: 7670b57cec5SDimitry Andric case DW_AT_call_target_clobbered: 7680b57cec5SDimitry Andric case DW_AT_call_data_location: 7690b57cec5SDimitry Andric case DW_AT_call_data_value: 7700b57cec5SDimitry Andric // Extensions. 7710b57cec5SDimitry Andric case DW_AT_GNU_call_site_value: 7728bcb0991SDimitry Andric case DW_AT_GNU_call_site_target: 7730b57cec5SDimitry Andric return true; 7740b57cec5SDimitry Andric default: 7750b57cec5SDimitry Andric return false; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric } 778