1*09467b48Spatrick //===- DWARFDie.cpp -------------------------------------------------------===// 2*09467b48Spatrick // 3*09467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*09467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*09467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*09467b48Spatrick // 7*09467b48Spatrick //===----------------------------------------------------------------------===// 8*09467b48Spatrick 9*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDie.h" 10*09467b48Spatrick #include "llvm/ADT/None.h" 11*09467b48Spatrick #include "llvm/ADT/Optional.h" 12*09467b48Spatrick #include "llvm/ADT/SmallSet.h" 13*09467b48Spatrick #include "llvm/ADT/StringRef.h" 14*09467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h" 15*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 16*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h" 17*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 18*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 19*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 20*09467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 21*09467b48Spatrick #include "llvm/Object/ObjectFile.h" 22*09467b48Spatrick #include "llvm/Support/DataExtractor.h" 23*09467b48Spatrick #include "llvm/Support/Format.h" 24*09467b48Spatrick #include "llvm/Support/FormatAdapters.h" 25*09467b48Spatrick #include "llvm/Support/FormatVariadic.h" 26*09467b48Spatrick #include "llvm/Support/MathExtras.h" 27*09467b48Spatrick #include "llvm/Support/WithColor.h" 28*09467b48Spatrick #include "llvm/Support/raw_ostream.h" 29*09467b48Spatrick #include <algorithm> 30*09467b48Spatrick #include <cassert> 31*09467b48Spatrick #include <cinttypes> 32*09467b48Spatrick #include <cstdint> 33*09467b48Spatrick #include <string> 34*09467b48Spatrick #include <utility> 35*09467b48Spatrick 36*09467b48Spatrick using namespace llvm; 37*09467b48Spatrick using namespace dwarf; 38*09467b48Spatrick using namespace object; 39*09467b48Spatrick 40*09467b48Spatrick static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { 41*09467b48Spatrick OS << " ("; 42*09467b48Spatrick do { 43*09467b48Spatrick uint64_t Shift = countTrailingZeros(Val); 44*09467b48Spatrick assert(Shift < 64 && "undefined behavior"); 45*09467b48Spatrick uint64_t Bit = 1ULL << Shift; 46*09467b48Spatrick auto PropName = ApplePropertyString(Bit); 47*09467b48Spatrick if (!PropName.empty()) 48*09467b48Spatrick OS << PropName; 49*09467b48Spatrick else 50*09467b48Spatrick OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); 51*09467b48Spatrick if (!(Val ^= Bit)) 52*09467b48Spatrick break; 53*09467b48Spatrick OS << ", "; 54*09467b48Spatrick } while (true); 55*09467b48Spatrick OS << ")"; 56*09467b48Spatrick } 57*09467b48Spatrick 58*09467b48Spatrick static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, 59*09467b48Spatrick const DWARFAddressRangesVector &Ranges, 60*09467b48Spatrick unsigned AddressSize, unsigned Indent, 61*09467b48Spatrick const DIDumpOptions &DumpOpts) { 62*09467b48Spatrick if (!DumpOpts.ShowAddresses) 63*09467b48Spatrick return; 64*09467b48Spatrick 65*09467b48Spatrick for (const DWARFAddressRange &R : Ranges) { 66*09467b48Spatrick OS << '\n'; 67*09467b48Spatrick OS.indent(Indent); 68*09467b48Spatrick R.dump(OS, AddressSize, DumpOpts, &Obj); 69*09467b48Spatrick } 70*09467b48Spatrick } 71*09467b48Spatrick 72*09467b48Spatrick static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, 73*09467b48Spatrick DWARFUnit *U, unsigned Indent, 74*09467b48Spatrick DIDumpOptions DumpOpts) { 75*09467b48Spatrick DWARFContext &Ctx = U->getContext(); 76*09467b48Spatrick const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 77*09467b48Spatrick if (FormValue.isFormClass(DWARFFormValue::FC_Block) || 78*09467b48Spatrick FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { 79*09467b48Spatrick ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); 80*09467b48Spatrick DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), 81*09467b48Spatrick Ctx.isLittleEndian(), 0); 82*09467b48Spatrick DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) 83*09467b48Spatrick .print(OS, MRI, U); 84*09467b48Spatrick return; 85*09467b48Spatrick } 86*09467b48Spatrick 87*09467b48Spatrick if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { 88*09467b48Spatrick uint64_t Offset = *FormValue.getAsSectionOffset(); 89*09467b48Spatrick 90*09467b48Spatrick if (FormValue.getForm() == DW_FORM_loclistx) { 91*09467b48Spatrick FormValue.dump(OS, DumpOpts); 92*09467b48Spatrick 93*09467b48Spatrick if (auto LoclistOffset = U->getLoclistOffset(Offset)) 94*09467b48Spatrick Offset = *LoclistOffset; 95*09467b48Spatrick else 96*09467b48Spatrick return; 97*09467b48Spatrick } 98*09467b48Spatrick U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), 99*09467b48Spatrick MRI, Ctx.getDWARFObj(), U, DumpOpts, 100*09467b48Spatrick Indent); 101*09467b48Spatrick return; 102*09467b48Spatrick } 103*09467b48Spatrick 104*09467b48Spatrick FormValue.dump(OS, DumpOpts); 105*09467b48Spatrick } 106*09467b48Spatrick 107*09467b48Spatrick /// Dump the name encoded in the type tag. 108*09467b48Spatrick static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) { 109*09467b48Spatrick StringRef TagStr = TagString(T); 110*09467b48Spatrick if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type")) 111*09467b48Spatrick return; 112*09467b48Spatrick OS << TagStr.substr(7, TagStr.size() - 12) << " "; 113*09467b48Spatrick } 114*09467b48Spatrick 115*09467b48Spatrick static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { 116*09467b48Spatrick Optional<uint64_t> Bound; 117*09467b48Spatrick for (const DWARFDie &C : D.children()) 118*09467b48Spatrick if (C.getTag() == DW_TAG_subrange_type) { 119*09467b48Spatrick Optional<uint64_t> LB; 120*09467b48Spatrick Optional<uint64_t> Count; 121*09467b48Spatrick Optional<uint64_t> UB; 122*09467b48Spatrick Optional<unsigned> DefaultLB; 123*09467b48Spatrick if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) 124*09467b48Spatrick LB = L->getAsUnsignedConstant(); 125*09467b48Spatrick if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) 126*09467b48Spatrick Count = CountV->getAsUnsignedConstant(); 127*09467b48Spatrick if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) 128*09467b48Spatrick UB = UpperV->getAsUnsignedConstant(); 129*09467b48Spatrick if (Optional<DWARFFormValue> LV = 130*09467b48Spatrick D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) 131*09467b48Spatrick if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) 132*09467b48Spatrick if ((DefaultLB = 133*09467b48Spatrick LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) 134*09467b48Spatrick if (LB && *LB == *DefaultLB) 135*09467b48Spatrick LB = None; 136*09467b48Spatrick if (!LB && !Count && !UB) 137*09467b48Spatrick OS << "[]"; 138*09467b48Spatrick else if (!LB && (Count || UB) && DefaultLB) 139*09467b48Spatrick OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']'; 140*09467b48Spatrick else { 141*09467b48Spatrick OS << "[["; 142*09467b48Spatrick if (LB) 143*09467b48Spatrick OS << *LB; 144*09467b48Spatrick else 145*09467b48Spatrick OS << '?'; 146*09467b48Spatrick OS << ", "; 147*09467b48Spatrick if (Count) 148*09467b48Spatrick if (LB) 149*09467b48Spatrick OS << *LB + *Count; 150*09467b48Spatrick else 151*09467b48Spatrick OS << "? + " << *Count; 152*09467b48Spatrick else if (UB) 153*09467b48Spatrick OS << *UB + 1; 154*09467b48Spatrick else 155*09467b48Spatrick OS << '?'; 156*09467b48Spatrick OS << ")]"; 157*09467b48Spatrick } 158*09467b48Spatrick } 159*09467b48Spatrick } 160*09467b48Spatrick 161*09467b48Spatrick /// Recursively dump the DIE type name when applicable. 162*09467b48Spatrick static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { 163*09467b48Spatrick if (!D.isValid()) 164*09467b48Spatrick return; 165*09467b48Spatrick 166*09467b48Spatrick if (const char *Name = D.getName(DINameKind::LinkageName)) { 167*09467b48Spatrick OS << Name; 168*09467b48Spatrick return; 169*09467b48Spatrick } 170*09467b48Spatrick 171*09467b48Spatrick // FIXME: We should have pretty printers per language. Currently we print 172*09467b48Spatrick // everything as if it was C++ and fall back to the TAG type name. 173*09467b48Spatrick const dwarf::Tag T = D.getTag(); 174*09467b48Spatrick switch (T) { 175*09467b48Spatrick case DW_TAG_array_type: 176*09467b48Spatrick case DW_TAG_pointer_type: 177*09467b48Spatrick case DW_TAG_ptr_to_member_type: 178*09467b48Spatrick case DW_TAG_reference_type: 179*09467b48Spatrick case DW_TAG_rvalue_reference_type: 180*09467b48Spatrick case DW_TAG_subroutine_type: 181*09467b48Spatrick break; 182*09467b48Spatrick default: 183*09467b48Spatrick dumpTypeTagName(OS, T); 184*09467b48Spatrick } 185*09467b48Spatrick 186*09467b48Spatrick // Follow the DW_AT_type if possible. 187*09467b48Spatrick DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type); 188*09467b48Spatrick dumpTypeName(OS, TypeDie); 189*09467b48Spatrick 190*09467b48Spatrick switch (T) { 191*09467b48Spatrick case DW_TAG_subroutine_type: { 192*09467b48Spatrick if (!TypeDie) 193*09467b48Spatrick OS << "void"; 194*09467b48Spatrick OS << '('; 195*09467b48Spatrick bool First = true; 196*09467b48Spatrick for (const DWARFDie &C : D.children()) { 197*09467b48Spatrick if (C.getTag() == DW_TAG_formal_parameter) { 198*09467b48Spatrick if (!First) 199*09467b48Spatrick OS << ", "; 200*09467b48Spatrick First = false; 201*09467b48Spatrick dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type)); 202*09467b48Spatrick } 203*09467b48Spatrick } 204*09467b48Spatrick OS << ')'; 205*09467b48Spatrick break; 206*09467b48Spatrick } 207*09467b48Spatrick case DW_TAG_array_type: { 208*09467b48Spatrick dumpArrayType(OS, D); 209*09467b48Spatrick break; 210*09467b48Spatrick } 211*09467b48Spatrick case DW_TAG_pointer_type: 212*09467b48Spatrick OS << '*'; 213*09467b48Spatrick break; 214*09467b48Spatrick case DW_TAG_ptr_to_member_type: 215*09467b48Spatrick if (DWARFDie Cont = 216*09467b48Spatrick D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) { 217*09467b48Spatrick dumpTypeName(OS << ' ', Cont); 218*09467b48Spatrick OS << "::"; 219*09467b48Spatrick } 220*09467b48Spatrick OS << '*'; 221*09467b48Spatrick break; 222*09467b48Spatrick case DW_TAG_reference_type: 223*09467b48Spatrick OS << '&'; 224*09467b48Spatrick break; 225*09467b48Spatrick case DW_TAG_rvalue_reference_type: 226*09467b48Spatrick OS << "&&"; 227*09467b48Spatrick break; 228*09467b48Spatrick default: 229*09467b48Spatrick break; 230*09467b48Spatrick } 231*09467b48Spatrick } 232*09467b48Spatrick 233*09467b48Spatrick static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, 234*09467b48Spatrick uint64_t *OffsetPtr, dwarf::Attribute Attr, 235*09467b48Spatrick dwarf::Form Form, unsigned Indent, 236*09467b48Spatrick DIDumpOptions DumpOpts) { 237*09467b48Spatrick if (!Die.isValid()) 238*09467b48Spatrick return; 239*09467b48Spatrick const char BaseIndent[] = " "; 240*09467b48Spatrick OS << BaseIndent; 241*09467b48Spatrick OS.indent(Indent + 2); 242*09467b48Spatrick WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); 243*09467b48Spatrick 244*09467b48Spatrick if (DumpOpts.Verbose || DumpOpts.ShowForm) 245*09467b48Spatrick OS << formatv(" [{0}]", Form); 246*09467b48Spatrick 247*09467b48Spatrick DWARFUnit *U = Die.getDwarfUnit(); 248*09467b48Spatrick DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr); 249*09467b48Spatrick 250*09467b48Spatrick OS << "\t("; 251*09467b48Spatrick 252*09467b48Spatrick StringRef Name; 253*09467b48Spatrick std::string File; 254*09467b48Spatrick auto Color = HighlightColor::Enumerator; 255*09467b48Spatrick if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { 256*09467b48Spatrick Color = HighlightColor::String; 257*09467b48Spatrick if (const auto *LT = U->getContext().getLineTableForUnit(U)) 258*09467b48Spatrick if (LT->getFileNameByIndex( 259*09467b48Spatrick FormValue.getAsUnsignedConstant().getValue(), 260*09467b48Spatrick U->getCompilationDir(), 261*09467b48Spatrick DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { 262*09467b48Spatrick File = '"' + File + '"'; 263*09467b48Spatrick Name = File; 264*09467b48Spatrick } 265*09467b48Spatrick } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) 266*09467b48Spatrick Name = AttributeValueString(Attr, *Val); 267*09467b48Spatrick 268*09467b48Spatrick if (!Name.empty()) 269*09467b48Spatrick WithColor(OS, Color) << Name; 270*09467b48Spatrick else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) 271*09467b48Spatrick OS << *FormValue.getAsUnsignedConstant(); 272*09467b48Spatrick else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && 273*09467b48Spatrick FormValue.getAsUnsignedConstant()) { 274*09467b48Spatrick if (DumpOpts.ShowAddresses) { 275*09467b48Spatrick // Print the actual address rather than the offset. 276*09467b48Spatrick uint64_t LowPC, HighPC, Index; 277*09467b48Spatrick if (Die.getLowAndHighPC(LowPC, HighPC, Index)) 278*09467b48Spatrick OS << format("0x%016" PRIx64, HighPC); 279*09467b48Spatrick else 280*09467b48Spatrick FormValue.dump(OS, DumpOpts); 281*09467b48Spatrick } 282*09467b48Spatrick } else if (Form == dwarf::Form::DW_FORM_exprloc || 283*09467b48Spatrick DWARFAttribute::mayHaveLocationDescription(Attr)) 284*09467b48Spatrick dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); 285*09467b48Spatrick else 286*09467b48Spatrick FormValue.dump(OS, DumpOpts); 287*09467b48Spatrick 288*09467b48Spatrick std::string Space = DumpOpts.ShowAddresses ? " " : ""; 289*09467b48Spatrick 290*09467b48Spatrick // We have dumped the attribute raw value. For some attributes 291*09467b48Spatrick // having both the raw value and the pretty-printed value is 292*09467b48Spatrick // interesting. These attributes are handled below. 293*09467b48Spatrick if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { 294*09467b48Spatrick if (const char *Name = 295*09467b48Spatrick Die.getAttributeValueAsReferencedDie(FormValue).getName( 296*09467b48Spatrick DINameKind::LinkageName)) 297*09467b48Spatrick OS << Space << "\"" << Name << '\"'; 298*09467b48Spatrick } else if (Attr == DW_AT_type) { 299*09467b48Spatrick OS << Space << "\""; 300*09467b48Spatrick dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue)); 301*09467b48Spatrick OS << '"'; 302*09467b48Spatrick } else if (Attr == DW_AT_APPLE_property_attribute) { 303*09467b48Spatrick if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) 304*09467b48Spatrick dumpApplePropertyAttribute(OS, *OptVal); 305*09467b48Spatrick } else if (Attr == DW_AT_ranges) { 306*09467b48Spatrick const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); 307*09467b48Spatrick // For DW_FORM_rnglistx we need to dump the offset separately, since 308*09467b48Spatrick // we have only dumped the index so far. 309*09467b48Spatrick if (FormValue.getForm() == DW_FORM_rnglistx) 310*09467b48Spatrick if (auto RangeListOffset = 311*09467b48Spatrick U->getRnglistOffset(*FormValue.getAsSectionOffset())) { 312*09467b48Spatrick DWARFFormValue FV = DWARFFormValue::createFromUValue( 313*09467b48Spatrick dwarf::DW_FORM_sec_offset, *RangeListOffset); 314*09467b48Spatrick FV.dump(OS, DumpOpts); 315*09467b48Spatrick } 316*09467b48Spatrick if (auto RangesOrError = Die.getAddressRanges()) 317*09467b48Spatrick dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), 318*09467b48Spatrick sizeof(BaseIndent) + Indent + 4, DumpOpts); 319*09467b48Spatrick else 320*09467b48Spatrick WithColor::error() << "decoding address ranges: " 321*09467b48Spatrick << toString(RangesOrError.takeError()) << '\n'; 322*09467b48Spatrick } 323*09467b48Spatrick 324*09467b48Spatrick OS << ")\n"; 325*09467b48Spatrick } 326*09467b48Spatrick 327*09467b48Spatrick bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; } 328*09467b48Spatrick 329*09467b48Spatrick bool DWARFDie::isSubroutineDIE() const { 330*09467b48Spatrick auto Tag = getTag(); 331*09467b48Spatrick return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; 332*09467b48Spatrick } 333*09467b48Spatrick 334*09467b48Spatrick Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const { 335*09467b48Spatrick if (!isValid()) 336*09467b48Spatrick return None; 337*09467b48Spatrick auto AbbrevDecl = getAbbreviationDeclarationPtr(); 338*09467b48Spatrick if (AbbrevDecl) 339*09467b48Spatrick return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); 340*09467b48Spatrick return None; 341*09467b48Spatrick } 342*09467b48Spatrick 343*09467b48Spatrick Optional<DWARFFormValue> 344*09467b48Spatrick DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { 345*09467b48Spatrick if (!isValid()) 346*09467b48Spatrick return None; 347*09467b48Spatrick auto AbbrevDecl = getAbbreviationDeclarationPtr(); 348*09467b48Spatrick if (AbbrevDecl) { 349*09467b48Spatrick for (auto Attr : Attrs) { 350*09467b48Spatrick if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) 351*09467b48Spatrick return Value; 352*09467b48Spatrick } 353*09467b48Spatrick } 354*09467b48Spatrick return None; 355*09467b48Spatrick } 356*09467b48Spatrick 357*09467b48Spatrick Optional<DWARFFormValue> 358*09467b48Spatrick DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { 359*09467b48Spatrick std::vector<DWARFDie> Worklist; 360*09467b48Spatrick Worklist.push_back(*this); 361*09467b48Spatrick 362*09467b48Spatrick // Keep track if DIEs already seen to prevent infinite recursion. 363*09467b48Spatrick // Empirically we rarely see a depth of more than 3 when dealing with valid 364*09467b48Spatrick // DWARF. This corresponds to following the DW_AT_abstract_origin and 365*09467b48Spatrick // DW_AT_specification just once. 366*09467b48Spatrick SmallSet<DWARFDie, 3> Seen; 367*09467b48Spatrick Seen.insert(*this); 368*09467b48Spatrick 369*09467b48Spatrick while (!Worklist.empty()) { 370*09467b48Spatrick DWARFDie Die = Worklist.back(); 371*09467b48Spatrick Worklist.pop_back(); 372*09467b48Spatrick 373*09467b48Spatrick if (!Die.isValid()) 374*09467b48Spatrick continue; 375*09467b48Spatrick 376*09467b48Spatrick if (auto Value = Die.find(Attrs)) 377*09467b48Spatrick return Value; 378*09467b48Spatrick 379*09467b48Spatrick if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 380*09467b48Spatrick if (Seen.insert(D).second) 381*09467b48Spatrick Worklist.push_back(D); 382*09467b48Spatrick 383*09467b48Spatrick if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) 384*09467b48Spatrick if (Seen.insert(D).second) 385*09467b48Spatrick Worklist.push_back(D); 386*09467b48Spatrick } 387*09467b48Spatrick 388*09467b48Spatrick return None; 389*09467b48Spatrick } 390*09467b48Spatrick 391*09467b48Spatrick DWARFDie 392*09467b48Spatrick DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { 393*09467b48Spatrick if (Optional<DWARFFormValue> F = find(Attr)) 394*09467b48Spatrick return getAttributeValueAsReferencedDie(*F); 395*09467b48Spatrick return DWARFDie(); 396*09467b48Spatrick } 397*09467b48Spatrick 398*09467b48Spatrick DWARFDie 399*09467b48Spatrick DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { 400*09467b48Spatrick if (auto SpecRef = V.getAsRelativeReference()) { 401*09467b48Spatrick if (SpecRef->Unit) 402*09467b48Spatrick return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset); 403*09467b48Spatrick if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset)) 404*09467b48Spatrick return SpecUnit->getDIEForOffset(SpecRef->Offset); 405*09467b48Spatrick } 406*09467b48Spatrick return DWARFDie(); 407*09467b48Spatrick } 408*09467b48Spatrick 409*09467b48Spatrick Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { 410*09467b48Spatrick return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); 411*09467b48Spatrick } 412*09467b48Spatrick 413*09467b48Spatrick Optional<uint64_t> DWARFDie::getLocBaseAttribute() const { 414*09467b48Spatrick return toSectionOffset(find(DW_AT_loclists_base)); 415*09467b48Spatrick } 416*09467b48Spatrick 417*09467b48Spatrick Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { 418*09467b48Spatrick if (auto FormValue = find(DW_AT_high_pc)) { 419*09467b48Spatrick if (auto Address = FormValue->getAsAddress()) { 420*09467b48Spatrick // High PC is an address. 421*09467b48Spatrick return Address; 422*09467b48Spatrick } 423*09467b48Spatrick if (auto Offset = FormValue->getAsUnsignedConstant()) { 424*09467b48Spatrick // High PC is an offset from LowPC. 425*09467b48Spatrick return LowPC + *Offset; 426*09467b48Spatrick } 427*09467b48Spatrick } 428*09467b48Spatrick return None; 429*09467b48Spatrick } 430*09467b48Spatrick 431*09467b48Spatrick bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 432*09467b48Spatrick uint64_t &SectionIndex) const { 433*09467b48Spatrick auto F = find(DW_AT_low_pc); 434*09467b48Spatrick auto LowPcAddr = toSectionedAddress(F); 435*09467b48Spatrick if (!LowPcAddr) 436*09467b48Spatrick return false; 437*09467b48Spatrick if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { 438*09467b48Spatrick LowPC = LowPcAddr->Address; 439*09467b48Spatrick HighPC = *HighPcAddr; 440*09467b48Spatrick SectionIndex = LowPcAddr->SectionIndex; 441*09467b48Spatrick return true; 442*09467b48Spatrick } 443*09467b48Spatrick return false; 444*09467b48Spatrick } 445*09467b48Spatrick 446*09467b48Spatrick Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { 447*09467b48Spatrick if (isNULL()) 448*09467b48Spatrick return DWARFAddressRangesVector(); 449*09467b48Spatrick // Single range specified by low/high PC. 450*09467b48Spatrick uint64_t LowPC, HighPC, Index; 451*09467b48Spatrick if (getLowAndHighPC(LowPC, HighPC, Index)) 452*09467b48Spatrick return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; 453*09467b48Spatrick 454*09467b48Spatrick Optional<DWARFFormValue> Value = find(DW_AT_ranges); 455*09467b48Spatrick if (Value) { 456*09467b48Spatrick if (Value->getForm() == DW_FORM_rnglistx) 457*09467b48Spatrick return U->findRnglistFromIndex(*Value->getAsSectionOffset()); 458*09467b48Spatrick return U->findRnglistFromOffset(*Value->getAsSectionOffset()); 459*09467b48Spatrick } 460*09467b48Spatrick return DWARFAddressRangesVector(); 461*09467b48Spatrick } 462*09467b48Spatrick 463*09467b48Spatrick void DWARFDie::collectChildrenAddressRanges( 464*09467b48Spatrick DWARFAddressRangesVector &Ranges) const { 465*09467b48Spatrick if (isNULL()) 466*09467b48Spatrick return; 467*09467b48Spatrick if (isSubprogramDIE()) { 468*09467b48Spatrick if (auto DIERangesOrError = getAddressRanges()) 469*09467b48Spatrick Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), 470*09467b48Spatrick DIERangesOrError.get().end()); 471*09467b48Spatrick else 472*09467b48Spatrick llvm::consumeError(DIERangesOrError.takeError()); 473*09467b48Spatrick } 474*09467b48Spatrick 475*09467b48Spatrick for (auto Child : children()) 476*09467b48Spatrick Child.collectChildrenAddressRanges(Ranges); 477*09467b48Spatrick } 478*09467b48Spatrick 479*09467b48Spatrick bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { 480*09467b48Spatrick auto RangesOrError = getAddressRanges(); 481*09467b48Spatrick if (!RangesOrError) { 482*09467b48Spatrick llvm::consumeError(RangesOrError.takeError()); 483*09467b48Spatrick return false; 484*09467b48Spatrick } 485*09467b48Spatrick 486*09467b48Spatrick for (const auto &R : RangesOrError.get()) 487*09467b48Spatrick if (R.LowPC <= Address && Address < R.HighPC) 488*09467b48Spatrick return true; 489*09467b48Spatrick return false; 490*09467b48Spatrick } 491*09467b48Spatrick 492*09467b48Spatrick Expected<DWARFLocationExpressionsVector> 493*09467b48Spatrick DWARFDie::getLocations(dwarf::Attribute Attr) const { 494*09467b48Spatrick Optional<DWARFFormValue> Location = find(Attr); 495*09467b48Spatrick if (!Location) 496*09467b48Spatrick return createStringError(inconvertibleErrorCode(), "No %s", 497*09467b48Spatrick dwarf::AttributeString(Attr).data()); 498*09467b48Spatrick 499*09467b48Spatrick if (Optional<uint64_t> Off = Location->getAsSectionOffset()) { 500*09467b48Spatrick uint64_t Offset = *Off; 501*09467b48Spatrick 502*09467b48Spatrick if (Location->getForm() == DW_FORM_loclistx) { 503*09467b48Spatrick if (auto LoclistOffset = U->getLoclistOffset(Offset)) 504*09467b48Spatrick Offset = *LoclistOffset; 505*09467b48Spatrick else 506*09467b48Spatrick return createStringError(inconvertibleErrorCode(), 507*09467b48Spatrick "Loclist table not found"); 508*09467b48Spatrick } 509*09467b48Spatrick return U->findLoclistFromOffset(Offset); 510*09467b48Spatrick } 511*09467b48Spatrick 512*09467b48Spatrick if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { 513*09467b48Spatrick return DWARFLocationExpressionsVector{ 514*09467b48Spatrick DWARFLocationExpression{None, to_vector<4>(*Expr)}}; 515*09467b48Spatrick } 516*09467b48Spatrick 517*09467b48Spatrick return createStringError( 518*09467b48Spatrick inconvertibleErrorCode(), "Unsupported %s encoding: %s", 519*09467b48Spatrick dwarf::AttributeString(Attr).data(), 520*09467b48Spatrick dwarf::FormEncodingString(Location->getForm()).data()); 521*09467b48Spatrick } 522*09467b48Spatrick 523*09467b48Spatrick const char *DWARFDie::getSubroutineName(DINameKind Kind) const { 524*09467b48Spatrick if (!isSubroutineDIE()) 525*09467b48Spatrick return nullptr; 526*09467b48Spatrick return getName(Kind); 527*09467b48Spatrick } 528*09467b48Spatrick 529*09467b48Spatrick const char *DWARFDie::getName(DINameKind Kind) const { 530*09467b48Spatrick if (!isValid() || Kind == DINameKind::None) 531*09467b48Spatrick return nullptr; 532*09467b48Spatrick // Try to get mangled name only if it was asked for. 533*09467b48Spatrick if (Kind == DINameKind::LinkageName) { 534*09467b48Spatrick if (auto Name = dwarf::toString( 535*09467b48Spatrick findRecursively({DW_AT_MIPS_linkage_name, DW_AT_linkage_name}), 536*09467b48Spatrick nullptr)) 537*09467b48Spatrick return Name; 538*09467b48Spatrick } 539*09467b48Spatrick if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr)) 540*09467b48Spatrick return Name; 541*09467b48Spatrick return nullptr; 542*09467b48Spatrick } 543*09467b48Spatrick 544*09467b48Spatrick uint64_t DWARFDie::getDeclLine() const { 545*09467b48Spatrick return toUnsigned(findRecursively(DW_AT_decl_line), 0); 546*09467b48Spatrick } 547*09467b48Spatrick 548*09467b48Spatrick void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 549*09467b48Spatrick uint32_t &CallColumn, 550*09467b48Spatrick uint32_t &CallDiscriminator) const { 551*09467b48Spatrick CallFile = toUnsigned(find(DW_AT_call_file), 0); 552*09467b48Spatrick CallLine = toUnsigned(find(DW_AT_call_line), 0); 553*09467b48Spatrick CallColumn = toUnsigned(find(DW_AT_call_column), 0); 554*09467b48Spatrick CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); 555*09467b48Spatrick } 556*09467b48Spatrick 557*09467b48Spatrick /// Helper to dump a DIE with all of its parents, but no siblings. 558*09467b48Spatrick static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, 559*09467b48Spatrick DIDumpOptions DumpOpts, unsigned Depth = 0) { 560*09467b48Spatrick if (!Die) 561*09467b48Spatrick return Indent; 562*09467b48Spatrick if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) 563*09467b48Spatrick return Indent; 564*09467b48Spatrick Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); 565*09467b48Spatrick Die.dump(OS, Indent, DumpOpts); 566*09467b48Spatrick return Indent + 2; 567*09467b48Spatrick } 568*09467b48Spatrick 569*09467b48Spatrick void DWARFDie::dump(raw_ostream &OS, unsigned Indent, 570*09467b48Spatrick DIDumpOptions DumpOpts) const { 571*09467b48Spatrick if (!isValid()) 572*09467b48Spatrick return; 573*09467b48Spatrick DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); 574*09467b48Spatrick const uint64_t Offset = getOffset(); 575*09467b48Spatrick uint64_t offset = Offset; 576*09467b48Spatrick if (DumpOpts.ShowParents) { 577*09467b48Spatrick DIDumpOptions ParentDumpOpts = DumpOpts; 578*09467b48Spatrick ParentDumpOpts.ShowParents = false; 579*09467b48Spatrick ParentDumpOpts.ShowChildren = false; 580*09467b48Spatrick Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); 581*09467b48Spatrick } 582*09467b48Spatrick 583*09467b48Spatrick if (debug_info_data.isValidOffset(offset)) { 584*09467b48Spatrick uint32_t abbrCode = debug_info_data.getULEB128(&offset); 585*09467b48Spatrick if (DumpOpts.ShowAddresses) 586*09467b48Spatrick WithColor(OS, HighlightColor::Address).get() 587*09467b48Spatrick << format("\n0x%8.8" PRIx64 ": ", Offset); 588*09467b48Spatrick 589*09467b48Spatrick if (abbrCode) { 590*09467b48Spatrick auto AbbrevDecl = getAbbreviationDeclarationPtr(); 591*09467b48Spatrick if (AbbrevDecl) { 592*09467b48Spatrick WithColor(OS, HighlightColor::Tag).get().indent(Indent) 593*09467b48Spatrick << formatv("{0}", getTag()); 594*09467b48Spatrick if (DumpOpts.Verbose) 595*09467b48Spatrick OS << format(" [%u] %c", abbrCode, 596*09467b48Spatrick AbbrevDecl->hasChildren() ? '*' : ' '); 597*09467b48Spatrick OS << '\n'; 598*09467b48Spatrick 599*09467b48Spatrick // Dump all data in the DIE for the attributes. 600*09467b48Spatrick for (const auto &AttrSpec : AbbrevDecl->attributes()) { 601*09467b48Spatrick if (AttrSpec.Form == DW_FORM_implicit_const) { 602*09467b48Spatrick // We are dumping .debug_info section , 603*09467b48Spatrick // implicit_const attribute values are not really stored here, 604*09467b48Spatrick // but in .debug_abbrev section. So we just skip such attrs. 605*09467b48Spatrick continue; 606*09467b48Spatrick } 607*09467b48Spatrick dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, 608*09467b48Spatrick Indent, DumpOpts); 609*09467b48Spatrick } 610*09467b48Spatrick 611*09467b48Spatrick DWARFDie child = getFirstChild(); 612*09467b48Spatrick if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { 613*09467b48Spatrick DumpOpts.ChildRecurseDepth--; 614*09467b48Spatrick DIDumpOptions ChildDumpOpts = DumpOpts; 615*09467b48Spatrick ChildDumpOpts.ShowParents = false; 616*09467b48Spatrick while (child) { 617*09467b48Spatrick child.dump(OS, Indent + 2, ChildDumpOpts); 618*09467b48Spatrick child = child.getSibling(); 619*09467b48Spatrick } 620*09467b48Spatrick } 621*09467b48Spatrick } else { 622*09467b48Spatrick OS << "Abbreviation code not found in 'debug_abbrev' class for code: " 623*09467b48Spatrick << abbrCode << '\n'; 624*09467b48Spatrick } 625*09467b48Spatrick } else { 626*09467b48Spatrick OS.indent(Indent) << "NULL\n"; 627*09467b48Spatrick } 628*09467b48Spatrick } 629*09467b48Spatrick } 630*09467b48Spatrick 631*09467b48Spatrick LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); } 632*09467b48Spatrick 633*09467b48Spatrick DWARFDie DWARFDie::getParent() const { 634*09467b48Spatrick if (isValid()) 635*09467b48Spatrick return U->getParent(Die); 636*09467b48Spatrick return DWARFDie(); 637*09467b48Spatrick } 638*09467b48Spatrick 639*09467b48Spatrick DWARFDie DWARFDie::getSibling() const { 640*09467b48Spatrick if (isValid()) 641*09467b48Spatrick return U->getSibling(Die); 642*09467b48Spatrick return DWARFDie(); 643*09467b48Spatrick } 644*09467b48Spatrick 645*09467b48Spatrick DWARFDie DWARFDie::getPreviousSibling() const { 646*09467b48Spatrick if (isValid()) 647*09467b48Spatrick return U->getPreviousSibling(Die); 648*09467b48Spatrick return DWARFDie(); 649*09467b48Spatrick } 650*09467b48Spatrick 651*09467b48Spatrick DWARFDie DWARFDie::getFirstChild() const { 652*09467b48Spatrick if (isValid()) 653*09467b48Spatrick return U->getFirstChild(Die); 654*09467b48Spatrick return DWARFDie(); 655*09467b48Spatrick } 656*09467b48Spatrick 657*09467b48Spatrick DWARFDie DWARFDie::getLastChild() const { 658*09467b48Spatrick if (isValid()) 659*09467b48Spatrick return U->getLastChild(Die); 660*09467b48Spatrick return DWARFDie(); 661*09467b48Spatrick } 662*09467b48Spatrick 663*09467b48Spatrick iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { 664*09467b48Spatrick return make_range(attribute_iterator(*this, false), 665*09467b48Spatrick attribute_iterator(*this, true)); 666*09467b48Spatrick } 667*09467b48Spatrick 668*09467b48Spatrick DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) 669*09467b48Spatrick : Die(D), Index(0) { 670*09467b48Spatrick auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); 671*09467b48Spatrick assert(AbbrDecl && "Must have abbreviation declaration"); 672*09467b48Spatrick if (End) { 673*09467b48Spatrick // This is the end iterator so we set the index to the attribute count. 674*09467b48Spatrick Index = AbbrDecl->getNumAttributes(); 675*09467b48Spatrick } else { 676*09467b48Spatrick // This is the begin iterator so we extract the value for this->Index. 677*09467b48Spatrick AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); 678*09467b48Spatrick updateForIndex(*AbbrDecl, 0); 679*09467b48Spatrick } 680*09467b48Spatrick } 681*09467b48Spatrick 682*09467b48Spatrick void DWARFDie::attribute_iterator::updateForIndex( 683*09467b48Spatrick const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { 684*09467b48Spatrick Index = I; 685*09467b48Spatrick // AbbrDecl must be valid before calling this function. 686*09467b48Spatrick auto NumAttrs = AbbrDecl.getNumAttributes(); 687*09467b48Spatrick if (Index < NumAttrs) { 688*09467b48Spatrick AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); 689*09467b48Spatrick // Add the previous byte size of any previous attribute value. 690*09467b48Spatrick AttrValue.Offset += AttrValue.ByteSize; 691*09467b48Spatrick uint64_t ParseOffset = AttrValue.Offset; 692*09467b48Spatrick auto U = Die.getDwarfUnit(); 693*09467b48Spatrick assert(U && "Die must have valid DWARF unit"); 694*09467b48Spatrick AttrValue.Value = DWARFFormValue::createFromUnit( 695*09467b48Spatrick AbbrDecl.getFormByIndex(Index), U, &ParseOffset); 696*09467b48Spatrick AttrValue.ByteSize = ParseOffset - AttrValue.Offset; 697*09467b48Spatrick } else { 698*09467b48Spatrick assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); 699*09467b48Spatrick AttrValue = {}; 700*09467b48Spatrick } 701*09467b48Spatrick } 702*09467b48Spatrick 703*09467b48Spatrick DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { 704*09467b48Spatrick if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) 705*09467b48Spatrick updateForIndex(*AbbrDecl, Index + 1); 706*09467b48Spatrick return *this; 707*09467b48Spatrick } 708*09467b48Spatrick 709*09467b48Spatrick bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { 710*09467b48Spatrick switch (Attr) { 711*09467b48Spatrick // From the DWARF v5 specification. 712*09467b48Spatrick case DW_AT_location: 713*09467b48Spatrick case DW_AT_byte_size: 714*09467b48Spatrick case DW_AT_bit_size: 715*09467b48Spatrick case DW_AT_string_length: 716*09467b48Spatrick case DW_AT_lower_bound: 717*09467b48Spatrick case DW_AT_return_addr: 718*09467b48Spatrick case DW_AT_bit_stride: 719*09467b48Spatrick case DW_AT_upper_bound: 720*09467b48Spatrick case DW_AT_count: 721*09467b48Spatrick case DW_AT_data_member_location: 722*09467b48Spatrick case DW_AT_frame_base: 723*09467b48Spatrick case DW_AT_segment: 724*09467b48Spatrick case DW_AT_static_link: 725*09467b48Spatrick case DW_AT_use_location: 726*09467b48Spatrick case DW_AT_vtable_elem_location: 727*09467b48Spatrick case DW_AT_allocated: 728*09467b48Spatrick case DW_AT_associated: 729*09467b48Spatrick case DW_AT_byte_stride: 730*09467b48Spatrick case DW_AT_rank: 731*09467b48Spatrick case DW_AT_call_value: 732*09467b48Spatrick case DW_AT_call_origin: 733*09467b48Spatrick case DW_AT_call_target: 734*09467b48Spatrick case DW_AT_call_target_clobbered: 735*09467b48Spatrick case DW_AT_call_data_location: 736*09467b48Spatrick case DW_AT_call_data_value: 737*09467b48Spatrick // Extensions. 738*09467b48Spatrick case DW_AT_GNU_call_site_value: 739*09467b48Spatrick case DW_AT_GNU_call_site_target: 740*09467b48Spatrick return true; 741*09467b48Spatrick default: 742*09467b48Spatrick return false; 743*09467b48Spatrick } 744*09467b48Spatrick } 745