|
8 | 8 |
|
9 | 9 | #include "DAP.h"
|
10 | 10 | #include "EventHelper.h"
|
11 |
| -#include "JSONUtils.h" |
| 11 | +#include "Protocol/ProtocolRequests.h" |
| 12 | +#include "Protocol/ProtocolTypes.h" |
12 | 13 | #include "RequestHandler.h"
|
13 | 14 |
|
| 15 | +using namespace llvm; |
| 16 | +using namespace lldb; |
| 17 | +using namespace lldb_dap::protocol; |
| 18 | + |
14 | 19 | namespace lldb_dap {
|
15 | 20 |
|
16 |
| -// "StepInRequest": { |
17 |
| -// "allOf": [ { "$ref": "#/definitions/Request" }, { |
18 |
| -// "type": "object", |
19 |
| -// "description": "StepIn request; value of command field is 'stepIn'. The |
20 |
| -// request starts the debuggee to step into a function/method if possible. |
21 |
| -// If it cannot step into a target, 'stepIn' behaves like 'next'. The debug |
22 |
| -// adapter first sends the StepInResponse and then a StoppedEvent (event |
23 |
| -// type 'step') after the step has completed. If there are multiple |
24 |
| -// function/method calls (or other targets) on the source line, the optional |
25 |
| -// argument 'targetId' can be used to control into which target the 'stepIn' |
26 |
| -// should occur. The list of possible targets for a given source line can be |
27 |
| -// retrieved via the 'stepInTargets' request.", "properties": { |
28 |
| -// "command": { |
29 |
| -// "type": "string", |
30 |
| -// "enum": [ "stepIn" ] |
31 |
| -// }, |
32 |
| -// "arguments": { |
33 |
| -// "$ref": "#/definitions/StepInArguments" |
34 |
| -// } |
35 |
| -// }, |
36 |
| -// "required": [ "command", "arguments" ] |
37 |
| -// }] |
38 |
| -// }, |
39 |
| -// "StepInArguments": { |
40 |
| -// "type": "object", |
41 |
| -// "description": "Arguments for 'stepIn' request.", |
42 |
| -// "properties": { |
43 |
| -// "threadId": { |
44 |
| -// "type": "integer", |
45 |
| -// "description": "Execute 'stepIn' for this thread." |
46 |
| -// }, |
47 |
| -// "targetId": { |
48 |
| -// "type": "integer", |
49 |
| -// "description": "Optional id of the target to step into." |
50 |
| -// }, |
51 |
| -// "granularity": { |
52 |
| -// "$ref": "#/definitions/SteppingGranularity", |
53 |
| -// "description": "Stepping granularity. If no granularity is specified, a |
54 |
| -// granularity of `statement` is assumed." |
55 |
| -// } |
56 |
| -// }, |
57 |
| -// "required": [ "threadId" ] |
58 |
| -// }, |
59 |
| -// "StepInResponse": { |
60 |
| -// "allOf": [ { "$ref": "#/definitions/Response" }, { |
61 |
| -// "type": "object", |
62 |
| -// "description": "Response to 'stepIn' request. This is just an |
63 |
| -// acknowledgement, so no body field is required." |
64 |
| -// }] |
65 |
| -// } |
66 |
| -void StepInRequestHandler::operator()(const llvm::json::Object &request) const { |
67 |
| - llvm::json::Object response; |
68 |
| - FillResponse(request, response); |
69 |
| - const auto *arguments = request.getObject("arguments"); |
| 21 | +// The request resumes the given thread to step into a function/method and |
| 22 | +// allows all other threads to run freely by resuming them. If the debug adapter |
| 23 | +// supports single thread execution (see capability |
| 24 | +// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument |
| 25 | +// to true prevents other suspended threads from resuming. If the request cannot |
| 26 | +// step into a target, `stepIn` behaves like the `next` request. The debug |
| 27 | +// adapter first sends the response and then a `stopped` event (with reason |
| 28 | +// `step`) after the step has completed. If there are multiple function/method |
| 29 | +// calls (or other targets) on the source line, the argument `targetId` can be |
| 30 | +// used to control into which target the `stepIn` should occur. The list of |
| 31 | +// possible targets for a given source line can be retrieved via the |
| 32 | +// `stepInTargets` request. |
| 33 | +Error StepInRequestHandler::Run(const StepInArguments &args) const { |
| 34 | + SBThread thread = dap.GetLLDBThread(args.threadId); |
| 35 | + if (!thread.IsValid()) |
| 36 | + return make_error<DAPError>("invalid thread"); |
| 37 | + |
| 38 | + // Remember the thread ID that caused the resume so we can set the |
| 39 | + // "threadCausedFocus" boolean value in the "stopped" events. |
| 40 | + dap.focus_tid = thread.GetThreadID(); |
| 41 | + |
| 42 | + if (args.granularity == eSteppingGranularityInstruction) { |
| 43 | + thread.StepInstruction(/*step_over=*/false); |
| 44 | + return Error::success(); |
| 45 | + } |
70 | 46 |
|
71 | 47 | std::string step_in_target;
|
72 |
| - const auto target_id = |
73 |
| - GetInteger<uint64_t>(arguments, "targetId").value_or(0); |
74 |
| - auto it = dap.step_in_targets.find(target_id); |
| 48 | + auto it = dap.step_in_targets.find(args.targetId.value_or(0)); |
75 | 49 | if (it != dap.step_in_targets.end())
|
76 | 50 | step_in_target = it->second;
|
77 | 51 |
|
78 |
| - const bool single_thread = |
79 |
| - GetBoolean(arguments, "singleThread").value_or(false); |
80 |
| - lldb::RunMode run_mode = |
81 |
| - single_thread ? lldb::eOnlyThisThread : lldb::eOnlyDuringStepping; |
82 |
| - lldb::SBThread thread = dap.GetLLDBThread(*arguments); |
83 |
| - if (thread.IsValid()) { |
84 |
| - // Remember the thread ID that caused the resume so we can set the |
85 |
| - // "threadCausedFocus" boolean value in the "stopped" events. |
86 |
| - dap.focus_tid = thread.GetThreadID(); |
87 |
| - if (HasInstructionGranularity(*arguments)) { |
88 |
| - thread.StepInstruction(/*step_over=*/false); |
89 |
| - } else { |
90 |
| - thread.StepInto(step_in_target.c_str(), run_mode); |
91 |
| - } |
92 |
| - } else { |
93 |
| - response["success"] = llvm::json::Value(false); |
94 |
| - } |
95 |
| - dap.SendJSON(llvm::json::Value(std::move(response))); |
| 52 | + RunMode run_mode = args.singleThread ? eOnlyThisThread : eOnlyDuringStepping; |
| 53 | + thread.StepInto(step_in_target.c_str(), run_mode); |
| 54 | + return Error::success(); |
96 | 55 | }
|
97 | 56 |
|
98 | 57 | } // namespace lldb_dap
|
0 commit comments