Skip to content

Commit b546baf

Browse files
authored
[lldb-dap] Support the Module Event (llvm#137380)
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 llvm#137058
1 parent a1bcc8f commit b546baf

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def __init__(self, recv, send, init_commands, log_file=None):
135135
self.breakpoint_events = []
136136
self.progress_events = []
137137
self.reverse_requests = []
138+
self.module_events = []
138139
self.sequence = 1
139140
self.threads = None
140141
self.recv_thread.start()
@@ -255,6 +256,11 @@ def handle_recv_packet(self, packet):
255256
# and 'progressEnd' events. Keep these around in case test
256257
# cases want to verify them.
257258
self.progress_events.append(packet)
259+
elif event == "module":
260+
# Module events indicate that some information about a module has changed.
261+
self.module_events.append(packet)
262+
# no need to add 'module' event packets to our packets list
263+
return keepGoing
258264

259265
elif packet_type == "response":
260266
if packet["command"] == "disconnect":

lldb/test/API/tools/lldb-dap/module/TestDAP_module.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@ def checkSymbolsLoadedWithSize():
5757
self.assertEqual(program, program_module["path"])
5858
self.assertIn("addressRange", program_module)
5959

60+
# Collect all the module names we saw as events.
61+
module_new_names = []
62+
module_changed_names = []
63+
for module_event in self.dap_server.module_events:
64+
module_name = module_event["body"]["module"]["name"]
65+
reason = module_event["body"]["reason"]
66+
if reason == "new":
67+
module_new_names.append(module_name)
68+
elif reason == "changed":
69+
module_changed_names.append(module_name)
70+
71+
# Make sure we got an event for every active module.
72+
self.assertNotEqual(len(module_new_names), 0)
73+
for module in active_modules:
74+
self.assertIn(module, module_new_names)
75+
76+
# Make sure we got an update event for the program module when the
77+
# symbols got added.
78+
self.assertNotEqual(len(module_changed_names), 0)
79+
self.assertIn(program_module["name"], module_changed_names)
80+
6081
@skipIfWindows
6182
def test_modules(self):
6283
"""

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,11 @@ void DAP::SetTarget(const lldb::SBTarget target) {
693693
lldb::SBListener listener = this->debugger.GetListener();
694694
listener.StartListeningForEvents(
695695
this->target.GetBroadcaster(),
696-
lldb::SBTarget::eBroadcastBitBreakpointChanged);
696+
lldb::SBTarget::eBroadcastBitBreakpointChanged |
697+
lldb::SBTarget::eBroadcastBitModulesLoaded |
698+
lldb::SBTarget::eBroadcastBitModulesUnloaded |
699+
lldb::SBTarget::eBroadcastBitSymbolsLoaded |
700+
lldb::SBTarget::eBroadcastBitSymbolsChanged);
697701
listener.StartListeningForEvents(this->broadcaster,
698702
eBroadcastBitStopEventThread);
699703
}

lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "lldb/API/SBEvent.h"
1616
#include "lldb/API/SBListener.h"
1717
#include "lldb/API/SBStream.h"
18+
#include "lldb/API/SBTarget.h"
19+
#include <cstdint>
1820

1921
using namespace lldb;
2022
using namespace lldb_dap::protocol;
@@ -108,6 +110,16 @@ void ProgressEventThreadFunction(DAP &dap) {
108110
}
109111
}
110112

113+
static llvm::StringRef GetModuleEventReason(uint32_t event_mask) {
114+
if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded)
115+
return "new";
116+
if (event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded)
117+
return "removed";
118+
assert(event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
119+
event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged);
120+
return "changed";
121+
}
122+
111123
// All events from the debugger, target, process, thread and frames are
112124
// received in this function that runs in its own thread. We are using a
113125
// "FILE *" to output packets back to VS Code and they have mutexes in them
@@ -193,6 +205,27 @@ static void EventThreadFunction(DAP &dap) {
193205
(event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
194206
SendStdOutStdErr(dap, process);
195207
}
208+
} else if (lldb::SBTarget::EventIsTargetEvent(event)) {
209+
if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
210+
event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
211+
event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
212+
event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
213+
llvm::StringRef reason = GetModuleEventReason(event_mask);
214+
const uint32_t num_modules = SBTarget::GetNumModulesFromEvent(event);
215+
for (uint32_t i = 0; i < num_modules; ++i) {
216+
lldb::SBModule module =
217+
SBTarget::GetModuleAtIndexFromEvent(i, event);
218+
if (!module.IsValid())
219+
continue;
220+
221+
llvm::json::Object body;
222+
body.try_emplace("reason", reason);
223+
body.try_emplace("module", CreateModule(dap.target, module));
224+
llvm::json::Object module_event = CreateEventObject("module");
225+
module_event.try_emplace("body", std::move(body));
226+
dap.SendJSON(llvm::json::Value(std::move(module_event)));
227+
}
228+
}
196229
} else if (lldb::SBBreakpoint::EventIsBreakpointEvent(event)) {
197230
if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
198231
auto event_type =

0 commit comments

Comments
 (0)