xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
105f757f3fSDimitry 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 
dumpApplePropertyAttribute(raw_ostream & OS,uint64_t Val)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 
dumpRanges(const DWARFObject & Obj,raw_ostream & OS,const DWARFAddressRangesVector & Ranges,unsigned AddressSize,unsigned Indent,const DIDumpOptions & DumpOpts)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 
dumpLocationList(raw_ostream & OS,const DWARFFormValue & FormValue,DWARFUnit * U,unsigned Indent,DIDumpOptions DumpOpts)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 
dumpLocationExpr(raw_ostream & OS,const DWARFFormValue & FormValue,DWARFUnit * U,unsigned Indent,DIDumpOptions DumpOpts)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 
resolveReferencedType(DWARFDie D,DWARFFormValue F)106349cc55cSDimitry Andric static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
107349cc55cSDimitry Andric   return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
dumpAttribute(raw_ostream & OS,const DWARFDie & Die,const DWARFAttribute & AttrValue,unsigned Indent,DIDumpOptions DumpOpts)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;
1515f757f3fSDimitry Andric   else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||
1525f757f3fSDimitry 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.
1945f757f3fSDimitry Andric   if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin ||
1955f757f3fSDimitry 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 
getFullName(raw_string_ostream & OS,std::string * OriginalFullName) const233349cc55cSDimitry 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 
isSubprogramDIE() const2430b57cec5SDimitry Andric bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }
2440b57cec5SDimitry Andric 
isSubroutineDIE() const2450b57cec5SDimitry 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 
find(dwarf::Attribute Attr) const250bdd1243dSDimitry 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>
find(ArrayRef<dwarf::Attribute> Attrs) const2600b57cec5SDimitry 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>
findRecursively(ArrayRef<dwarf::Attribute> Attrs) const2740b57cec5SDimitry 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
getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const3070b57cec5SDimitry 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
getAttributeValueAsReferencedDie(const DWARFFormValue & V) const3140b57cec5SDimitry Andric DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
315349cc55cSDimitry Andric   DWARFDie Result;
316*0fca6ea1SDimitry Andric   if (std::optional<uint64_t> Offset = V.getAsRelativeReference()) {
317*0fca6ea1SDimitry Andric     Result = const_cast<DWARFUnit *>(V.getUnit())
318*0fca6ea1SDimitry Andric                  ->getDIEForOffset(V.getUnit()->getOffset() + *Offset);
319*0fca6ea1SDimitry Andric   } else if (Offset = V.getAsDebugInfoReference(); Offset) {
320*0fca6ea1SDimitry Andric     if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))
321*0fca6ea1SDimitry Andric       Result = SpecUnit->getDIEForOffset(*Offset);
3220b57cec5SDimitry Andric   }
323349cc55cSDimitry Andric   return Result;
324349cc55cSDimitry Andric }
325349cc55cSDimitry Andric 
resolveTypeUnitReference() const326349cc55cSDimitry Andric DWARFDie DWARFDie::resolveTypeUnitReference() const {
327349cc55cSDimitry Andric   if (auto Attr = find(DW_AT_signature)) {
328bdd1243dSDimitry Andric     if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
329349cc55cSDimitry Andric       if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
330349cc55cSDimitry Andric               U->getVersion(), *Sig, U->isDWOUnit()))
331349cc55cSDimitry Andric         return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
332349cc55cSDimitry Andric     }
333349cc55cSDimitry Andric   }
334349cc55cSDimitry Andric   return *this;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
getRangesBaseAttribute() const337bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
3380b57cec5SDimitry Andric   return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
getLocBaseAttribute() const341bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getLocBaseAttribute() const {
342480093f4SDimitry Andric   return toSectionOffset(find(DW_AT_loclists_base));
343480093f4SDimitry Andric }
344480093f4SDimitry Andric 
getHighPC(uint64_t LowPC) const345bdd1243dSDimitry Andric std::optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
346e8d8bef9SDimitry Andric   uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize());
347e8d8bef9SDimitry Andric   if (LowPC == Tombstone)
348bdd1243dSDimitry Andric     return std::nullopt;
3490b57cec5SDimitry Andric   if (auto FormValue = find(DW_AT_high_pc)) {
3500b57cec5SDimitry Andric     if (auto Address = FormValue->getAsAddress()) {
3510b57cec5SDimitry Andric       // High PC is an address.
3520b57cec5SDimitry Andric       return Address;
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric     if (auto Offset = FormValue->getAsUnsignedConstant()) {
3550b57cec5SDimitry Andric       // High PC is an offset from LowPC.
3560b57cec5SDimitry Andric       return LowPC + *Offset;
3570b57cec5SDimitry Andric     }
3580b57cec5SDimitry Andric   }
359bdd1243dSDimitry Andric   return std::nullopt;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
getLowAndHighPC(uint64_t & LowPC,uint64_t & HighPC,uint64_t & SectionIndex) const3620b57cec5SDimitry Andric bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
3630b57cec5SDimitry Andric                                uint64_t &SectionIndex) const {
3640b57cec5SDimitry Andric   auto F = find(DW_AT_low_pc);
3650b57cec5SDimitry Andric   auto LowPcAddr = toSectionedAddress(F);
3660b57cec5SDimitry Andric   if (!LowPcAddr)
3670b57cec5SDimitry Andric     return false;
3680b57cec5SDimitry Andric   if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) {
3690b57cec5SDimitry Andric     LowPC = LowPcAddr->Address;
3700b57cec5SDimitry Andric     HighPC = *HighPcAddr;
3710b57cec5SDimitry Andric     SectionIndex = LowPcAddr->SectionIndex;
3720b57cec5SDimitry Andric     return true;
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric   return false;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
getAddressRanges() const3770b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {
3780b57cec5SDimitry Andric   if (isNULL())
3790b57cec5SDimitry Andric     return DWARFAddressRangesVector();
3800b57cec5SDimitry Andric   // Single range specified by low/high PC.
3810b57cec5SDimitry Andric   uint64_t LowPC, HighPC, Index;
3820b57cec5SDimitry Andric   if (getLowAndHighPC(LowPC, HighPC, Index))
3830b57cec5SDimitry Andric     return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
3840b57cec5SDimitry Andric 
385bdd1243dSDimitry Andric   std::optional<DWARFFormValue> Value = find(DW_AT_ranges);
3860b57cec5SDimitry Andric   if (Value) {
3870b57cec5SDimitry Andric     if (Value->getForm() == DW_FORM_rnglistx)
3880b57cec5SDimitry Andric       return U->findRnglistFromIndex(*Value->getAsSectionOffset());
3890b57cec5SDimitry Andric     return U->findRnglistFromOffset(*Value->getAsSectionOffset());
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   return DWARFAddressRangesVector();
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
addressRangeContainsAddress(const uint64_t Address) const3940b57cec5SDimitry Andric bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
3950b57cec5SDimitry Andric   auto RangesOrError = getAddressRanges();
3960b57cec5SDimitry Andric   if (!RangesOrError) {
3970b57cec5SDimitry Andric     llvm::consumeError(RangesOrError.takeError());
3980b57cec5SDimitry Andric     return false;
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   for (const auto &R : RangesOrError.get())
4020b57cec5SDimitry Andric     if (R.LowPC <= Address && Address < R.HighPC)
4030b57cec5SDimitry Andric       return true;
4040b57cec5SDimitry Andric   return false;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
407480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector>
getLocations(dwarf::Attribute Attr) const408480093f4SDimitry Andric DWARFDie::getLocations(dwarf::Attribute Attr) const {
409bdd1243dSDimitry Andric   std::optional<DWARFFormValue> Location = find(Attr);
410480093f4SDimitry Andric   if (!Location)
411480093f4SDimitry Andric     return createStringError(inconvertibleErrorCode(), "No %s",
412480093f4SDimitry Andric                              dwarf::AttributeString(Attr).data());
413480093f4SDimitry Andric 
414bdd1243dSDimitry Andric   if (std::optional<uint64_t> Off = Location->getAsSectionOffset()) {
415480093f4SDimitry Andric     uint64_t Offset = *Off;
416480093f4SDimitry Andric 
417480093f4SDimitry Andric     if (Location->getForm() == DW_FORM_loclistx) {
418480093f4SDimitry Andric       if (auto LoclistOffset = U->getLoclistOffset(Offset))
419480093f4SDimitry Andric         Offset = *LoclistOffset;
420480093f4SDimitry Andric       else
421480093f4SDimitry Andric         return createStringError(inconvertibleErrorCode(),
422480093f4SDimitry Andric                                  "Loclist table not found");
423480093f4SDimitry Andric     }
424480093f4SDimitry Andric     return U->findLoclistFromOffset(Offset);
425480093f4SDimitry Andric   }
426480093f4SDimitry Andric 
427bdd1243dSDimitry Andric   if (std::optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {
428480093f4SDimitry Andric     return DWARFLocationExpressionsVector{
429bdd1243dSDimitry Andric         DWARFLocationExpression{std::nullopt, to_vector<4>(*Expr)}};
430480093f4SDimitry Andric   }
431480093f4SDimitry Andric 
432480093f4SDimitry Andric   return createStringError(
433480093f4SDimitry Andric       inconvertibleErrorCode(), "Unsupported %s encoding: %s",
434480093f4SDimitry Andric       dwarf::AttributeString(Attr).data(),
435480093f4SDimitry Andric       dwarf::FormEncodingString(Location->getForm()).data());
436480093f4SDimitry Andric }
437480093f4SDimitry Andric 
getSubroutineName(DINameKind Kind) const4380b57cec5SDimitry Andric const char *DWARFDie::getSubroutineName(DINameKind Kind) const {
4390b57cec5SDimitry Andric   if (!isSubroutineDIE())
4400b57cec5SDimitry Andric     return nullptr;
4410b57cec5SDimitry Andric   return getName(Kind);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric 
getName(DINameKind Kind) const4440b57cec5SDimitry Andric const char *DWARFDie::getName(DINameKind Kind) const {
4450b57cec5SDimitry Andric   if (!isValid() || Kind == DINameKind::None)
4460b57cec5SDimitry Andric     return nullptr;
4470b57cec5SDimitry Andric   // Try to get mangled name only if it was asked for.
4480b57cec5SDimitry Andric   if (Kind == DINameKind::LinkageName) {
4495ffd83dbSDimitry Andric     if (auto Name = getLinkageName())
4500b57cec5SDimitry Andric       return Name;
4510b57cec5SDimitry Andric   }
4525ffd83dbSDimitry Andric   return getShortName();
4535ffd83dbSDimitry Andric }
4545ffd83dbSDimitry Andric 
getShortName() const4555ffd83dbSDimitry Andric const char *DWARFDie::getShortName() const {
4565ffd83dbSDimitry Andric   if (!isValid())
4570b57cec5SDimitry Andric     return nullptr;
4585ffd83dbSDimitry Andric 
4595ffd83dbSDimitry Andric   return dwarf::toString(findRecursively(dwarf::DW_AT_name), nullptr);
4605ffd83dbSDimitry Andric }
4615ffd83dbSDimitry Andric 
getLinkageName() const4625ffd83dbSDimitry Andric const char *DWARFDie::getLinkageName() const {
4635ffd83dbSDimitry Andric   if (!isValid())
4645ffd83dbSDimitry Andric     return nullptr;
4655ffd83dbSDimitry Andric 
4665ffd83dbSDimitry Andric   return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name,
4675ffd83dbSDimitry Andric                                           dwarf::DW_AT_linkage_name}),
4685ffd83dbSDimitry Andric                          nullptr);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
getDeclLine() const4710b57cec5SDimitry Andric uint64_t DWARFDie::getDeclLine() const {
4720b57cec5SDimitry Andric   return toUnsigned(findRecursively(DW_AT_decl_line), 0);
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
475e8d8bef9SDimitry Andric std::string
getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const476e8d8bef9SDimitry Andric DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
477349cc55cSDimitry Andric   if (auto FormValue = findRecursively(DW_AT_decl_file))
478349cc55cSDimitry Andric     if (auto OptString = FormValue->getAsFile(Kind))
479349cc55cSDimitry Andric       return *OptString;
480349cc55cSDimitry Andric   return {};
481e8d8bef9SDimitry Andric }
482e8d8bef9SDimitry Andric 
getCallerFrame(uint32_t & CallFile,uint32_t & CallLine,uint32_t & CallColumn,uint32_t & CallDiscriminator) const4830b57cec5SDimitry Andric void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
4840b57cec5SDimitry Andric                               uint32_t &CallColumn,
4850b57cec5SDimitry Andric                               uint32_t &CallDiscriminator) const {
4860b57cec5SDimitry Andric   CallFile = toUnsigned(find(DW_AT_call_file), 0);
4870b57cec5SDimitry Andric   CallLine = toUnsigned(find(DW_AT_call_line), 0);
4880b57cec5SDimitry Andric   CallColumn = toUnsigned(find(DW_AT_call_column), 0);
4890b57cec5SDimitry Andric   CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
4925f757f3fSDimitry Andric static std::optional<uint64_t>
getTypeSizeImpl(DWARFDie Die,uint64_t PointerSize,SmallPtrSetImpl<const DWARFDebugInfoEntry * > & Visited)4935f757f3fSDimitry Andric getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,
4945f757f3fSDimitry Andric                 SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) {
4955f757f3fSDimitry Andric   // Cycle detected?
4965f757f3fSDimitry Andric   if (!Visited.insert(Die.getDebugInfoEntry()).second)
4975f757f3fSDimitry Andric     return {};
4985f757f3fSDimitry Andric   if (auto SizeAttr = Die.find(DW_AT_byte_size))
499bdd1243dSDimitry Andric     if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())
50081ad6265SDimitry Andric       return Size;
50181ad6265SDimitry Andric 
5025f757f3fSDimitry Andric   switch (Die.getTag()) {
50381ad6265SDimitry Andric   case DW_TAG_pointer_type:
50481ad6265SDimitry Andric   case DW_TAG_reference_type:
50581ad6265SDimitry Andric   case DW_TAG_rvalue_reference_type:
50681ad6265SDimitry Andric     return PointerSize;
50781ad6265SDimitry Andric   case DW_TAG_ptr_to_member_type: {
5085f757f3fSDimitry Andric     if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
50981ad6265SDimitry Andric       if (BaseType.getTag() == DW_TAG_subroutine_type)
51081ad6265SDimitry Andric         return 2 * PointerSize;
51181ad6265SDimitry Andric     return PointerSize;
51281ad6265SDimitry Andric   }
51381ad6265SDimitry Andric   case DW_TAG_const_type:
51481ad6265SDimitry Andric   case DW_TAG_immutable_type:
51581ad6265SDimitry Andric   case DW_TAG_volatile_type:
51681ad6265SDimitry Andric   case DW_TAG_restrict_type:
517*0fca6ea1SDimitry Andric   case DW_TAG_template_alias:
51881ad6265SDimitry Andric   case DW_TAG_typedef: {
5195f757f3fSDimitry Andric     if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
5205f757f3fSDimitry Andric       return getTypeSizeImpl(BaseType, PointerSize, Visited);
52181ad6265SDimitry Andric     break;
52281ad6265SDimitry Andric   }
52381ad6265SDimitry Andric   case DW_TAG_array_type: {
5245f757f3fSDimitry Andric     DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type);
52581ad6265SDimitry Andric     if (!BaseType)
526bdd1243dSDimitry Andric       return std::nullopt;
5275f757f3fSDimitry Andric     std::optional<uint64_t> BaseSize =
5285f757f3fSDimitry Andric         getTypeSizeImpl(BaseType, PointerSize, Visited);
52981ad6265SDimitry Andric     if (!BaseSize)
530bdd1243dSDimitry Andric       return std::nullopt;
53181ad6265SDimitry Andric     uint64_t Size = *BaseSize;
5325f757f3fSDimitry 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:
5525f757f3fSDimitry Andric     if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
5535f757f3fSDimitry Andric       return getTypeSizeImpl(BaseType, PointerSize, Visited);
55481ad6265SDimitry Andric     break;
55581ad6265SDimitry Andric   }
556bdd1243dSDimitry Andric   return std::nullopt;
55781ad6265SDimitry Andric }
55881ad6265SDimitry Andric 
getTypeSize(uint64_t PointerSize)5595f757f3fSDimitry Andric std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
5605f757f3fSDimitry Andric   SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited;
5615f757f3fSDimitry Andric   return getTypeSizeImpl(*this, PointerSize, Visited);
5625f757f3fSDimitry Andric }
5635f757f3fSDimitry Andric 
5640b57cec5SDimitry Andric /// Helper to dump a DIE with all of its parents, but no siblings.
dumpParentChain(DWARFDie Die,raw_ostream & OS,unsigned Indent,DIDumpOptions DumpOpts,unsigned Depth=0)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 
dump(raw_ostream & OS,unsigned Indent,DIDumpOptions DumpOpts) const5760b57cec5SDimitry 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 
dump() const6340b57cec5SDimitry Andric LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }
6350b57cec5SDimitry Andric 
getParent() const6360b57cec5SDimitry Andric DWARFDie DWARFDie::getParent() const {
6370b57cec5SDimitry Andric   if (isValid())
6380b57cec5SDimitry Andric     return U->getParent(Die);
6390b57cec5SDimitry Andric   return DWARFDie();
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
getSibling() const6420b57cec5SDimitry Andric DWARFDie DWARFDie::getSibling() const {
6430b57cec5SDimitry Andric   if (isValid())
6440b57cec5SDimitry Andric     return U->getSibling(Die);
6450b57cec5SDimitry Andric   return DWARFDie();
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
getPreviousSibling() const6480b57cec5SDimitry Andric DWARFDie DWARFDie::getPreviousSibling() const {
6490b57cec5SDimitry Andric   if (isValid())
6500b57cec5SDimitry Andric     return U->getPreviousSibling(Die);
6510b57cec5SDimitry Andric   return DWARFDie();
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric 
getFirstChild() const6540b57cec5SDimitry Andric DWARFDie DWARFDie::getFirstChild() const {
6550b57cec5SDimitry Andric   if (isValid())
6560b57cec5SDimitry Andric     return U->getFirstChild(Die);
6570b57cec5SDimitry Andric   return DWARFDie();
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
getLastChild() const6600b57cec5SDimitry Andric DWARFDie DWARFDie::getLastChild() const {
6610b57cec5SDimitry Andric   if (isValid())
6620b57cec5SDimitry Andric     return U->getLastChild(Die);
6630b57cec5SDimitry Andric   return DWARFDie();
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
attributes() const6660b57cec5SDimitry 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 
attribute_iterator(DWARFDie D,bool End)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 
updateForIndex(const DWARFAbbreviationDeclaration & AbbrDecl,uint32_t I)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 
operator ++()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 
mayHaveLocationList(dwarf::Attribute Attr)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 
mayHaveLocationExpr(dwarf::Attribute Attr)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 
dumpTypeQualifiedName(const DWARFDie & DIE,raw_ostream & OS)77604eeddc0SDimitry Andric void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) {
77704eeddc0SDimitry Andric   DWARFTypePrinter(OS).appendQualifiedName(DIE);
77804eeddc0SDimitry Andric }
77904eeddc0SDimitry Andric 
dumpTypeUnqualifiedName(const DWARFDie & DIE,raw_ostream & OS,std::string * OriginalFullName)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