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