Skip to content

Commit ab4e9d8

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' and the 'process' event to use the new protocol serialization handlers and updates the call sites to use the new helper.
1 parent fbb8929 commit ab4e9d8

15 files changed

+262
-106
lines changed

lldb/tools/lldb-dap/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ add_lldb_tool(lldb-dap
3737
Transport.cpp
3838
Watchpoint.cpp
3939

40+
Events/ExitedEventHandler.cpp
41+
Events/ProcessEventHandler.cpp
42+
4043
Handler/ResponseHandler.cpp
4144
Handler/AttachRequestHandler.cpp
4245
Handler/BreakpointLocationsHandler.cpp
@@ -75,8 +78,9 @@ add_lldb_tool(lldb-dap
7578
Handler/VariablesRequestHandler.cpp
7679

7780
Protocol/ProtocolBase.cpp
78-
Protocol/ProtocolTypes.cpp
81+
Protocol/ProtocolEvents.cpp
7982
Protocol/ProtocolRequests.cpp
83+
Protocol/ProtocolTypes.cpp
8084

8185
LINK_LIBS
8286
liblldb

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "DAP.h"
1010
#include "DAPLog.h"
11+
#include "Events/EventHandler.h"
1112
#include "Handler/RequestHandler.h"
1213
#include "Handler/ResponseHandler.h"
1314
#include "JSONUtils.h"
@@ -82,7 +83,9 @@ DAP::DAP(llvm::StringRef path, std::ofstream *log,
8283
configuration_done_sent(false), waiting_for_run_in_terminal(false),
8384
progress_event_reporter(
8485
[&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }),
85-
reverse_request_seq(0), repl_mode(default_repl_mode) {}
86+
reverse_request_seq(0), repl_mode(default_repl_mode),
87+
onExited(ExitedEventHandler(*this)),
88+
onProcess(ProcessEventHandler(*this)) {}
8689

8790
DAP::~DAP() = default;
8891

lldb/tools/lldb-dap/DAP.h

Lines changed: 14 additions & 0 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... Args> using OutgoingEvent = std::function<void(Args...)>;
63+
6164
enum class OutputType { Console, Stdout, Stderr, Telemetry };
6265

6366
/// Buffer size for handling output events.
@@ -230,6 +233,17 @@ struct DAP {
230233
void operator=(const DAP &rhs) = delete;
231234
/// @}
232235

236+
/// Typed Events Handlers
237+
/// @{
238+
239+
/// onExited sends an event that the debuggee has exited.
240+
OutgoingEvent<> onExited;
241+
/// onProcess sends an event that indicates that the debugger has begun
242+
/// debugging a new process.
243+
OutgoingEvent<> onProcess;
244+
245+
/// @}
246+
233247
ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
234248
ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
235249

lldb/tools/lldb-dap/EventHelper.cpp

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -32,87 +32,6 @@ static void SendThreadExitedEvent(DAP &dap, lldb::tid_t tid) {
3232
dap.SendJSON(llvm::json::Value(std::move(event)));
3333
}
3434

35-
// "ProcessEvent": {
36-
// "allOf": [
37-
// { "$ref": "#/definitions/Event" },
38-
// {
39-
// "type": "object",
40-
// "description": "Event message for 'process' event type. The event
41-
// indicates that the debugger has begun debugging a
42-
// new process. Either one that it has launched, or one
43-
// that it has attached to.",
44-
// "properties": {
45-
// "event": {
46-
// "type": "string",
47-
// "enum": [ "process" ]
48-
// },
49-
// "body": {
50-
// "type": "object",
51-
// "properties": {
52-
// "name": {
53-
// "type": "string",
54-
// "description": "The logical name of the process. This is
55-
// usually the full path to process's executable
56-
// file. Example: /home/myproj/program.js."
57-
// },
58-
// "systemProcessId": {
59-
// "type": "integer",
60-
// "description": "The system process id of the debugged process.
61-
// This property will be missing for non-system
62-
// processes."
63-
// },
64-
// "isLocalProcess": {
65-
// "type": "boolean",
66-
// "description": "If true, the process is running on the same
67-
// computer as the debug adapter."
68-
// },
69-
// "startMethod": {
70-
// "type": "string",
71-
// "enum": [ "launch", "attach", "attachForSuspendedLaunch" ],
72-
// "description": "Describes how the debug engine started
73-
// debugging this process.",
74-
// "enumDescriptions": [
75-
// "Process was launched under the debugger.",
76-
// "Debugger attached to an existing process.",
77-
// "A project launcher component has launched a new process in
78-
// a suspended state and then asked the debugger to attach."
79-
// ]
80-
// }
81-
// },
82-
// "required": [ "name" ]
83-
// }
84-
// },
85-
// "required": [ "event", "body" ]
86-
// }
87-
// ]
88-
// }
89-
void SendProcessEvent(DAP &dap, LaunchMethod launch_method) {
90-
lldb::SBFileSpec exe_fspec = dap.target.GetExecutable();
91-
char exe_path[PATH_MAX];
92-
exe_fspec.GetPath(exe_path, sizeof(exe_path));
93-
llvm::json::Object event(CreateEventObject("process"));
94-
llvm::json::Object body;
95-
EmplaceSafeString(body, "name", std::string(exe_path));
96-
const auto pid = dap.target.GetProcess().GetProcessID();
97-
body.try_emplace("systemProcessId", (int64_t)pid);
98-
body.try_emplace("isLocalProcess", true);
99-
const char *startMethod = nullptr;
100-
switch (launch_method) {
101-
case Launch:
102-
startMethod = "launch";
103-
break;
104-
case Attach:
105-
startMethod = "attach";
106-
break;
107-
case AttachForSuspendedLaunch:
108-
startMethod = "attachForSuspendedLaunch";
109-
break;
110-
}
111-
body.try_emplace("startMethod", startMethod);
112-
event.try_emplace("body", std::move(body));
113-
dap.SendJSON(llvm::json::Value(std::move(event)));
114-
}
115-
11635
// Send a thread stopped event for all threads as long as the process
11736
// is stopped.
11837
void SendThreadStoppedEvent(DAP &dap) {
@@ -235,13 +154,4 @@ void SendContinuedEvent(DAP &dap) {
235154
dap.SendJSON(llvm::json::Value(std::move(event)));
236155
}
237156

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-
247157
} // namespace lldb_dap

lldb/tools/lldb-dap/EventHelper.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
namespace lldb_dap {
1515
struct DAP;
1616

17-
enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
18-
19-
void SendProcessEvent(DAP &dap, LaunchMethod launch_method);
20-
2117
void SendThreadStoppedEvent(DAP &dap);
2218

2319
void SendTerminatedEvent(DAP &dap);
@@ -26,8 +22,6 @@ void SendStdOutStdErr(DAP &dap, lldb::SBProcess &process);
2622

2723
void SendContinuedEvent(DAP &dap);
2824

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

3327
#endif
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===-- EventHandler.h ----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_TOOLS_LLDB_DAP_EVENTS_EVENT_HANDLER
10+
#define LLDB_TOOLS_LLDB_DAP_EVENTS_EVENT_HANDLER
11+
12+
#include "DAP.h"
13+
#include "Protocol/ProtocolBase.h"
14+
#include "Protocol/ProtocolEvents.h"
15+
#include "lldb/API/SBProcess.h"
16+
17+
namespace lldb_dap {
18+
19+
template <typename Body, typename... Args> class BaseEventHandler {
20+
public:
21+
BaseEventHandler(DAP &dap) : dap(dap) {}
22+
23+
virtual ~BaseEventHandler() = default;
24+
25+
virtual llvm::StringLiteral getEvent() const = 0;
26+
virtual Body Handler(Args...) const = 0;
27+
28+
void operator()(Args... args) const {
29+
Body body = Handler(args...);
30+
protocol::Event event{/*event=*/getEvent().str(), /*body=*/std::move(body)};
31+
dap.Send(event);
32+
}
33+
34+
protected:
35+
DAP &dap;
36+
};
37+
38+
/// Handler for the event indicates that the debuggee has exited and returns its
39+
/// exit code.
40+
class ExitedEventHandler : public BaseEventHandler<protocol::ExitedEventBody> {
41+
public:
42+
using BaseEventHandler::BaseEventHandler;
43+
llvm::StringLiteral getEvent() const override { return "exited"; }
44+
protocol::ExitedEventBody Handler() const override;
45+
};
46+
47+
class ProcessEventHandler
48+
: public BaseEventHandler<protocol::ProcessEventBody> {
49+
public:
50+
using BaseEventHandler::BaseEventHandler;
51+
llvm::StringLiteral getEvent() const override { return "process"; }
52+
protocol::ProcessEventBody Handler() const override;
53+
};
54+
55+
} // end namespace lldb_dap
56+
57+
#endif
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- ExitedEventHandler.cpp --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Events/EventHandler.h"
10+
#include "lldb/API/SBProcess.h"
11+
12+
namespace lldb_dap {
13+
14+
protocol::ExitedEventBody ExitedEventHandler::Handler() const {
15+
protocol::ExitedEventBody body;
16+
body.exitCode = dap.target.GetProcess().GetExitStatus();
17+
return body;
18+
}
19+
20+
} // namespace lldb_dap
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- ProcessEventHandler.cpp -------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Events/EventHandler.h"
10+
#include "Protocol/ProtocolEvents.h"
11+
#include "lldb/API/SBProcess.h"
12+
#include "lldb/API/SBTarget.h"
13+
14+
using namespace llvm;
15+
using namespace lldb_dap::protocol;
16+
17+
namespace lldb_dap {
18+
19+
ProcessEventBody ProcessEventHandler::Handler() const {
20+
ProcessEventBody body;
21+
22+
char path[PATH_MAX] = {0};
23+
dap.target.GetExecutable().GetPath(path, sizeof(path));
24+
body.name = path;
25+
body.systemProcessId = dap.target.GetProcess().GetProcessID();
26+
body.isLocalProcess = dap.target.GetPlatform().GetName() ==
27+
lldb::SBPlatform::GetHostPlatform().GetName();
28+
body.startMethod = dap.is_attach ? ProcessEventBody::StartMethod::attach
29+
: ProcessEventBody::StartMethod::launch;
30+
body.pointerSize = dap.target.GetAddressByteSize();
31+
return body;
32+
}
33+
34+
} // namespace lldb_dap

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ void AttachRequestHandler::operator()(const llvm::json::Object &request) const {
201201

202202
dap.SendJSON(llvm::json::Value(std::move(response)));
203203
if (error.Success()) {
204-
SendProcessEvent(dap, Attach);
204+
dap.onProcess();
205205
dap.SendJSON(CreateEventObject("initialized"));
206206
}
207207
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static void EventThreadFunction(DAP &dap) {
178178
// Run any exit LLDB commands the user specified in the
179179
// launch.json
180180
dap.RunExitCommands();
181-
SendProcessExitedEvent(dap, process);
181+
dap.onExited();
182182
dap.SendTerminatedEvent();
183183
done = true;
184184
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,7 @@ void LaunchRequestHandler::operator()(const llvm::json::Object &request) const {
124124
dap.SendJSON(llvm::json::Value(std::move(response)));
125125

126126
if (!status.Fail()) {
127-
if (dap.is_attach)
128-
SendProcessEvent(dap, Attach); // this happens when doing runInTerminal
129-
else
130-
SendProcessEvent(dap, Launch);
127+
dap.onProcess();
131128
}
132129
dap.SendJSON(CreateEventObject("initialized"));
133130
}

lldb/tools/lldb-dap/Protocol/ProtocolBase.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
//
1818
//===----------------------------------------------------------------------===//
1919

20-
#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_H
21-
#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_H
20+
#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H
21+
#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H
2222

2323
#include "llvm/Support/JSON.h"
2424
#include <cstdint>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===-- ProtocolEvents.cpp ------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Protocol/ProtocolEvents.h"
10+
#include "llvm/Support/JSON.h"
11+
12+
using namespace llvm;
13+
14+
namespace lldb_dap::protocol {
15+
16+
json::Value toJSON(const ExitedEventBody &EEB) {
17+
return json::Object{{"exitCode", EEB.exitCode}};
18+
}
19+
20+
json::Value toJSON(const ProcessEventBody::StartMethod &m) {
21+
switch (m) {
22+
case ProcessEventBody::StartMethod::launch:
23+
return "launch";
24+
case ProcessEventBody::StartMethod::attach:
25+
return "attach";
26+
case ProcessEventBody::StartMethod::attachForSuspendedLaunch:
27+
return "attachForSuspendedLaunch";
28+
}
29+
}
30+
31+
json::Value toJSON(const ProcessEventBody &PEB) {
32+
json::Object result{{"name", PEB.name}};
33+
34+
if (PEB.systemProcessId)
35+
result.insert({"systemProcessId", PEB.systemProcessId});
36+
if (PEB.isLocalProcess)
37+
result.insert({"isLocalProcess", PEB.isLocalProcess});
38+
if (PEB.startMethod)
39+
result.insert({"startMethod", PEB.startMethod});
40+
if (PEB.pointerSize)
41+
result.insert({"pointerSize", PEB.pointerSize});
42+
43+
return std::move(result);
44+
}
45+
46+
} // namespace lldb_dap::protocol

0 commit comments

Comments
 (0)