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