https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/137380
>From 681beb0f851d20896456b53c51b8ee84382a1254 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Fri, 25 Apr 2025 10:40:45 -0700 Subject: [PATCH 1/2] [lldb-dap] Support the Module Event The module event indicates that some information about a module has changed. The event is supported by the Emacs and Visual Studio DAP clients. This PR adds support for emitting the event from lldb-dap. Fixes #137058 --- .../test/tools/lldb-dap/dap_server.py | 6 +++++ .../tools/lldb-dap/module/TestDAP_module.py | 11 +++++++++ lldb/tools/lldb-dap/DAP.cpp | 4 +++- .../Handler/InitializeRequestHandler.cpp | 24 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 0f8a84461c9e7..5c43c91734b43 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -135,6 +135,7 @@ def __init__(self, recv, send, init_commands, log_file=None): self.breakpoint_events = [] self.progress_events = [] self.reverse_requests = [] + self.module_events = [] self.sequence = 1 self.threads = None self.recv_thread.start() @@ -255,6 +256,11 @@ def handle_recv_packet(self, packet): # and 'progressEnd' events. Keep these around in case test # cases want to verify them. self.progress_events.append(packet) + elif event == "module": + # Module events indicate that some information about a module has changed. + self.module_events.append(packet) + # no need to add 'module' event packets to our packets list + return keepGoing elif packet_type == "response": if packet["command"] == "disconnect": diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py index a4e0f04d450d9..e839d46e1d114 100644 --- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py +++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py @@ -57,6 +57,17 @@ def checkSymbolsLoadedWithSize(): self.assertEqual(program, program_module["path"]) self.assertIn("addressRange", program_module) + # Collect all the module names we saw as events. + module_event_names = set() + for module_event in self.dap_server.module_events: + module_event_names.add(module_event["body"]["module"]["name"]) + self.assertNotEqual(len(module_event_names), 0) + + # Make sure we got an event for every active module. + for module in active_modules: + # assertIn doesn't work with set. + self.assertTrue(module in module_event_names) + @skipIfWindows def test_modules(self): """ diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index f8dbc4c1398e6..f866886c33014 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -692,7 +692,9 @@ void DAP::SetTarget(const lldb::SBTarget target) { lldb::SBListener listener = this->debugger.GetListener(); listener.StartListeningForEvents( this->target.GetBroadcaster(), - lldb::SBTarget::eBroadcastBitBreakpointChanged); + lldb::SBTarget::eBroadcastBitBreakpointChanged | + lldb::SBTarget::eBroadcastBitModulesLoaded | + lldb::SBTarget::eBroadcastBitModulesUnloaded); listener.StartListeningForEvents(this->broadcaster, eBroadcastBitStopEventThread); } diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp index 7d8ac676ba935..f98c4d743b2d8 100644 --- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp @@ -15,6 +15,8 @@ #include "lldb/API/SBEvent.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBTarget.h" +#include <cstdint> using namespace lldb; using namespace lldb_dap::protocol; @@ -193,6 +195,28 @@ static void EventThreadFunction(DAP &dap) { (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) { SendStdOutStdErr(dap, process); } + } else if (lldb::SBTarget::EventIsTargetEvent(event)) { + if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded || + event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded) { + const llvm::StringRef reason = + event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded + ? "new" + : "removed"; + const uint32_t num_modules = SBTarget::GetNumModulesFromEvent(event); + for (uint32_t i = 0; i < num_modules; ++i) { + lldb::SBModule module = + SBTarget::GetModuleAtIndexFromEvent(i, event); + if (!module.IsValid()) + continue; + + llvm::json::Object body; + body.try_emplace("reason", reason); + body.try_emplace("module", CreateModule(dap.target, module)); + llvm::json::Object module_event = CreateEventObject("module"); + module_event.try_emplace("body", std::move(body)); + dap.SendJSON(llvm::json::Value(std::move(module_event))); + } + } } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(event)) { if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) { auto event_type = >From 47b5695312f540cfd2e1facd397cfd1ffa7889a7 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Fri, 25 Apr 2025 12:05:11 -0700 Subject: [PATCH 2/2] Support changed event too --- .../tools/lldb-dap/module/TestDAP_module.py | 20 ++++++++++++++----- lldb/tools/lldb-dap/DAP.cpp | 4 +++- .../Handler/InitializeRequestHandler.cpp | 19 +++++++++++++----- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py index e839d46e1d114..210819cfdd732 100644 --- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py +++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py @@ -58,15 +58,25 @@ def checkSymbolsLoadedWithSize(): self.assertIn("addressRange", program_module) # Collect all the module names we saw as events. - module_event_names = set() + module_new_names = [] + module_changed_names = [] for module_event in self.dap_server.module_events: - module_event_names.add(module_event["body"]["module"]["name"]) - self.assertNotEqual(len(module_event_names), 0) + module_name = module_event["body"]["module"]["name"] + reason = module_event["body"]["reason"] + if reason == "new": + module_new_names.append(module_name) + elif reason == "changed": + module_changed_names.append(module_name) # Make sure we got an event for every active module. + self.assertNotEqual(len(module_new_names), 0) for module in active_modules: - # assertIn doesn't work with set. - self.assertTrue(module in module_event_names) + self.assertIn(module, module_new_names) + + # Make sure we got an update event for the program module when the + # symbols got added. + self.assertNotEqual(len(module_changed_names), 0) + self.assertIn(program_module["name"], module_changed_names) @skipIfWindows def test_modules(self): diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index f866886c33014..23198acb8e7cd 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -694,7 +694,9 @@ void DAP::SetTarget(const lldb::SBTarget target) { this->target.GetBroadcaster(), lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded | - lldb::SBTarget::eBroadcastBitModulesUnloaded); + lldb::SBTarget::eBroadcastBitModulesUnloaded | + lldb::SBTarget::eBroadcastBitSymbolsLoaded | + lldb::SBTarget::eBroadcastBitSymbolsChanged); listener.StartListeningForEvents(this->broadcaster, eBroadcastBitStopEventThread); } diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp index f98c4d743b2d8..ce34c52bcc334 100644 --- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp @@ -110,6 +110,16 @@ void ProgressEventThreadFunction(DAP &dap) { } } +static llvm::StringRef GetModuleEventReason(uint32_t event_mask) { + if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded) + return "new"; + if (event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded) + return "removed"; + assert(event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded || + event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged); + return "changed"; +} + // All events from the debugger, target, process, thread and frames are // received in this function that runs in its own thread. We are using a // "FILE *" to output packets back to VS Code and they have mutexes in them @@ -197,11 +207,10 @@ static void EventThreadFunction(DAP &dap) { } } else if (lldb::SBTarget::EventIsTargetEvent(event)) { if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded || - event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded) { - const llvm::StringRef reason = - event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded - ? "new" - : "removed"; + event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded || + event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded || + event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) { + llvm::StringRef reason = GetModuleEventReason(event_mask); const uint32_t num_modules = SBTarget::GetNumModulesFromEvent(event); for (uint32_t i = 0; i < num_modules; ++i) { lldb::SBModule module = _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits