xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (revision 4652422eb477731f284b1345afeefef7f269da50)
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