https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/214380
>From 5053ab600be380b720aee34ed6c9cbdd7c1a00ce Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <[email protected]> Date: Wed, 5 Aug 2026 18:04:00 -0700 Subject: [PATCH 1/2] [lldb] Use the standard GDB remote thread for a non-Wasm process CanDebug returns true whenever the plugin is requested by name, and the architecture is not known until the stub reports it after connecting. This means that a non-Wasm process can end up with a ThreadWasm whose register context and unwinder have nothing to operate on. Create the plain ThreadGDBRemote once the architecture is known, and add a helper so that the check covers wasm64 as well as wasm32. --- .../Plugins/Process/wasm/ProcessWasm.cpp | 6 ++- .../source/Plugins/Process/wasm/ProcessWasm.h | 5 ++ .../Plugins/Process/wasm/ThreadWasm.cpp | 3 +- .../gdb_remote_client/TestWasm.py | 49 +++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp index e119b3e3ecf6d..c8eadfed4c5e4 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -73,8 +73,7 @@ bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, if (Module *exe_module = target_sp->GetExecutableModulePointer()) { if (ObjectFile *exe_objfile = exe_module->GetObjectFile()) - return exe_objfile->GetArchitecture().GetMachine() == - llvm::Triple::wasm32; + return IsWasmArchitecture(exe_objfile->GetArchitecture()); } // However, if there is no wasm module, we return false, otherwise, @@ -83,6 +82,9 @@ bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, } std::shared_ptr<ThreadGDBRemote> ProcessWasm::CreateThread(lldb::tid_t tid) { + if (!IsWasmArchitecture(GetTarget().GetArchitecture())) + return ProcessGDBRemote::CreateThread(tid); + return std::make_shared<ThreadWasm>(*this, tid); } diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h index 9bce07ec5691c..70551c2a045f5 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.h +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -16,6 +16,11 @@ namespace lldb_private { namespace wasm { +inline bool IsWasmArchitecture(const ArchSpec &arch) { + const llvm::Triple::ArchType machine = arch.GetMachine(); + return machine == llvm::Triple::wasm32 || machine == llvm::Triple::wasm64; +} + /// ProcessWasm provides the access to the Wasm program state /// retrieved from the Wasm engine. class ProcessWasm : public process_gdb_remote::ProcessGDBRemote { diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp index c7c05cb815261..09c44c8ea3000 100644 --- a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -20,8 +20,7 @@ using namespace lldb_private::wasm; Unwind &ThreadWasm::GetUnwinder() { if (!m_unwinder_up) { - assert(CalculateTarget()->GetArchitecture().GetMachine() == - llvm::Triple::wasm32); + assert(IsWasmArchitecture(CalculateTarget()->GetArchitecture())); m_unwinder_up.reset(new wasm::UnwindWasm(*this)); } return *m_unwinder_up; diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py index 114ddd7adce5a..4e4a21d9416b1 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py @@ -501,3 +501,52 @@ def test_read_global(self): # Likewise for a global that does not exist. process.ReadMemory(globals_addr + 99, 4, error) self.assertFalse(error.Success()) + + @skipIfXmlSupportMissing + def test_non_wasm_process(self): + """Test that the plugin falls back to plain GDB remote debugging when + it is requested by name for a process that isn't WebAssembly.""" + + class NonWasmResponder(MockGDBServerResponder): + def qHostInfo(self): + return "triple:%s;ptrsize:8;endian:little;" % hex_encode_bytes( + "x86_64-unknown-linux-gnu" + ) + + def qfThreadInfo(self): + return "m1" + + def haltReason(self): + return "T02thread:1;threads:1;thread-pcs:10001bc00;" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return ( + """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", + False, + ) + return None, False + + self.server.responder = NonWasmResponder() + + target = self.dbg.CreateTarget("") + process = self.connect(target, "wasm") + lldbutil.expect_state_changes( + self, self.dbg.GetListener(), process, [lldb.eStateStopped] + ) + + self.assertEqual(process.GetPluginName(), "wasm") + self.assertIn("x86_64", target.GetTriple()) + + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread.IsValid()) + self.assertEqual(thread.GetFrameAtIndex(0).GetPC(), 0x10001BC00) + self.assertNotIn( + "qWasmCallStack", "".join(self.server.responder.packetLog.get_received()) + ) >From c21b4ad0bbf65310c91dfeb03f4c0b5cd01c0a1b Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <[email protected]> Date: Wed, 5 Aug 2026 20:18:09 -0700 Subject: [PATCH 2/2] Use llvm::Triple::isWasm --- lldb/source/Plugins/Process/wasm/ProcessWasm.cpp | 4 ++-- lldb/source/Plugins/Process/wasm/ProcessWasm.h | 5 ----- lldb/source/Plugins/Process/wasm/ThreadWasm.cpp | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp index c8eadfed4c5e4..f7d744c967ea0 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -73,7 +73,7 @@ bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, if (Module *exe_module = target_sp->GetExecutableModulePointer()) { if (ObjectFile *exe_objfile = exe_module->GetObjectFile()) - return IsWasmArchitecture(exe_objfile->GetArchitecture()); + return exe_objfile->GetArchitecture().GetTriple().isWasm(); } // However, if there is no wasm module, we return false, otherwise, @@ -82,7 +82,7 @@ bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, } std::shared_ptr<ThreadGDBRemote> ProcessWasm::CreateThread(lldb::tid_t tid) { - if (!IsWasmArchitecture(GetTarget().GetArchitecture())) + if (!GetTarget().GetArchitecture().GetTriple().isWasm()) return ProcessGDBRemote::CreateThread(tid); return std::make_shared<ThreadWasm>(*this, tid); diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h index 70551c2a045f5..9bce07ec5691c 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.h +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -16,11 +16,6 @@ namespace lldb_private { namespace wasm { -inline bool IsWasmArchitecture(const ArchSpec &arch) { - const llvm::Triple::ArchType machine = arch.GetMachine(); - return machine == llvm::Triple::wasm32 || machine == llvm::Triple::wasm64; -} - /// ProcessWasm provides the access to the Wasm program state /// retrieved from the Wasm engine. class ProcessWasm : public process_gdb_remote::ProcessGDBRemote { diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp index 09c44c8ea3000..bbf474906806d 100644 --- a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -20,7 +20,7 @@ using namespace lldb_private::wasm; Unwind &ThreadWasm::GetUnwinder() { if (!m_unwinder_up) { - assert(IsWasmArchitecture(CalculateTarget()->GetArchitecture())); + assert(CalculateTarget()->GetArchitecture().GetTriple().isWasm()); m_unwinder_up.reset(new wasm::UnwindWasm(*this)); } return *m_unwinder_up; _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
