Skip to content

Commit b9fb980

Browse files
committed
[lldb-dap] Adding support for well typed events.
This adds a mechanism for registering well typed events with the DAP. For a proof of concept, this updates the 'exited' event to use the new protocol serialization handlers and updates the call sites to use the new helper.
1 parent 36d0fec commit b9fb980

File tree

7 files changed

+69
-15
lines changed

7 files changed

+69
-15
lines changed

lldb/tools/lldb-dap/DAP.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
5858
typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
5959
InstructionBreakpointMap;
6060

61+
/// A debug adapter initiated event.
62+
template <typename T> using OutgoingEvent = std::function<void(const T &)>;
63+
6164
enum class OutputType { Console, Stdout, Stderr, Telemetry };
6265

6366
/// Buffer size for handling output events.
@@ -123,21 +126,21 @@ struct Variables {
123126

124127
struct StartDebuggingRequestHandler : public lldb::SBCommandPluginInterface {
125128
DAP &dap;
126-
explicit StartDebuggingRequestHandler(DAP &d) : dap(d) {};
129+
explicit StartDebuggingRequestHandler(DAP &d) : dap(d){};
127130
bool DoExecute(lldb::SBDebugger debugger, char **command,
128131
lldb::SBCommandReturnObject &result) override;
129132
};
130133

131134
struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
132135
DAP &dap;
133-
explicit ReplModeRequestHandler(DAP &d) : dap(d) {};
136+
explicit ReplModeRequestHandler(DAP &d) : dap(d){};
134137
bool DoExecute(lldb::SBDebugger debugger, char **command,
135138
lldb::SBCommandReturnObject &result) override;
136139
};
137140

138141
struct SendEventRequestHandler : public lldb::SBCommandPluginInterface {
139142
DAP &dap;
140-
explicit SendEventRequestHandler(DAP &d) : dap(d) {};
143+
explicit SendEventRequestHandler(DAP &d) : dap(d){};
141144
bool DoExecute(lldb::SBDebugger debugger, char **command,
142145
lldb::SBCommandReturnObject &result) override;
143146
};
@@ -207,6 +210,14 @@ struct DAP {
207210
// will contain that expression.
208211
std::string last_nonempty_var_expression;
209212

213+
/// Typed Events Handlers
214+
/// @{
215+
216+
/// onExited sends an event that the debuggee has exited.
217+
OutgoingEvent<protocol::ExitedEventBody> onExited;
218+
219+
/// @}
220+
210221
DAP(std::string name, llvm::StringRef path, std::ofstream *log,
211222
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
212223
std::vector<std::string> pre_init_commands);
@@ -345,6 +356,10 @@ struct DAP {
345356
request_handlers[Handler::getCommand()] = std::make_unique<Handler>(*this);
346357
}
347358

359+
/// Registeres an event handler for sending Debug Adapter Protocol events.
360+
template <typename Body>
361+
OutgoingEvent<Body> RegisterEvent(llvm::StringLiteral Event);
362+
348363
/// Debuggee will continue from stopped state.
349364
void WillContinue() { variables.Clear(); }
350365

@@ -378,6 +393,16 @@ struct DAP {
378393
InstructionBreakpoint *GetInstructionBPFromStopReason(lldb::SBThread &thread);
379394
};
380395

396+
template <typename Body>
397+
OutgoingEvent<Body> DAP::RegisterEvent(llvm::StringLiteral Event) {
398+
return [&, Event](const Body &B) {
399+
protocol::Event Evt;
400+
Evt.event = Event;
401+
Evt.rawBody = std::move(B);
402+
SendJSON(std::move(Evt));
403+
};
404+
}
405+
381406
} // namespace lldb_dap
382407

383408
#endif

lldb/tools/lldb-dap/EventHelper.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "DAP.h"
1111
#include "JSONUtils.h"
1212
#include "LLDBUtils.h"
13+
#include "Protocol.h"
1314
#include "lldb/API/SBFileSpec.h"
1415

1516
#if defined(_WIN32)
@@ -235,13 +236,4 @@ void SendContinuedEvent(DAP &dap) {
235236
dap.SendJSON(llvm::json::Value(std::move(event)));
236237
}
237238

