1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "rawdebugsession.h" |
6 | #include "dap/session.h" |
7 | #include "dap/protocol.h" |
8 | #include "objects.hpp" |
9 | |
10 | #include <QDebug> |
11 | |
12 | namespace dap { |
13 | |
14 | /** |
15 | * @brief rawDebugSession implimented by original dap |
16 | * protocol.TODO(mozart):Decide whether to use synchronous |
17 | * or asynchronous. |
18 | * @param parent |
19 | */ |
20 | RawDebugSession::RawDebugSession(std::shared_ptr<Session> &_session, QObject *parent) |
21 | : QObject(parent) |
22 | , session(_session) |
23 | { |
24 | initialize(); |
25 | } |
26 | |
27 | bool RawDebugSession::initialize() |
28 | { |
29 | errHandler = [&](const std::string& err){ |
30 | onError(err); |
31 | }; |
32 | return true; |
33 | } |
34 | |
35 | Promise<InitializeRequest> RawDebugSession::initialize(const InitializeRequest &args) |
36 | { |
37 | auto response = send(args); |
38 | auto capabilities = response.get().response; |
39 | mergeCapabilities(capabilities); |
40 | return response; |
41 | } |
42 | |
43 | bool RawDebugSession::disconnect(const DisconnectRequest &args) |
44 | { |
45 | optional<boolean> terminateDebuggee; |
46 | if (capabilities().supportTerminateDebuggee) |
47 | terminateDebuggee = args.terminateDebuggee; |
48 | return shutdown(terminateDebuggee, args.restart); |
49 | } |
50 | |
51 | void RawDebugSession::mergeCapabilities(const InitializeResponse &capabilities) |
52 | { |
53 | _capabilities = objects::mixin(_capabilities, capabilities); |
54 | } |
55 | |
56 | void RawDebugSession::onError(const std::string& error) |
57 | { |
58 | qInfo() << "Error :" << error.data(); |
59 | } |
60 | |
61 | void RawDebugSession::start() |
62 | { |
63 | // All the handlers we care about have now been registered. |
64 | // We now bind the session to stdin and stdout to connect to the client. |
65 | // After the call to bind() we should start receiving requests, starting with |
66 | // the Initialize request. |
67 | // std::shared_ptr<dap::Reader> in = dap::file(stdin, false); |
68 | // std::shared_ptr<dap::Writer> out = dap::file(stdout, false); |
69 | |
70 | // // connect to server. |
71 | // session->connect(in, out); |
72 | } |
73 | |
74 | Promise<LaunchRequest> RawDebugSession::launch(const LaunchRequest &request) |
75 | { |
76 | auto response = send(request); |
77 | return response; |
78 | } |
79 | |
80 | Promise<AttachRequest> RawDebugSession::attach(const AttachRequest &request) |
81 | { |
82 | auto response = send(request); |
83 | return response; |
84 | } |
85 | |
86 | bool RawDebugSession::terminate(bool restart) |
87 | { |
88 | Q_UNUSED(restart) |
89 | if (capabilities().supportsTerminateRequest) { |
90 | TerminateRequest request; |
91 | auto response = send(request); |
92 | response.wait(); |
93 | return true; |
94 | } |
95 | qInfo() << "terminated not supported" ; |
96 | return false; |
97 | } |
98 | |
99 | bool RawDebugSession::restart(const RestartRequest &request) |
100 | { |
101 | if (_capabilities.supportsRestartRequest) { |
102 | send(request); |
103 | return true; |
104 | } |
105 | qInfo() << "restart not supported" ; |
106 | return false; |
107 | } |
108 | |
109 | Promise<NextRequest> RawDebugSession::next(const NextRequest &request) |
110 | { |
111 | auto response = send(request); |
112 | response.wait(); |
113 | // fire notify event. |
114 | return response; |
115 | } |
116 | |
117 | Promise<StepInRequest> RawDebugSession::stepIn(const StepInRequest &request) |
118 | { |
119 | auto response = send(request); |
120 | response.wait(); |
121 | // fire notify event. |
122 | return response; |
123 | } |
124 | |
125 | Promise<StepOutRequest> RawDebugSession::stepOut(const StepOutRequest &request) |
126 | { |
127 | auto response = send(request); |
128 | response.wait(); |
129 | // fire notify event. |
130 | return response; |
131 | } |
132 | |
133 | Promise<ContinueRequest> RawDebugSession::continueDbg(const ContinueRequest &request) |
134 | { |
135 | auto response = send(request); |
136 | response.wait(); |
137 | auto responseBody = response.get().response; |
138 | if (responseBody.allThreadsContinued.has_value()) { |
139 | allThreadsContinued = responseBody.allThreadsContinued.value(); |
140 | } |
141 | // fire event. |
142 | |
143 | return response; |
144 | } |
145 | |
146 | Promise<PauseRequest> RawDebugSession::pause(const PauseRequest &request) |
147 | { |
148 | auto response = send(request); |
149 | return response; |
150 | } |
151 | |
152 | Promise<TerminateThreadsRequest> RawDebugSession::terminateThreads(const TerminateThreadsRequest &request) |
153 | { |
154 | if (_capabilities.supportsTerminateThreadsRequest) { |
155 | return send(request); |
156 | } |
157 | qInfo() << "terminateThreads not supported" ; |
158 | return {}; |
159 | } |
160 | |
161 | Promise<SetVariableRequest> RawDebugSession::setVariable(const SetVariableRequest &request) |
162 | { |
163 | if (_capabilities.supportsSetVariable) { |
164 | return send(request); |
165 | } |
166 | qInfo() << "supportsSetVariable not supported" ; |
167 | return {}; |
168 | } |
169 | |
170 | Promise<SetExpressionRequest> RawDebugSession::setExpression(const SetExpressionRequest &request) |
171 | { |
172 | if (_capabilities.supportsSetExpression) { |
173 | return send(request); |
174 | } |
175 | qInfo() << "supportsSetExpression not supported" ; |
176 | return {}; |
177 | } |
178 | |
179 | Promise<RestartFrameRequest> RawDebugSession::restartFrame(const RestartFrameRequest &request) |
180 | { |
181 | if (_capabilities.supportsRestartFrame) { |
182 | auto response = send(request); |
183 | response.wait(); |
184 | return response; |
185 | } |
186 | qInfo() << "supportsRestartFrame not supported" ; |
187 | return {}; |
188 | } |
189 | |
190 | Promise<StepInTargetsRequest> RawDebugSession::stepInTargets(const StepInTargetsRequest &request) |
191 | { |
192 | if (_capabilities.supportsStepInTargetsRequest) { |
193 | return send(request); |
194 | } |
195 | qInfo() << "supportsStepInTargetsRequest not supported" ; |
196 | return {}; |
197 | } |
198 | |
199 | Promise<CompletionsRequest> RawDebugSession::completions(const CompletionsRequest &request) |
200 | { |
201 | if (_capabilities.supportsCompletionsRequest) { |
202 | return send(request); |
203 | } |
204 | qInfo() << "supportsCompletionsRequest not supported" ; |
205 | return {}; |
206 | } |
207 | |
208 | Promise<SetBreakpointsRequest> RawDebugSession::setBreakpoints(const SetBreakpointsRequest &request) |
209 | { |
210 | return send(request); |
211 | } |
212 | |
213 | Promise<SetFunctionBreakpointsRequest> RawDebugSession::setFunctionBreakpoints( |
214 | const SetFunctionBreakpointsRequest &request) |
215 | { |
216 | if (_capabilities.supportsFunctionBreakpoints) { |
217 | return send(request); |
218 | } |
219 | qInfo() << "supportsFunctionBreakpoints not supported" ; |
220 | return {}; |
221 | } |
222 | |
223 | Promise<DataBreakpointInfoRequest> RawDebugSession::dataBreakpointInfo(const DataBreakpointInfoRequest &request) |
224 | { |
225 | if (_capabilities.supportsDataBreakpoints) { |
226 | return send(request); |
227 | } |
228 | qInfo() << "supportsDataBreakpoints not supported" ; |
229 | return {}; |
230 | } |
231 | |
232 | Promise<SetDataBreakpointsRequest> RawDebugSession::setDataBreakpoints(const SetDataBreakpointsRequest &request) |
233 | { |
234 | if (_capabilities.supportsDataBreakpoints) { |
235 | return send(request); |
236 | } |
237 | qInfo() << "supportsDataBreakpoints not supported" ; |
238 | return {}; |
239 | } |
240 | |
241 | Promise<SetExceptionBreakpointsRequest> RawDebugSession::setExceptionBreakpoints( |
242 | const SetExceptionBreakpointsRequest &request) |
243 | { |
244 | return send(request); |
245 | } |
246 | |
247 | Promise<BreakpointLocationsRequest> RawDebugSession::breakpointLocations(const BreakpointLocationsRequest &request) |
248 | { |
249 | if (_capabilities.supportsBreakpointLocationsRequest) { |
250 | return send(request); |
251 | } |
252 | qInfo() << "supportsBreakpointLocationsRequest not supported" ; |
253 | return {}; |
254 | } |
255 | |
256 | Promise<ConfigurationDoneRequest> RawDebugSession::configurationDone() |
257 | { |
258 | if (_capabilities.supportsConfigurationDoneRequest) |
259 | return send(ConfigurationDoneRequest()); |
260 | qInfo() << "supportsConfigurationDoneRequest not supported" ; |
261 | return {}; |
262 | } |
263 | |
264 | Promise<StackTraceRequest> RawDebugSession::stackTrace(const StackTraceRequest &request) |
265 | { |
266 | return send(request); |
267 | } |
268 | |
269 | Promise<ExceptionInfoRequest> RawDebugSession::exceptionInfo(const ExceptionInfoRequest &request) |
270 | { |
271 | if (_capabilities.supportsExceptionInfoRequest) { |
272 | return send(request); |
273 | } |
274 | qInfo() << "supportsExceptionInfoRequest not supported" ; |
275 | return {}; |
276 | } |
277 | |
278 | Promise<ScopesRequest> RawDebugSession::scopes(const ScopesRequest &request) |
279 | { |
280 | return send(request); |
281 | } |
282 | |
283 | Promise<VariablesRequest> RawDebugSession::variables(const VariablesRequest &request) |
284 | { |
285 | return send(request); |
286 | } |
287 | |
288 | Promise<SourceRequest> RawDebugSession::source(const SourceRequest &request) |
289 | { |
290 | return send(request); |
291 | } |
292 | |
293 | Promise<LoadedSourcesRequest> RawDebugSession::loadedSources(const LoadedSourcesRequest &request) |
294 | { |
295 | if (_capabilities.supportsLoadedSourcesRequest) { |
296 | return send(request); |
297 | } |
298 | qInfo() << "supportsLoadedSourcesRequest not supported" ; |
299 | return {}; |
300 | } |
301 | |
302 | Promise<ThreadsRequest> RawDebugSession::threads() |
303 | { |
304 | ThreadsRequest request; |
305 | return send(request); |
306 | } |
307 | |
308 | Promise<EvaluateRequest> RawDebugSession::evaluate(const EvaluateRequest &request) |
309 | { |
310 | return send(request); |
311 | } |
312 | |
313 | Promise<StepBackRequest> RawDebugSession::stepBack(const StepBackRequest &request) |
314 | { |
315 | if (_capabilities.supportsStepBack) { |
316 | auto response = send(request); |
317 | response.wait(); |
318 | // fire event. |
319 | return response; |
320 | } |
321 | qInfo() << "supportsStepBack not supported" ; |
322 | return {}; |
323 | } |
324 | |
325 | Promise<ReverseContinueRequest> RawDebugSession::reverseContinue(const ReverseContinueRequest &request) |
326 | { |
327 | if (_capabilities.supportsStepBack) { |
328 | auto response = send(request); |
329 | response.wait(); |
330 | // fire event. |
331 | return response; |
332 | } |
333 | qInfo() << "supportsStepBack not supported" ; |
334 | return {}; |
335 | } |
336 | |
337 | Promise<GotoTargetsRequest> RawDebugSession::gotoTargets(const GotoTargetsRequest &request) |
338 | { |
339 | if (_capabilities.supportsGotoTargetsRequest) { |
340 | return send(request); |
341 | } |
342 | qInfo() << "supportsGotoTargetsRequest not supported" ; |
343 | return {}; |
344 | } |
345 | |
346 | Promise<GotoRequest> RawDebugSession::goto_(const GotoRequest &request) |
347 | { |
348 | if (_capabilities.supportsGotoTargetsRequest) { |
349 | auto response = send(request); |
350 | response.wait(); |
351 | // fire event. |
352 | return response; |
353 | } |
354 | qInfo() << "supportsGotoTargetsRequest not supported" ; |
355 | return {}; |
356 | } |
357 | |
358 | Promise<SetInstructionBreakpointsRequest> RawDebugSession::setInstructionBreakpoints(const SetInstructionBreakpointsRequest &request) |
359 | { |
360 | if (_capabilities.supportsInstructionBreakpoints) { |
361 | auto response = send(request); |
362 | response.wait(); |
363 | // fire event. |
364 | return response; |
365 | } |
366 | qInfo() << "supportsInstructionBreakpoints not supported" ; |
367 | return {}; |
368 | } |
369 | |
370 | Promise<DisassembleRequest> RawDebugSession::disassemble(const DisassembleRequest &request) |
371 | { |
372 | if (_capabilities.supportsDisassembleRequest) { |
373 | auto response = send(request); |
374 | response.wait(); |
375 | // fire event. |
376 | return response; |
377 | } |
378 | qInfo() << "supportsDisassembleRequest not supported" ; |
379 | return {}; |
380 | } |
381 | |
382 | Promise<CancelRequest> RawDebugSession::cancel(const CancelRequest &request) |
383 | { |
384 | return send(request); |
385 | } |
386 | |
387 | const Capabilities &RawDebugSession::capabilities() const |
388 | { |
389 | return _capabilities; |
390 | } |
391 | |
392 | bool RawDebugSession::shutdown(optional<boolean> terminateDebuggee, optional<boolean> restart) |
393 | { |
394 | if (!inShutdown) { |
395 | inShutdown = true; |
396 | DisconnectRequest request; |
397 | request.restart = restart; |
398 | request.terminateDebuggee = terminateDebuggee; |
399 | syncSend(request); |
400 | } |
401 | return true; |
402 | } |
403 | |
404 | bool RawDebugSession::readyForBreakpoints() const |
405 | { |
406 | return _readyForBreakpoints; |
407 | } |
408 | |
409 | void RawDebugSession::setReadyForBreakpoints(bool bReady) |
410 | { |
411 | _readyForBreakpoints = bReady; |
412 | } |
413 | |
414 | void RawDebugSession::registerHandlers() |
415 | { |
416 | /* |
417 | * Register events. |
418 | */ |
419 | |
420 | // The event indicates that one or more capabilities have changed. |
421 | session->registerHandler([&](const CapabilitiesEvent &event){ |
422 | _capabilities = objects::mixin(_capabilities, event.capabilities); |
423 | qInfo() << "\n--> recv : " << "CapabilitiesEvent" ; |
424 | }); |
425 | |
426 | // The event indicates that the execution of the debuggee has continued. |
427 | session->registerHandler([&](const ContinuedEvent &event){ |
428 | allThreadsContinued = event.allThreadsContinued.value(); |
429 | Q_UNUSED(event) |
430 | qInfo() << "\n--> recv : " << "ContinuedEvent" ; |
431 | }); |
432 | } |
433 | |
434 | template<typename REQUEST, typename RESPONSE> |
435 | bool RawDebugSession::send(const REQUEST &request, RESPONSE *res) |
436 | { |
437 | auto r = session->send(request).get(); |
438 | if (r.error) { |
439 | errHandler(r.error.message); |
440 | return false; |
441 | } |
442 | *res = r.response; |
443 | return true; |
444 | } |
445 | |
446 | template<typename REQUEST> |
447 | bool RawDebugSession::syncSend(const REQUEST &request) |
448 | { |
449 | using RESPONSE = typename REQUEST::Response; |
450 | RESPONSE response; |
451 | return send(request, &response); |
452 | } |
453 | |
454 | template<typename REQUEST> |
455 | Promise<REQUEST> RawDebugSession::send(const REQUEST &request) |
456 | { |
457 | return session->send(request); |
458 | } |
459 | } // end namespace. |
460 | |