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//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_TOOLS_LLDB_DAP_DAP_H
10#define LLDB_TOOLS_LLDB_DAP_DAP_H
11
12#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
13
14#include <atomic>
15#include <condition_variable>
16#include <cstdio>
17#include <future>
18#include <iosfwd>
19#include <map>
20#include <optional>
21#include <set>
22#include <thread>
23
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"
30
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/SBFormat.h"
40#include "lldb/API/SBHostOS.h"
41#include "lldb/API/SBInstruction.h"
42#include "lldb/API/SBInstructionList.h"
43#include "lldb/API/SBLanguageRuntime.h"
44#include "lldb/API/SBLaunchInfo.h"
45#include "lldb/API/SBLineEntry.h"
46#include "lldb/API/SBListener.h"
47#include "lldb/API/SBProcess.h"
48#include "lldb/API/SBStream.h"
49#include "lldb/API/SBStringList.h"
50#include "lldb/API/SBTarget.h"
51#include "lldb/API/SBThread.h"
52
53#include "ExceptionBreakpoint.h"
54#include "FunctionBreakpoint.h"
55#include "IOStream.h"
56#include "ProgressEvent.h"
57#include "RunInTerminal.h"
58#include "SourceBreakpoint.h"
59
60#define VARREF_LOCALS (int64_t)1
61#define VARREF_GLOBALS (int64_t)2
62#define VARREF_REGS (int64_t)3
63#define VARREF_FIRST_VAR_IDX (int64_t)4
64#define NO_TYPENAME "<no-type>"
65
66namespace lldb_dap {
67
68typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
69typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
70enum class OutputType { Console, Stdout, Stderr, Telemetry };
71
72enum DAPBroadcasterBits {
73 eBroadcastBitStopEventThread = 1u << 0,
74 eBroadcastBitStopProgressThread = 1u << 1
75};
76
77typedef void (*RequestCallback)(const llvm::json::Object &command);
78typedef void (*ResponseCallback)(llvm::Expected<llvm::json::Value> value);
79
80enum class PacketStatus {
81 Success = 0,
82 EndOfFile,
83 JSONMalformed,
84 JSONNotObject
85};
86
87enum class ReplMode { Variable = 0, Command, Auto };
88
89/// The detected context of an expression based off the current repl mode.
90enum class ExpressionContext {
91 Variable = 0,
92 Command,
93};
94
95struct Variables {
96 /// Variable_reference start index of permanent expandable variable.
97 static constexpr int64_t PermanentVariableStartIndex = (1ll << 32);
98
99 lldb::SBValueList locals;
100 lldb::SBValueList globals;
101 lldb::SBValueList registers;
102
103 int64_t next_temporary_var_ref{VARREF_FIRST_VAR_IDX};
104 int64_t next_permanent_var_ref{PermanentVariableStartIndex};
105
106 /// Expandable variables that are alive in this stop state.
107 /// Will be cleared when debuggee resumes.
108 llvm::DenseMap<int64_t, lldb::SBValue> expandable_variables;
109 /// Expandable variables that persist across entire debug session.
110 /// These are the variables evaluated from debug console REPL.
111 llvm::DenseMap<int64_t, lldb::SBValue> expandable_permanent_variables;
112
113 /// Check if \p var_ref points to a variable that should persist for the
114 /// entire duration of the debug session, e.g. repl expandable variables
115 static bool IsPermanentVariableReference(int64_t var_ref);
116
117 /// \return a new variableReference.
118 /// Specify is_permanent as true for variable that should persist entire
119 /// debug session.
120 int64_t GetNewVariableReference(bool is_permanent);
121
122 /// \return the expandable variable corresponding with variableReference
123 /// value of \p value.
124 /// If \p var_ref is invalid an empty SBValue is returned.
125 lldb::SBValue GetVariable(int64_t var_ref) const;
126
127 /// Insert a new \p variable.
128 /// \return variableReference assigned to this expandable variable.
129 int64_t InsertExpandableVariable(lldb::SBValue variable, bool is_permanent);
130
131 /// Clear all scope variables and non-permanent expandable variables.
132 void Clear();
133};
134
135struct StartDebuggingRequestHandler : public lldb::SBCommandPluginInterface {
136 bool DoExecute(lldb::SBDebugger debugger, char **command,
137 lldb::SBCommandReturnObject &result) override;
138};
139
140struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
141 bool DoExecute(lldb::SBDebugger debugger, char **command,
142 lldb::SBCommandReturnObject &result) override;
143};
144
145struct DAP {
146 std::string debug_adaptor_path;
147 InputStream input;
148 OutputStream output;
149 lldb::SBDebugger debugger;
150 lldb::SBTarget target;
151 Variables variables;
152 lldb::SBBroadcaster broadcaster;
153 std::thread event_thread;
154 std::thread progress_event_thread;
155 std::unique_ptr<std::ofstream> log;
156 llvm::StringMap<SourceBreakpointMap> source_breakpoints;
157 FunctionBreakpointMap function_breakpoints;
158 std::vector<ExceptionBreakpoint> exception_breakpoints;
159 std::vector<std::string> init_commands;
160 std::vector<std::string> pre_run_commands;
161 std::vector<std::string> post_run_commands;
162 std::vector<std::string> exit_commands;
163 std::vector<std::string> stop_commands;
164 std::vector<std::string> terminate_commands;
165 // A copy of the last LaunchRequest or AttachRequest so we can reuse its
166 // arguments if we get a RestartRequest.
167 std::optional<llvm::json::Object> last_launch_or_attach_request;
168 lldb::tid_t focus_tid;
169 std::atomic<bool> sent_terminated_event;
170 bool stop_at_entry;
171 bool is_attach;
172 bool enable_auto_variable_summaries;
173 bool enable_synthetic_child_debugging;
174 // The process event thread normally responds to process exited events by
175 // shutting down the entire adapter. When we're restarting, we keep the id of
176 // the old process here so we can detect this case and keep running.
177 lldb::pid_t restarting_process_id;
178 bool configuration_done_sent;
179 std::map<std::string, RequestCallback> request_handlers;
180 bool waiting_for_run_in_terminal;
181 ProgressEventReporter progress_event_reporter;
182 // Keep track of the last stop thread index IDs as threads won't go away
183 // unless we send a "thread" event to indicate the thread exited.
184 llvm::DenseSet<lldb::tid_t> thread_ids;
185 uint32_t reverse_request_seq;
186 std::mutex call_mutex;
187 std::map<int /* request_seq */, ResponseCallback /* reply handler */>
188 inflight_reverse_requests;
189 StartDebuggingRequestHandler start_debugging_request_handler;
190 ReplModeRequestHandler repl_mode_request_handler;
191 ReplMode repl_mode;
192 std::string command_escape_prefix = "`";
193 lldb::SBFormat frame_format;
194 lldb::SBFormat thread_format;
195
196 DAP();
197 ~DAP();
198 DAP(const DAP &rhs) = delete;
199 void operator=(const DAP &rhs) = delete;
200 ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
201 ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
202
203 // Serialize the JSON value into a string and send the JSON packet to
204 // the "out" stream.
205 void SendJSON(const llvm::json::Value &json);
206
207 std::string ReadJSON();
208
209 void SendOutput(OutputType o, const llvm::StringRef output);
210
211 void SendProgressEvent(uint64_t progress_id, const char *message,
212 uint64_t completed, uint64_t total);
213
214 void __attribute__((format(printf, 3, 4)))
215 SendFormattedOutput(OutputType o, const char *format, ...);
216
217 static int64_t GetNextSourceReference();
218
219 ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
220
221 lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
222
223 lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
224
225 llvm::json::Value CreateTopLevelScopes();
226
227 /// \return
228 /// Attempt to determine if an expression is a variable expression or
229 /// lldb command using a hueristic based on the first term of the
230 /// expression.
231 ExpressionContext DetectExpressionContext(lldb::SBFrame frame,
232 std::string &expression);
233
234 /// \return
235 /// \b false if a fatal error was found while executing these commands,
236 /// according to the rules of \a LLDBUtils::RunLLDBCommands.
237 bool RunLLDBCommands(llvm::StringRef prefix,
238 llvm::ArrayRef<std::string> commands);
239
240 llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
241 llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
242 llvm::Error RunInitCommands();
243 llvm::Error RunPreRunCommands();
244 void RunPostRunCommands();
245 void RunStopCommands();
246 void RunExitCommands();
247 void RunTerminateCommands();
248
249 /// Create a new SBTarget object from the given request arguments.
250 /// \param[in] arguments
251 /// Launch configuration arguments.
252 ///
253 /// \param[out] error
254 /// An SBError object that will contain an error description if
255 /// function failed to create the target.
256 ///
257 /// \return
258 /// An SBTarget object.
259 lldb::SBTarget CreateTargetFromArguments(const llvm::json::Object &arguments,
260 lldb::SBError &error);
261
262 /// Set given target object as a current target for lldb-dap and start
263 /// listeing for its breakpoint events.
264 void SetTarget(const lldb::SBTarget target);
265
266 const std::map<std::string, RequestCallback> &GetRequestHandlers();
267
268 PacketStatus GetNextObject(llvm::json::Object &object);
269 bool HandleObject(const llvm::json::Object &object);
270
271 llvm::Error Loop();
272
273 /// Send a Debug Adapter Protocol reverse request to the IDE.
274 ///
275 /// \param[in] command
276 /// The reverse request command.
277 ///
278 /// \param[in] arguments
279 /// The reverse request arguements.
280 ///
281 /// \param[in] callback
282 /// A callback to execute when the response arrives.
283 void SendReverseRequest(llvm::StringRef command, llvm::json::Value arguments,
284 ResponseCallback callback);
285
286 /// Registers a callback handler for a Debug Adapter Protocol request
287 ///
288 /// \param[in] request
289 /// The name of the request following the Debug Adapter Protocol
290 /// specification.
291 ///
292 /// \param[in] callback
293 /// The callback to execute when the given request is triggered by the
294 /// IDE.
295 void RegisterRequestCallback(std::string request, RequestCallback callback);
296
297 /// Debuggee will continue from stopped state.
298 void WillContinue() { variables.Clear(); }
299
300 /// Poll the process to wait for it to reach the eStateStopped state.
301 ///
302 /// Wait for the process hit a stopped state. When running a launch with
303 /// "launchCommands", or attach with "attachCommands", the calls might take
304 /// some time to stop at the entry point since the command is asynchronous. We
305 /// need to sync up with the process and make sure it is stopped before we
306 /// proceed to do anything else as we will soon be asked to set breakpoints
307 /// and other things that require the process to be stopped. We must use
308 /// polling because "attachCommands" or "launchCommands" may or may not send
309 /// process state change events depending on if the user modifies the async
310 /// setting in the debugger. Since both "attachCommands" and "launchCommands"
311 /// could end up using any combination of LLDB commands, we must ensure we can
312 /// also catch when the process stops, so we must poll the process to make
313 /// sure we handle all cases.
314 ///
315 /// \param[in] seconds
316 /// The number of seconds to poll the process to wait until it is stopped.
317 ///
318 /// \return Error if waiting for the process fails, no error if succeeds.
319 lldb::SBError WaitForProcessToStop(uint32_t seconds);
320
321 void SetFrameFormat(llvm::StringRef format);
322
323 void SetThreadFormat(llvm::StringRef format);
324
325private:
326 // Send the JSON in "json_str" to the "out" stream. Correctly send the
327 // "Content-Length:" field followed by the length, followed by the raw
328 // JSON bytes.
329 void SendJSON(const std::string &json_str);
330};
331
332extern DAP g_dap;
333
334} // namespace lldb_dap
335
336#endif
337

source code of lldb/tools/lldb-dap/DAP.h