Author: Jonas Devlieghere
Date: 2026-07-28T17:49:21Z
New Revision: 7ac6b9ff31dbd3a028585ccd18d8a7a290303d58

URL: 
https://github.com/llvm/llvm-project/commit/7ac6b9ff31dbd3a028585ccd18d8a7a290303d58
DIFF: 
https://github.com/llvm/llvm-project/commit/7ac6b9ff31dbd3a028585ccd18d8a7a290303d58.diff

LOG: [lldb] Report the unwound PC for WebAssembly caller frames (#212326)

RegisterContextWasm delegated the PC register read to
GDBRemoteRegisterContext, which reports the live innermost PC for every
frame. Resolving a variable whose DWARF location is a location list in a
caller frame therefore chose the entry using the innermost frame's PC
instead of the caller's, so the variable read back as unavailable even
though its location covered the caller's PC.

Return the program counter the WebAssembly unwinder recorded for the
frame (from qWasmCallStack) when reading a caller frame's PC, so the
location list entry uses the correct frame.

Added: 
    

Modified: 
    lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
    lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
    lldb/source/Plugins/Process/wasm/ThreadWasm.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp 
b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
index bdeb0c927a387..a05fbd56e8680 100644
--- a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
+++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
@@ -64,14 +64,27 @@ const RegisterSet 
*RegisterContextWasm::GetRegisterSet(size_t reg_set) {
 
 bool RegisterContextWasm::ReadRegister(const RegisterInfo *reg_info,
                                        RegisterValue &value) {
-  // The only real registers is the PC.
-  if (reg_info->name)
+  ThreadWasm &wasm_thread = static_cast<ThreadWasm &>(GetThread());
+
+  // The only real register is the PC.
+  if (reg_info->name) {
+    // A caller frame's PC is the unwound return address, which the base
+    // register context cannot provide because it only sees the innermost
+    // frame's live PC. Use the PC the unwinder recorded for this frame.
+    if (m_concrete_frame_idx > 0) {
+      lldb::addr_t pc = wasm_thread.GetConcreteFramePC(m_concrete_frame_idx);
+      if (pc != LLDB_INVALID_ADDRESS) {
+        value.SetUInt(pc, reg_info->byte_size);
+        return true;
+      }
+    }
     return GDBRemoteRegisterContext::ReadRegister(reg_info, value);
+  }
 
   // Read the virtual registers.
-  ThreadWasm *thread = static_cast<ThreadWasm *>(&GetThread());
-  ProcessWasm *process = static_cast<ProcessWasm 
*>(thread->GetProcess().get());
-  if (!thread)
+  ProcessWasm *process =
+      static_cast<ProcessWasm *>(wasm_thread.GetProcess().get());
+  if (!process)
     return false;
 
   uint32_t frame_index = m_concrete_frame_idx;

diff  --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp 
b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
index 0666b75d4afe0..c7c05cb815261 100644
--- a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
@@ -12,6 +12,7 @@
 #include "RegisterContextWasm.h"
 #include "UnwindWasm.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -34,6 +35,15 @@ llvm::Expected<std::vector<lldb::addr_t>> 
ThreadWasm::GetWasmCallStack() {
   return llvm::createStringError("no process");
 }
 
+lldb::addr_t ThreadWasm::GetConcreteFramePC(uint32_t concrete_frame_idx) {
+  lldb::addr_t cfa, pc;
+  bool behaves_like_zeroth_frame;
+  if (GetUnwinder().GetFrameInfoAtIndex(concrete_frame_idx, cfa, pc,
+                                        behaves_like_zeroth_frame))
+    return pc;
+  return LLDB_INVALID_ADDRESS;
+}
+
 lldb::RegisterContextSP
 ThreadWasm::CreateRegisterContextForFrame(StackFrame *frame) {
   uint32_t concrete_frame_idx = 0;

diff  --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h 
b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
index c2f5762b30484..a2d1d66ced0d7 100644
--- a/lldb/source/Plugins/Process/wasm/ThreadWasm.h
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
@@ -25,6 +25,10 @@ class ThreadWasm : public 
process_gdb_remote::ThreadGDBRemote {
   /// Retrieve the current call stack from the WebAssembly remote process.
   llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack();
 
+  /// Return the program counter the Wasm unwinder recorded for the given
+  /// concrete frame index, or LLDB_INVALID_ADDRESS if it is unavailable.
+  lldb::addr_t GetConcreteFramePC(uint32_t concrete_frame_idx);
+
   lldb::RegisterContextSP
   CreateRegisterContextForFrame(StackFrame *frame) override;
 


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

Reply via email to