diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp')
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 284 |
1 files changed, 153 insertions, 131 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 89b83b1..111f0bb 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -1,4 +1,4 @@ -//===-- DWARFDie.cpp ------------------------------------------------------===// +//===- DWARFDie.cpp -------------------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -9,23 +9,31 @@ #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "SyntaxHighlighting.h" -#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cinttypes> +#include <cstdint> +#include <string> +#include <utility> using namespace llvm; using namespace dwarf; using namespace syntax; -namespace { - static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { +static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { OS << " ("; do { uint64_t Shift = countTrailingZeros(Val); @@ -52,14 +60,15 @@ static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, OS << '\n'; OS.indent(Indent); OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", - AddressSize*2, Range.first, - AddressSize*2, Range.second); + AddressSize*2, Range.LowPC, + AddressSize*2, Range.HighPC); } } static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, uint32_t *OffsetPtr, dwarf::Attribute Attr, - dwarf::Form Form, unsigned Indent) { + dwarf::Form Form, unsigned Indent, + DIDumpOptions DumpOpts) { if (!Die.isValid()) return; const char BaseIndent[] = " "; @@ -70,13 +79,15 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, WithColor(OS, syntax::Attribute) << attrString; else WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); - - auto formString = FormEncodingString(Form); - if (!formString.empty()) - OS << " [" << formString << ']'; - else - OS << format(" [DW_FORM_Unknown_%x]", Form); - + + if (!DumpOpts.Brief) { + auto formString = FormEncodingString(Form); + if (!formString.empty()) + OS << " [" << formString << ']'; + else + OS << format(" [DW_FORM_Unknown_%x]", Form); + } + DWARFUnit *U = Die.getDwarfUnit(); DWARFFormValue formValue(Form); @@ -122,8 +133,6 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, OS << ")\n"; } -} // end anonymous namespace - bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; } @@ -134,7 +143,7 @@ bool DWARFDie::isSubroutineDIE() const { } Optional<DWARFFormValue> -DWARFDie::getAttributeValue(dwarf::Attribute Attr) const { +DWARFDie::find(dwarf::Attribute Attr) const { if (!isValid()) return None; auto AbbrevDecl = getAbbreviationDeclarationPtr(); @@ -143,54 +152,41 @@ DWARFDie::getAttributeValue(dwarf::Attribute Attr) const { return None; } -const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr, - const char *FailValue) const { - auto FormValue = getAttributeValue(Attr); - if (!FormValue) - return FailValue; - Optional<const char *> Result = FormValue->getAsCString(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -Optional<uint64_t> -DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsAddress(); - return None; -} - -Optional<int64_t> -DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsSignedConstant(); - return None; -} - -Optional<uint64_t> -DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsUnsignedConstant(); - return None; -} - -Optional<uint64_t> -DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsReference(); +Optional<DWARFFormValue> +DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { + if (!isValid()) + return None; + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) { + for (auto Attr : Attrs) { + if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) + return Value; + } + } return None; } -Optional<uint64_t> -DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsSectionOffset(); +Optional<DWARFFormValue> +DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { + if (!isValid()) + return None; + auto Die = *this; + if (auto Value = Die.find(Attrs)) + return Value; + if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Die = D; + if (auto Value = Die.find(Attrs)) + return Value; + if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) + Die = D; + if (auto Value = Die.find(Attrs)) + return Value; return None; } - DWARFDie DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { - auto SpecRef = getAttributeValueAsReference(Attr); + auto SpecRef = toReference(find(Attr)); if (SpecRef) { auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef); if (SpecUnit) @@ -201,14 +197,11 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { - auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base); - if (Result) - return Result; - return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base); + return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); } Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { - if (auto FormValue = getAttributeValue(DW_AT_high_pc)) { + if (auto FormValue = find(DW_AT_high_pc)) { if (auto Address = FormValue->getAsAddress()) { // High PC is an address. return Address; @@ -221,13 +214,16 @@ Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { return None; } -bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { - auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc); +bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SectionIndex) const { + auto F = find(DW_AT_low_pc); + auto LowPcAddr = toAddress(F); if (!LowPcAddr) return false; if (auto HighPcAddr = getHighPC(*LowPcAddr)) { LowPC = *LowPcAddr; HighPC = *HighPcAddr; + SectionIndex = F->getSectionIndex(); return true; } return false; @@ -238,12 +234,12 @@ DWARFDie::getAddressRanges() const { if (isNULL()) return DWARFAddressRangesVector(); // Single range specified by low/high PC. - uint64_t LowPC, HighPC; - if (getLowAndHighPC(LowPC, HighPC)) { - return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); - } + uint64_t LowPC, HighPC, Index; + if (getLowAndHighPC(LowPC, HighPC, Index)) + return {{LowPC, HighPC, Index}}; + // Multiple ranges from .debug_ranges section. - auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges); + auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); if (RangesOffset) { DWARFDebugRangeList RangeList; if (U->extractRangeList(*RangesOffset, RangeList)) @@ -267,7 +263,7 @@ DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { for (const auto& R : getAddressRanges()) { - if (R.first <= Address && Address < R.second) + if (R.LowPC <= Address && Address < R.HighPC) return true; } return false; @@ -284,40 +280,35 @@ const char * DWARFDie::getName(DINameKind Kind) const { if (!isValid() || Kind == DINameKind::None) return nullptr; - const char *name = nullptr; // Try to get mangled name only if it was asked for. if (Kind == DINameKind::LinkageName) { - if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr))) - return name; - if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr))) - return name; + if (auto Name = dwarf::toString(findRecursively({DW_AT_MIPS_linkage_name, + DW_AT_linkage_name}), nullptr)) + return Name; } - if ((name = getAttributeValueAsString(DW_AT_name, nullptr))) - return name; - // Try to get name from specification DIE. - DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification); - if (SpecDie && (name = SpecDie.getName(Kind))) - return name; - // Try to get name from abstract origin DIE. - DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin); - if (AbsDie && (name = AbsDie.getName(Kind))) - return name; + if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr)) + return Name; return nullptr; } +uint64_t DWARFDie::getDeclLine() const { + return toUnsigned(findRecursively(DW_AT_decl_line), 0); +} + void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, - uint32_t &CallColumn) const { - CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0); - CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0); - CallColumn = - getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0); + uint32_t &CallColumn, + uint32_t &CallDiscriminator) const { + CallFile = toUnsigned(find(DW_AT_call_file), 0); + CallLine = toUnsigned(find(DW_AT_call_line), 0); + CallColumn = toUnsigned(find(DW_AT_call_column), 0); + CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); } -void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, - unsigned Indent) const { +void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent, + DIDumpOptions DumpOpts) const { if (!isValid()) return; - DataExtractor debug_info_data = U->getDebugInfoExtractor(); + DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); const uint32_t Offset = getOffset(); uint32_t offset = Offset; @@ -334,20 +325,28 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, else WithColor(OS, syntax::Tag).get().indent(Indent) << format("DW_TAG_Unknown_%x", getTag()); - - OS << format(" [%u] %c\n", abbrCode, - AbbrevDecl->hasChildren() ? '*' : ' '); - + + if (!DumpOpts.Brief) + OS << format(" [%u] %c", abbrCode, + AbbrevDecl->hasChildren() ? '*' : ' '); + OS << '\n'; + // Dump all data in the DIE for the attributes. for (const auto &AttrSpec : AbbrevDecl->attributes()) { + if (AttrSpec.Form == DW_FORM_implicit_const) { + // We are dumping .debug_info section , + // implicit_const attribute values are not really stored here, + // but in .debug_abbrev section. So we just skip such attrs. + continue; + } dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, - Indent); + Indent, DumpOpts); } DWARFDie child = getFirstChild(); if (RecurseDepth > 0 && child) { while (child) { - child.dump(OS, RecurseDepth-1, Indent+2); + child.dump(OS, RecurseDepth-1, Indent+2, DumpOpts); child = child.getSibling(); } } @@ -361,33 +360,6 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, } } - -void DWARFDie::getInlinedChainForAddress( - const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const { - if (isNULL()) - return; - DWARFDie DIE(*this); - while (DIE) { - // Append current DIE to inlined chain only if it has correct tag - // (e.g. it is not a lexical block). - if (DIE.isSubroutineDIE()) - InlinedChain.push_back(DIE); - - // Try to get child which also contains provided address. - DWARFDie Child = DIE.getFirstChild(); - while (Child) { - if (Child.addressRangeContainsAddress(Address)) { - // Assume there is only one such child. - break; - } - Child = Child.getSibling(); - } - DIE = Child; - } - // Reverse the obtained chain to make the root of inlined chain last. - std::reverse(InlinedChain.begin(), InlinedChain.end()); -} - DWARFDie DWARFDie::getParent() const { if (isValid()) return U->getParent(Die); @@ -399,3 +371,53 @@ DWARFDie DWARFDie::getSibling() const { return U->getSibling(Die); return DWARFDie(); } + +iterator_range<DWARFDie::attribute_iterator> +DWARFDie::attributes() const { + return make_range(attribute_iterator(*this, false), + attribute_iterator(*this, true)); +} + +DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) : + Die(D), AttrValue(0), Index(0) { + auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); + assert(AbbrDecl && "Must have abbreviation declaration"); + if (End) { + // This is the end iterator so we set the index to the attribute count. + Index = AbbrDecl->getNumAttributes(); + } else { + // This is the begin iterator so we extract the value for this->Index. + AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); + updateForIndex(*AbbrDecl, 0); + } +} + +void DWARFDie::attribute_iterator::updateForIndex( + const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { + Index = I; + // AbbrDecl must be valid before calling this function. + auto NumAttrs = AbbrDecl.getNumAttributes(); + if (Index < NumAttrs) { + AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); + // Add the previous byte size of any previous attribute value. + AttrValue.Offset += AttrValue.ByteSize; + AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index)); + uint32_t ParseOffset = AttrValue.Offset; + auto U = Die.getDwarfUnit(); + assert(U && "Die must have valid DWARF unit"); + bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), + &ParseOffset, U); + (void)b; + assert(b && "extractValue cannot fail on fully parsed DWARF"); + AttrValue.ByteSize = ParseOffset - AttrValue.Offset; + } else { + assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); + AttrValue.clear(); + } +} + +DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { + if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) + updateForIndex(*AbbrDecl, Index + 1); + return *this; +} |