1 //===-- DAP.h ---------------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TOOLS_LLDB_DAP_DAP_H
10 #define LLDB_TOOLS_LLDB_DAP_DAP_H
12 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
15 #include <condition_variable>
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/DenseSet.h"
26 #include "llvm/ADT/StringMap.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/JSON.h"
29 #include "llvm/Support/raw_ostream.h"
31 #include "lldb/API/SBAttachInfo.h"
32 #include "lldb/API/SBBreakpoint.h"
33 #include "lldb/API/SBBreakpointLocation.h"
34 #include "lldb/API/SBCommandInterpreter.h"
35 #include "lldb/API/SBCommandReturnObject.h"
36 #include "lldb/API/SBCommunication.h"
37 #include "lldb/API/SBDebugger.h"
38 #include "lldb/API/SBEvent.h"
39 #include "lldb/API/SBHostOS.h"
40 #include "lldb/API/SBInstruction.h"
41 #include "lldb/API/SBInstructionList.h"
42 #include "lldb/API/SBLanguageRuntime.h"
43 #include "lldb/API/SBLaunchInfo.h"
44 #include "lldb/API/SBLineEntry.h"
45 #include "lldb/API/SBListener.h"
46 #include "lldb/API/SBProcess.h"
47 #include "lldb/API/SBStream.h"
48 #include "lldb/API/SBStringList.h"
49 #include "lldb/API/SBTarget.h"
50 #include "lldb/API/SBThread.h"
52 #include "ExceptionBreakpoint.h"
53 #include "FunctionBreakpoint.h"
55 #include "ProgressEvent.h"
56 #include "RunInTerminal.h"
57 #include "SourceBreakpoint.h"
59 #define VARREF_LOCALS (int64_t)1
60 #define VARREF_GLOBALS (int64_t)2
61 #define VARREF_REGS (int64_t)3
62 #define VARREF_FIRST_VAR_IDX (int64_t)4
63 #define NO_TYPENAME "<no-type>"
67 typedef llvm::DenseMap
<uint32_t, SourceBreakpoint
> SourceBreakpointMap
;
68 typedef llvm::StringMap
<FunctionBreakpoint
> FunctionBreakpointMap
;
69 enum class OutputType
{ Console
, Stdout
, Stderr
, Telemetry
};
71 enum DAPBroadcasterBits
{
72 eBroadcastBitStopEventThread
= 1u << 0,
73 eBroadcastBitStopProgressThread
= 1u << 1
76 typedef void (*RequestCallback
)(const llvm::json::Object
&command
);
77 typedef void (*ResponseCallback
)(llvm::Expected
<llvm::json::Value
> value
);
79 enum class PacketStatus
{
86 enum class ReplMode
{ Variable
= 0, Command
, Auto
};
88 /// The detected context of an expression based off the current repl mode.
89 enum class ExpressionContext
{
95 /// Variable_reference start index of permanent expandable variable.
96 static constexpr int64_t PermanentVariableStartIndex
= (1ll << 32);
98 lldb::SBValueList locals
;
99 lldb::SBValueList globals
;
100 lldb::SBValueList registers
;
102 int64_t next_temporary_var_ref
{VARREF_FIRST_VAR_IDX
};
103 int64_t next_permanent_var_ref
{PermanentVariableStartIndex
};
105 /// Expandable variables that are alive in this stop state.
106 /// Will be cleared when debuggee resumes.
107 llvm::DenseMap
<int64_t, lldb::SBValue
> expandable_variables
;
108 /// Expandable variables that persist across entire debug session.
109 /// These are the variables evaluated from debug console REPL.
110 llvm::DenseMap
<int64_t, lldb::SBValue
> expandable_permanent_variables
;
112 /// Check if \p var_ref points to a variable that should persist for the
113 /// entire duration of the debug session, e.g. repl expandable variables
114 static bool IsPermanentVariableReference(int64_t var_ref
);
116 /// \return a new variableReference.
117 /// Specify is_permanent as true for variable that should persist entire
119 int64_t GetNewVariableReference(bool is_permanent
);
121 /// \return the expandable variable corresponding with variableReference
122 /// value of \p value.
123 /// If \p var_ref is invalid an empty SBValue is returned.
124 lldb::SBValue
GetVariable(int64_t var_ref
) const;
126 /// Insert a new \p variable.
127 /// \return variableReference assigned to this expandable variable.
128 int64_t InsertExpandableVariable(lldb::SBValue variable
, bool is_permanent
);
130 /// Clear all scope variables and non-permanent expandable variables.
134 struct StartDebuggingRequestHandler
: public lldb::SBCommandPluginInterface
{
135 bool DoExecute(lldb::SBDebugger debugger
, char **command
,
136 lldb::SBCommandReturnObject
&result
) override
;
139 struct ReplModeRequestHandler
: public lldb::SBCommandPluginInterface
{
140 bool DoExecute(lldb::SBDebugger debugger
, char **command
,
141 lldb::SBCommandReturnObject
&result
) override
;
145 std::string debug_adaptor_path
;
148 lldb::SBDebugger debugger
;
149 lldb::SBTarget target
;
151 lldb::SBBroadcaster broadcaster
;
152 std::thread event_thread
;
153 std::thread progress_event_thread
;
154 std::unique_ptr
<std::ofstream
> log
;
155 llvm::StringMap
<SourceBreakpointMap
> source_breakpoints
;
156 FunctionBreakpointMap function_breakpoints
;
157 std::vector
<ExceptionBreakpoint
> exception_breakpoints
;
158 std::vector
<std::string
> init_commands
;
159 std::vector
<std::string
> pre_run_commands
;
160 std::vector
<std::string
> exit_commands
;
161 std::vector
<std::string
> stop_commands
;
162 std::vector
<std::string
> terminate_commands
;
163 // A copy of the last LaunchRequest or AttachRequest so we can reuse its
164 // arguments if we get a RestartRequest.
165 std::optional
<llvm::json::Object
> last_launch_or_attach_request
;
166 lldb::tid_t focus_tid
;
167 std::atomic
<bool> sent_terminated_event
;
170 bool enable_auto_variable_summaries
;
171 bool enable_synthetic_child_debugging
;
172 // The process event thread normally responds to process exited events by
173 // shutting down the entire adapter. When we're restarting, we keep the id of
174 // the old process here so we can detect this case and keep running.
175 lldb::pid_t restarting_process_id
;
176 bool configuration_done_sent
;
177 std::map
<std::string
, RequestCallback
> request_handlers
;
178 bool waiting_for_run_in_terminal
;
179 ProgressEventReporter progress_event_reporter
;
180 // Keep track of the last stop thread index IDs as threads won't go away
181 // unless we send a "thread" event to indicate the thread exited.
182 llvm::DenseSet
<lldb::tid_t
> thread_ids
;
183 uint32_t reverse_request_seq
;
184 std::mutex call_mutex
;
185 std::map
<int /* request_seq */, ResponseCallback
/* reply handler */>
186 inflight_reverse_requests
;
187 StartDebuggingRequestHandler start_debugging_request_handler
;
188 ReplModeRequestHandler repl_mode_request_handler
;
190 bool auto_repl_mode_collision_warning
;
191 std::string command_escape_prefix
= "`";
195 DAP(const DAP
&rhs
) = delete;
196 void operator=(const DAP
&rhs
) = delete;
197 ExceptionBreakpoint
*GetExceptionBreakpoint(const std::string
&filter
);
198 ExceptionBreakpoint
*GetExceptionBreakpoint(const lldb::break_id_t bp_id
);
200 // Serialize the JSON value into a string and send the JSON packet to
202 void SendJSON(const llvm::json::Value
&json
);
204 std::string
ReadJSON();
206 void SendOutput(OutputType o
, const llvm::StringRef output
);
208 void SendProgressEvent(uint64_t progress_id
, const char *message
,
209 uint64_t completed
, uint64_t total
);
211 void __attribute__((format(printf
, 3, 4)))
212 SendFormattedOutput(OutputType o
, const char *format
, ...);
214 static int64_t GetNextSourceReference();
216 ExceptionBreakpoint
*GetExceptionBPFromStopReason(lldb::SBThread
&thread
);
218 lldb::SBThread
GetLLDBThread(const llvm::json::Object
&arguments
);
220 lldb::SBFrame
GetLLDBFrame(const llvm::json::Object
&arguments
);
222 llvm::json::Value
CreateTopLevelScopes();
224 ExpressionContext
DetectExpressionContext(lldb::SBFrame
&frame
,
227 void RunLLDBCommands(llvm::StringRef prefix
,
228 const std::vector
<std::string
> &commands
);
230 void RunInitCommands();
231 void RunPreRunCommands();
232 void RunStopCommands();
233 void RunExitCommands();
234 void RunTerminateCommands();
236 /// Create a new SBTarget object from the given request arguments.
237 /// \param[in] arguments
238 /// Launch configuration arguments.
240 /// \param[out] error
241 /// An SBError object that will contain an error description if
242 /// function failed to create the target.
245 /// An SBTarget object.
246 lldb::SBTarget
CreateTargetFromArguments(const llvm::json::Object
&arguments
,
247 lldb::SBError
&error
);
249 /// Set given target object as a current target for lldb-dap and start
250 /// listeing for its breakpoint events.
251 void SetTarget(const lldb::SBTarget target
);
253 const std::map
<std::string
, RequestCallback
> &GetRequestHandlers();
255 PacketStatus
GetNextObject(llvm::json::Object
&object
);
256 bool HandleObject(const llvm::json::Object
&object
);
260 /// Send a Debug Adapter Protocol reverse request to the IDE.
262 /// \param[in] command
263 /// The reverse request command.
265 /// \param[in] arguments
266 /// The reverse request arguements.
268 /// \param[in] callback
269 /// A callback to execute when the response arrives.
270 void SendReverseRequest(llvm::StringRef command
, llvm::json::Value arguments
,
271 ResponseCallback callback
);
273 /// Registers a callback handler for a Debug Adapter Protocol request
275 /// \param[in] request
276 /// The name of the request following the Debug Adapter Protocol
279 /// \param[in] callback
280 /// The callback to execute when the given request is triggered by the
282 void RegisterRequestCallback(std::string request
, RequestCallback callback
);
284 /// Debuggee will continue from stopped state.
285 void WillContinue() { variables
.Clear(); }
287 /// Poll the process to wait for it to reach the eStateStopped state.
289 /// Wait for the process hit a stopped state. When running a launch with
290 /// "launchCommands", or attach with "attachCommands", the calls might take
291 /// some time to stop at the entry point since the command is asynchronous. We
292 /// need to sync up with the process and make sure it is stopped before we
293 /// proceed to do anything else as we will soon be asked to set breakpoints
294 /// and other things that require the process to be stopped. We must use
295 /// polling because "attachCommands" or "launchCommands" may or may not send
296 /// process state change events depending on if the user modifies the async
297 /// setting in the debugger. Since both "attachCommands" and "launchCommands"
298 /// could end up using any combination of LLDB commands, we must ensure we can
299 /// also catch when the process stops, so we must poll the process to make
300 /// sure we handle all cases.
302 /// \param[in] seconds
303 /// The number of seconds to poll the process to wait until it is stopped.
305 /// \return Error if waiting for the process fails, no error if succeeds.
306 lldb::SBError
WaitForProcessToStop(uint32_t seconds
);
309 // Send the JSON in "json_str" to the "out" stream. Correctly send the
310 // "Content-Length:" field followed by the length, followed by the raw
312 void SendJSON(const std::string
&json_str
);
317 } // namespace lldb_dap