[Lldb-commits] [lldb] [LLDB] Fix DW_OP_implicit_value GetOpcodeDataSize() error (PR #201344)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 3 23:18:28 PDT 2026
https://github.com/Thrrreeee updated https://github.com/llvm/llvm-project/pull/201344
>From 4537fa98178df2c89c770ab4c9a07e71f4910846 Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Wed, 3 Jun 2026 20:30:35 +0800
Subject: [PATCH 1/2] [LLDB] Fix DW_OP_implicit_value GetOpcodeDataSize() error
---
lldb/source/Expression/DWARFExpression.cpp | 2 +-
.../DWARF/x86/DW_OP_impilict_value.s | 166 ++++++++++++++++++
2 files changed, 167 insertions(+), 1 deletion(-)
create mode 100644 lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 106e3b4d59283..dd436e0c8afd9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -414,7 +414,7 @@ GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset,
case DW_OP_implicit_value: // 0x9e ULEB128 size followed by block of that size
// (DWARF4)
{
- uint64_t block_len = data.Skip_LEB128(&offset);
+ uint64_t block_len = data.GetULEB128(&offset);
offset += block_len;
return offset - data_offset;
}
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
new file mode 100644
index 0000000000000..311f60981c04b
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
@@ -0,0 +1,166 @@
+# Test that LLDB correctly handles DW_OP_implicit_value for scalar
+# and aggregate types.
+#
+# RUN: llvm-mc -filetype=obj -o %t -triple x86_64-pc-linux %s
+# RUN: %lldb %t \
+# RUN: -o "target variable int_val" \
+# RUN: -o "target variable point" \
+# RUN: -o "target variable char_val" \
+# RUN: -b 2>&1 | FileCheck %s
+
+# CHECK: (lldb) target variable int_val
+# CHECK-NOT: error:
+# CHECK-NEXT: (int) int_val = 42
+
+# CHECK: (lldb) target variable point
+# CHECK-NOT: error:
+# CHECK-NEXT: (Point) point = {
+# CHECK-NEXT: x = 10
+# CHECK-NEXT: y = 20
+# CHECK-NEXT: }
+
+# CHECK: (lldb) target variable char_val
+# CHECK-NOT: error:
+# CHECK-NEXT: (char) char_val = 'A'
+
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbrev [1] DW_TAG_compile_unit
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 11 # DW_FORM_data1
+ .byte 0
+ .byte 0
+
+ .byte 2 # Abbrev [2] DW_TAG_variable
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 8 # DW_FORM_string
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0
+ .byte 0
+
+ .byte 3 # Abbrev [3] DW_TAG_base_type
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 8 # DW_FORM_string
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0
+ .byte 0
+
+ .byte 4 # Abbrev [4] DW_TAG_structure_type
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 3 # DW_AT_name
+ .byte 8 # DW_FORM_string
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0
+ .byte 0
+
+ .byte 5 # Abbrev [5] DW_TAG_member
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 8 # DW_FORM_string
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0
+ .byte 0
+
+ .byte 0 # End of abbrev table
+
+ .section .debug_info,"", at progbits
+.Lcu_begin0:
+ .long .Lcu_end0 - .Lcu_start0
+.Lcu_start0:
+ .short 5 # DWARF version 5
+ .byte 1 # DW_UT_compile
+ .byte 8 # Address size
+ .long .debug_abbrev
+
+ .byte 1 # DW_TAG_compile_unit
+ .byte 12 # DW_LANG_C99
+
+# ---- Base types ----
+.Lint_type:
+ .byte 3 # DW_TAG_base_type
+ .asciz "int"
+ .byte 5 # DW_ATE_signed
+ .byte 4 # 4 bytes
+
+.Lchar_type:
+ .byte 3 # DW_TAG_base_type
+ .asciz "char"
+ .byte 6 # DW_ATE_signed_char
+ .byte 1 # 1 byte
+
+.Llong_type:
+ .byte 3 # DW_TAG_base_type
+ .asciz "long"
+ .byte 5 # DW_ATE_signed
+ .byte 8 # 8 bytes
+
+.Lstruct_type:
+ .byte 4 # DW_TAG_structure_type
+ .asciz "Point"
+ .byte 8 # byte_size = 8
+
+ .byte 5 # DW_TAG_member: x
+ .asciz "x"
+ .long .Lint_type - .Lcu_begin0
+ .byte 0 # offset 0
+
+ .byte 5 # DW_TAG_member: y
+ .asciz "y"
+ .long .Lint_type - .Lcu_begin0
+ .byte 4 # offset 4
+
+ .byte 0 # end of struct children
+
+# int int_val = 42
+ .byte 2 # DW_TAG_variable
+ .asciz "int_val"
+ .long .Lint_type - .Lcu_begin0
+ .byte .Lint_loc_end - .Lint_loc_start
+.Lint_loc_start:
+ .byte 0x9e # DW_OP_implicit_value
+ .uleb128 4 # length = 4 bytes
+ .long 42 # value = 42
+.Lint_loc_end:
+
+# Point point = {10, 20}
+ .byte 2 # DW_TAG_variable
+ .asciz "point"
+ .long .Lstruct_type - .Lcu_begin0
+ .byte .Lpoint_loc_end - .Lpoint_loc_start
+.Lpoint_loc_start:
+ .byte 0x9e # DW_OP_implicit_value
+ .uleb128 8 # length = 8 bytes (two ints)
+ .long 10 # x = 10
+ .long 20 # y = 20
+.Lpoint_loc_end:
+
+# char char_val = 'A'
+ .byte 2 # DW_TAG_variable
+ .asciz "char_val"
+ .long .Lchar_type - .Lcu_begin0
+ .byte .Lchar_loc_end - .Lchar_loc_start
+.Lchar_loc_start:
+ .byte 0x9e # DW_OP_implicit_value
+ .uleb128 1 # length = 1 byte
+ .byte 0x41 # value = 'A'
+.Lchar_loc_end:
+
+ .byte 0 # End of compile unit children
+.Lcu_end0:
\ No newline at end of file
>From c6f121eb1b6c39e0ce38359d5a22f946b0259dc7 Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Thu, 4 Jun 2026 14:17:17 +0800
Subject: [PATCH 2/2] fix and add test
---
.../Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s | 2 +-
lldb/unittests/Expression/DWARFExpressionTest.cpp | 10 ++++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
index 311f60981c04b..caa45e4131c51 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_impilict_value.s
@@ -163,4 +163,4 @@
.Lchar_loc_end:
.byte 0 # End of compile unit children
-.Lcu_end0:
\ No newline at end of file
+.Lcu_end0:
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 00ee6b13ad93c..fe379ebbcc579 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -623,6 +623,16 @@ TEST(DWARFExpression, DW_OP_implicit_value) {
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_implicit_value, bytes, 0x11, 0x22, 0x33, 0x44}),
ExpectHostAddress({0x11, 0x22, 0x33, 0x44}));
+
+ // Verify that GetOpcodeDataSize correctly skips DW_OP_implicit_value
+ // (ULEB128 length + 1-byte data block)
+ std::vector<uint8_t> expr = {DW_OP_implicit_value, 1, 0x11,
+ DW_OP_addr, 0x10, 0x20, 0x30, 0x40};
+ DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
+ /*addr_size*/ 4);
+ DWARFExpression dwarf_expr(extractor);
+ EXPECT_THAT_EXPECTED(dwarf_expr.GetLocation_DW_OP_addr(nullptr),
+ llvm::HasValue(0x40302010u));
}
TEST(DWARFExpression, DW_OP_unknown) {
More information about the lldb-commits
mailing list