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 <iosfwd> 13 #include <map> 14 #include <set> 15 #include <stdio.h> 16 #include <thread> 17 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/raw_ostream.h" 23 24 #include "lldb/API/SBAttachInfo.h" 25 #include "lldb/API/SBBreakpoint.h" 26 #include "lldb/API/SBBreakpointLocation.h" 27 #include "lldb/API/SBCommandInterpreter.h" 28 #include "lldb/API/SBCommandReturnObject.h" 29 #include "lldb/API/SBCommunication.h" 30 #include "lldb/API/SBDebugger.h" 31 #include "lldb/API/SBEvent.h" 32 #include "lldb/API/SBHostOS.h" 33 #include "lldb/API/SBInstruction.h" 34 #include "lldb/API/SBInstructionList.h" 35 #include "lldb/API/SBLanguageRuntime.h" 36 #include "lldb/API/SBLaunchInfo.h" 37 #include "lldb/API/SBLineEntry.h" 38 #include "lldb/API/SBListener.h" 39 #include "lldb/API/SBProcess.h" 40 #include "lldb/API/SBStream.h" 41 #include "lldb/API/SBStringList.h" 42 #include "lldb/API/SBTarget.h" 43 #include "lldb/API/SBThread.h" 44 45 #include "ExceptionBreakpoint.h" 46 #include "FunctionBreakpoint.h" 47 #include "IOStream.h" 48 #include "SourceBreakpoint.h" 49 #include "SourceReference.h" 50 51 #define VARREF_LOCALS (int64_t)1 52 #define VARREF_GLOBALS (int64_t)2 53 #define VARREF_REGS (int64_t)3 54 #define VARREF_FIRST_VAR_IDX (int64_t)4 55 #define VARREF_IS_SCOPE(v) (VARREF_LOCALS <= 1 && v < VARREF_FIRST_VAR_IDX) 56 #define VARIDX_TO_VARREF(i) ((i) + VARREF_FIRST_VAR_IDX) 57 #define VARREF_TO_VARIDX(v) ((v)-VARREF_FIRST_VAR_IDX) 58 #define NO_TYPENAME "<no-type>" 59 60 namespace lldb_vscode { 61 62 typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap; 63 typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap; 64 enum class OutputType { Console, Stdout, Stderr, Telemetry }; 65 66 enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 }; 67 68 struct VSCode { 69 InputStream input; 70 OutputStream output; 71 lldb::SBDebugger debugger; 72 lldb::SBTarget target; 73 lldb::SBValueList variables; 74 lldb::SBBroadcaster broadcaster; 75 int64_t num_regs; 76 int64_t num_locals; 77 int64_t num_globals; 78 std::thread event_thread; 79 std::unique_ptr<std::ofstream> log; 80 llvm::DenseMap<lldb::addr_t, int64_t> addr_to_source_ref; 81 llvm::DenseMap<int64_t, SourceReference> source_map; 82 llvm::StringMap<SourceBreakpointMap> source_breakpoints; 83 FunctionBreakpointMap function_breakpoints; 84 std::vector<ExceptionBreakpoint> exception_breakpoints; 85 std::vector<std::string> init_commands; 86 std::vector<std::string> pre_run_commands; 87 std::vector<std::string> exit_commands; 88 std::vector<std::string> stop_commands; 89 std::vector<std::string> terminate_commands; 90 lldb::tid_t focus_tid; 91 bool sent_terminated_event; 92 bool stop_at_entry; 93 bool is_attach; 94 // Keep track of the last stop thread index IDs as threads won't go away 95 // unless we send a "thread" event to indicate the thread exited. 96 llvm::DenseSet<lldb::tid_t> thread_ids; 97 VSCode(); 98 ~VSCode(); 99 VSCode(const VSCode &rhs) = delete; 100 void operator=(const VSCode &rhs) = delete; 101 int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const; 102 ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter); 103 ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id); 104 // Send the JSON in "json_str" to the "out" stream. Correctly send the 105 // "Content-Length:" field followed by the length, followed by the raw 106 // JSON bytes. 107 void SendJSON(const std::string &json_str); 108 109 // Serialize the JSON value into a string and send the JSON packet to 110 // the "out" stream. 111 void SendJSON(const llvm::json::Value &json); 112 113 std::string ReadJSON(); 114 115 void SendOutput(OutputType o, const llvm::StringRef output); 116 117 void __attribute__((format(printf, 3, 4))) 118 SendFormattedOutput(OutputType o, const char *format, ...); 119 120 static int64_t GetNextSourceReference(); 121 122 ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread); 123 124 lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments); 125 126 lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments); 127 128 llvm::json::Value CreateTopLevelScopes(); 129 130 void RunLLDBCommands(llvm::StringRef prefix, 131 const std::vector<std::string> &commands); 132 133 void RunInitCommands(); 134 void RunPreRunCommands(); 135 void RunStopCommands(); 136 void RunExitCommands(); 137 void RunTerminateCommands(); 138 139 /// Create a new SBTarget object from the given request arguments. 140 /// \param[in] arguments 141 /// Launch configuration arguments. 142 /// 143 /// \param[out] error 144 /// An SBError object that will contain an error description if 145 /// function failed to create the target. 146 /// 147 /// \return 148 /// An SBTarget object. 149 lldb::SBTarget CreateTargetFromArguments( 150 const llvm::json::Object &arguments, 151 lldb::SBError &error); 152 153 /// Set given target object as a current target for lldb-vscode and start 154 /// listeing for its breakpoint events. 155 void SetTarget(const lldb::SBTarget target); 156 }; 157 158 extern VSCode g_vsc; 159 160 } // namespace lldb_vscode 161 162 #endif 163