1 //===-- Trace.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_TARGET_TRACE_H 10 #define LLDB_TARGET_TRACE_H 11 12 #include <unordered_map> 13 14 #include "llvm/Support/JSON.h" 15 16 #include "lldb/Core/PluginInterface.h" 17 #include "lldb/Target/Thread.h" 18 #include "lldb/Target/TraceCursor.h" 19 #include "lldb/Utility/ArchSpec.h" 20 #include "lldb/Utility/TraceGDBRemotePackets.h" 21 #include "lldb/Utility/UnimplementedError.h" 22 #include "lldb/lldb-private.h" 23 24 namespace lldb_private { 25 26 /// \class Trace Trace.h "lldb/Target/Trace.h" 27 /// A plug-in interface definition class for trace information. 28 /// 29 /// Trace plug-ins allow processor trace information to be loaded into LLDB so 30 /// that the data can be dumped, used for reverse and forward stepping to allow 31 /// introspection into the reason your process crashed or found its way to its 32 /// current state. 33 /// 34 /// Trace information can be loaded into a target without a process to allow 35 /// introspection of the trace information during post mortem analysis, such as 36 /// when loading core files. 37 /// 38 /// Processor trace information can also be fetched through the process 39 /// interfaces during a live debug session if your process supports gathering 40 /// this information. 41 /// 42 /// In order to support live tracing, the name of the plug-in should match the 43 /// name of the tracing type returned by the gdb-remote packet 44 /// \a jLLDBTraceSupported. 45 class Trace : public PluginInterface, 46 public std::enable_shared_from_this<Trace> { 47 public: 48 /// Dump the trace data that this plug-in has access to. 49 /// 50 /// This function will dump all of the trace data for all threads in a user 51 /// readable format. Options for dumping can be added as this API is iterated 52 /// on. 53 /// 54 /// \param[in] s 55 /// A stream object to dump the information to. 56 virtual void Dump(Stream *s) const = 0; 57 58 /// Find a trace plug-in using JSON data. 59 /// 60 /// When loading trace data from disk, the information for the trace data 61 /// can be contained in multiple files and require plug-in specific 62 /// information about the CPU. Using data like JSON provides an 63 /// easy way to specify all of the settings and information that we will need 64 /// to load trace data into LLDB. This structured data can include: 65 /// - The plug-in name (this allows a specific plug-in to be selected) 66 /// - Architecture or target triple 67 /// - one or more paths to the trace data file on disk 68 /// - core trace data 69 /// - thread events or related information 70 /// - shared library load information to use for this trace data that 71 /// allows a target to be created so the trace information can be 72 /// symbolicated so that the trace information can be displayed to the 73 /// user 74 /// - shared library path 75 /// - load address 76 /// - information on how to fetch the shared library 77 /// - path to locally cached file on disk 78 /// - URL to download the file 79 /// - Any information needed to load the trace file 80 /// - CPU information 81 /// - Custom plug-in information needed to decode the trace information 82 /// correctly. 83 /// 84 /// \param[in] debugger 85 /// The debugger instance where new Targets will be created as part of the 86 /// JSON data parsing. 87 /// 88 /// \param[in] trace_session_file 89 /// The contents of the trace session file describing the trace session. 90 /// See \a TraceSessionFileParser::BuildSchema for more information about 91 /// the schema of this JSON file. 92 /// 93 /// \param[in] session_file_dir 94 /// The path to the directory that contains the session file. It's used to 95 /// resolved relative paths in the session file. 96 static llvm::Expected<lldb::TraceSP> 97 FindPluginForPostMortemProcess(Debugger &debugger, 98 const llvm::json::Value &trace_session_file, 99 llvm::StringRef session_file_dir); 100 101 /// Find a trace plug-in to trace a live process. 102 /// 103 /// \param[in] plugin_name 104 /// Plug-in name to search. 105 /// 106 /// \param[in] process 107 /// Live process to trace. 108 /// 109 /// \return 110 /// A \a TraceSP instance, or an \a llvm::Error if the plug-in name 111 /// doesn't match any registered plug-ins or tracing couldn't be 112 /// started. 113 static llvm::Expected<lldb::TraceSP> 114 FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process); 115 116 /// Get the schema of a Trace plug-in given its name. 117 /// 118 /// \param[in] plugin_name 119 /// Name of the trace plugin. 120 static llvm::Expected<llvm::StringRef> 121 FindPluginSchema(llvm::StringRef plugin_name); 122 123 /// Get the command handle for the "process trace start" command. 124 virtual lldb::CommandObjectSP 125 GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0; 126 127 /// Get the command handle for the "thread trace start" command. 128 virtual lldb::CommandObjectSP 129 GetThreadTraceStartCommand(CommandInterpreter &interpreter) = 0; 130 131 /// \return 132 /// The JSON schema of this Trace plug-in. 133 virtual llvm::StringRef GetSchema() = 0; 134 135 /// Get a \a TraceCursor for the given thread's trace. 136 /// 137 /// \return 138 /// A \a TraceCursorUP. If the thread is not traced or its trace 139 /// information failed to load, the corresponding error is embedded in the 140 /// trace. 141 virtual lldb::TraceCursorUP GetCursor(Thread &thread) = 0; 142 143 /// Dump general info about a given thread's trace. Each Trace plug-in 144 /// decides which data to show. 145 /// 146 /// \param[in] thread 147 /// The thread that owns the trace in question. 148 /// 149 /// \param[in] s 150 /// The stream object where the info will be printed printed. 151 /// 152 /// \param[in] verbose 153 /// If \b true, print detailed info 154 /// If \b false, print compact info 155 virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) = 0; 156 157 /// Check if a thread is currently traced by this object. 158 /// 159 /// \param[in] thread 160 /// The thread in question. 161 /// 162 /// \return 163 /// \b true if the thread is traced by this instance, \b false otherwise. 164 virtual bool IsTraced(const Thread &thread) = 0; 165 166 /// \return 167 /// A description of the parameters to use for the \a Trace::Start method. 168 virtual const char *GetStartConfigurationHelp() = 0; 169 170 /// Start tracing a live process. 171 /// 172 /// \param[in] configuration 173 /// See \a SBTrace::Start(const lldb::SBStructuredData &) for more 174 /// information. 175 /// 176 /// \return 177 /// \a llvm::Error::success if the operation was successful, or 178 /// \a llvm::Error otherwise. 179 virtual llvm::Error Start( 180 StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 181 182 /// Start tracing live threads. 183 /// 184 /// \param[in] tids 185 /// Threads to trace. This method tries to trace as many threads as 186 /// possible. 187 /// 188 /// \param[in] configuration 189 /// See \a SBTrace::Start(const lldb::SBThread &, const 190 /// lldb::SBStructuredData &) for more information. 191 /// 192 /// \return 193 /// \a llvm::Error::success if the operation was successful, or 194 /// \a llvm::Error otherwise. 195 virtual llvm::Error Start( 196 llvm::ArrayRef<lldb::tid_t> tids, 197 StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 198 199 /// Stop tracing live threads. 200 /// 201 /// \param[in] tids 202 /// The threads to stop tracing on. 203 /// 204 /// \return 205 /// \a llvm::Error::success if the operation was successful, or 206 /// \a llvm::Error otherwise. 207 llvm::Error Stop(llvm::ArrayRef<lldb::tid_t> tids); 208 209 /// Stop tracing all current and future threads of a live process. 210 /// 211 /// \param[in] request 212 /// The information determining which threads or process to stop tracing. 213 /// 214 /// \return 215 /// \a llvm::Error::success if the operation was successful, or 216 /// \a llvm::Error otherwise. 217 llvm::Error Stop(); 218 219 /// Get the trace file of the given post mortem thread. 220 llvm::Expected<const FileSpec &> GetPostMortemTraceFile(lldb::tid_t tid); 221 222 /// \return 223 /// The stop ID of the live process being traced, or an invalid stop ID 224 /// if the trace is in an error or invalid state. 225 uint32_t GetStopID(); 226 227 protected: 228 /// Get binary data of a live thread given a data identifier. 229 /// 230 /// \param[in] tid 231 /// The thread whose data is requested. 232 /// 233 /// \param[in] kind 234 /// The kind of data requested. 235 /// 236 /// \return 237 /// A vector of bytes with the requested data, or an \a llvm::Error in 238 /// case of failures. 239 llvm::Expected<llvm::ArrayRef<uint8_t>> 240 GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind); 241 242 /// Get binary data of the current process given a data identifier. 243 /// 244 /// \param[in] kind 245 /// The kind of data requested. 246 /// 247 /// \return 248 /// A vector of bytes with the requested data, or an \a llvm::Error in 249 /// case of failures. 250 llvm::Expected<llvm::ArrayRef<uint8_t>> 251 GetLiveProcessBinaryData(llvm::StringRef kind); 252 253 /// Get the size of the data returned by \a GetLiveThreadBinaryData 254 llvm::Optional<size_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid, 255 llvm::StringRef kind); 256 257 /// Get the size of the data returned by \a GetLiveProcessBinaryData 258 llvm::Optional<size_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind); 259 /// Constructor for post mortem processes 260 Trace() = default; 261 262 /// Constructor for a live process Trace(Process & live_process)263 Trace(Process &live_process) : m_live_process(&live_process) {} 264 265 /// Start tracing a live process or its threads. 266 /// 267 /// \param[in] request 268 /// JSON object with the information necessary to start tracing. In the 269 /// case of gdb-remote processes, this JSON object should conform to the 270 /// jLLDBTraceStart packet. 271 /// 272 /// \return 273 /// \a llvm::Error::success if the operation was successful, or 274 /// \a llvm::Error otherwise. 275 llvm::Error Start(const llvm::json::Value &request); 276 277 /// Get the current tracing state of a live process and its threads. 278 /// 279 /// \return 280 /// A JSON object string with custom data depending on the trace 281 /// technology, or an \a llvm::Error in case of errors. 282 llvm::Expected<std::string> GetLiveProcessState(); 283 284 /// Method to be overriden by the plug-in to refresh its own state. 285 /// 286 /// This is invoked by RefreshLiveProcessState when a new state is found. 287 /// 288 /// \param[in] state 289 /// The jLLDBTraceGetState response. 290 virtual void 291 DoRefreshLiveProcessState(llvm::Expected<TraceGetStateResponse> state) = 0; 292 293 /// Method to be invoked by the plug-in to refresh the live process state. 294 /// 295 /// The result is cached through the same process stop. 296 void RefreshLiveProcessState(); 297 298 uint32_t m_stop_id = LLDB_INVALID_STOP_ID; 299 /// Process traced by this object if doing live tracing. Otherwise it's null. 300 Process *m_live_process = nullptr; 301 /// tid -> data kind -> size 302 std::map<lldb::tid_t, std::unordered_map<std::string, size_t>> 303 m_live_thread_data; 304 /// data kind -> size 305 std::unordered_map<std::string, size_t> m_live_process_data; 306 }; 307 308 } // namespace lldb_private 309 310 #endif // LLDB_TARGET_TRACE_H 311