[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