diff options
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFDie.cpp')
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFDie.cpp | 165 |
1 files changed, 105 insertions, 60 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index 91f0f8501f0c..904ceab7b286 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "SyntaxHighlighting.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" @@ -22,7 +22,9 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -34,7 +36,6 @@ using namespace llvm; using namespace dwarf; using namespace object; -using namespace syntax; static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { OS << " ("; @@ -62,13 +63,11 @@ static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, if (DumpOpts.Verbose) SectionNames = Obj.getSectionNames(); - for (size_t I = 0; I < Ranges.size(); ++I) { - const DWARFAddressRange &R = Ranges[I]; + for (const DWARFAddressRange &R : Ranges) { OS << '\n'; OS.indent(Indent); - OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", AddressSize * 2, - R.LowPC, AddressSize * 2, R.HighPC); + R.dump(OS, AddressSize); if (SectionNames.empty() || R.SectionIndex == -1ULL) continue; @@ -103,15 +102,18 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, const DWARFSection &LocSection = Obj.getLocSection(); const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); uint32_t Offset = *FormValue.getAsSectionOffset(); - if (!LocSection.Data.empty()) { DWARFDebugLoc DebugLoc; DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), Obj.getAddressSize()); auto LL = DebugLoc.parseOneLocationList(Data, &Offset); - if (LL) - LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); - else + if (LL) { + uint64_t BaseAddr = 0; + if (Optional<BaseAddress> BA = U->getBaseAddress()) + BaseAddr = BA->Address; + LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr, + Indent); + } else OS << "error extracting location list."; } else if (!LocDWOSection.Data.empty()) { DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0); @@ -191,19 +193,10 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, const char BaseIndent[] = " "; OS << BaseIndent; OS.indent(Indent + 2); - auto attrString = AttributeString(Attr); - if (!attrString.empty()) - WithColor(OS, syntax::Attribute) << attrString; - else - WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); + WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); - if (DumpOpts.Verbose || DumpOpts.ShowForm) { - auto formString = FormEncodingString(Form); - if (!formString.empty()) - OS << " [" << formString << ']'; - else - OS << format(" [DW_FORM_Unknown_%x]", Form); - } + if (DumpOpts.Verbose || DumpOpts.ShowForm) + OS << formatv(" [{0}]", Form); DWARFUnit *U = Die.getDwarfUnit(); DWARFFormValue formValue(Form); @@ -216,9 +209,9 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, StringRef Name; std::string File; - auto Color = syntax::Enumerator; + auto Color = HighlightColor::Enumerator; if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { - Color = syntax::String; + Color = HighlightColor::String; if (const auto *LT = U->getContext().getLineTableForUnit(U)) if (LT->getFileNameByIndex( formValue.getAsUnsignedConstant().getValue(), @@ -267,8 +260,22 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, dumpApplePropertyAttribute(OS, *OptVal); } else if (Attr == DW_AT_ranges) { const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); - dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(), - sizeof(BaseIndent) + Indent + 4, DumpOpts); + // For DW_FORM_rnglistx we need to dump the offset separately, since + // we have only dumped the index so far. + Optional<DWARFFormValue> Value = Die.find(DW_AT_ranges); + if (Value && Value->getForm() == DW_FORM_rnglistx) + if (auto RangeListOffset = + U->getRnglistOffset(*Value->getAsSectionOffset())) { + DWARFFormValue FV(dwarf::DW_FORM_sec_offset); + FV.setUValue(*RangeListOffset); + FV.dump(OS, DumpOpts); + } + if (auto RangesOrError = Die.getAddressRanges()) + dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), + sizeof(BaseIndent) + Indent + 4, DumpOpts); + else + WithColor::error() << "decoding address ranges: " + << toString(RangesOrError.takeError()) << '\n'; } OS << ")\n"; @@ -306,18 +313,37 @@ DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { Optional<DWARFFormValue> DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { - if (!isValid()) - return None; - if (auto Value = find(Attrs)) - return Value; - if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) { - if (auto Value = Die.findRecursively(Attrs)) - return Value; - } - if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification)) { - if (auto Value = Die.findRecursively(Attrs)) + std::vector<DWARFDie> Worklist; + Worklist.push_back(*this); + + // Keep track if DIEs already seen to prevent infinite recursion. + // Empirically we rarely see a depth of more than 3 when dealing with valid + // DWARF. This corresponds to following the DW_AT_abstract_origin and + // DW_AT_specification just once. + SmallSet<DWARFDie, 3> Seen; + + while (!Worklist.empty()) { + DWARFDie Die = Worklist.back(); + Worklist.pop_back(); + + if (!Die.isValid()) + continue; + + if (Seen.count(Die)) + continue; + + Seen.insert(Die); + + if (auto Value = Die.find(Attrs)) return Value; + + if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Worklist.push_back(D); + + if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) + Worklist.push_back(D); } + return None; } @@ -363,20 +389,19 @@ bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, return false; } -DWARFAddressRangesVector DWARFDie::getAddressRanges() const { +Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { if (isNULL()) return DWARFAddressRangesVector(); // Single range specified by low/high PC. uint64_t LowPC, HighPC, Index; if (getLowAndHighPC(LowPC, HighPC, Index)) - return {{LowPC, HighPC, Index}}; - - // Multiple ranges from .debug_ranges section. - auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); - if (RangesOffset) { - DWARFDebugRangeList RangeList; - if (U->extractRangeList(*RangesOffset, RangeList)) - return RangeList.getAbsoluteRanges(U->getBaseAddress()); + return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; + + Optional<DWARFFormValue> Value = find(DW_AT_ranges); + if (Value) { + if (Value->getForm() == DW_FORM_rnglistx) + return U->findRnglistFromIndex(*Value->getAsSectionOffset()); + return U->findRnglistFromOffset(*Value->getAsSectionOffset()); } return DWARFAddressRangesVector(); } @@ -386,8 +411,11 @@ void DWARFDie::collectChildrenAddressRanges( if (isNULL()) return; if (isSubprogramDIE()) { - const auto &DIERanges = getAddressRanges(); - Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + if (auto DIERangesOrError = getAddressRanges()) + Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), + DIERangesOrError.get().end()); + else + llvm::consumeError(DIERangesOrError.takeError()); } for (auto Child : children()) @@ -395,10 +423,15 @@ void DWARFDie::collectChildrenAddressRanges( } bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { - for (const auto &R : getAddressRanges()) { + auto RangesOrError = getAddressRanges(); + if (!RangesOrError) { + llvm::consumeError(RangesOrError.takeError()); + return false; + } + + for (const auto &R : RangesOrError.get()) if (R.LowPC <= Address && Address < R.HighPC) return true; - } return false; } @@ -454,25 +487,23 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, const uint32_t Offset = getOffset(); uint32_t offset = Offset; if (DumpOpts.ShowParents) { - DumpOpts.ShowParents = false; - Indent = dumpParentChain(getParent(), OS, Indent, DumpOpts); + DIDumpOptions ParentDumpOpts = DumpOpts; + ParentDumpOpts.ShowParents = false; + ParentDumpOpts.ShowChildren = false; + Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); } if (debug_info_data.isValidOffset(offset)) { uint32_t abbrCode = debug_info_data.getULEB128(&offset); if (DumpOpts.ShowAddresses) - WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); + WithColor(OS, HighlightColor::Address).get() + << format("\n0x%8.8x: ", Offset); if (abbrCode) { auto AbbrevDecl = getAbbreviationDeclarationPtr(); if (AbbrevDecl) { - auto tagString = TagString(getTag()); - if (!tagString.empty()) - WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; - else - WithColor(OS, syntax::Tag).get().indent(Indent) - << format("DW_TAG_Unknown_%x", getTag()); - + WithColor(OS, HighlightColor::Tag).get().indent(Indent) + << formatv("{0}", getTag()); if (DumpOpts.Verbose) OS << format(" [%u] %c", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); @@ -493,8 +524,10 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, DWARFDie child = getFirstChild(); if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) { DumpOpts.RecurseDepth--; + DIDumpOptions ChildDumpOpts = DumpOpts; + ChildDumpOpts.ShowParents = false; while (child) { - child.dump(OS, Indent + 2, DumpOpts); + child.dump(OS, Indent + 2, ChildDumpOpts); child = child.getSibling(); } } @@ -522,12 +555,24 @@ DWARFDie DWARFDie::getSibling() const { return DWARFDie(); } +DWARFDie DWARFDie::getPreviousSibling() const { + if (isValid()) + return U->getPreviousSibling(Die); + return DWARFDie(); +} + DWARFDie DWARFDie::getFirstChild() const { if (isValid()) return U->getFirstChild(Die); return DWARFDie(); } +DWARFDie DWARFDie::getLastChild() const { + if (isValid()) + return U->getLastChild(Die); + return DWARFDie(); +} + iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { return make_range(attribute_iterator(*this, false), attribute_iterator(*this, true)); |