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" 10*5f757f3fSDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 110b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 130b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 1681ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 1781ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 190b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 2081ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" 2181ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 220b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 230b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 240b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 250b57cec5SDimitry Andric #include "llvm/Support/Format.h" 260b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 270b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 280b57cec5SDimitry Andric #include "llvm/Support/WithColor.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 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 { 4306c3fb27SDimitry Andric uint64_t Shift = llvm::countr_zero(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 72fe6060f1SDimitry Andric static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue, 730b57cec5SDimitry Andric DWARFUnit *U, unsigned Indent, 740b57cec5SDimitry Andric DIDumpOptions DumpOpts) { 75fe6060f1SDimitry Andric assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) && 76fe6060f1SDimitry Andric "bad FORM for location list"); 770b57cec5SDimitry Andric DWARFContext &Ctx = U->getContext(); 788bcb0991SDimitry Andric uint64_t Offset = *FormValue.getAsSectionOffset(); 79480093f4SDimitry Andric 80480093f4SDimitry Andric if (FormValue.getForm() == DW_FORM_loclistx) { 81480093f4SDimitry Andric FormValue.dump(OS, DumpOpts); 82480093f4SDimitry Andric 83480093f4SDimitry Andric if (auto LoclistOffset = U->getLoclistOffset(Offset)) 84480093f4SDimitry Andric Offset = *LoclistOffset; 85480093f4SDimitry Andric else 86480093f4SDimitry Andric return; 87480093f4SDimitry Andric } 88bdd1243dSDimitry Andric U->getLocationTable().dumpLocationList( 89bdd1243dSDimitry Andric &Offset, OS, U->getBaseAddress(), Ctx.getDWARFObj(), U, DumpOpts, Indent); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 92fe6060f1SDimitry Andric static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue, 93fe6060f1SDimitry Andric DWARFUnit *U, unsigned Indent, 94fe6060f1SDimitry Andric DIDumpOptions DumpOpts) { 95fe6060f1SDimitry Andric assert((FormValue.isFormClass(DWARFFormValue::FC_Block) || 96fe6060f1SDimitry Andric FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) && 97fe6060f1SDimitry Andric "bad FORM for location expression"); 98fe6060f1SDimitry Andric DWARFContext &Ctx = U->getContext(); 99fe6060f1SDimitry Andric ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); 100fe6060f1SDimitry Andric DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), 101fe6060f1SDimitry Andric Ctx.isLittleEndian(), 0); 102fe6060f1SDimitry Andric DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) 103bdd1243dSDimitry Andric .print(OS, DumpOpts, U); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 106349cc55cSDimitry Andric static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { 107349cc55cSDimitry Andric return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, 1114652422eSDimitry Andric const DWARFAttribute &AttrValue, unsigned Indent, 1120b57cec5SDimitry Andric DIDumpOptions DumpOpts) { 1130b57cec5SDimitry Andric if (!Die.isValid()) 1140b57cec5SDimitry Andric return; 1150b57cec5SDimitry Andric const char BaseIndent[] = " "; 1160b57cec5SDimitry Andric OS << BaseIndent; 1170b57cec5SDimitry Andric OS.indent(Indent + 2); 1184652422eSDimitry Andric dwarf::Attribute Attr = AttrValue.Attr; 1190b57cec5SDimitry Andric WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); 1200b57cec5SDimitry Andric 1214652422eSDimitry Andric dwarf::Form Form = AttrValue.Value.getForm(); 1220b57cec5SDimitry Andric if (DumpOpts.Verbose || DumpOpts.ShowForm) 1230b57cec5SDimitry Andric OS << formatv(" [{0}]", Form); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric DWARFUnit *U = Die.getDwarfUnit(); 1264652422eSDimitry Andric const DWARFFormValue &FormValue = AttrValue.Value; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric OS << "\t("; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric StringRef Name; 1310b57cec5SDimitry Andric std::string File; 1320b57cec5SDimitry Andric auto Color = HighlightColor::Enumerator; 1330b57cec5SDimitry Andric if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { 1340b57cec5SDimitry Andric Color = HighlightColor::String; 135753f127fSDimitry Andric if (const auto *LT = U->getContext().getLineTableForUnit(U)) { 136bdd1243dSDimitry Andric if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) { 1370b57cec5SDimitry Andric if (LT->getFileNameByIndex( 138753f127fSDimitry Andric *Val, U->getCompilationDir(), 139753f127fSDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 140753f127fSDimitry Andric File)) { 1410b57cec5SDimitry Andric File = '"' + File + '"'; 1420b57cec5SDimitry Andric Name = File; 1430b57cec5SDimitry Andric } 144753f127fSDimitry Andric } 145753f127fSDimitry Andric } 146bdd1243dSDimitry Andric } else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) 1470b57cec5SDimitry Andric Name = AttributeValueString(Attr, *Val); 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric if (!Name.empty()) 1500b57cec5SDimitry Andric WithColor(OS, Color) << Name; 151*5f757f3fSDimitry Andric else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column || 152*5f757f3fSDimitry Andric Attr == DW_AT_call_line || Attr == DW_AT_call_column) { 153bdd1243dSDimitry Andric if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) 154753f127fSDimitry Andric OS << *Val; 155753f127fSDimitry Andric else 156753f127fSDimitry Andric FormValue.dump(OS, DumpOpts); 157753f127fSDimitry Andric } else if (Attr == DW_AT_low_pc && 158e8d8bef9SDimitry Andric (FormValue.getAsAddress() == 159e8d8bef9SDimitry Andric dwarf::computeTombstoneAddress(U->getAddressByteSize()))) { 160e8d8bef9SDimitry Andric if (DumpOpts.Verbose) { 161e8d8bef9SDimitry Andric FormValue.dump(OS, DumpOpts); 162e8d8bef9SDimitry Andric OS << " ("; 163e8d8bef9SDimitry Andric } 164e8d8bef9SDimitry Andric OS << "dead code"; 165e8d8bef9SDimitry Andric if (DumpOpts.Verbose) 166e8d8bef9SDimitry Andric OS << ')'; 167e8d8bef9SDimitry Andric } else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && 1680b57cec5SDimitry Andric FormValue.getAsUnsignedConstant()) { 1690b57cec5SDimitry Andric if (DumpOpts.ShowAddresses) { 1700b57cec5SDimitry Andric // Print the actual address rather than the offset. 1710b57cec5SDimitry Andric uint64_t LowPC, HighPC, Index; 1720b57cec5SDimitry Andric if (Die.getLowAndHighPC(LowPC, HighPC, Index)) 173e8d8bef9SDimitry Andric DWARFFormValue::dumpAddress(OS, U->getAddressByteSize(), HighPC); 1740b57cec5SDimitry Andric else 1750b57cec5SDimitry Andric FormValue.dump(OS, DumpOpts); 1760b57cec5SDimitry Andric } 177fe6060f1SDimitry Andric } else if (DWARFAttribute::mayHaveLocationList(Attr) && 178fe6060f1SDimitry Andric FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) 179fe6060f1SDimitry Andric dumpLocationList(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, 180fe6060f1SDimitry Andric DumpOpts); 181fe6060f1SDimitry Andric else if (FormValue.isFormClass(DWARFFormValue::FC_Exprloc) || 182fe6060f1SDimitry Andric (DWARFAttribute::mayHaveLocationExpr(Attr) && 183fe6060f1SDimitry Andric FormValue.isFormClass(DWARFFormValue::FC_Block))) 184fe6060f1SDimitry Andric dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, 185fe6060f1SDimitry Andric DumpOpts); 1860b57cec5SDimitry Andric else 1870b57cec5SDimitry Andric FormValue.dump(OS, DumpOpts); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric std::string Space = DumpOpts.ShowAddresses ? " " : ""; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // We have dumped the attribute raw value. For some attributes 1920b57cec5SDimitry Andric // having both the raw value and the pretty-printed value is 1930b57cec5SDimitry Andric // interesting. These attributes are handled below. 194*5f757f3fSDimitry Andric if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin || 195*5f757f3fSDimitry Andric Attr == DW_AT_call_origin) { 1960b57cec5SDimitry Andric if (const char *Name = 1970b57cec5SDimitry Andric Die.getAttributeValueAsReferencedDie(FormValue).getName( 1980b57cec5SDimitry Andric DINameKind::LinkageName)) 1990b57cec5SDimitry Andric OS << Space << "\"" << Name << '\"'; 20081ad6265SDimitry Andric } else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) { 201349cc55cSDimitry Andric DWARFDie D = resolveReferencedType(Die, FormValue); 202349cc55cSDimitry Andric if (D && !D.isNULL()) { 2030b57cec5SDimitry Andric OS << Space << "\""; 20404eeddc0SDimitry Andric dumpTypeQualifiedName(D, OS); 2050b57cec5SDimitry Andric OS << '"'; 206349cc55cSDimitry Andric } 2070b57cec5SDimitry Andric } else if (Attr == DW_AT_APPLE_property_attribute) { 208bdd1243dSDimitry Andric if (std::optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) 2090b57cec5SDimitry Andric dumpApplePropertyAttribute(OS, *OptVal); 2100b57cec5SDimitry Andric } else if (Attr == DW_AT_ranges) { 2110b57cec5SDimitry Andric const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); 2120b57cec5SDimitry Andric // For DW_FORM_rnglistx we need to dump the offset separately, since 2130b57cec5SDimitry Andric // we have only dumped the index so far. 2140b57cec5SDimitry Andric if (FormValue.getForm() == DW_FORM_rnglistx) 2150b57cec5SDimitry Andric if (auto RangeListOffset = 2160b57cec5SDimitry Andric U->getRnglistOffset(*FormValue.getAsSectionOffset())) { 2170b57cec5SDimitry Andric DWARFFormValue FV = DWARFFormValue::createFromUValue( 2180b57cec5SDimitry Andric dwarf::DW_FORM_sec_offset, *RangeListOffset); 2190b57cec5SDimitry Andric FV.dump(OS, DumpOpts); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric if (auto RangesOrError = Die.getAddressRanges()) 2220b57cec5SDimitry Andric dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), 2230b57cec5SDimitry Andric sizeof(BaseIndent) + Indent + 4, DumpOpts); 2240b57cec5SDimitry Andric else 2255ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(createStringError( 2265ffd83dbSDimitry Andric errc::invalid_argument, "decoding address ranges: %s", 2275ffd83dbSDimitry Andric toString(RangesOrError.takeError()).c_str())); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric OS << ")\n"; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 233349cc55cSDimitry Andric void DWARFDie::getFullName(raw_string_ostream &OS, 234349cc55cSDimitry Andric std::string *OriginalFullName) const { 235349cc55cSDimitry Andric const char *NamePtr = getShortName(); 236349cc55cSDimitry Andric if (!NamePtr) 237349cc55cSDimitry Andric return; 23804eeddc0SDimitry Andric if (getTag() == DW_TAG_GNU_template_parameter_pack) 23904eeddc0SDimitry Andric return; 24004eeddc0SDimitry Andric dumpTypeUnqualifiedName(*this, OS, OriginalFullName); 241349cc55cSDimitry Andric } 242349cc55cSDimitry Andric 2430b57cec5SDimitry Andric bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric bool DWARFDie::isSubroutineDIE() const { 2460b57cec5SDimitry Andric auto Tag = getTag(); 2470b57cec5SDimitry Andric return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 250bdd1243dSDimitry Andric std::optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const { 2510b57cec5SDimitry Andric if (!isValid()) 252bdd1243dSDimitry Andric return std::nullopt; 2530b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 2540b57cec5SDimitry Andric if (AbbrevDecl) 2550b57cec5SDimitry Andric return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); 256bdd1243dSDimitry Andric return std::nullopt; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 259bdd1243dSDimitry Andric std::optional<DWARFFormValue> 2600b57cec5SDimitry Andric DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { 2610b57cec5SDimitry Andric if (!isValid()) 262bdd1243dSDimitry Andric return std::nullopt; 2630b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 2640b57cec5SDimitry Andric if (AbbrevDecl) { 2650b57cec5SDimitry Andric for (auto Attr : Attrs) { 2660b57cec5SDimitry Andric if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) 2670b57cec5SDimitry Andric return Value; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric } 270bdd1243dSDimitry Andric return std::nullopt; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 273bdd1243dSDimitry Andric std::optional<DWARFFormValue> 2740b57cec5SDimitry Andric DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { 2755ffd83dbSDimitry Andric SmallVector<DWARFDie, 3> Worklist; 2760b57cec5SDimitry Andric Worklist.push_back(*this); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // Keep track if DIEs already seen to prevent infinite recursion. 2790b57cec5SDimitry Andric // Empirically we rarely see a depth of more than 3 when dealing with valid 2800b57cec5SDimitry Andric // DWARF. This corresponds to following the DW_AT_abstract_origin and 2810b57cec5SDimitry Andric // DW_AT_specification just once. 2820b57cec5SDimitry Andric SmallSet<DWARFDie, 3> Seen; 2830b57cec5SDimitry Andric Seen.insert(*this); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric while (!Worklist.empty()) { 286e8d8bef9SDimitry Andric DWARFDie Die = Worklist.pop_back_val(); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric if (!Die.isValid()) 2890b57cec5SDimitry Andric continue; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric if (auto Value = Die.find(Attrs)) 2920b57cec5SDimitry Andric return Value; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 2950b57cec5SDimitry Andric if (Seen.insert(D).second) 2960b57cec5SDimitry Andric Worklist.push_back(D); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) 2990b57cec5SDimitry Andric if (Seen.insert(D).second) 3000b57cec5SDimitry Andric Worklist.push_back(D); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 303bdd1243dSDimitry Andric return std::nullopt; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric DWARFDie 3070b57cec5SDimitry Andric DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { 308bdd1243dSDimitry Andric if (std::optional<DWARFFormValue> F = find(Attr)) 3090b57cec5SDimitry Andric return getAttributeValueAsReferencedDie(*F); 3100b57cec5SDimitry Andric return DWARFDie(); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric DWARFDie 3140b57cec5SDimitry Andric DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { 315349cc55cSDimitry Andric DWARFDie Result; 3160b57cec5SDimitry Andric if (auto SpecRef = V.getAsRelativeReference()) { 3170b57cec5SDimitry Andric if (SpecRef->Unit) 318349cc55cSDimitry Andric Result = SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + 319349cc55cSDimitry Andric SpecRef->Offset); 320349cc55cSDimitry Andric else if (auto SpecUnit = 321349cc55cSDimitry Andric U->getUnitVector().getUnitForOffset(SpecRef->Offset)) 322349cc55cSDimitry Andric Result = SpecUnit->getDIEForOffset(SpecRef->Offset); 3230b57cec5SDimitry Andric } 324349cc55cSDimitry Andric return Result; 325349cc55cSDimitry Andric } 326349cc55cSDimitry Andric 327349cc55cSDimitry Andric DWARFDie DWARFDie::resolveTypeUnitReference() const { 328349cc55cSDimitry Andric if (auto Attr = find(DW_AT_signature)) { 329bdd1243dSDimitry Andric if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) { 330349cc55cSDimitry Andric if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash( 331349cc55cSDimitry Andric U->getVersion(), *Sig, U->isDWOUnit())) 332349cc55cSDimitry Andric return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset()); 333349cc55cSDimitry Andric } 334349cc55cSDimitry Andric } 335349cc55cSDimitry Andric return *this; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 338bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { 3390b57cec5SDimitry Andric return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 342bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getLocBaseAttribute() const { 343480093f4SDimitry Andric return toSectionOffset(find(DW_AT_loclists_base)); 344480093f4SDimitry Andric } 345480093f4SDimitry Andric 346bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { 347e8d8bef9SDimitry Andric uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize()); 348e8d8bef9SDimitry Andric if (LowPC == Tombstone) 349bdd1243dSDimitry Andric return std::nullopt; 3500b57cec5SDimitry Andric if (auto FormValue = find(DW_AT_high_pc)) { 3510b57cec5SDimitry Andric if (auto Address = FormValue->getAsAddress()) { 3520b57cec5SDimitry Andric // High PC is an address. 3530b57cec5SDimitry Andric return Address; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric if (auto Offset = FormValue->getAsUnsignedConstant()) { 3560b57cec5SDimitry Andric // High PC is an offset from LowPC. 3570b57cec5SDimitry Andric return LowPC + *Offset; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 360bdd1243dSDimitry Andric return std::nullopt; 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 3640b57cec5SDimitry Andric uint64_t &SectionIndex) const { 3650b57cec5SDimitry Andric auto F = find(DW_AT_low_pc); 3660b57cec5SDimitry Andric auto LowPcAddr = toSectionedAddress(F); 3670b57cec5SDimitry Andric if (!LowPcAddr) 3680b57cec5SDimitry Andric return false; 3690b57cec5SDimitry Andric if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { 3700b57cec5SDimitry Andric LowPC = LowPcAddr->Address; 3710b57cec5SDimitry Andric HighPC = *HighPcAddr; 3720b57cec5SDimitry Andric SectionIndex = LowPcAddr->SectionIndex; 3730b57cec5SDimitry Andric return true; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric return false; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { 3790b57cec5SDimitry Andric if (isNULL()) 3800b57cec5SDimitry Andric return DWARFAddressRangesVector(); 3810b57cec5SDimitry Andric // Single range specified by low/high PC. 3820b57cec5SDimitry Andric uint64_t LowPC, HighPC, Index; 3830b57cec5SDimitry Andric if (getLowAndHighPC(LowPC, HighPC, Index)) 3840b57cec5SDimitry Andric return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; 3850b57cec5SDimitry Andric 386bdd1243dSDimitry Andric std::optional<DWARFFormValue> Value = find(DW_AT_ranges); 3870b57cec5SDimitry Andric if (Value) { 3880b57cec5SDimitry Andric if (Value->getForm() == DW_FORM_rnglistx) 3890b57cec5SDimitry Andric return U->findRnglistFromIndex(*Value->getAsSectionOffset()); 3900b57cec5SDimitry Andric return U->findRnglistFromOffset(*Value->getAsSectionOffset()); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric return DWARFAddressRangesVector(); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { 3960b57cec5SDimitry Andric auto RangesOrError = getAddressRanges(); 3970b57cec5SDimitry Andric if (!RangesOrError) { 3980b57cec5SDimitry Andric llvm::consumeError(RangesOrError.takeError()); 3990b57cec5SDimitry Andric return false; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric for (const auto &R : RangesOrError.get()) 4030b57cec5SDimitry Andric if (R.LowPC <= Address && Address < R.HighPC) 4040b57cec5SDimitry Andric return true; 4050b57cec5SDimitry Andric return false; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 408480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector> 409480093f4SDimitry Andric DWARFDie::getLocations(dwarf::Attribute Attr) const { 410bdd1243dSDimitry Andric std::optional<DWARFFormValue> Location = find(Attr); 411480093f4SDimitry Andric if (!Location) 412480093f4SDimitry Andric return createStringError(inconvertibleErrorCode(), "No %s", 413480093f4SDimitry Andric dwarf::AttributeString(Attr).data()); 414480093f4SDimitry Andric 415bdd1243dSDimitry Andric if (std::optional<uint64_t> Off = Location->getAsSectionOffset()) { 416480093f4SDimitry Andric uint64_t Offset = *Off; 417480093f4SDimitry Andric 418480093f4SDimitry Andric if (Location->getForm() == DW_FORM_loclistx) { 419480093f4SDimitry Andric if (auto LoclistOffset = U->getLoclistOffset(Offset)) 420480093f4SDimitry Andric Offset = *LoclistOffset; 421480093f4SDimitry Andric else 422480093f4SDimitry Andric return createStringError(inconvertibleErrorCode(), 423480093f4SDimitry Andric "Loclist table not found"); 424480093f4SDimitry Andric } 425480093f4SDimitry Andric return U->findLoclistFromOffset(Offset); 426480093f4SDimitry Andric } 427480093f4SDimitry Andric 428bdd1243dSDimitry Andric if (std::optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { 429480093f4SDimitry Andric return DWARFLocationExpressionsVector{ 430bdd1243dSDimitry Andric DWARFLocationExpression{std::nullopt, to_vector<4>(*Expr)}}; 431480093f4SDimitry Andric } 432480093f4SDimitry Andric 433480093f4SDimitry Andric return createStringError( 434480093f4SDimitry Andric inconvertibleErrorCode(), "Unsupported %s encoding: %s", 435480093f4SDimitry Andric dwarf::AttributeString(Attr).data(), 436480093f4SDimitry Andric dwarf::FormEncodingString(Location->getForm()).data()); 437480093f4SDimitry Andric } 438480093f4SDimitry Andric 4390b57cec5SDimitry Andric const char *DWARFDie::getSubroutineName(DINameKind Kind) const { 4400b57cec5SDimitry Andric if (!isSubroutineDIE()) 4410b57cec5SDimitry Andric return nullptr; 4420b57cec5SDimitry Andric return getName(Kind); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric const char *DWARFDie::getName(DINameKind Kind) const { 4460b57cec5SDimitry Andric if (!isValid() || Kind == DINameKind::None) 4470b57cec5SDimitry Andric return nullptr; 4480b57cec5SDimitry Andric // Try to get mangled name only if it was asked for. 4490b57cec5SDimitry Andric if (Kind == DINameKind::LinkageName) { 4505ffd83dbSDimitry Andric if (auto Name = getLinkageName()) 4510b57cec5SDimitry Andric return Name; 4520b57cec5SDimitry Andric } 4535ffd83dbSDimitry Andric return getShortName(); 4545ffd83dbSDimitry Andric } 4555ffd83dbSDimitry Andric 4565ffd83dbSDimitry Andric const char *DWARFDie::getShortName() const { 4575ffd83dbSDimitry Andric if (!isValid()) 4580b57cec5SDimitry Andric return nullptr; 4595ffd83dbSDimitry Andric 4605ffd83dbSDimitry Andric return dwarf::toString(findRecursively(dwarf::DW_AT_name), nullptr); 4615ffd83dbSDimitry Andric } 4625ffd83dbSDimitry Andric 4635ffd83dbSDimitry Andric const char *DWARFDie::getLinkageName() const { 4645ffd83dbSDimitry Andric if (!isValid()) 4655ffd83dbSDimitry Andric return nullptr; 4665ffd83dbSDimitry Andric 4675ffd83dbSDimitry Andric return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name, 4685ffd83dbSDimitry Andric dwarf::DW_AT_linkage_name}), 4695ffd83dbSDimitry Andric nullptr); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric uint64_t DWARFDie::getDeclLine() const { 4730b57cec5SDimitry Andric return toUnsigned(findRecursively(DW_AT_decl_line), 0); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 476e8d8bef9SDimitry Andric std::string 477e8d8bef9SDimitry Andric DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { 478349cc55cSDimitry Andric if (auto FormValue = findRecursively(DW_AT_decl_file)) 479349cc55cSDimitry Andric if (auto OptString = FormValue->getAsFile(Kind)) 480349cc55cSDimitry Andric return *OptString; 481349cc55cSDimitry Andric return {}; 482e8d8bef9SDimitry Andric } 483e8d8bef9SDimitry Andric 4840b57cec5SDimitry Andric void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 4850b57cec5SDimitry Andric uint32_t &CallColumn, 4860b57cec5SDimitry Andric uint32_t &CallDiscriminator) const { 4870b57cec5SDimitry Andric CallFile = toUnsigned(find(DW_AT_call_file), 0); 4880b57cec5SDimitry Andric CallLine = toUnsigned(find(DW_AT_call_line), 0); 4890b57cec5SDimitry Andric CallColumn = toUnsigned(find(DW_AT_call_column), 0); 4900b57cec5SDimitry Andric CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 493*5f757f3fSDimitry Andric static std::optional<uint64_t> 494*5f757f3fSDimitry Andric getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize, 495*5f757f3fSDimitry Andric SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) { 496*5f757f3fSDimitry Andric // Cycle detected? 497*5f757f3fSDimitry Andric if (!Visited.insert(Die.getDebugInfoEntry()).second) 498*5f757f3fSDimitry Andric return {}; 499*5f757f3fSDimitry Andric if (auto SizeAttr = Die.find(DW_AT_byte_size)) 500bdd1243dSDimitry Andric if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) 50181ad6265SDimitry Andric return Size; 50281ad6265SDimitry Andric 503*5f757f3fSDimitry Andric switch (Die.getTag()) { 50481ad6265SDimitry Andric case DW_TAG_pointer_type: 50581ad6265SDimitry Andric case DW_TAG_reference_type: 50681ad6265SDimitry Andric case DW_TAG_rvalue_reference_type: 50781ad6265SDimitry Andric return PointerSize; 50881ad6265SDimitry Andric case DW_TAG_ptr_to_member_type: { 509*5f757f3fSDimitry Andric if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) 51081ad6265SDimitry Andric if (BaseType.getTag() == DW_TAG_subroutine_type) 51181ad6265SDimitry Andric return 2 * PointerSize; 51281ad6265SDimitry Andric return PointerSize; 51381ad6265SDimitry Andric } 51481ad6265SDimitry Andric case DW_TAG_const_type: 51581ad6265SDimitry Andric case DW_TAG_immutable_type: 51681ad6265SDimitry Andric case DW_TAG_volatile_type: 51781ad6265SDimitry Andric case DW_TAG_restrict_type: 51881ad6265SDimitry Andric case DW_TAG_typedef: { 519*5f757f3fSDimitry Andric if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) 520*5f757f3fSDimitry Andric return getTypeSizeImpl(BaseType, PointerSize, Visited); 52181ad6265SDimitry Andric break; 52281ad6265SDimitry Andric } 52381ad6265SDimitry Andric case DW_TAG_array_type: { 524*5f757f3fSDimitry Andric DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type); 52581ad6265SDimitry Andric if (!BaseType) 526bdd1243dSDimitry Andric return std::nullopt; 527*5f757f3fSDimitry Andric std::optional<uint64_t> BaseSize = 528*5f757f3fSDimitry Andric getTypeSizeImpl(BaseType, PointerSize, Visited); 52981ad6265SDimitry Andric if (!BaseSize) 530bdd1243dSDimitry Andric return std::nullopt; 53181ad6265SDimitry Andric uint64_t Size = *BaseSize; 532*5f757f3fSDimitry Andric for (DWARFDie Child : Die) { 53381ad6265SDimitry Andric if (Child.getTag() != DW_TAG_subrange_type) 53481ad6265SDimitry Andric continue; 53581ad6265SDimitry Andric 53681ad6265SDimitry Andric if (auto ElemCountAttr = Child.find(DW_AT_count)) 537bdd1243dSDimitry Andric if (std::optional<uint64_t> ElemCount = 53881ad6265SDimitry Andric ElemCountAttr->getAsUnsignedConstant()) 53981ad6265SDimitry Andric Size *= *ElemCount; 54081ad6265SDimitry Andric if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) 541bdd1243dSDimitry Andric if (std::optional<int64_t> UpperBound = 54281ad6265SDimitry Andric UpperBoundAttr->getAsSignedConstant()) { 54381ad6265SDimitry Andric int64_t LowerBound = 0; 54481ad6265SDimitry Andric if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) 54581ad6265SDimitry Andric LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0); 54681ad6265SDimitry Andric Size *= *UpperBound - LowerBound + 1; 54781ad6265SDimitry Andric } 54881ad6265SDimitry Andric } 54981ad6265SDimitry Andric return Size; 55081ad6265SDimitry Andric } 55181ad6265SDimitry Andric default: 552*5f757f3fSDimitry Andric if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) 553*5f757f3fSDimitry Andric return getTypeSizeImpl(BaseType, PointerSize, Visited); 55481ad6265SDimitry Andric break; 55581ad6265SDimitry Andric } 556bdd1243dSDimitry Andric return std::nullopt; 55781ad6265SDimitry Andric } 55881ad6265SDimitry Andric 559*5f757f3fSDimitry Andric std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) { 560*5f757f3fSDimitry Andric SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited; 561*5f757f3fSDimitry Andric return getTypeSizeImpl(*this, PointerSize, Visited); 562*5f757f3fSDimitry Andric } 563*5f757f3fSDimitry Andric 5640b57cec5SDimitry Andric /// Helper to dump a DIE with all of its parents, but no siblings. 5650b57cec5SDimitry Andric static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, 5660b57cec5SDimitry Andric DIDumpOptions DumpOpts, unsigned Depth = 0) { 5670b57cec5SDimitry Andric if (!Die) 5680b57cec5SDimitry Andric return Indent; 5690b57cec5SDimitry Andric if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) 5700b57cec5SDimitry Andric return Indent; 5710b57cec5SDimitry Andric Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); 5720b57cec5SDimitry Andric Die.dump(OS, Indent, DumpOpts); 5730b57cec5SDimitry Andric return Indent + 2; 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric void DWARFDie::dump(raw_ostream &OS, unsigned Indent, 5770b57cec5SDimitry Andric DIDumpOptions DumpOpts) const { 5780b57cec5SDimitry Andric if (!isValid()) 5790b57cec5SDimitry Andric return; 5800b57cec5SDimitry Andric DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); 5818bcb0991SDimitry Andric const uint64_t Offset = getOffset(); 5828bcb0991SDimitry Andric uint64_t offset = Offset; 5830b57cec5SDimitry Andric if (DumpOpts.ShowParents) { 5840b57cec5SDimitry Andric DIDumpOptions ParentDumpOpts = DumpOpts; 5850b57cec5SDimitry Andric ParentDumpOpts.ShowParents = false; 5860b57cec5SDimitry Andric ParentDumpOpts.ShowChildren = false; 5870b57cec5SDimitry Andric Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric if (debug_info_data.isValidOffset(offset)) { 5910b57cec5SDimitry Andric uint32_t abbrCode = debug_info_data.getULEB128(&offset); 5920b57cec5SDimitry Andric if (DumpOpts.ShowAddresses) 5930b57cec5SDimitry Andric WithColor(OS, HighlightColor::Address).get() 5948bcb0991SDimitry Andric << format("\n0x%8.8" PRIx64 ": ", Offset); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric if (abbrCode) { 5970b57cec5SDimitry Andric auto AbbrevDecl = getAbbreviationDeclarationPtr(); 5980b57cec5SDimitry Andric if (AbbrevDecl) { 5990b57cec5SDimitry Andric WithColor(OS, HighlightColor::Tag).get().indent(Indent) 6000b57cec5SDimitry Andric << formatv("{0}", getTag()); 601349cc55cSDimitry Andric if (DumpOpts.Verbose) { 6020b57cec5SDimitry Andric OS << format(" [%u] %c", abbrCode, 6030b57cec5SDimitry Andric AbbrevDecl->hasChildren() ? '*' : ' '); 604bdd1243dSDimitry Andric if (std::optional<uint32_t> ParentIdx = Die->getParentIdx()) 605349cc55cSDimitry Andric OS << format(" (0x%8.8" PRIx64 ")", 606349cc55cSDimitry Andric U->getDIEAtIndex(*ParentIdx).getOffset()); 607349cc55cSDimitry Andric } 6080b57cec5SDimitry Andric OS << '\n'; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric // Dump all data in the DIE for the attributes. 6114652422eSDimitry Andric for (const DWARFAttribute &AttrValue : attributes()) 6124652422eSDimitry Andric dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts); 6130b57cec5SDimitry Andric 614fe6060f1SDimitry Andric if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) { 615fe6060f1SDimitry Andric DWARFDie Child = getFirstChild(); 6160b57cec5SDimitry Andric DumpOpts.ChildRecurseDepth--; 6170b57cec5SDimitry Andric DIDumpOptions ChildDumpOpts = DumpOpts; 6180b57cec5SDimitry Andric ChildDumpOpts.ShowParents = false; 619fe6060f1SDimitry Andric while (Child) { 620fe6060f1SDimitry Andric Child.dump(OS, Indent + 2, ChildDumpOpts); 621fe6060f1SDimitry Andric Child = Child.getSibling(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric } else { 6250b57cec5SDimitry Andric OS << "Abbreviation code not found in 'debug_abbrev' class for code: " 6260b57cec5SDimitry Andric << abbrCode << '\n'; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric } else { 6290b57cec5SDimitry Andric OS.indent(Indent) << "NULL\n"; 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric DWARFDie DWARFDie::getParent() const { 6370b57cec5SDimitry Andric if (isValid()) 6380b57cec5SDimitry Andric return U->getParent(Die); 6390b57cec5SDimitry Andric return DWARFDie(); 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric DWARFDie DWARFDie::getSibling() const { 6430b57cec5SDimitry Andric if (isValid()) 6440b57cec5SDimitry Andric return U->getSibling(Die); 6450b57cec5SDimitry Andric return DWARFDie(); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric DWARFDie DWARFDie::getPreviousSibling() const { 6490b57cec5SDimitry Andric if (isValid()) 6500b57cec5SDimitry Andric return U->getPreviousSibling(Die); 6510b57cec5SDimitry Andric return DWARFDie(); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric DWARFDie DWARFDie::getFirstChild() const { 6550b57cec5SDimitry Andric if (isValid()) 6560b57cec5SDimitry Andric return U->getFirstChild(Die); 6570b57cec5SDimitry Andric return DWARFDie(); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric DWARFDie DWARFDie::getLastChild() const { 6610b57cec5SDimitry Andric if (isValid()) 6620b57cec5SDimitry Andric return U->getLastChild(Die); 6630b57cec5SDimitry Andric return DWARFDie(); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { 6670b57cec5SDimitry Andric return make_range(attribute_iterator(*this, false), 6680b57cec5SDimitry Andric attribute_iterator(*this, true)); 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) 6720b57cec5SDimitry Andric : Die(D), Index(0) { 6730b57cec5SDimitry Andric auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); 6740b57cec5SDimitry Andric assert(AbbrDecl && "Must have abbreviation declaration"); 6750b57cec5SDimitry Andric if (End) { 6760b57cec5SDimitry Andric // This is the end iterator so we set the index to the attribute count. 6770b57cec5SDimitry Andric Index = AbbrDecl->getNumAttributes(); 6780b57cec5SDimitry Andric } else { 6790b57cec5SDimitry Andric // This is the begin iterator so we extract the value for this->Index. 6800b57cec5SDimitry Andric AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); 6810b57cec5SDimitry Andric updateForIndex(*AbbrDecl, 0); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric void DWARFDie::attribute_iterator::updateForIndex( 6860b57cec5SDimitry Andric const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { 6870b57cec5SDimitry Andric Index = I; 6880b57cec5SDimitry Andric // AbbrDecl must be valid before calling this function. 6890b57cec5SDimitry Andric auto NumAttrs = AbbrDecl.getNumAttributes(); 6900b57cec5SDimitry Andric if (Index < NumAttrs) { 6910b57cec5SDimitry Andric AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); 6920b57cec5SDimitry Andric // Add the previous byte size of any previous attribute value. 6930b57cec5SDimitry Andric AttrValue.Offset += AttrValue.ByteSize; 6948bcb0991SDimitry Andric uint64_t ParseOffset = AttrValue.Offset; 6954652422eSDimitry Andric if (AbbrDecl.getAttrIsImplicitConstByIndex(Index)) 6964652422eSDimitry Andric AttrValue.Value = DWARFFormValue::createFromSValue( 6974652422eSDimitry Andric AbbrDecl.getFormByIndex(Index), 6984652422eSDimitry Andric AbbrDecl.getAttrImplicitConstValueByIndex(Index)); 6994652422eSDimitry Andric else { 7000b57cec5SDimitry Andric auto U = Die.getDwarfUnit(); 7010b57cec5SDimitry Andric assert(U && "Die must have valid DWARF unit"); 7020b57cec5SDimitry Andric AttrValue.Value = DWARFFormValue::createFromUnit( 7030b57cec5SDimitry Andric AbbrDecl.getFormByIndex(Index), U, &ParseOffset); 7044652422eSDimitry Andric } 7050b57cec5SDimitry Andric AttrValue.ByteSize = ParseOffset - AttrValue.Offset; 7060b57cec5SDimitry Andric } else { 7070b57cec5SDimitry Andric assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); 7080b57cec5SDimitry Andric AttrValue = {}; 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { 7130b57cec5SDimitry Andric if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) 7140b57cec5SDimitry Andric updateForIndex(*AbbrDecl, Index + 1); 7150b57cec5SDimitry Andric return *this; 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 718fe6060f1SDimitry Andric bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) { 719fe6060f1SDimitry Andric switch(Attr) { 720fe6060f1SDimitry Andric case DW_AT_location: 721fe6060f1SDimitry Andric case DW_AT_string_length: 722fe6060f1SDimitry Andric case DW_AT_return_addr: 723fe6060f1SDimitry Andric case DW_AT_data_member_location: 724fe6060f1SDimitry Andric case DW_AT_frame_base: 725fe6060f1SDimitry Andric case DW_AT_static_link: 726fe6060f1SDimitry Andric case DW_AT_segment: 727fe6060f1SDimitry Andric case DW_AT_use_location: 728fe6060f1SDimitry Andric case DW_AT_vtable_elem_location: 729fe6060f1SDimitry Andric return true; 730fe6060f1SDimitry Andric default: 731fe6060f1SDimitry Andric return false; 732fe6060f1SDimitry Andric } 733fe6060f1SDimitry Andric } 734fe6060f1SDimitry Andric 735fe6060f1SDimitry Andric bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) { 7360b57cec5SDimitry Andric switch (Attr) { 7370b57cec5SDimitry Andric // From the DWARF v5 specification. 7380b57cec5SDimitry Andric case DW_AT_location: 7390b57cec5SDimitry Andric case DW_AT_byte_size: 740fe6060f1SDimitry Andric case DW_AT_bit_offset: 7410b57cec5SDimitry Andric case DW_AT_bit_size: 7420b57cec5SDimitry Andric case DW_AT_string_length: 7430b57cec5SDimitry Andric case DW_AT_lower_bound: 7440b57cec5SDimitry Andric case DW_AT_return_addr: 7450b57cec5SDimitry Andric case DW_AT_bit_stride: 7460b57cec5SDimitry Andric case DW_AT_upper_bound: 7470b57cec5SDimitry Andric case DW_AT_count: 7480b57cec5SDimitry Andric case DW_AT_data_member_location: 7490b57cec5SDimitry Andric case DW_AT_frame_base: 7500b57cec5SDimitry Andric case DW_AT_segment: 7510b57cec5SDimitry Andric case DW_AT_static_link: 7520b57cec5SDimitry Andric case DW_AT_use_location: 7530b57cec5SDimitry Andric case DW_AT_vtable_elem_location: 7540b57cec5SDimitry Andric case DW_AT_allocated: 7550b57cec5SDimitry Andric case DW_AT_associated: 756fe6060f1SDimitry Andric case DW_AT_data_location: 7570b57cec5SDimitry Andric case DW_AT_byte_stride: 7580b57cec5SDimitry Andric case DW_AT_rank: 7590b57cec5SDimitry Andric case DW_AT_call_value: 7600b57cec5SDimitry Andric case DW_AT_call_origin: 7610b57cec5SDimitry Andric case DW_AT_call_target: 7620b57cec5SDimitry Andric case DW_AT_call_target_clobbered: 7630b57cec5SDimitry Andric case DW_AT_call_data_location: 7640b57cec5SDimitry Andric case DW_AT_call_data_value: 7650b57cec5SDimitry Andric // Extensions. 7660b57cec5SDimitry Andric case DW_AT_GNU_call_site_value: 7678bcb0991SDimitry Andric case DW_AT_GNU_call_site_target: 7680b57cec5SDimitry Andric return true; 7690b57cec5SDimitry Andric default: 7700b57cec5SDimitry Andric return false; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric } 77304eeddc0SDimitry Andric 77404eeddc0SDimitry Andric namespace llvm { 77504eeddc0SDimitry Andric 77604eeddc0SDimitry Andric void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) { 77704eeddc0SDimitry Andric DWARFTypePrinter(OS).appendQualifiedName(DIE); 77804eeddc0SDimitry Andric } 77904eeddc0SDimitry Andric 78004eeddc0SDimitry Andric void dumpTypeUnqualifiedName(const DWARFDie &DIE, raw_ostream &OS, 78104eeddc0SDimitry Andric std::string *OriginalFullName) { 78204eeddc0SDimitry Andric DWARFTypePrinter(OS).appendUnqualifiedName(DIE, OriginalFullName); 78304eeddc0SDimitry Andric } 78404eeddc0SDimitry Andric 78504eeddc0SDimitry Andric } // namespace llvm 786