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