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 @@ -144,6 +144,27 @@ const dwarf::Attribute Attr, const DWARFUnit &U) const; + /// Compute an offset from a DIE specified by DIE offset and attribute index. + /// + /// \param AttrIndex an index of DWARF attribute. + /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation + /// code in the .debug_info data. + /// \param U the DWARFUnit the contains the DIE. + /// \returns an offset of the attribute. + uint64_t getAttributeOffsetFromIndex(uint32_t AttrIndex, uint64_t DIEOffset, + const DWARFUnit &U) const; + + /// Extract a DWARF form value from a DIE speccified by attribute index and + /// its offset. + /// + /// \param AttrIndex an index of DWARF attribute. + /// \param Offset offset of the attribute. + /// \param U the DWARFUnit the contains the DIE. + /// \returns Optional DWARF form value if the attribute was extracted. + Optional + getAttributeValueFromOffset(uint32_t AttrIndex, uint64_t Offset, + const DWARFUnit &U) const; + bool extract(DataExtractor Data, uint64_t* OffsetPtr); void dump(raw_ostream &OS) const; 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 @@ -147,41 +147,57 @@ return None; } -Optional DWARFAbbreviationDeclaration::getAttributeValue( - const uint64_t DIEOffset, const dwarf::Attribute Attr, - const DWARFUnit &U) 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); - if (!MatchAttrIndex) - return None; - - auto DebugInfoData = U.getDebugInfoExtractor(); +uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex( + uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const { + DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); // Add the byte size of ULEB that for the abbrev Code so we can start // skipping the attribute data. uint64_t Offset = DIEOffset + CodeByteSize; - for (uint32_t CurAttrIdx = 0; CurAttrIdx != *MatchAttrIndex; ++CurAttrIdx) + for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx) // Match Offset along until we get to the attribute we want. if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U)) Offset += *FixedSize; else DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData, &Offset, U.getFormParams()); + return Offset; +} + +Optional +DWARFAbbreviationDeclaration::getAttributeValueFromOffset( + uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const { + if (AttributeSpecs.size() <= AttrIndex) + return None; // We have arrived at the attribute to extract, extract if from Offset. - const AttributeSpec &Spec = AttributeSpecs[*MatchAttrIndex]; + const AttributeSpec &Spec = AttributeSpecs[AttrIndex]; if (Spec.isImplicitConst()) return DWARFFormValue::createFromSValue(Spec.Form, Spec.getImplicitConstValue()); DWARFFormValue FormValue(Spec.Form); + DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) return FormValue; - return None; } +Optional +DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset, + const dwarf::Attribute Attr, + const DWARFUnit &U) 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); + if (!MatchAttrIndex) + return None; + + uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U); + + return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U); +} + size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( const DWARFUnit &U) const { size_t ByteSize = NumBytes; diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -1782,6 +1782,13 @@ auto A = it->getAttrByIndex(0); EXPECT_EQ(A, Attr); + Optional AttrIndex = it->findAttributeIndex(A); + EXPECT_TRUE((bool)AttrIndex); + uint64_t OffsetVal = + it->getAttributeOffsetFromIndex(*AttrIndex, /* offset */ 0, *U); + EXPECT_TRUE( + it->getAttributeValueFromOffset(*AttrIndex, OffsetVal, *U).hasValue()); + auto FormValue = it->getAttributeValue(/* offset */ 0, A, *U); EXPECT_TRUE((bool)FormValue); EXPECT_EQ(FormValue->getForm(), dwarf::DW_FORM_implicit_const);