[Lldb-commits] [lldb] [lldb] Read Wasm globals through a frame of the stub's own thread (PR #237195)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Oct 30 05:16:35 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Felipe de Azevedo Piovezan (felipepiovezan)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/237195.diff
3 Files Affected:
- (modified) lldb/source/Plugins/Process/wasm/ProcessWasm.cpp (+10-10)
- (modified) lldb/test/API/functionalities/gdb_remote_client/TestWasm.py (+27)
- (added) lldb/test/API/functionalities/gdb_remote_client/wasm_operating_system.py (+40)
``````````diff
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..f643d1fa80031f 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -1050,6 +1050,33 @@ 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 a global is read through a frame of the stub's own thread
+ when the stub can only read a global through a frame and the selected
+ thread comes from an OS plugin, whose frames the stub does not know."""
+
+ 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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/237195
More information about the lldb-commits
mailing list