https://github.com/firmiana402 created https://github.com/llvm/llvm-project/pull/208435
This PR fixes two DW_OP_convert-related issues in LLDB. #208203 #208197 First, a nonzero DW_OP_convert operand must reference a DW_TAG_base_type DIE. LLDB previously accepted any DIE that happened to carry base-type-like size and encoding attributes. This patch rejects non-base-type DIEs before using them as DW_OP_convert target types. Second, for base types that carry both DW_AT_bit_size and DW_AT_byte_size, LLDB previously derived the conversion width from DW_AT_byte_size * 8. This is incorrect for types such as C _BitInt(31), where DW_AT_bit_size describes the actual value width. This patch prefers DW_AT_bit_size when present and falls back to DW_AT_byte_size otherwise. ## Tests Extended DWARFExpression.DW_OP_convert coverage to verify: - non-DW_TAG_base_type DIEs are rejected as DW_OP_convert target types; - DW_AT_bit_size is preferred over DW_AT_byte_size for conversion width. >From 5f80116cf6c48cfb7423c175b901f00dc77ecdb1 Mon Sep 17 00:00:00 2001 From: firmiana402 <[email protected]> Date: Thu, 9 Jul 2026 19:20:48 +0800 Subject: [PATCH 1/2] [lldb] Reject non-base type DIEs for DW_OP_convert --- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 3 +++ .../Expression/DWARFExpressionTest.cpp | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 4b02124e987e8..aea2267277656 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -724,6 +724,9 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const { DWARFDIE die = const_cast<DWARFUnit *>(this)->GetDIE(abs_die_offset); if (!die) return llvm::createStringError("cannot resolve DW_OP_convert type DIE"); + if (die.Tag() != DW_TAG_base_type) + return llvm::createStringError( + "DW_OP_convert type DIE is not a DW_TAG_base_type"); uint64_t encoding = die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user); uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index 75162ca0b5f3e..bb64425ca9426 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -445,6 +445,14 @@ TEST(DWARFExpression, DW_OP_convert) { Form: DW_FORM_data1 - Attribute: DW_AT_byte_size Form: DW_FORM_data1 + - Code: 0x00000003 + Tag: DW_TAG_enumeration_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 debug_info: - Version: 4 AddrSize: 8 @@ -493,15 +501,21 @@ TEST(DWARFExpression, DW_OP_convert) { Values: - Value: 0x000000000000000b # DW_ATE_numeric_string - Value: 0x0000000000000001 + # 0x00000020: + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000007 # DW_ATE_unsigned + - Value: 0x0000000000000004 - AbbrCode: 0x00000000 )"; - // Compile unit relative offsets to each DW_TAG_base_type + // Compile unit relative offsets to type DIEs. uint8_t offs_uint32_t = 0x0000000e; uint8_t offs_uint64_t = 0x00000011; uint8_t offs_sint64_t = 0x00000014; uint8_t offs_uchar = 0x00000017; uint8_t offs_schar = 0x0000001a; + uint8_t offs_enum = 0x00000020; DWARFExpressionTester t(yamldata, /*cu_index=*/1); ASSERT_TRUE((bool)t.GetDwarfUnit()); @@ -575,6 +589,12 @@ TEST(DWARFExpression, DW_OP_convert) { t.Eval({DW_OP_const1s, 'X', DW_OP_convert, 0x1d}).takeError(), llvm::Failed()); + // Not a DW_TAG_base_type. + EXPECT_THAT_ERROR( + t.Eval({DW_OP_const1s, 'X', DW_OP_convert, offs_enum}).takeError(), + llvm::FailedWithMessage( + "DW_OP_convert type DIE is not a DW_TAG_base_type")); + // A non-zero DIE offset with no DWARF unit. EXPECT_THAT_ERROR( Evaluate({DW_OP_const1s, 'X', DW_OP_convert, 0x01}, nullptr, nullptr) >From 8a192c1dde2e4bb8f55d8ee0b4aca3256fbb4a6a Mon Sep 17 00:00:00 2001 From: firmiana402 <[email protected]> Date: Thu, 9 Jul 2026 19:23:06 +0800 Subject: [PATCH 2/2] [lldb] Prefer DW_AT_bit_size for DW_OP_convert type width --- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 4 ++-- .../Expression/DWARFExpressionTest.cpp | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index aea2267277656..3fe8bbb8fdf56 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -729,9 +729,9 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const { "DW_OP_convert type DIE is not a DW_TAG_base_type"); uint64_t encoding = die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user); - uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); if (!bit_size) - bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); + bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; if (!bit_size) return llvm::createStringError("unsupported type size"); bool sign; diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index bb64425ca9426..c5ce2c3ec7afb 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -453,6 +453,16 @@ TEST(DWARFExpression, DW_OP_convert) { Form: DW_FORM_data1 - Attribute: DW_AT_byte_size Form: DW_FORM_data1 + - Code: 0x00000004 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Attribute: DW_AT_bit_size + Form: DW_FORM_data1 debug_info: - Version: 4 AddrSize: 8 @@ -506,6 +516,12 @@ TEST(DWARFExpression, DW_OP_convert) { Values: - Value: 0x0000000000000007 # DW_ATE_unsigned - Value: 0x0000000000000004 + # 0x00000023: + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000005 # DW_ATE_signed + - Value: 0x0000000000000004 + - Value: 0x000000000000001f - AbbrCode: 0x00000000 )"; @@ -516,6 +532,7 @@ TEST(DWARFExpression, DW_OP_convert) { uint8_t offs_uchar = 0x00000017; uint8_t offs_schar = 0x0000001a; uint8_t offs_enum = 0x00000020; + uint8_t offs_sint31_t = 0x00000023; DWARFExpressionTester t(yamldata, /*cu_index=*/1); ASSERT_TRUE((bool)t.GetDwarfUnit()); @@ -569,6 +586,11 @@ TEST(DWARFExpression, DW_OP_convert) { offs_schar, DW_OP_stack_value}), ExpectScalar(8, 'A', is_signed)); + // Prefer DW_AT_bit_size over DW_AT_byte_size when both are present. + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4u, 0x00, 0x00, 0x00, 0x40, + DW_OP_convert, offs_sint31_t, DW_OP_stack_value}), + ExpectScalar(31, 0x40000000, is_signed)); + // // Errors. // _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
