diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -27,12 +27,15 @@ class DWARFAbbreviationDeclaration { public: struct AttributeSpec { - AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value) - : Attr(A), Form(F), Value(Value) { + AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value, + uint32_t AttrOffset = -1U, uint32_t FormOffset = -1U) + : Attr(A), Form(F), AttrOffset(AttrOffset), FormOffset(FormOffset), + Value(Value) { assert(isImplicitConst()); } - AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional ByteSize) - : Attr(A), Form(F) { + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional ByteSize, + uint32_t AttrOffset = -1U, uint32_t FormOffset = -1U) + : Attr(A), Form(F), AttrOffset(AttrOffset), FormOffset(FormOffset) { assert(!isImplicitConst()); this->ByteSize.HasByteSize = ByteSize.hasValue(); if (this->ByteSize.HasByteSize) @@ -41,6 +44,8 @@ dwarf::Attribute Attr; dwarf::Form Form; + uint32_t AttrOffset; + uint32_t FormOffset; private: /// The following field is used for ByteSize for non-implicit_const @@ -121,6 +126,8 @@ return AttributeSpecs[idx].getImplicitConstValue(); } + const AttributeSpec *findAttribute(dwarf::Attribute Attr) const; + /// Get the index of the specified attribute. /// /// Searches the this abbreviation declaration for the index of the specified @@ -142,7 +149,8 @@ /// \returns Optional DWARF form value if the attribute was extracted. Optional getAttributeValue(const uint64_t DIEOffset, const dwarf::Attribute Attr, - const DWARFUnit &U) const; + const DWARFUnit &U, + uint64_t *OffsetPtr = 0) const; bool extract(DataExtractor Data, uint64_t* OffsetPtr); void dump(raw_ostream &OS) const; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -350,6 +350,10 @@ /// into "SectionedAddress Address" DIEsForAddress getDIEsForAddress(uint64_t Address); + /// Get offset to an attribute value within a compile unit + /// or 0 if the attribute was not found. + uint64_t getAttrFieldOffsetForUnit(DWARFUnit *U, dwarf::Attribute Attr) const; + DILineInfo getLineInfoForAddress( object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -139,7 +139,8 @@ /// \param Attr the attribute to extract. /// \returns an optional DWARFFormValue that will have the form value if the /// attribute was successfully extracted. - Optional find(dwarf::Attribute Attr) const; + Optional find(dwarf::Attribute Attr, + uint64_t *OffsetPtr = 0) const; /// Extract the first value of any attribute in Attrs from this DIE. /// diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -60,13 +60,15 @@ // Read all of the abbreviation attributes and forms. while (true) { + uint32_t AOff = *OffsetPtr; auto A = static_cast(Data.getULEB128(OffsetPtr)); + uint32_t FOff = *OffsetPtr; auto F = static_cast
(Data.getULEB128(OffsetPtr)); if (A && F) { bool IsImplicitConst = (F == DW_FORM_implicit_const); if (IsImplicitConst) { int64_t V = Data.getSLEB128(OffsetPtr); - AttributeSpecs.push_back(AttributeSpec(A, F, V)); + AttributeSpecs.push_back(AttributeSpec(A, F, V, AOff, FOff)); continue; } Optional ByteSize; @@ -108,7 +110,7 @@ break; } // Record this attribute and its fixed size if it has one. - AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize)); + AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize, AOff, FOff)); } else if (A == 0 && F == 0) { // We successfully reached the end of this abbreviation declaration // since both attribute and form are zero. @@ -138,6 +140,15 @@ OS << '\n'; } +const DWARFAbbreviationDeclaration::AttributeSpec * +DWARFAbbreviationDeclaration::findAttribute(dwarf::Attribute Attr) const { + for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { + if (AttributeSpecs[i].Attr == Attr) + return &AttributeSpecs[i]; + } + return nullptr; +} + Optional DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { @@ -148,8 +159,8 @@ } Optional DWARFAbbreviationDeclaration::getAttributeValue( - const uint64_t DIEOffset, const dwarf::Attribute Attr, - const DWARFUnit &U) const { + const uint64_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U, + uint64_t *OffsetPtr) const { // Check if this abbreviation has this attribute without needing to skip // any data so we can return quickly if it doesn't. Optional MatchAttrIndex = findAttributeIndex(Attr); @@ -170,6 +181,8 @@ &Offset, U.getFormParams()); // We have arrived at the attribute to extract, extract if from Offset. + if (OffsetPtr) + *OffsetPtr = Offset; const AttributeSpec &Spec = AttributeSpecs[*MatchAttrIndex]; if (Spec.isImplicitConst()) return DWARFFormValue::createFromSValue(Spec.Form, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1363,6 +1363,19 @@ return InliningInfo; } +uint64_t DWARFContext::getAttrFieldOffsetForUnit(DWARFUnit *U, + dwarf::Attribute Attr) const { + const auto UnitDIE = U->getUnitDIE(); + if (!UnitDIE) + return 0; + + uint64_t Offset = 0; + if (!UnitDIE.find(Attr, &Offset)) + return 0; + + return Offset; +} + std::shared_ptr DWARFContext::getDWOContext(StringRef AbsolutePath) { if (auto S = DWP.lock()) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -342,12 +342,13 @@ return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; } -Optional DWARFDie::find(dwarf::Attribute Attr) const { +Optional DWARFDie::find(dwarf::Attribute Attr, + uint64_t *OffsetPtr) const { if (!isValid()) return None; auto AbbrevDecl = getAbbreviationDeclarationPtr(); if (AbbrevDecl) - return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); + return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U, OffsetPtr); return None; }