https://github.com/Thrrreeee updated 
https://github.com/llvm/llvm-project/pull/203182

>From e50ddd754233924e97414746c3796c733e3a7df7 Mon Sep 17 00:00:00 2001
From: shijinrui <[email protected]>
Date: Tue, 23 Jun 2026 17:42:32 +0800
Subject: [PATCH 1/3] Support for DW_OP_Implicit_pointer

---
 lldb/include/lldb/Core/Value.h                |  18 ++
 .../include/lldb/Expression/DWARFExpression.h |   1 +
 lldb/source/Core/Value.cpp                    |   7 +-
 lldb/source/Expression/DWARFExpression.cpp    |  47 +++-
 .../Plugins/SymbolFile/DWARF/DWARFUnit.h      |   3 +
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  62 ++++-
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |   6 +
 lldb/source/ValueObject/ValueObject.cpp       |  56 ++++
 .../DWARF/x86/DW_OP_implicit_pointer.s        | 243 ++++++++++++++++++
 .../Expression/DWARFExpressionTest.cpp        |  48 +++-
 10 files changed, 467 insertions(+), 24 deletions(-)
 create mode 100644 
lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_implicit_pointer.s

diff --git a/lldb/include/lldb/Core/Value.h b/lldb/include/lldb/Core/Value.h
index 3714621b469ec..2f4f7a3d23cb2 100644
--- a/lldb/include/lldb/Core/Value.h
+++ b/lldb/include/lldb/Core/Value.h
@@ -19,6 +19,7 @@
 
 #include "llvm/ADT/APInt.h"
 
+#include <optional>
 #include <vector>
 
 #include <cstdint>
