diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/CodeGen/DIE.h | 14 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h | 29 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp | 35 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 4 | ||||
-rw-r--r-- | llvm/test/DebugInfo/Inputs/implicit-const-test.o | 0 | ||||
-rw-r--r-- | llvm/test/DebugInfo/dwarfdump-implicit-const.test | 2 | ||||
-rw-r--r-- | llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp | 30 |
11 files changed, 115 insertions, 22 deletions
diff --git a/llvm/include/llvm/CodeGen/DIE.h b/llvm/include/llvm/CodeGen/DIE.h index 09c3bf6a1b5..95c4b4248bb 100644 --- a/llvm/include/llvm/CodeGen/DIE.h +++ b/llvm/include/llvm/CodeGen/DIE.h @@ -52,13 +52,20 @@ class DIEAbbrevData { /// Dwarf form code. dwarf::Form Form; + /// Dwarf attribute value for DW_FORM_implicit_const + int64_t Value; + public: - DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) + : Attribute(A), Form(F), Value(0) {} + DIEAbbrevData(dwarf::Attribute A, int64_t V) + : Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {} /// Accessors. /// @{ dwarf::Attribute getAttribute() const { return Attribute; } dwarf::Form getForm() const { return Form; } + int64_t getValue() const { return Value; } /// @} /// Used to gather unique data for the abbreviation folding set. @@ -102,6 +109,11 @@ public: Data.push_back(DIEAbbrevData(Attribute, Form)); } + /// Adds attribute with DW_FORM_implicit_const value + void AddImplicitConstAttribute(dwarf::Attribute Attribute, int64_t Value) { + Data.push_back(DIEAbbrevData(Attribute, Value)); + } + /// Used to gather unique data for the abbreviation folding set. void Profile(FoldingSetNodeID &ID) const; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 778817f57bf..db9bd506be8 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -23,21 +23,32 @@ class raw_ostream; class DWARFAbbreviationDeclaration { public: struct AttributeSpec { - AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> S) - : Attr(A), Form(F), ByteSize(S) {} + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V) + : Attr(A), Form(F), ByteSizeOrValue(V) {} dwarf::Attribute Attr; dwarf::Form Form; - /// If ByteSize has a value, then it contains the fixed size in bytes for - /// the Form in this object. If ByteSize doesn't have a value, then the - /// byte size of Form either varies according to the DWARFUnit that it is - /// contained in or the value size varies and must be decoded from the - /// debug information in order to determine its size. - Optional<uint8_t> ByteSize; + /// The following field is used for ByteSize for non-implicit_const + /// attributes and as value for implicit_const ones, indicated by + /// Form == DW_FORM_implicit_const. + /// The following cases are distinguished: + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue has a value: + /// ByteSizeOrValue contains the fixed size in bytes + /// for the Form in this object. + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue is None: + /// byte size of Form either varies according to the DWARFUnit + /// that it is contained in or the value size varies and must be + /// decoded from the debug information in order to determine its size. + /// * Form == DW_FORM_implicit_const: + /// ByteSizeOrValue contains value for the implicit_const attribute. + Optional<int64_t> ByteSizeOrValue; + bool isImplicitConst() const { + return Form == dwarf::DW_FORM_implicit_const; + } /// Get the fixed byte size of this Form if possible. This function might /// use the DWARFUnit to calculate the size of the Form, like for /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for /// the ByteSize member. - Optional<uint8_t> getByteSize(const DWARFUnit &U) const; + Optional<int64_t> getByteSize(const DWARFUnit &U) const; }; typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 920880cea10..1b7659dfb04 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -57,6 +57,9 @@ public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {} dwarf::Form getForm() const { return Form; } void setForm(dwarf::Form F) { Form = F; } + void setUValue(uint64_t V) { Value.uval = V; } + void setSValue(int64_t V) { Value.sval = V; } + void setPValue(const char *V) { Value.cstr = V; } bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS) const; diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index 8ae2f2487ca..a8a3b30d5b6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -79,6 +79,13 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const { // Emit form type. AP->EmitULEB128(AttrData.getForm(), dwarf::FormEncodingString(AttrData.getForm()).data()); + + // Emit value for DW_FORM_implicit_const. + if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) { + assert(AP->getDwarfVersion() >= 5 && + "DW_FORM_implicit_const is supported starting from DWARFv5"); + AP->EmitSLEB128(AttrData.getValue()); + } } // Mark end of abbreviation. @@ -160,7 +167,11 @@ DIE *DIE::getParent() const { DIEAbbrev DIE::generateAbbrev() const { DIEAbbrev Abbrev(Tag, hasChildren()); for (const DIEValue &V : values()) - Abbrev.AddAttribute(V.getAttribute(), V.getForm()); + if (V.getForm() == dwarf::DW_FORM_implicit_const) + Abbrev.AddImplicitConstAttribute(V.getAttribute(), + V.getDIEInteger().getValue()); + else + Abbrev.AddAttribute(V.getAttribute(), V.getForm()); return Abbrev; } @@ -342,6 +353,8 @@ void DIEValue::dump() const { /// void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { switch (Form) { + case dwarf::DW_FORM_implicit_const: + LLVM_FALLTHROUGH; case dwarf::DW_FORM_flag_present: // Emit something to keep the lines and comments in sync. // FIXME: Is there a better way to do this? @@ -406,6 +419,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { /// unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { switch (Form) { + case dwarf::DW_FORM_implicit_const: LLVM_FALLTHROUGH; case dwarf::DW_FORM_flag_present: return 0; case dwarf::DW_FORM_flag: LLVM_FALLTHROUGH; case dwarf::DW_FORM_ref1: LLVM_FALLTHROUGH; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 4f90245c6d4..2a866c071f5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -200,6 +200,8 @@ void DwarfUnit::addUInt(DIEValueList &Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form, uint64_t Integer) { if (!Form) Form = DIEInteger::BestForm(false, Integer); + assert(Form != dwarf::DW_FORM_implicit_const && + "DW_FORM_implicit_const is used only for signed integers"); Die.addValue(DIEValueAllocator, Attribute, *Form, DIEInteger(Integer)); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 6126470aa09..08bc74a81e9 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -56,13 +56,20 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr)); auto F = static_cast<Form>(Data.getULEB128(OffsetPtr)); if (A && F) { - auto FixedFormByteSize = DWARFFormValue::getFixedByteSize(F); - AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize)); + Optional<int64_t> V; + bool IsImplicitConst = (F == DW_FORM_implicit_const); + if (IsImplicitConst) + V = Data.getSLEB128(OffsetPtr); + else if (auto Size = DWARFFormValue::getFixedByteSize(F)) + V = *Size; + AttributeSpecs.push_back(AttributeSpec(A, F, V)); + if (IsImplicitConst) + continue; // If this abbrevation still has a fixed byte size, then update the // FixedAttributeSize as needed. if (FixedAttributeSize) { - if (FixedFormByteSize) - FixedAttributeSize->NumBytes += *FixedFormByteSize; + if (V) + FixedAttributeSize->NumBytes += *V; else { switch (F) { case DW_FORM_addr: @@ -129,6 +136,8 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { OS << formString; else OS << format("DW_FORM_Unknown_%x", Spec.Form); + if (Spec.isImplicitConst()) + OS << '\t' << *Spec.ByteSizeOrValue; OS << '\n'; } OS << '\n'; @@ -160,11 +169,15 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( if (*MatchAttrIndex == AttrIndex) { // We have arrived at the attribute to extract, extract if from Offset. DWARFFormValue FormValue(Spec.Form); + if (Spec.isImplicitConst()) { + FormValue.setSValue(*Spec.ByteSizeOrValue); + return FormValue; + } if (FormValue.extractValue(DebugInfoData, &Offset, &U)) return FormValue; } // March Offset along until we get to the attribute we want. - if (Optional<uint8_t> FixedSize = Spec.getByteSize(U)) + if (auto FixedSize = Spec.getByteSize(U)) Offset += *FixedSize; else DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U); @@ -185,9 +198,17 @@ size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( return ByteSize; } -Optional<uint8_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( +Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( const DWARFUnit &U) const { - return ByteSize ? ByteSize : DWARFFormValue::getFixedByteSize(Form, &U); + if (isImplicitConst()) + return 0; + if (ByteSizeOrValue) + return ByteSizeOrValue; + Optional<int64_t> S; + auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U); + if (FixedByteSize) + S = *FixedByteSize; + return S; } Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 9f623e4954c..c487e1dca7c 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -57,7 +57,7 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, // Skip all data in the .debug_info for the attributes for (const auto &AttrSpec : AbbrevDecl->attributes()) { // Check if this attribute has a fixed byte size. - if (Optional<uint8_t> FixedSize = AttrSpec.getByteSize(U)) { + if (auto FixedSize = AttrSpec.getByteSize(U)) { // Attribute byte size if fixed, just add the size to the offset. *OffsetPtr += *FixedSize; } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index e48a6f0981b..dc9310dc4e8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -153,7 +153,7 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) { return 16; case DW_FORM_implicit_const: - // The implicit value is stored in the abbreviation as a ULEB128, any + // The implicit value is stored in the abbreviation as a SLEB128, and // there no data in debug info. return 0; @@ -280,6 +280,8 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: return (FC == FC_String); + case DW_FORM_implicit_const: + return (FC == FC_Constant); default: break; } diff --git a/llvm/test/DebugInfo/Inputs/implicit-const-test.o b/llvm/test/DebugInfo/Inputs/implicit-const-test.o new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/llvm/test/DebugInfo/Inputs/implicit-const-test.o diff --git a/llvm/test/DebugInfo/dwarfdump-implicit-const.test b/llvm/test/DebugInfo/dwarfdump-implicit-const.test new file mode 100644 index 00000000000..5458ada1a17 --- /dev/null +++ b/llvm/test/DebugInfo/dwarfdump-implicit-const.test @@ -0,0 +1,2 @@ +RUN: llvm-dwarfdump -debug-dump=abbrev %p/Inputs/implicit-const-test.o | FileCheck %s +CHECK: DW_FORM_implicit_const -9223372036854775808 diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp index 4435b794268..4ad9e22dba1 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -77,6 +77,7 @@ void TestAllForms() { const uint64_t Data8 = 0x0011223344556677ULL; const uint64_t Data8_2 = 0xAABBCCDDEEFF0011ULL; const int64_t SData = INT64_MIN; + const int64_t ICSData = INT64_MAX; // DW_FORM_implicit_const SData const uint64_t UData[] = {UINT64_MAX - 1, UINT64_MAX - 2, UINT64_MAX - 3, UINT64_MAX - 4, UINT64_MAX - 5, UINT64_MAX - 6, UINT64_MAX - 7, UINT64_MAX - 8, UINT64_MAX - 9}; @@ -181,6 +182,12 @@ void TestAllForms() { const auto Attr_DW_FORM_sdata = static_cast<dwarf::Attribute>(Attr++); CUDie.addAttribute(Attr_DW_FORM_sdata, DW_FORM_sdata, SData); + const auto Attr_DW_FORM_implicit_const = + static_cast<dwarf::Attribute>(Attr++); + if (Version >= 5) + CUDie.addAttribute(Attr_DW_FORM_implicit_const, DW_FORM_implicit_const, + ICSData); + //---------------------------------------------------------------------- // Test ULEB128 based forms //---------------------------------------------------------------------- @@ -323,13 +330,14 @@ void TestAllForms() { Attr_DW_FORM_flag_present, 0ULL), 1ULL); - // TODO: test Attr_DW_FORM_implicit_const extraction - //---------------------------------------------------------------------- // Test SLEB128 based forms //---------------------------------------------------------------------- EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata, 0), SData); + if (Version >= 5) + EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant( + Attr_DW_FORM_implicit_const, 0), ICSData); //---------------------------------------------------------------------- // Test ULEB128 based forms @@ -408,6 +416,24 @@ TEST(DWARFDebugInfo, TestDWARF32Version4Addr8AllForms) { TestAllForms<4, AddrType, RefAddrType>(); } +TEST(DWARFDebugInfo, TestDWARF32Version5Addr4AllForms) { + // Test that we can decode all forms for DWARF32, version 5, with 4 byte + // addresses. + typedef uint32_t AddrType; + // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later + typedef uint32_t RefAddrType; + TestAllForms<5, AddrType, RefAddrType>(); +} + +TEST(DWARFDebugInfo, TestDWARF32Version5Addr8AllForms) { + // Test that we can decode all forms for DWARF32, version 5, with 8 byte + // addresses. + typedef uint64_t AddrType; + // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later + typedef uint32_t RefAddrType; + TestAllForms<5, AddrType, RefAddrType>(); +} + template <uint16_t Version, class AddrType> void TestChildren() { // Test that we can decode DW_FORM_ref_addr values correctly in DWARF 2 with // 4 byte addresses. DW_FORM_ref_addr values should be 4 bytes when using |