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