xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-vscode/VSCode.h (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 //===-- VSCode.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_VSCODE_VSCODE_H
10 #define LLDB_TOOLS_LLDB_VSCODE_VSCODE_H
11 
12 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
13 
14 #include <condition_variable>
15 #include <cstdio>
16 #include <iosfwd>
17 #include <map>
18 #include <set>
19 #include <thread>
20 
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/DenseSet.h"
23 #include "llvm/ADT/StringMap.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Support/JSON.h"
26 #include "llvm/Support/raw_ostream.h"
27 
28 #include "lldb/API/SBAttachInfo.h"
29 #include "lldb/API/SBBreakpoint.h"
30 #include "lldb/API/SBBreakpointLocation.h"
31 #include "lldb/API/SBCommandInterpreter.h"
32 #include "lldb/API/SBCommandReturnObject.h"
33 #include "lldb/API/SBCommunication.h"
34 #include "lldb/API/SBDebugger.h"
35 #include "lldb/API/SBEvent.h"
36 #include "lldb/API/SBHostOS.h"
37 #include "lldb/API/SBInstruction.h"
38 #include "lldb/API/SBInstructionList.h"
39 #include "lldb/API/SBLanguageRuntime.h"
40 #include "lldb/API/SBLaunchInfo.h"
41 #include "lldb/API/SBLineEntry.h"
42 #include "lldb/API/SBListener.h"
43 #include "lldb/API/SBProcess.h"
44 #include "lldb/API/SBStream.h"
45 #include "lldb/API/SBStringList.h"
46 #include "lldb/API/SBTarget.h"
47 #include "lldb/API/SBThread.h"
48 
49 #include "ExceptionBreakpoint.h"
50 #include "FunctionBreakpoint.h"
51 #include "IOStream.h"
52 #include "ProgressEvent.h"
53 #include "RunInTerminal.h"
54 #include "SourceBreakpoint.h"
55 #include "SourceReference.h"
56 
57 #define VARREF_LOCALS (int64_t)1
58 #define VARREF_GLOBALS (int64_t)2
59 #define VARREF_REGS (int64_t)3
60 #define VARREF_FIRST_VAR_IDX (int64_t)4
61 #define VARREF_IS_SCOPE(v) (VARREF_LOCALS <= 1 && v < VARREF_FIRST_VAR_IDX)
62 #define VARIDX_TO_VARREF(i) ((i) + VARREF_FIRST_VAR_IDX)
63 #define VARREF_TO_VARIDX(v) ((v)-VARREF_FIRST_VAR_IDX)
64 #define NO_TYPENAME "<no-type>"
65 
66 namespace lldb_vscode {
67 
68 typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
69 typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
70 enum class OutputType { Console, Stdout, Stderr, Telemetry };
71 
72 enum VSCodeBroadcasterBits {
73   eBroadcastBitStopEventThread = 1u << 0,
74   eBroadcastBitStopProgressThread = 1u << 1
75 };
76 
77 typedef void (*RequestCallback)(const llvm::json::Object &command);
78 
79 enum class PacketStatus {
80   Success = 0,
81   EndOfFile,
82   JSONMalformed,
83   JSONNotObject
84 };
85 
86 struct VSCode {
87   std::string debug_adaptor_path;
88   InputStream input;
89   OutputStream output;
90   lldb::SBDebugger debugger;
91   lldb::SBTarget target;
92   lldb::SBValueList variables;
93   lldb::SBBroadcaster broadcaster;
94   int64_t num_regs;
95   int64_t num_locals;
96   int64_t num_globals;
97   std::thread event_thread;
98   std::thread progress_event_thread;
99   std::unique_ptr<std::ofstream> log;
100   llvm::DenseMap<lldb::addr_t, int64_t> addr_to_source_ref;
101   llvm::DenseMap<int64_t, SourceReference> source_map;
102   llvm::StringMap<SourceBreakpointMap> source_breakpoints;
103   FunctionBreakpointMap function_breakpoints;
104   std::vector<ExceptionBreakpoint> exception_breakpoints;
105   std::vector<std::string> init_commands;
106   std::vector<std::string> pre_run_commands;
107   std::vector<std::string> exit_commands;
108   std::vector<std::string> stop_commands;
109   std::vector<std::string> terminate_commands;
110   lldb::tid_t focus_tid;
111   bool sent_terminated_event;
112   bool stop_at_entry;
113   bool is_attach;
114   uint32_t reverse_request_seq;
115   std::map<std::string, RequestCallback> request_handlers;
116   bool waiting_for_run_in_terminal;
117   ProgressEventReporter progress_event_reporter;
118   // Keep track of the last stop thread index IDs as threads won't go away
119   // unless we send a "thread" event to indicate the thread exited.
120   llvm::DenseSet<lldb::tid_t> thread_ids;
121   VSCode();
122   ~VSCode();
123   VSCode(const VSCode &rhs) = delete;
124   void operator=(const VSCode &rhs) = delete;
125   int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const;
126   ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
127   ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
128 
129   // Serialize the JSON value into a string and send the JSON packet to
130   // the "out" stream.
131   void SendJSON(const llvm::json::Value &json);
132 
133   std::string ReadJSON();
134 
135   void SendOutput(OutputType o, const llvm::StringRef output);
136 
137   void SendProgressEvent(uint64_t progress_id, const char *message,
138                          uint64_t completed, uint64_t total);
139 
140   void __attribute__((format(printf, 3, 4)))
141   SendFormattedOutput(OutputType o, const char *format, ...);
142 
143   static int64_t GetNextSourceReference();
144 
145   ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
146 
147   lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
148 
149   lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
150 
151   llvm::json::Value CreateTopLevelScopes();
152 
153   void RunLLDBCommands(llvm::StringRef prefix,
154                        const std::vector<std::string> &commands);
155 
156   void RunInitCommands();
157   void RunPreRunCommands();
158   void RunStopCommands();
159   void RunExitCommands();
160   void RunTerminateCommands();
161 
162   /// Create a new SBTarget object from the given request arguments.
163   /// \param[in] arguments
164   ///     Launch configuration arguments.
165   ///
166   /// \param[out] error
167   ///     An SBError object that will contain an error description if
168   ///     function failed to create the target.
169   ///
170   /// \return
171   ///     An SBTarget object.
172   lldb::SBTarget CreateTargetFromArguments(const llvm::json::Object &arguments,
173                                            lldb::SBError &error);
174 
175   /// Set given target object as a current target for lldb-vscode and start
176   /// listeing for its breakpoint events.
177   void SetTarget(const lldb::SBTarget target);
178 
179   const std::map<std::string, RequestCallback> &GetRequestHandlers();
180 
181   PacketStatus GetNextObject(llvm::json::Object &object);
182   bool HandleObject(const llvm::json::Object &object);
183 
184   /// Send a Debug Adapter Protocol reverse request to the IDE
185   ///
186   /// \param[in] request
187   ///   The payload of the request to send.
188   ///
189   /// \param[out] response
190   ///   The response of the IDE. It might be undefined if there was an error.
191   ///
192   /// \return
193   ///   A \a PacketStatus object indicating the sucess or failure of the
194   ///   request.
195   PacketStatus SendReverseRequest(llvm::json::Object request,
196                                   llvm::json::Object &response);
197 
198   /// Registers a callback handler for a Debug Adapter Protocol request
199   ///
200   /// \param[in] request
201   ///     The name of the request following the Debug Adapter Protocol
202   ///     specification.
203   ///
204   /// \param[in] callback
205   ///     The callback to execute when the given request is triggered by the
206   ///     IDE.
207   void RegisterRequestCallback(std::string request, RequestCallback callback);
208 
209 private:
210   // Send the JSON in "json_str" to the "out" stream. Correctly send the
211   // "Content-Length:" field followed by the length, followed by the raw
212   // JSON bytes.
213   void SendJSON(const std::string &json_str);
214 };
215 
216 extern VSCode g_vsc;
217 
218 } // namespace lldb_vscode
219 
220 #endif
221