[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / lldb / tools / lldb-dap / DAP.h
blobae496236f13369cdd910946f0bd8f8ee44608feb
1 //===-- DAP.h ---------------------------------------------------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TOOLS_LLDB_DAP_DAP_H
10 #define LLDB_TOOLS_LLDB_DAP_DAP_H
12 #include <cstdio>
13 #include <iosfwd>
14 #include <map>
15 #include <optional>
16 #include <thread>
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/JSON.h"
23 #include "llvm/Support/Threading.h"
24 #include "llvm/Support/raw_ostream.h"
26 #include "lldb/API/SBAttachInfo.h"
27 #include "lldb/API/SBCommandInterpreter.h"
28 #include "lldb/API/SBCommandReturnObject.h"
29 #include "lldb/API/SBDebugger.h"
30 #include "lldb/API/SBEvent.h"
31 #include "lldb/API/SBFormat.h"
32 #include "lldb/API/SBLaunchInfo.h"
33 #include "lldb/API/SBTarget.h"
34 #include "lldb/API/SBThread.h"
36 #include "ExceptionBreakpoint.h"
37 #include "FunctionBreakpoint.h"
38 #include "IOStream.h"
39 #include "InstructionBreakpoint.h"
40 #include "ProgressEvent.h"
41 #include "SourceBreakpoint.h"
43 #define VARREF_LOCALS (int64_t)1
44 #define VARREF_GLOBALS (int64_t)2
45 #define VARREF_REGS (int64_t)3
46 #define VARREF_FIRST_VAR_IDX (int64_t)4
47 #define NO_TYPENAME "<no-type>"
49 namespace lldb_dap {
51 typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
52 typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
53 typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
54 InstructionBreakpointMap;
56 enum class OutputType { Console, Stdout, Stderr, Telemetry };
58 /// Buffer size for handling output events.
59 constexpr uint64_t OutputBufferSize = (1u << 12);
61 enum DAPBroadcasterBits {
62 eBroadcastBitStopEventThread = 1u << 0,
63 eBroadcastBitStopProgressThread = 1u << 1
66 typedef void (*RequestCallback)(DAP &dap, const llvm::json::Object &command);
67 typedef void (*ResponseCallback)(llvm::Expected<llvm::json::Value> value);
69 enum class PacketStatus {
70 Success = 0,
71 EndOfFile,
72 JSONMalformed,
73 JSONNotObject
76 enum class ReplMode { Variable = 0, Command, Auto };
78 struct Variables {
79 /// Variable_reference start index of permanent expandable variable.
80 static constexpr int64_t PermanentVariableStartIndex = (1ll << 32);
82 lldb::SBValueList locals;
83 lldb::SBValueList globals;
84 lldb::SBValueList registers;
86 int64_t next_temporary_var_ref{VARREF_FIRST_VAR_IDX};
87 int64_t next_permanent_var_ref{PermanentVariableStartIndex};
89 /// Variables that are alive in this stop state.
90 /// Will be cleared when debuggee resumes.
91 llvm::DenseMap<int64_t, lldb::SBValue> referenced_variables;
92 /// Variables that persist across entire debug session.
93 /// These are the variables evaluated from debug console REPL.
94 llvm::DenseMap<int64_t, lldb::SBValue> referenced_permanent_variables;
96 /// Check if \p var_ref points to a variable that should persist for the
97 /// entire duration of the debug session, e.g. repl expandable variables
98 static bool IsPermanentVariableReference(int64_t var_ref);
100 /// \return a new variableReference.
101 /// Specify is_permanent as true for variable that should persist entire
102 /// debug session.
103 int64_t GetNewVariableReference(bool is_permanent);
105 /// \return the expandable variable corresponding with variableReference
106 /// value of \p value.
107 /// If \p var_ref is invalid an empty SBValue is returned.
108 lldb::SBValue GetVariable(int64_t var_ref) const;
110 /// Insert a new \p variable.
111 /// \return variableReference assigned to this expandable variable.
112 int64_t InsertVariable(lldb::SBValue variable, bool is_permanent);
114 /// Clear all scope variables and non-permanent expandable variables.
115 void Clear();
118 struct StartDebuggingRequestHandler : public lldb::SBCommandPluginInterface {
119 DAP &dap;
120 explicit StartDebuggingRequestHandler(DAP &d) : dap(d) {};
121 bool DoExecute(lldb::SBDebugger debugger, char **command,
122 lldb::SBCommandReturnObject &result) override;
125 struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
126 DAP &dap;
127 explicit ReplModeRequestHandler(DAP &d) : dap(d) {};
128 bool DoExecute(lldb::SBDebugger debugger, char **command,
129 lldb::SBCommandReturnObject &result) override;
132 struct SendEventRequestHandler : public lldb::SBCommandPluginInterface {
133 DAP &dap;
134 explicit SendEventRequestHandler(DAP &d) : dap(d) {};
135 bool DoExecute(lldb::SBDebugger debugger, char **command,
136 lldb::SBCommandReturnObject &result) override;
139 struct DAP {
140 llvm::StringRef debug_adaptor_path;
141 InputStream input;
142 OutputStream output;
143 lldb::SBDebugger debugger;
144 lldb::SBTarget target;
145 Variables variables;
146 lldb::SBBroadcaster broadcaster;
147 std::thread event_thread;
148 std::thread progress_event_thread;
149 std::unique_ptr<std::ofstream> log;
150 llvm::StringMap<SourceBreakpointMap> source_breakpoints;
151 FunctionBreakpointMap function_breakpoints;
152 InstructionBreakpointMap instruction_breakpoints;
153 std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
154 llvm::once_flag init_exception_breakpoints_flag;
155 std::vector<std::string> pre_init_commands;
156 std::vector<std::string> init_commands;
157 std::vector<std::string> pre_run_commands;
158 std::vector<std::string> post_run_commands;
159 std::vector<std::string> exit_commands;
160 std::vector<std::string> stop_commands;
161 std::vector<std::string> terminate_commands;
162 // Map step in target id to list of function targets that user can choose.
163 llvm::DenseMap<lldb::addr_t, std::string> step_in_targets;
164 // A copy of the last LaunchRequest or AttachRequest so we can reuse its
165 // arguments if we get a RestartRequest.
166 std::optional<llvm::json::Object> last_launch_or_attach_request;
167 lldb::tid_t focus_tid;
168 bool disconnecting = false;
169 llvm::once_flag terminated_event_flag;
170 bool stop_at_entry;
171 bool is_attach;
172 bool enable_auto_variable_summaries;
173 bool enable_synthetic_child_debugging;
174 bool display_extended_backtrace;
175 // The process event thread normally responds to process exited events by
176 // shutting down the entire adapter. When we're restarting, we keep the id of
177 // the old process here so we can detect this case and keep running.
178 lldb::pid_t restarting_process_id;
179 bool configuration_done_sent;
180 std::map<std::string, RequestCallback, std::less<>> request_handlers;
181 bool waiting_for_run_in_terminal;
182 ProgressEventReporter progress_event_reporter;
183 // Keep track of the last stop thread index IDs as threads won't go away
184 // unless we send a "thread" event to indicate the thread exited.
185 llvm::DenseSet<lldb::tid_t> thread_ids;
186 uint32_t reverse_request_seq;
187 std::mutex call_mutex;
188 std::map<int /* request_seq */, ResponseCallback /* reply handler */>
189 inflight_reverse_requests;
190 ReplMode repl_mode;
191 std::string command_escape_prefix = "`";
192 lldb::SBFormat frame_format;
193 lldb::SBFormat thread_format;
194 // This is used to allow request_evaluate to handle empty expressions
195 // (ie the user pressed 'return' and expects the previous expression to
196 // repeat). If the previous expression was a command, this string will be
197 // empty; if the previous expression was a variable expression, this string
198 // will contain that expression.
199 std::string last_nonempty_var_expression;
201 DAP(llvm::StringRef path, ReplMode repl_mode);
202 ~DAP();
203 DAP(const DAP &rhs) = delete;
204 void operator=(const DAP &rhs) = delete;
205 ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
206 ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
208 // Serialize the JSON value into a string and send the JSON packet to
209 // the "out" stream.
210 void SendJSON(const llvm::json::Value &json);
212 std::string ReadJSON();
214 void SendOutput(OutputType o, const llvm::StringRef output);
216 void SendProgressEvent(uint64_t progress_id, const char *message,
217 uint64_t completed, uint64_t total);
219 void __attribute__((format(printf, 3, 4)))
220 SendFormattedOutput(OutputType o, const char *format, ...);
222 static int64_t GetNextSourceReference();
224 ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
226 lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
228 lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
230 llvm::json::Value CreateTopLevelScopes();
232 void PopulateExceptionBreakpoints();
234 /// Attempt to determine if an expression is a variable expression or
235 /// lldb command using a heuristic based on the first term of the
236 /// expression.
238 /// \param[in] frame
239 /// The frame, used as context to detect local variable names
240 /// \param[inout] expression
241 /// The expression string. Might be modified by this function to
242 /// remove the leading escape character.
243 /// \param[in] partial_expression
244 /// Whether the provided `expression` is only a prefix of the
245 /// final expression. If `true`, this function might return
246 /// `ReplMode::Auto` to indicate that the expression could be
247 /// either an expression or a statement, depending on the rest of
248 /// the expression.
249 /// \return the expression mode
250 ReplMode DetectReplMode(lldb::SBFrame frame, std::string &expression,
251 bool partial_expression);
253 /// \return
254 /// \b false if a fatal error was found while executing these commands,
255 /// according to the rules of \a LLDBUtils::RunLLDBCommands.
256 bool RunLLDBCommands(llvm::StringRef prefix,
257 llvm::ArrayRef<std::string> commands);
259 llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
260 llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
261 llvm::Error RunPreInitCommands();
262 llvm::Error RunInitCommands();
263 llvm::Error RunPreRunCommands();
264 void RunPostRunCommands();
265 void RunStopCommands();
266 void RunExitCommands();
267 void RunTerminateCommands();
269 /// Create a new SBTarget object from the given request arguments.
270 /// \param[in] arguments
271 /// Launch configuration arguments.
273 /// \param[out] error
274 /// An SBError object that will contain an error description if
275 /// function failed to create the target.
277 /// \return
278 /// An SBTarget object.
279 lldb::SBTarget CreateTargetFromArguments(const llvm::json::Object &arguments,
280 lldb::SBError &error);
282 /// Set given target object as a current target for lldb-dap and start
283 /// listeing for its breakpoint events.
284 void SetTarget(const lldb::SBTarget target);
286 const std::map<std::string, RequestCallback> &GetRequestHandlers();
288 PacketStatus GetNextObject(llvm::json::Object &object);
289 bool HandleObject(const llvm::json::Object &object);
291 llvm::Error Loop();
293 /// Send a Debug Adapter Protocol reverse request to the IDE.
295 /// \param[in] command
296 /// The reverse request command.
298 /// \param[in] arguments
299 /// The reverse request arguements.
301 /// \param[in] callback
302 /// A callback to execute when the response arrives.
303 void SendReverseRequest(llvm::StringRef command, llvm::json::Value arguments,
304 ResponseCallback callback);
306 /// Registers a callback handler for a Debug Adapter Protocol request
308 /// \param[in] request
309 /// The name of the request following the Debug Adapter Protocol
310 /// specification.
312 /// \param[in] callback
313 /// The callback to execute when the given request is triggered by the
314 /// IDE.
315 void RegisterRequestCallback(std::string request, RequestCallback callback);
317 /// Debuggee will continue from stopped state.
318 void WillContinue() { variables.Clear(); }
320 /// Poll the process to wait for it to reach the eStateStopped state.
322 /// Wait for the process hit a stopped state. When running a launch with
323 /// "launchCommands", or attach with "attachCommands", the calls might take
324 /// some time to stop at the entry point since the command is asynchronous. We
325 /// need to sync up with the process and make sure it is stopped before we
326 /// proceed to do anything else as we will soon be asked to set breakpoints
327 /// and other things that require the process to be stopped. We must use
328 /// polling because "attachCommands" or "launchCommands" may or may not send
329 /// process state change events depending on if the user modifies the async
330 /// setting in the debugger. Since both "attachCommands" and "launchCommands"
331 /// could end up using any combination of LLDB commands, we must ensure we can
332 /// also catch when the process stops, so we must poll the process to make
333 /// sure we handle all cases.
335 /// \param[in] seconds
336 /// The number of seconds to poll the process to wait until it is stopped.
338 /// \return Error if waiting for the process fails, no error if succeeds.
339 lldb::SBError WaitForProcessToStop(uint32_t seconds);
341 void SetFrameFormat(llvm::StringRef format);
343 void SetThreadFormat(llvm::StringRef format);
345 InstructionBreakpoint *GetInstructionBreakpoint(const lldb::break_id_t bp_id);
347 InstructionBreakpoint *GetInstructionBPFromStopReason(lldb::SBThread &thread);
349 private:
350 // Send the JSON in "json_str" to the "out" stream. Correctly send the
351 // "Content-Length:" field followed by the length, followed by the raw
352 // JSON bytes.
353 void SendJSON(const std::string &json_str);
356 } // namespace lldb_dap
358 #endif