[Lldb-commits] [lldb] [lldb] Read Wasm globals through a frame of the stub's own thread (PR #237195)

Felipe de Azevedo Piovezan via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 30 05:22:40 PDT 2026


https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/237195

>From 459aab3edf0b66516c5570871155b61b4efa7955 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 28 Oct 2026 22:35:20 +0000
Subject: [PATCH] [lldb] Read Wasm globals through a frame of the stub's own
 thread

This commit fixes an unconditional cast from Thread to ThreadWasm, which
ignores the possibility of an OS plugin, by using the real thread list.

Note that using the qWasmGlobal variant that expects a frame index is
unlikely to succeed in the presence of a custom unwinder that presents a
different view of frames. But at the very least we shouldn't crash by
doing an invalid cast, which this fixes.
---
 .../Plugins/Process/wasm/ProcessWasm.cpp      | 20 +++++-----
 .../gdb_remote_client/TestWasm.py             | 25 ++++++++++++
 .../wasm_operating_system.py                  | 40 +++++++++++++++++++
 3 files changed, 75 insertions(+), 10 deletions(-)
 create mode 100644 lldb/test/API/functionalities/gdb_remote_client/wasm_operating_system.py

diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
index 87c3a32f0cd5d3..be2a5266636ff8 100644
--- a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
@@ -11,7 +11,6 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Value.h"
-#include "lldb/Target/StackFrame.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "llvm/Support/ErrorExtras.h"
 #include <cstring>
@@ -132,16 +131,17 @@ ProcessWasm::GetFallbackFrameIndex(uint32_t module_id) {
     return llvm::createStringError(
         "the global belongs to no known module instance");
 
-  ThreadSP thread = GetThreadList().GetSelectedThread();
-  StackFrameSP frame =
-      thread ? thread->GetSelectedFrame(DoNoSelectMostRelevantFrame) : nullptr;
-  if (frame) {
-    // A frame can only stand in for the module the stub reports it executing.
-    const uint32_t frame_index = frame->GetConcreteFrameIndex();
+  // Use the real thread list in case an OS plugin is providing threads.
+  if (ThreadSP thread = m_thread_list_real.GetSelectedThread()) {
     ThreadWasm &wasm_thread = static_cast<ThreadWasm &>(*thread);
-    if (GetWasmModuleID(wasm_thread.GetConcreteFramePC(frame_index)) ==
-        module_id)
-      return frame_index;
+    // A frame can only stand in for the module the stub reports it executing.
+    for (uint32_t frame_index = 0;; ++frame_index) {
+      lldb::addr_t pc = wasm_thread.GetConcreteFramePC(frame_index);
+      if (pc == LLDB_INVALID_ADDRESS)
+        break;
+      if (GetWasmModuleID(pc) == module_id)
+        return frame_index;
+    }
   }
 
   return llvm::createStringErrorV(
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
index fb02c4eecbdbb2..6f0101014b87b5 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -1050,6 +1050,31 @@ def test_read_global_legacy_server_other_instance(self):
 
         self.assertPacketLogReceived(["qWasmGlobal:0;0"])
 
+    @skipIfAsan
+    @skipIfXmlSupportMissing
+    def test_read_global_legacy_server_os_plugin_thread(self):
+        """Test that an OS plugin thread doesn't get in the way of computing the right frame."""
+
+        call_stacks = [WasmCallStack([WasmStackFrame(0x019C)])]
+        process, globals_addr = self.connect_to_globals(
+            call_stacks, supports_instance=False
+        )
+
+        os_plugin_path = os.path.join(self.getSourceDir(), "wasm_operating_system.py")
+        self.runCmd(
+            "settings set target.process.python-os-plugin-path '%s'" % os_plugin_path
+        )
+        # The thread wasm_operating_system.py reports.
+        thread = process.GetThreadByID(0x2)
+        self.assertTrue(thread.IsValid())
+        self.assertTrue(process.SetSelectedThread(thread))
+
+        error = lldb.SBError()
+        data = process.ReadMemory(globals_addr + 0, 4, error)
+        self.assertSuccess(error)
+        self.assertEqual(int.from_bytes(data, "little"), WASM_GLOBALS[0][1])
+        self.assertPacketLogReceived(["qWasmGlobal:0;0"])
+
     def reload_modules(self, modules, reloaded_modules):
         """
         Connect to a fake stub holding the given modules, continue it until it
diff --git a/lldb/test/API/functionalities/gdb_remote_client/wasm_operating_system.py b/lldb/test/API/functionalities/gdb_remote_client/wasm_operating_system.py
new file mode 100644
index 00000000000000..59bcd45b00e10d
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/wasm_operating_system.py
@@ -0,0 +1,40 @@
+import lldb
+import struct
+
+# The thread this plug-in reports. No thread of the stub backs it.
+OS_THREAD_ID = 0x2
+
+
+class OperatingSystemPlugIn(object):
+    def __init__(self, process):
+        self.process = process
+
+    def get_thread_info(self):
+        return [
+            {
+                "tid": OS_THREAD_ID,
+                "name": "os",
+                "state": "stopped",
+                "stop_reason": "none",
+            }
+        ]
+
+    def get_register_info(self):
+        return {
+            "sets": ["GPR"],
+            "registers": [
+                {
+                    "name": "pc",
+                    "bitsize": 64,
+                    "offset": 0,
+                    "encoding": "uint",
+                    "format": "hex",
+                    "set": 0,
+                    "generic": "pc",
+                }
+            ],
+        }
+
+    def get_register_data(self, tid):
+        # A PC outside every module, so the thread executes no instance.
+        return struct.pack("Q", 0)



More information about the lldb-commits mailing list