238-
// Send a "exited" event to indicate the process has exited.
239-
void SendProcessExitedEvent(DAP &dap, lldb::SBProcess &process) {
240-
llvm::json::Object event(CreateEventObject("exited"));
241-
llvm::json::Object body;
242-
body.try_emplace("exitCode", (int64_t)process.GetExitStatus());
243-
event.try_emplace("body", std::move(body));
244-
dap.SendJSON(llvm::json::Value(std::move(event)));
245-
}
246-
247239
} // namespace lldb_dap

lldb/tools/lldb-dap/EventHelper.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ void SendStdOutStdErr(DAP &dap, lldb::SBProcess &process);
2626

2727
void SendContinuedEvent(DAP &dap);
2828

29-
void SendProcessExitedEvent(DAP &dap, lldb::SBProcess &process);
30-
3129
} // namespace lldb_dap
3230

3331
#endif

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "DAP.h"
1010
#include "EventHelper.h"
1111
#include "JSONUtils.h"
12+
#include "Protocol.h"
1213
#include "RequestHandler.h"
1314
#include "lldb/API/SBEvent.h"
1415
#include "lldb/API/SBListener.h"
@@ -178,7 +179,7 @@ static void EventThreadFunction(DAP &dap) {
178179
// Run any exit LLDB commands the user specified in the
179180
// launch.json
180181
dap.RunExitCommands();
181-
SendProcessExitedEvent(dap, process);
182+
dap.onExited(protocol::ExitedEventBody{/*exitCode=*/process.GetExitStatus()});
182183
dap.SendTerminatedEvent();
183184
done = true;
184185
}

lldb/tools/lldb-dap/Protocol.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ bool fromJSON(const llvm::json::Value &Params, Source &S, llvm::json::Path P) {
315315
O.mapOptional("sourceReference", S.sourceReference);
316316
}
317317

318+
llvm::json::Value toJSON(const ExitedEventBody &EEB) {
319+
return llvm::json::Object{{"exitCode", EEB.exitCode}};
320+
}
321+
318322
bool fromJSON(const llvm::json::Value &Params, SourceArguments &SA,
319323
llvm::json::Path P) {
320324
llvm::json::ObjectMapper O(Params, P);

lldb/tools/lldb-dap/Protocol.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,36 @@ struct Source {
316316
bool fromJSON(const llvm::json::Value &, Source &, llvm::json::Path);
317317
llvm::json::Value toJSON(const Source &);
318318

319+
// MARK: Events
320+
321+
// "ExitedEvent": {
322+
// "allOf": [ { "$ref": "#/definitions/Event" }, {
323+
// "type": "object",
324+
// "description": "The event indicates that the debuggee has exited and
325+
// returns its exit code.", "properties": {
326+
// "event": {
327+
// "type": "string",
328+
// "enum": [ "exited" ]
329+
// },
330+
// "body": {
331+
// "type": "object",
332+
// "properties": {
333+
// "exitCode": {
334+
// "type": "integer",
335+
// "description": "The exit code returned from the debuggee."
336+
// }
337+
// },
338+
// "required": [ "exitCode" ]
339+
// }
340+
// },
341+
// "required": [ "event", "body" ]
342+
// }]
343+
// }
344+
struct ExitedEventBody {
345+
int exitCode;
346+
};
347+
llvm::json::Value toJSON(const ExitedEventBody &);
348+
319349
// MARK: Requests
320350

321351
// "SourceArguments": {

lldb/tools/lldb-dap/lldb-dap.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "DAP.h"
1010
#include "EventHelper.h"
1111
#include "Handler/RequestHandler.h"
12+
#include "Protocol.h"
1213
#include "RunInTerminal.h"
1314
#include "lldb/API/SBDebugger.h"
1415
#include "lldb/API/SBStream.h"
@@ -151,6 +152,9 @@ static void RegisterRequestCallbacks(DAP &dap) {
151152

152153
// Testing requests
153154
dap.RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
155+
156+
// Event handlers
157+
dap.onExited = dap.RegisterEvent<protocol::ExitedEventBody>("exited");
154158
}
155159

156160
static void PrintHelp(LLDBDAPOptTable &table, llvm::StringRef tool_name) {

0 commit comments

Comments
 (0)