@@ -37,6 +38,11 @@ namespace lldb_private {
 
 class Value {
 public:
+  struct ImplicitPointerInfo {
+    uint64_t die_offset = 0;
+    int64_t byte_offset = 0;
+  };
+
   /// Type that describes Value::m_value.
   enum class ValueType {
     Invalid = -1,
@@ -93,6 +99,17 @@ class Value {
     m_context_type = ContextType::Invalid;
   }
 
+  bool IsImplicitPointer() const { return m_implicit_pointer_info.has_value(); 
}
+
+  ImplicitPointerInfo GetImplicitPointerInfo() const {
+    return *m_implicit_pointer_info;
+  }
+
+  void SetImplicitPointer(ImplicitPointerInfo implicit_pointer) {
+    m_implicit_pointer_info = implicit_pointer;
+    m_value_type = ValueType::Invalid;
+  }
+
   void SetContext(ContextType context_type, void *p) {
     m_context_type = context_type;
     m_context = p;
@@ -182,6 +199,7 @@ class Value {
   ValueType m_value_type = ValueType::Scalar;
   ContextType m_context_type = ContextType::Invalid;
   DataBufferHeap m_data_buffer;
+  std::optional<ImplicitPointerInfo> m_implicit_pointer_info;
 };
 
 class ValueList {
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h 
b/lldb/include/lldb/Expression/DWARFExpression.h
index b1895690985a7..38e4fb5c34c57 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -44,6 +44,7 @@ class DWARFExpression {
 
     virtual uint16_t GetVersion() const = 0;
     virtual dw_addr_t GetBaseAddress() const = 0;
+    virtual llvm::dwarf::DwarfFormat GetDwarfFormat() const = 0;
     virtual uint8_t GetAddressByteSize() const = 0;
     virtual llvm::Expected<std::pair<uint64_t, bool>>
     GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0;
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index f9e65d397f05f..e9b57efcfe066 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -55,7 +55,8 @@ Value::Value(const void *bytes, int len)
 Value::Value(const Value &v)
     : m_value(v.m_value), m_compiler_type(v.m_compiler_type),
       m_context(v.m_context), m_value_type(v.m_value_type),
-      m_context_type(v.m_context_type), m_data_buffer() {
+      m_context_type(v.m_context_type), m_data_buffer(),
+      m_implicit_pointer_info(v.m_implicit_pointer_info) {
   const uintptr_t rhs_value =
       (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);
   if ((rhs_value != 0) &&
@@ -74,6 +75,7 @@ Value &Value::operator=(const Value &rhs) {
     m_context = rhs.m_context;
     m_value_type = rhs.m_value_type;
     m_context_type = rhs.m_context_type;
+    m_implicit_pointer_info = rhs.m_implicit_pointer_info;
     const uintptr_t rhs_value =
         (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS);
     if ((rhs_value != 0) &&
@@ -89,12 +91,14 @@ Value &Value::operator=(const Value &rhs) {
 
 void Value::SetBytes(const void *bytes, int len) {
   m_value_type = ValueType::HostAddress;
+  m_implicit_pointer_info.reset();
   m_data_buffer.CopyData(bytes, len);
   m_value = (uintptr_t)m_data_buffer.GetBytes();
 }
 
 void Value::AppendBytes(const void *bytes, int len) {
   m_value_type = ValueType::HostAddress;
+  m_implicit_pointer_info.reset();
   m_data_buffer.AppendData(bytes, len);
   m_value = (uintptr_t)m_data_buffer.GetBytes();
 }
@@ -639,6 +643,7 @@ void Value::Clear() {
   m_value_type = ValueType::Scalar;
   m_context = nullptr;
   m_context_type = ContextType::Invalid;
+  m_implicit_pointer_info.reset();
   m_data_buffer.Clear();
 }
 
diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index dd436e0c8afd9..519716b5041ab 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -219,7 +219,6 @@ GetOpcodeDataSize(const DataExtractor &data, const 
lldb::offset_t data_offset,
   case DW_OP_APPLE_uninit:
   case DW_OP_PGI_omp_thread_num:
   case DW_OP_hi_user:
-  case DW_OP_GNU_implicit_pointer:
     break;
 
   case DW_OP_addr:
@@ -419,12 +418,14 @@ GetOpcodeDataSize(const DataExtractor &data, const 
lldb::offset_t data_offset,
     return offset - data_offset;
   }
 
-  case DW_OP_implicit_pointer: // 0xa0 4-byte (or 8-byte for DWARF 64) constant
-                               // + LEB128
+  case DW_OP_implicit_pointer: // 0xa0 4-byte (or 8-byte for DWARF64) DIE 
offset
+  case DW_OP_GNU_implicit_pointer: // 0xf2 4-byte (or 8-byte for DWARF64) DIE
+                                   // offset followed by SLEB128 byte offset.
   {
+    DwarfFormat format = dwarf_cu ? dwarf_cu->GetDwarfFormat() : DWARF32;
+    offset += getDwarfOffsetByteSize(format);
     data.Skip_LEB128(&offset);
-    return (dwarf_cu ? dwarf_cu->GetAddressByteSize() : 4) + offset -
-           data_offset;
+    return offset - data_offset;
   }
 
   case DW_OP_GNU_entry_value:
@@ -943,6 +944,9 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
   // Deref a register or implicit location and truncate the value to `size`
   // bytes. See the corresponding comment in DW_OP_deref for more details on
   // why we deref these locations this way.
+  if (eval_ctx.stack.back().IsImplicitPointer())
+    return llvm::createStringError("cannot dereference an implicit pointer");
+
   if (eval_ctx.loc_desc_kind == Register ||
       eval_ctx.loc_desc_kind == Implicit) {
     // Reset context to default values.
@@ -1077,6 +1081,10 @@ static llvm::Error Evaluate_DW_OP_piece(EvalContext 
&eval_ctx,
   if (piece_byte_size == 0)
     return llvm::Error::success();
 
+  if (eval_ctx.pieces.IsImplicitPointer())
+    return llvm::createStringError(
+        "DW_OP_piece cannot combine DW_OP_implicit_pointer with other pieces");
+
   Value curr_piece;
 
   if (eval_ctx.stack.empty()) {
@@ -1100,6 +1108,16 @@ static llvm::Error Evaluate_DW_OP_piece(EvalContext 
&eval_ctx,
     UpdateValueTypeFromLocationDescription(eval_ctx, piece_locdesc,
                                            &curr_piece_source_value);
 
+    if (curr_piece_source_value.IsImplicitPointer()) {
+      if (eval_ctx.pieces.GetBuffer().GetByteSize() != 0)
+        return llvm::createStringError(
+            "DW_OP_piece cannot combine DW_OP_implicit_pointer with other "
+            "pieces");
+      eval_ctx.pieces = curr_piece_source_value;
+      eval_ctx.op_piece_offset += piece_byte_size;
+      return llvm::Error::success();
+    }
+
     const Value::ValueType curr_piece_source_value_type =
         curr_piece_source_value.GetValueType();
     Scalar &scalar = curr_piece_source_value.GetScalar();
@@ -1299,7 +1317,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     const Value *object_address_ptr) {
   uint32_t address_size = opcodes.GetAddressByteSize();
   llvm::DataExtractor expr_data = opcodes.GetAsLLVM();
-  llvm::DWARFExpression expr(expr_data, address_size);
+  std::optional<DwarfFormat> dwarf_format =
+      dwarf_cu ? dwarf_cu->GetDwarfFormat() : DWARF32;
+  llvm::DWARFExpression expr(expr_data, address_size, dwarf_format);
 
   if (expr_data.size() == 0)
     return llvm::createStringError(
@@ -1853,10 +1873,16 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
     }
 
-    case DW_OP_implicit_pointer: {
+    case DW_OP_implicit_pointer:
+    case DW_OP_GNU_implicit_pointer: {
       eval_ctx.loc_desc_kind = Implicit;
-      return llvm::createStringError("could not evaluate %s",
-                                     DW_OP_value_to_name(opcode));
+      uint64_t die_offset = op->getRawOperand(0);
+      int64_t byte_offset = static_cast<int64_t>(op->getRawOperand(1));
+
+      Value result;
+      result.SetImplicitPointer({die_offset, byte_offset});
+      stack.push_back(result);
+      break;
     }
 
     case DW_OP_push_object_address:
@@ -1981,7 +2007,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   if (stack.empty()) {
     // Nothing on the stack, check if we created a piece value from DW_OP_piece
     // or DW_OP_bit_piece opcodes
-    if (eval_ctx.pieces.GetBuffer().GetByteSize())
+    if (eval_ctx.pieces.GetBuffer().GetByteSize() ||
+        eval_ctx.pieces.IsImplicitPointer())
       return eval_ctx.pieces;
 
     return llvm::createStringError("stack empty after evaluation");
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 6fde9af57fa8b..c02060a622ada 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -122,6 +122,9 @@ class DWARFUnit : public DWARFExpression::Delegate, public 
UserID {
   const llvm::dwarf::FormParams &GetFormParams() const {
     return m_header.getFormParams();
   }
+  llvm::dwarf::DwarfFormat GetDwarfFormat() const override {
+    return m_header.getFormat();
+  }
   const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
   dw_offset_t GetAbbrevOffset() const;
   uint8_t GetAddressByteSize() const override {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c81fd1c83be85..f72fc002fc4cf 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -60,7 +60,10 @@
 #include "lldb/Symbol/TypeMap.h"
 #include "lldb/Symbol/TypeSystem.h"
 #include "lldb/Symbol/VariableList.h"
+#include "lldb/ValueObject/ValueObjectConstResult.h"
+#include "lldb/ValueObject/ValueObjectVariable.h"
 
+#include "lldb/Target/ExecutionContextScope.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/Target.h"
 
@@ -89,6 +92,7 @@
 #include "llvm/Support/FormatVariadic.h"
 
 #include <algorithm>
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <optional>
@@ -96,7 +100,7 @@
 #include <cctype>
 #include <cstring>
 
-//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+// #define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
 
 #ifdef ENABLE_DEBUG_PRINTF
 #include <cstdio>
@@ -3443,6 +3447,62 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const 
SymbolContext &sc) {
   return 0;
 }
 
+lldb::ValueObjectSP SymbolFileDWARF::ResolveImplicitPointer(
+    uint64_t die_offset, int64_t byte_offset, CompilerType pointee_type,
+    ExecutionContextScope *exe_scope, Variable *context_var) {
+  if (!pointee_type || !exe_scope)
+    return nullptr;
+
+  SymbolContext sc;
+  if (context_var)
+    context_var->CalculateSymbolContext(&sc);
+  if (!sc.comp_unit)
+    if (StackFrameSP frame_sp = exe_scope->CalculateStackFrame())
+      sc = frame_sp->GetSymbolContext(eSymbolContextCompUnit |
+                                      eSymbolContextFunction |
+                                      eSymbolContextBlock);
+
+  DWARFDIE target_die = DebugInfo().GetDIE(DIERef::Section::DebugInfo,
+                                           die_offset);
+  if (!target_die)
+    return nullptr;
+
+  if (!sc.comp_unit) {
+    if (DWARFUnit *dwarf_cu = target_die.GetCU())
+      if (auto *compile_unit = llvm::dyn_cast<DWARFCompileUnit>(dwarf_cu))
+        sc.comp_unit = GetCompUnitForDWARFCompUnit(*compile_unit);
+  }
+
+  VariableSP target_var_sp = ParseVariableDIECached(sc, target_die);
+  if (!target_var_sp)
+    return nullptr;
+
+  ValueObjectSP target_valobj_sp =
+      ValueObjectVariable::Create(exe_scope, target_var_sp);
+  if (!target_valobj_sp || !target_valobj_sp->UpdateValueIfNeeded(false))
+    return nullptr;
+
+  DataExtractor target_data;
+  Status target_error;
+  target_valobj_sp->GetData(target_data, target_error);
+  if (target_error.Fail() || target_data.GetByteSize() == 0)
+    return nullptr;
+
+  if (byte_offset < 0 ||
+      static_cast<uint64_t>(byte_offset) > target_data.GetByteSize())
+    return nullptr;
+
+  lldb::offset_t data_offset = byte_offset;
+  lldb::offset_t data_size = target_data.GetByteSize() - data_offset;
+  if (auto type_size =
+          llvm::expectedToOptional(pointee_type.GetByteSize(exe_scope)))
+    data_size = std::min<lldb::offset_t>(data_size, *type_size);
+
+  DataExtractor pointee_data(target_data, data_offset, data_size);
+  return ValueObjectConstResult::Create(exe_scope, pointee_type, ConstString(),
+                                        pointee_data, LLDB_INVALID_ADDRESS);
+}
+
 VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
                                                    const DWARFDIE &die) {
   if (!die)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 21a190d1b38f0..32f646ecc79c7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -136,6 +136,12 @@ class SymbolFileDWARF : public SymbolFileCommon {
 
   size_t ParseVariablesForContext(const SymbolContext &sc) override;
 
+  lldb::ValueObjectSP
+  ResolveImplicitPointer(uint64_t die_offset, int64_t byte_offset,
+                         CompilerType pointee_type,
+                         ExecutionContextScope *exe_scope,
+                         Variable *context_var);
+
   std::optional<ArrayInfo>
   GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,
                             const ExecutionContext *exe_ctx) override;
diff --git a/lldb/source/ValueObject/ValueObject.cpp 
b/lldb/source/ValueObject/ValueObject.cpp
index 32332c2962e87..afd65ac6b0805 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/Variable.h"
 #include "lldb/Target/ABI.h"
@@ -51,7 +52,9 @@
 #include "lldb/ValueObject/ValueObjectVTable.h"
 #include "lldb/lldb-enumerations.h"
 
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Casting.h"
 
 #include <algorithm>
 #include <atomic>
@@ -2393,6 +2396,18 @@ ValueObjectSP 
ValueObject::GetValueForExpressionPath_Impl(
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
         return ValueObjectSP();
       }
+      root->UpdateValueIfNeeded(false);
+      if (root->GetValue().IsImplicitPointer()) {
+        Status error;
+        root = DereferenceValueOrAlternate(
+            *root, options.m_synthetic_children_traversal, error);
+        if (error.Fail() || !root) {
+          *reason_to_stop =
+              ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
+          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
+          return ValueObjectSP();
+        }
+      }
     }
       [[fallthrough]];
     case '.': // or fallthrough from ->
@@ -2817,6 +2832,47 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
   if (m_deref_valobj)
     return m_deref_valobj->GetSP();
 
+  UpdateValueIfNeeded(false);
+  if (m_value.IsImplicitPointer()) {
+    CompilerType pointee_type = GetCompilerType().GetPointeeType();
+    if (!pointee_type) {
+      error = Status::FromErrorString("implicit pointer has no pointee type");
+      return ValueObjectSP();
+    }
+
+    ModuleSP module_sp = GetModule();
+    SymbolFile *symbol_file = module_sp ? module_sp->GetSymbolFile() : nullptr;
+    if (!symbol_file) {
+      error = Status::FromErrorString(
+          "cannot resolve DW_OP_implicit_pointer without symbol file");
+      return ValueObjectSP();
+    }
+
+    ExecutionContext exe_ctx(GetExecutionContextRef());
+    Value::ImplicitPointerInfo implicit_pointer =
+        m_value.GetImplicitPointerInfo();
+    auto *dwarf_symbol_file = llvm::dyn_cast<plugin::dwarf::SymbolFileDWARF>(
+        symbol_file->GetBackingSymbolFile());
+    if (!dwarf_symbol_file) {
+      error = Status::FromErrorString(
+          "cannot resolve DW_OP_implicit_pointer without DWARF symbol file");
+      return ValueObjectSP();
+    }
+
+    ValueObjectSP result_sp = dwarf_symbol_file->ResolveImplicitPointer(
+        implicit_pointer.die_offset, implicit_pointer.byte_offset,
+        pointee_type, exe_ctx.GetBestExecutionContextScope(), 
GetVariable().get());
+    if (!result_sp) {
+      error = Status::FromErrorStringWithFormat(
+          "cannot resolve DW_OP_implicit_pointer target DIE 0x%" PRIx64,
+          implicit_pointer.die_offset);
+      return ValueObjectSP();
+    }
+
+    error.Clear();
+    return result_sp;
+  }
+
   std::string deref_name_str;
   uint32_t deref_byte_size = 0;
   int32_t deref_byte_offset = 0;
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_implicit_pointer.s 
b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_implicit_pointer.s
new file mode 100644
index 0000000000000..1e4dc45733775
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_OP_implicit_pointer.s
@@ -0,0 +1,243 @@
+# Test DW_OP_implicit_pointer for both scalar types (int, char) and struct 
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 *int_ptr" \
+# RUN:   -o "target variable char_val" \
+# RUN:   -o "target variable *char_ptr" \
+# RUN:   -o "target variable point" \
+# RUN:   -o "target variable *struct_ptr" \
+# RUN:   -o "target variable struct_ptr->y" \
+# RUN:   -b | FileCheck %s
+
+# CHECK:      (lldb) target variable int_val
+# CHECK:      (int) int_val = 42
+
+# CHECK:      (lldb) target variable *int_ptr
+# CHECK:      (int) {{.*}} = 42
+
+# CHECK:      (lldb) target variable char_val
+# CHECK:      (char) char_val = 'A'
+
+# CHECK:      (lldb) target variable *char_ptr
+# CHECK:      (char) {{.*}} = 'A'
+
+# CHECK:      (lldb) target variable point
+# CHECK:      (Point) point = {
+# CHECK-NEXT:   x = 10
+# CHECK-NEXT:   y = 20
+# CHECK-NEXT: }
+
+# CHECK:      (lldb) target variable *struct_ptr
+# CHECK:      (Point) {{.*}} = {
+# CHECK-NEXT:   x = 10
+# CHECK-NEXT:   y = 20
+# CHECK-NEXT: }
+
+# CHECK:      (lldb) target variable struct_ptr->y
+# CHECK:      (int) {{.*}} = 20
+
+        .section        .debug_abbrev,"",@progbits
+        .byte   1                       # Abbrev [1] DW_TAG_compile_unit
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   1                       # DW_CHILDREN_yes
+        .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_pointer_type
+        .byte   15                      # DW_TAG_pointer_type
+        .byte   0                       # DW_CHILDREN_no
+        .byte   73                      # DW_AT_type
+        .byte   19                      # DW_FORM_ref4
+        .byte   0
+        .byte   0
+
+        .byte   5                       # Abbrev [5] 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   6                       # Abbrev [6] 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,"",@progbits
+.Ldummy_cu_begin:
+        .long   .Ldummy_cu_end - .Ldummy_cu_start
+.Ldummy_cu_start:
+        .short  5                       # DWARF version 5
+        .byte   1                       # DW_UT_compile
+        .byte   8                       # Address size
+        .long   .debug_abbrev
+
+        .byte   1                       # DW_TAG_compile_unit
+        .byte   0                       # End of compile unit children
+.Ldummy_cu_end:
+
+.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
+
+# ---- 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
+
+# ---- Pointer types ----
+.Lint_ptr_type:
+        .byte   4                       # DW_TAG_pointer_type
+        .long   .Lint_type - .Lcu_begin0
+
+.Lchar_ptr_type:
+        .byte   4                       # DW_TAG_pointer_type
+        .long   .Lchar_type - .Lcu_begin0
+
+.Lstruct_ptr_type:
+        .byte   4                       # DW_TAG_pointer_type
+        .long   .Lstruct_type - .Lcu_begin0
+
+# ---- struct Point { int x; int y; } ----
+.Lstruct_type:
+        .byte   5                       # DW_TAG_structure_type
+        .asciz  "Point"
+        .byte   8                       # byte_size = 8
+
+        .byte   6                       # DW_TAG_member
+        .asciz  "x"
+        .long   .Lint_type - .Lcu_begin0
+        .byte   0                       # offset 0
+
+        .byte   6                       # DW_TAG_member
+        .asciz  "y"
+        .long   .Lint_type - .Lcu_begin0
+        .byte   4                       # offset 4
+
+        .byte   0                       # end of struct children
+
+# int_val = 42
+.Lint_val:
+        .byte   2                       # DW_TAG_variable
+        .asciz  "int_val"
+        .long   .Lint_type - .Lcu_begin0
+        .byte   .Lint_val_loc_end - .Lint_val_loc_start
+.Lint_val_loc_start:
+        .byte   0x9e                    # DW_OP_implicit_value
+        .uleb128 4                      # length = 4
+        .long   42
+.Lint_val_loc_end:
+
+# char_val = 'A' (0x41)
+.Lchar_val:
+        .byte   2                       # DW_TAG_variable
+        .asciz  "char_val"
+        .long   .Lchar_type - .Lcu_begin0
+        .byte   .Lchar_val_loc_end - .Lchar_val_loc_start
+.Lchar_val_loc_start:
+        .byte   0x9e                    # DW_OP_implicit_value
+        .uleb128 1                      # length = 1
+        .byte   0x41                    # 'A'
+.Lchar_val_loc_end:
+
+# point = {x=10, y=20}
+.Lpoint_val:
+        .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 (two ints)
+        .long   10                      # x = 10
+        .long   20                      # y = 20
+.Lpoint_loc_end:
+
+# int *int_ptr -> points to int_val, offset 0
+        .byte   2                       # DW_TAG_variable
+        .asciz  "int_ptr"
+        .long   .Lint_ptr_type - .Lcu_begin0
+        .byte   .Lint_ptr_loc_end - .Lint_ptr_loc_start
+.Lint_ptr_loc_start:
+        .byte   0xa0                    # DW_OP_implicit_pointer
+        .long   .Lint_val               # reference to int_val DIE
+        .sleb128 0                      # byte offset = 0
+.Lint_ptr_loc_end:
+
+# char *char_ptr -> points to char_val, offset 0
+        .byte   2                       # DW_TAG_variable
+        .asciz  "char_ptr"
+        .long   .Lchar_ptr_type - .Lcu_begin0
+        .byte   .Lchar_ptr_loc_end - .Lchar_ptr_loc_start
+.Lchar_ptr_loc_start:
+        .byte   0xa0                    # DW_OP_implicit_pointer
+        .long   .Lchar_val              # reference to char_val DIE
+        .sleb128 0                      # byte offset = 0
+.Lchar_ptr_loc_end:
+
+# Point *struct_ptr -> points to point, offset 0
+        .byte   2                       # DW_TAG_variable
+        .asciz  "struct_ptr"
+        .long   .Lstruct_ptr_type - .Lcu_begin0
+        .byte   .Lstruct_ptr_loc_end - .Lstruct_ptr_loc_start
+.Lstruct_ptr_loc_start:
+        .byte   0xa0                    # DW_OP_implicit_pointer
+        .long   .Lpoint_val             # reference to point DIE
+        .sleb128 0                      # byte offset = 0
+.Lstruct_ptr_loc_end:
+
+        .byte   0                       # End of compile unit children
+.Lcu_end0:
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 6d4a624505390..433433bb0d186 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -48,11 +48,21 @@ class MockDwarfDelegate : public DWARFExpression::Delegate {
   static constexpr uint16_t DEFAULT_DWARF_VERSION = 5;
   static MockDwarfDelegate Dwarf5() { return MockDwarfDelegate(5); }
   static MockDwarfDelegate Dwarf2() { return MockDwarfDelegate(2); }
+  static MockDwarfDelegate Dwarf64() {
+    return MockDwarfDelegate(5, llvm::dwarf::DWARF64);
+  }
 
   MockDwarfDelegate() : MockDwarfDelegate(DEFAULT_DWARF_VERSION) {}
-  explicit MockDwarfDelegate(uint16_t version) : m_dwarf_version(version) {}
+  explicit MockDwarfDelegate(uint16_t version,
+                             llvm::dwarf::DwarfFormat dwarf_format =
+                                 llvm::dwarf::DWARF32)
+      : m_dwarf_version(version),
+        m_dwarf_format(dwarf_format) {}
 
   uint16_t GetVersion() const override { return m_dwarf_version; }
+  llvm::dwarf::DwarfFormat GetDwarfFormat() const override {
+    return m_dwarf_format;
+  }
 
   dw_addr_t GetBaseAddress() const override { return 0; }
 
@@ -83,6 +93,7 @@ class MockDwarfDelegate : public DWARFExpression::Delegate {
 
 private:
   uint16_t m_dwarf_version;
+  llvm::dwarf::DwarfFormat m_dwarf_format;
 };
 
 /// Mock memory implementation for testing.
@@ -1020,17 +1031,30 @@ TEST(DWARFExpression, DW_OP_call_ref_unhandled) {
           "unhandled opcode DW_OP_call_ref in DWARFExpression"));
 }
 
-TEST(DWARFExpression, DW_OP_implicit_pointer_unimplemented) {
-  EXPECT_THAT_EXPECTED(
-      Evaluate({DW_OP_implicit_pointer, 0x00, 0x00, 0x00, 0x00, 0x00}),
-      llvm::Failed());
-}
-
-TEST(DWARFExpression, DW_OP_GNU_implicit_pointer_unhandled) {
-  EXPECT_THAT_EXPECTED(
-      Evaluate({DW_OP_GNU_implicit_pointer, 0x00, 0x00, 0x00, 0x00, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_GNU_implicit_pointer in DWARFExpression"));
+TEST(DWARFExpression, DW_OP_implicit_pointer) {
+  MockDwarfDelegate dwarf32 = MockDwarfDelegate::Dwarf5();
+  llvm::Expected<Value> result = Evaluate(
+      {DW_OP_implicit_pointer, 0x34, 0x12, 0x00, 0x00, 0x00}, {}, &dwarf32);
+  ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
+  ASSERT_TRUE(result->IsImplicitPointer());
+  Value::ImplicitPointerInfo implicit_pointer =
+      result->GetImplicitPointerInfo();
+  EXPECT_EQ(implicit_pointer.die_offset, 0x1234u);
+  EXPECT_EQ(implicit_pointer.byte_offset, 0);
+}
+
+TEST(DWARFExpression, DW_OP_implicit_pointer_DWARF64) {
+  MockDwarfDelegate dwarf64 = MockDwarfDelegate::Dwarf64();
+  llvm::Expected<Value> result =
+      Evaluate({DW_OP_implicit_pointer, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00,
+                0x00, 0x00, 0x02},
+               {}, &dwarf64);
+  ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
+  ASSERT_TRUE(result->IsImplicitPointer());
+  Value::ImplicitPointerInfo implicit_pointer =
+      result->GetImplicitPointerInfo();
+  EXPECT_EQ(implicit_pointer.die_offset, 0x12345678u);
+  EXPECT_EQ(implicit_pointer.byte_offset, 2);
 }
 
 TEST(DWARFExpression, DW_OP_const_type_unhandled) {

>From 787bfa924d07906e298da2334abac717e5d8b029 Mon Sep 17 00:00:00 2001
From: shijinrui <[email protected]>
Date: Tue, 23 Jun 2026 17:48:35 +0800
Subject: [PATCH 2/3] fix format

---
 lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 10 +++++-----
 lldb/source/ValueObject/ValueObject.cpp                |  6 +++---
 lldb/unittests/Expression/DWARFExpressionTest.cpp      |  9 ++++-----
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 32f646ecc79c7..067dd2a660ead 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -136,11 +136,11 @@ class SymbolFileDWARF : public SymbolFileCommon {
 
   size_t ParseVariablesForContext(const SymbolContext &sc) override;
 
-  lldb::ValueObjectSP
-  ResolveImplicitPointer(uint64_t die_offset, int64_t byte_offset,
-                         CompilerType pointee_type,
-                         ExecutionContextScope *exe_scope,
-                         Variable *context_var);
+  lldb::ValueObjectSP ResolveImplicitPointer(uint64_t die_offset,
+                                             int64_t byte_offset,
+                                             CompilerType pointee_type,
+                                             ExecutionContextScope *exe_scope,
+                                             Variable *context_var);
 
   std::optional<ArrayInfo>
   GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,
diff --git a/lldb/source/ValueObject/ValueObject.cpp 
b/lldb/source/ValueObject/ValueObject.cpp
index afd65ac6b0805..357cc88058c70 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -53,8 +53,8 @@
 #include "lldb/lldb-enumerations.h"
 
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
-#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
 
 #include <algorithm>
 #include <atomic>
@@ -2860,8 +2860,8 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
     }
 
     ValueObjectSP result_sp = dwarf_symbol_file->ResolveImplicitPointer(
-        implicit_pointer.die_offset, implicit_pointer.byte_offset,
-        pointee_type, exe_ctx.GetBestExecutionContextScope(), 
GetVariable().get());
+        implicit_pointer.die_offset, implicit_pointer.byte_offset, 
pointee_type,
+        exe_ctx.GetBestExecutionContextScope(), GetVariable().get());
     if (!result_sp) {
       error = Status::FromErrorStringWithFormat(
           "cannot resolve DW_OP_implicit_pointer target DIE 0x%" PRIx64,
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 433433bb0d186..75a87ced8438c 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -53,11 +53,10 @@ class MockDwarfDelegate : public DWARFExpression::Delegate {
   }
 
   MockDwarfDelegate() : MockDwarfDelegate(DEFAULT_DWARF_VERSION) {}
-  explicit MockDwarfDelegate(uint16_t version,
-                             llvm::dwarf::DwarfFormat dwarf_format =
-                                 llvm::dwarf::DWARF32)
-      : m_dwarf_version(version),
-        m_dwarf_format(dwarf_format) {}
+  explicit MockDwarfDelegate(
+      uint16_t version,
+      llvm::dwarf::DwarfFormat dwarf_format = llvm::dwarf::DWARF32)
+      : m_dwarf_version(version), m_dwarf_format(dwarf_format) {}
 
   uint16_t GetVersion() const override { return m_dwarf_version; }
   llvm::dwarf::DwarfFormat GetDwarfFormat() const override {

>From c2da33b3ef1d63eaa50ca6db261369e78c678a55 Mon Sep 17 00:00:00 2001
From: shijinrui <[email protected]>
Date: Tue, 23 Jun 2026 18:56:35 +0800
Subject: [PATCH 3/3] fix

---
 lldb/include/lldb/Symbol/SymbolFile.h          |  5 +++++
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp       |  4 ++--
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.h |  2 +-
 lldb/source/ValueObject/ValueObject.cpp        | 18 +++++-------------
 4 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/lldb/include/lldb/Symbol/SymbolFile.h 
b/lldb/include/lldb/Symbol/SymbolFile.h
index ae6504c016d7b..dd11c4a36ab33 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -207,6 +207,11 @@ class SymbolFile : public PluginInterface {
                        std::vector<SourceModule> &imported_modules) = 0;
   virtual size_t ParseBlocksRecursive(Function &func) = 0;
   virtual size_t ParseVariablesForContext(const SymbolContext &sc) = 0;
+  virtual lldb::ValueObjectSP ResolveImplicitPointer(
+      uint64_t die_offset, int64_t byte_offset, CompilerType pointee_type,
+      ExecutionContextScope *exe_scope, Variable *context_var) {
+    return {};
+  }
   virtual Type *ResolveTypeUID(lldb::user_id_t type_uid) = 0;
 
   /// The characteristics of an array type.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index f72fc002fc4cf..afc1272256746 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3462,8 +3462,8 @@ lldb::ValueObjectSP 
SymbolFileDWARF::ResolveImplicitPointer(
                                       eSymbolContextFunction |
                                       eSymbolContextBlock);
 
-  DWARFDIE target_die = DebugInfo().GetDIE(DIERef::Section::DebugInfo,
-                                           die_offset);
+  DWARFDIE target_die =
+      DebugInfo().GetDIE(DIERef::Section::DebugInfo, die_offset);
   if (!target_die)
     return nullptr;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 067dd2a660ead..7f19142c42575 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -140,7 +140,7 @@ class SymbolFileDWARF : public SymbolFileCommon {
                                              int64_t byte_offset,
                                              CompilerType pointee_type,
                                              ExecutionContextScope *exe_scope,
-                                             Variable *context_var);
+                                             Variable *context_var) override;
 
   std::optional<ArrayInfo>
   GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,
diff --git a/lldb/source/ValueObject/ValueObject.cpp 
b/lldb/source/ValueObject/ValueObject.cpp
index 357cc88058c70..eff9d9bada125 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -52,8 +52,6 @@
 #include "lldb/ValueObject/ValueObjectVTable.h"
 #include "lldb/lldb-enumerations.h"
 
-#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
-#include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 
 #include <algorithm>
@@ -2851,17 +2849,11 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
     ExecutionContext exe_ctx(GetExecutionContextRef());
     Value::ImplicitPointerInfo implicit_pointer =
         m_value.GetImplicitPointerInfo();
-    auto *dwarf_symbol_file = llvm::dyn_cast<plugin::dwarf::SymbolFileDWARF>(
-        symbol_file->GetBackingSymbolFile());
-    if (!dwarf_symbol_file) {
-      error = Status::FromErrorString(
-          "cannot resolve DW_OP_implicit_pointer without DWARF symbol file");
-      return ValueObjectSP();
-    }
-
-    ValueObjectSP result_sp = dwarf_symbol_file->ResolveImplicitPointer(
-        implicit_pointer.die_offset, implicit_pointer.byte_offset, 
pointee_type,
-        exe_ctx.GetBestExecutionContextScope(), GetVariable().get());
+    ValueObjectSP result_sp =
+        symbol_file->GetBackingSymbolFile()->ResolveImplicitPointer(
+            implicit_pointer.die_offset, implicit_pointer.byte_offset,
+            pointee_type, exe_ctx.GetBestExecutionContextScope(),
+            GetVariable().get());
     if (!result_sp) {
       error = Status::FromErrorStringWithFormat(
           "cannot resolve DW_OP_implicit_pointer target DIE 0x%" PRIx64,

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to