Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
35294 views
//===- DWARFDie.cpp -------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFDie.h"9#include "llvm/ADT/SmallPtrSet.h"10#include "llvm/ADT/SmallSet.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/BinaryFormat/Dwarf.h"13#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"14#include "llvm/DebugInfo/DWARF/DWARFContext.h"15#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"17#include "llvm/DebugInfo/DWARF/DWARFExpression.h"18#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"19#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"20#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"21#include "llvm/DebugInfo/DWARF/DWARFUnit.h"22#include "llvm/Object/ObjectFile.h"23#include "llvm/Support/DataExtractor.h"24#include "llvm/Support/Format.h"25#include "llvm/Support/FormatVariadic.h"26#include "llvm/Support/MathExtras.h"27#include "llvm/Support/WithColor.h"28#include "llvm/Support/raw_ostream.h"29#include <cassert>30#include <cinttypes>31#include <cstdint>32#include <string>33#include <utility>3435using namespace llvm;36using namespace dwarf;37using namespace object;3839static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {40OS << " (";41do {42uint64_t Shift = llvm::countr_zero(Val);43assert(Shift < 64 && "undefined behavior");44uint64_t Bit = 1ULL << Shift;45auto PropName = ApplePropertyString(Bit);46if (!PropName.empty())47OS << PropName;48else49OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);50if (!(Val ^= Bit))51break;52OS << ", ";53} while (true);54OS << ")";55}5657static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,58const DWARFAddressRangesVector &Ranges,59unsigned AddressSize, unsigned Indent,60const DIDumpOptions &DumpOpts) {61if (!DumpOpts.ShowAddresses)62return;6364for (const DWARFAddressRange &R : Ranges) {65OS << '\n';66OS.indent(Indent);67R.dump(OS, AddressSize, DumpOpts, &Obj);68}69}7071static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,72DWARFUnit *U, unsigned Indent,73DIDumpOptions DumpOpts) {74assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) &&75"bad FORM for location list");76DWARFContext &Ctx = U->getContext();77uint64_t Offset = *FormValue.getAsSectionOffset();7879if (FormValue.getForm() == DW_FORM_loclistx) {80FormValue.dump(OS, DumpOpts);8182if (auto LoclistOffset = U->getLoclistOffset(Offset))83Offset = *LoclistOffset;84else85return;86}87U->getLocationTable().dumpLocationList(88&Offset, OS, U->getBaseAddress(), Ctx.getDWARFObj(), U, DumpOpts, Indent);89}9091static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,92DWARFUnit *U, unsigned Indent,93DIDumpOptions DumpOpts) {94assert((FormValue.isFormClass(DWARFFormValue::FC_Block) ||95FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) &&96"bad FORM for location expression");97DWARFContext &Ctx = U->getContext();98ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();99DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),100Ctx.isLittleEndian(), 0);101DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)102.print(OS, DumpOpts, U);103}104105static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {106return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();107}108109static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,110const DWARFAttribute &AttrValue, unsigned Indent,111DIDumpOptions DumpOpts) {112if (!Die.isValid())113return;114const char BaseIndent[] = " ";115OS << BaseIndent;116OS.indent(Indent + 2);117dwarf::Attribute Attr = AttrValue.Attr;118WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);119120dwarf::Form Form = AttrValue.Value.getForm();121if (DumpOpts.Verbose || DumpOpts.ShowForm)122OS << formatv(" [{0}]", Form);123124DWARFUnit *U = Die.getDwarfUnit();125const DWARFFormValue &FormValue = AttrValue.Value;126127OS << "\t(";128129StringRef Name;130std::string File;131auto Color = HighlightColor::Enumerator;132if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {133Color = HighlightColor::String;134if (const auto *LT = U->getContext().getLineTableForUnit(U)) {135if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) {136if (LT->getFileNameByIndex(137*Val, U->getCompilationDir(),138DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,139File)) {140File = '"' + File + '"';141Name = File;142}143}144}145} else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())146Name = AttributeValueString(Attr, *Val);147148if (!Name.empty())149WithColor(OS, Color) << Name;150else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||151Attr == DW_AT_call_line || Attr == DW_AT_call_column) {152if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())153OS << *Val;154else155FormValue.dump(OS, DumpOpts);156} else if (Attr == DW_AT_low_pc &&157(FormValue.getAsAddress() ==158dwarf::computeTombstoneAddress(U->getAddressByteSize()))) {159if (DumpOpts.Verbose) {160FormValue.dump(OS, DumpOpts);161OS << " (";162}163OS << "dead code";164if (DumpOpts.Verbose)165OS << ')';166} else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&167FormValue.getAsUnsignedConstant()) {168if (DumpOpts.ShowAddresses) {169// Print the actual address rather than the offset.170uint64_t LowPC, HighPC, Index;171if (Die.getLowAndHighPC(LowPC, HighPC, Index))172DWARFFormValue::dumpAddress(OS, U->getAddressByteSize(), HighPC);173else174FormValue.dump(OS, DumpOpts);175}176} else if (DWARFAttribute::mayHaveLocationList(Attr) &&177FormValue.isFormClass(DWARFFormValue::FC_SectionOffset))178dumpLocationList(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,179DumpOpts);180else if (FormValue.isFormClass(DWARFFormValue::FC_Exprloc) ||181(DWARFAttribute::mayHaveLocationExpr(Attr) &&182FormValue.isFormClass(DWARFFormValue::FC_Block)))183dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,184DumpOpts);185else186FormValue.dump(OS, DumpOpts);187188std::string Space = DumpOpts.ShowAddresses ? " " : "";189190// We have dumped the attribute raw value. For some attributes191// having both the raw value and the pretty-printed value is192// interesting. These attributes are handled below.193if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin ||194Attr == DW_AT_call_origin) {195if (const char *Name =196Die.getAttributeValueAsReferencedDie(FormValue).getName(197DINameKind::LinkageName))198OS << Space << "\"" << Name << '\"';199} else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) {200DWARFDie D = resolveReferencedType(Die, FormValue);201if (D && !D.isNULL()) {202OS << Space << "\"";203dumpTypeQualifiedName(D, OS);204OS << '"';205}206} else if (Attr == DW_AT_APPLE_property_attribute) {207if (std::optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant())208dumpApplePropertyAttribute(OS, *OptVal);209} else if (Attr == DW_AT_ranges) {210const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();211// For DW_FORM_rnglistx we need to dump the offset separately, since212// we have only dumped the index so far.213if (FormValue.getForm() == DW_FORM_rnglistx)214if (auto RangeListOffset =215U->getRnglistOffset(*FormValue.getAsSectionOffset())) {216DWARFFormValue FV = DWARFFormValue::createFromUValue(217dwarf::DW_FORM_sec_offset, *RangeListOffset);218FV.dump(OS, DumpOpts);219}220if (auto RangesOrError = Die.getAddressRanges())221dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(),222sizeof(BaseIndent) + Indent + 4, DumpOpts);223else224DumpOpts.RecoverableErrorHandler(createStringError(225errc::invalid_argument, "decoding address ranges: %s",226toString(RangesOrError.takeError()).c_str()));227}228229OS << ")\n";230}231232void DWARFDie::getFullName(raw_string_ostream &OS,233std::string *OriginalFullName) const {234const char *NamePtr = getShortName();235if (!NamePtr)236return;237if (getTag() == DW_TAG_GNU_template_parameter_pack)238return;239dumpTypeUnqualifiedName(*this, OS, OriginalFullName);240}241242bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }243244bool DWARFDie::isSubroutineDIE() const {245auto Tag = getTag();246return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;247}248249std::optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {250if (!isValid())251return std::nullopt;252auto AbbrevDecl = getAbbreviationDeclarationPtr();253if (AbbrevDecl)254return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);255return std::nullopt;256}257258std::optional<DWARFFormValue>259DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {260if (!isValid())261return std::nullopt;262auto AbbrevDecl = getAbbreviationDeclarationPtr();263if (AbbrevDecl) {264for (auto Attr : Attrs) {265if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))266return Value;267}268}269return std::nullopt;270}271272std::optional<DWARFFormValue>273DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {274SmallVector<DWARFDie, 3> Worklist;275Worklist.push_back(*this);276277// Keep track if DIEs already seen to prevent infinite recursion.278// Empirically we rarely see a depth of more than 3 when dealing with valid279// DWARF. This corresponds to following the DW_AT_abstract_origin and280// DW_AT_specification just once.281SmallSet<DWARFDie, 3> Seen;282Seen.insert(*this);283284while (!Worklist.empty()) {285DWARFDie Die = Worklist.pop_back_val();286287if (!Die.isValid())288continue;289290if (auto Value = Die.find(Attrs))291return Value;292293if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))294if (Seen.insert(D).second)295Worklist.push_back(D);296297if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))298if (Seen.insert(D).second)299Worklist.push_back(D);300}301302return std::nullopt;303}304305DWARFDie306DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {307if (std::optional<DWARFFormValue> F = find(Attr))308return getAttributeValueAsReferencedDie(*F);309return DWARFDie();310}311312DWARFDie313DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {314DWARFDie Result;315if (std::optional<uint64_t> Offset = V.getAsRelativeReference()) {316Result = const_cast<DWARFUnit *>(V.getUnit())317->getDIEForOffset(V.getUnit()->getOffset() + *Offset);318} else if (Offset = V.getAsDebugInfoReference(); Offset) {319if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))320Result = SpecUnit->getDIEForOffset(*Offset);321}322return Result;323}324325DWARFDie DWARFDie::resolveTypeUnitReference() const {326if (auto Attr = find(DW_AT_signature)) {327if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {328if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(329U->getVersion(), *Sig, U->isDWOUnit()))330return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());331}332}333return *this;334}335336std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {337return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));338}339340std::optional<uint64_t> DWARFDie::getLocBaseAttribute() const {341return toSectionOffset(find(DW_AT_loclists_base));342}343344std::optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {345uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize());346if (LowPC == Tombstone)347return std::nullopt;348if (auto FormValue = find(DW_AT_high_pc)) {349if (auto Address = FormValue->getAsAddress()) {350// High PC is an address.351return Address;352}353if (auto Offset = FormValue->getAsUnsignedConstant()) {354// High PC is an offset from LowPC.355return LowPC + *Offset;356}357}358return std::nullopt;359}360361bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,362uint64_t &SectionIndex) const {363auto F = find(DW_AT_low_pc);364auto LowPcAddr = toSectionedAddress(F);365if (!LowPcAddr)366return false;367if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) {368LowPC = LowPcAddr->Address;369HighPC = *HighPcAddr;370SectionIndex = LowPcAddr->SectionIndex;371return true;372}373return false;374}375376Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {377if (isNULL())378return DWARFAddressRangesVector();379// Single range specified by low/high PC.380uint64_t LowPC, HighPC, Index;381if (getLowAndHighPC(LowPC, HighPC, Index))382return DWARFAddressRangesVector{{LowPC, HighPC, Index}};383384std::optional<DWARFFormValue> Value = find(DW_AT_ranges);385if (Value) {386if (Value->getForm() == DW_FORM_rnglistx)387return U->findRnglistFromIndex(*Value->getAsSectionOffset());388return U->findRnglistFromOffset(*Value->getAsSectionOffset());389}390return DWARFAddressRangesVector();391}392393bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {394auto RangesOrError = getAddressRanges();395if (!RangesOrError) {396llvm::consumeError(RangesOrError.takeError());397return false;398}399400for (const auto &R : RangesOrError.get())401if (R.LowPC <= Address && Address < R.HighPC)402return true;403return false;404}405406Expected<DWARFLocationExpressionsVector>407DWARFDie::getLocations(dwarf::Attribute Attr) const {408std::optional<DWARFFormValue> Location = find(Attr);409if (!Location)410return createStringError(inconvertibleErrorCode(), "No %s",411dwarf::AttributeString(Attr).data());412413if (std::optional<uint64_t> Off = Location->getAsSectionOffset()) {414uint64_t Offset = *Off;415416if (Location->getForm() == DW_FORM_loclistx) {417if (auto LoclistOffset = U->getLoclistOffset(Offset))418Offset = *LoclistOffset;419else420return createStringError(inconvertibleErrorCode(),421"Loclist table not found");422}423return U->findLoclistFromOffset(Offset);424}425426if (std::optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {427return DWARFLocationExpressionsVector{428DWARFLocationExpression{std::nullopt, to_vector<4>(*Expr)}};429}430431return createStringError(432inconvertibleErrorCode(), "Unsupported %s encoding: %s",433dwarf::AttributeString(Attr).data(),434dwarf::FormEncodingString(Location->getForm()).data());435}436437const char *DWARFDie::getSubroutineName(DINameKind Kind) const {438if (!isSubroutineDIE())439return nullptr;440return getName(Kind);441}442443const char *DWARFDie::getName(DINameKind Kind) const {444if (!isValid() || Kind == DINameKind::None)445return nullptr;446// Try to get mangled name only if it was asked for.447if (Kind == DINameKind::LinkageName) {448if (auto Name = getLinkageName())449return Name;450}451return getShortName();452}453454const char *DWARFDie::getShortName() const {455if (!isValid())456return nullptr;457458return dwarf::toString(findRecursively(dwarf::DW_AT_name), nullptr);459}460461const char *DWARFDie::getLinkageName() const {462if (!isValid())463return nullptr;464465return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name,466dwarf::DW_AT_linkage_name}),467nullptr);468}469470uint64_t DWARFDie::getDeclLine() const {471return toUnsigned(findRecursively(DW_AT_decl_line), 0);472}473474std::string475DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {476if (auto FormValue = findRecursively(DW_AT_decl_file))477if (auto OptString = FormValue->getAsFile(Kind))478return *OptString;479return {};480}481482void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,483uint32_t &CallColumn,484uint32_t &CallDiscriminator) const {485CallFile = toUnsigned(find(DW_AT_call_file), 0);486CallLine = toUnsigned(find(DW_AT_call_line), 0);487CallColumn = toUnsigned(find(DW_AT_call_column), 0);488CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);489}490491static std::optional<uint64_t>492getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,493SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) {494// Cycle detected?495if (!Visited.insert(Die.getDebugInfoEntry()).second)496return {};497if (auto SizeAttr = Die.find(DW_AT_byte_size))498if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())499return Size;500501switch (Die.getTag()) {502case DW_TAG_pointer_type:503case DW_TAG_reference_type:504case DW_TAG_rvalue_reference_type:505return PointerSize;506case DW_TAG_ptr_to_member_type: {507if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))508if (BaseType.getTag() == DW_TAG_subroutine_type)509return 2 * PointerSize;510return PointerSize;511}512case DW_TAG_const_type:513case DW_TAG_immutable_type:514case DW_TAG_volatile_type:515case DW_TAG_restrict_type:516case DW_TAG_template_alias:517case DW_TAG_typedef: {518if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))519return getTypeSizeImpl(BaseType, PointerSize, Visited);520break;521}522case DW_TAG_array_type: {523DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type);524if (!BaseType)525return std::nullopt;526std::optional<uint64_t> BaseSize =527getTypeSizeImpl(BaseType, PointerSize, Visited);528if (!BaseSize)529return std::nullopt;530uint64_t Size = *BaseSize;531for (DWARFDie Child : Die) {532if (Child.getTag() != DW_TAG_subrange_type)533continue;534535if (auto ElemCountAttr = Child.find(DW_AT_count))536if (std::optional<uint64_t> ElemCount =537ElemCountAttr->getAsUnsignedConstant())538Size *= *ElemCount;539if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound))540if (std::optional<int64_t> UpperBound =541UpperBoundAttr->getAsSignedConstant()) {542int64_t LowerBound = 0;543if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound))544LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0);545Size *= *UpperBound - LowerBound + 1;546}547}548return Size;549}550default:551if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))552return getTypeSizeImpl(BaseType, PointerSize, Visited);553break;554}555return std::nullopt;556}557558std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {559SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited;560return getTypeSizeImpl(*this, PointerSize, Visited);561}562563/// Helper to dump a DIE with all of its parents, but no siblings.564static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,565DIDumpOptions DumpOpts, unsigned Depth = 0) {566if (!Die)567return Indent;568if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth)569return Indent;570Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1);571Die.dump(OS, Indent, DumpOpts);572return Indent + 2;573}574575void DWARFDie::dump(raw_ostream &OS, unsigned Indent,576DIDumpOptions DumpOpts) const {577if (!isValid())578return;579DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();580const uint64_t Offset = getOffset();581uint64_t offset = Offset;582if (DumpOpts.ShowParents) {583DIDumpOptions ParentDumpOpts = DumpOpts;584ParentDumpOpts.ShowParents = false;585ParentDumpOpts.ShowChildren = false;586Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts);587}588589if (debug_info_data.isValidOffset(offset)) {590uint32_t abbrCode = debug_info_data.getULEB128(&offset);591if (DumpOpts.ShowAddresses)592WithColor(OS, HighlightColor::Address).get()593<< format("\n0x%8.8" PRIx64 ": ", Offset);594595if (abbrCode) {596auto AbbrevDecl = getAbbreviationDeclarationPtr();597if (AbbrevDecl) {598WithColor(OS, HighlightColor::Tag).get().indent(Indent)599<< formatv("{0}", getTag());600if (DumpOpts.Verbose) {601OS << format(" [%u] %c", abbrCode,602AbbrevDecl->hasChildren() ? '*' : ' ');603if (std::optional<uint32_t> ParentIdx = Die->getParentIdx())604OS << format(" (0x%8.8" PRIx64 ")",605U->getDIEAtIndex(*ParentIdx).getOffset());606}607OS << '\n';608609// Dump all data in the DIE for the attributes.610for (const DWARFAttribute &AttrValue : attributes())611dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts);612613if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) {614DWARFDie Child = getFirstChild();615DumpOpts.ChildRecurseDepth--;616DIDumpOptions ChildDumpOpts = DumpOpts;617ChildDumpOpts.ShowParents = false;618while (Child) {619Child.dump(OS, Indent + 2, ChildDumpOpts);620Child = Child.getSibling();621}622}623} else {624OS << "Abbreviation code not found in 'debug_abbrev' class for code: "625<< abbrCode << '\n';626}627} else {628OS.indent(Indent) << "NULL\n";629}630}631}632633LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }634635DWARFDie DWARFDie::getParent() const {636if (isValid())637return U->getParent(Die);638return DWARFDie();639}640641DWARFDie DWARFDie::getSibling() const {642if (isValid())643return U->getSibling(Die);644return DWARFDie();645}646647DWARFDie DWARFDie::getPreviousSibling() const {648if (isValid())649return U->getPreviousSibling(Die);650return DWARFDie();651}652653DWARFDie DWARFDie::getFirstChild() const {654if (isValid())655return U->getFirstChild(Die);656return DWARFDie();657}658659DWARFDie DWARFDie::getLastChild() const {660if (isValid())661return U->getLastChild(Die);662return DWARFDie();663}664665iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const {666return make_range(attribute_iterator(*this, false),667attribute_iterator(*this, true));668}669670DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End)671: Die(D), Index(0) {672auto AbbrDecl = Die.getAbbreviationDeclarationPtr();673assert(AbbrDecl && "Must have abbreviation declaration");674if (End) {675// This is the end iterator so we set the index to the attribute count.676Index = AbbrDecl->getNumAttributes();677} else {678// This is the begin iterator so we extract the value for this->Index.679AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();680updateForIndex(*AbbrDecl, 0);681}682}683684void DWARFDie::attribute_iterator::updateForIndex(685const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {686Index = I;687// AbbrDecl must be valid before calling this function.688auto NumAttrs = AbbrDecl.getNumAttributes();689if (Index < NumAttrs) {690AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);691// Add the previous byte size of any previous attribute value.692AttrValue.Offset += AttrValue.ByteSize;693uint64_t ParseOffset = AttrValue.Offset;694if (AbbrDecl.getAttrIsImplicitConstByIndex(Index))695AttrValue.Value = DWARFFormValue::createFromSValue(696AbbrDecl.getFormByIndex(Index),697AbbrDecl.getAttrImplicitConstValueByIndex(Index));698else {699auto U = Die.getDwarfUnit();700assert(U && "Die must have valid DWARF unit");701AttrValue.Value = DWARFFormValue::createFromUnit(702AbbrDecl.getFormByIndex(Index), U, &ParseOffset);703}704AttrValue.ByteSize = ParseOffset - AttrValue.Offset;705} else {706assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");707AttrValue = {};708}709}710711DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {712if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())713updateForIndex(*AbbrDecl, Index + 1);714return *this;715}716717bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) {718switch(Attr) {719case DW_AT_location:720case DW_AT_string_length:721case DW_AT_return_addr:722case DW_AT_data_member_location:723case DW_AT_frame_base:724case DW_AT_static_link:725case DW_AT_segment:726case DW_AT_use_location:727case DW_AT_vtable_elem_location:728return true;729default:730return false;731}732}733734bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) {735switch (Attr) {736// From the DWARF v5 specification.737case DW_AT_location:738case DW_AT_byte_size:739case DW_AT_bit_offset:740case DW_AT_bit_size:741case DW_AT_string_length:742case DW_AT_lower_bound:743case DW_AT_return_addr:744case DW_AT_bit_stride:745case DW_AT_upper_bound:746case DW_AT_count:747case DW_AT_data_member_location:748case DW_AT_frame_base:749case DW_AT_segment:750case DW_AT_static_link:751case DW_AT_use_location:752case DW_AT_vtable_elem_location:753case DW_AT_allocated:754case DW_AT_associated:755case DW_AT_data_location:756case DW_AT_byte_stride:757case DW_AT_rank:758case DW_AT_call_value:759case DW_AT_call_origin:760case DW_AT_call_target:761case DW_AT_call_target_clobbered:762case DW_AT_call_data_location:763case DW_AT_call_data_value:764// Extensions.765case DW_AT_GNU_call_site_value:766case DW_AT_GNU_call_site_target:767return true;768default:769return false;770}771}772773namespace llvm {774775void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) {776DWARFTypePrinter(OS).appendQualifiedName(DIE);777}778779void dumpTypeUnqualifiedName(const DWARFDie &DIE, raw_ostream &OS,780std::string *OriginalFullName) {781DWARFTypePrinter(OS).appendUnqualifiedName(DIE, OriginalFullName);782}783784} // namespace llvm785786787