1e8d8bef9SDimitry Andric //===-- Trace.h -------------------------------------------------*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #ifndef LLDB_TARGET_TRACE_H 10e8d8bef9SDimitry Andric #define LLDB_TARGET_TRACE_H 11e8d8bef9SDimitry Andric 12fe6060f1SDimitry Andric #include <unordered_map> 13fe6060f1SDimitry Andric 14e8d8bef9SDimitry Andric #include "llvm/Support/JSON.h" 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include "lldb/Core/PluginInterface.h" 17fe6060f1SDimitry Andric #include "lldb/Target/Thread.h" 18fe6060f1SDimitry Andric #include "lldb/Target/TraceCursor.h" 19e8d8bef9SDimitry Andric #include "lldb/Utility/ArchSpec.h" 20fe6060f1SDimitry Andric #include "lldb/Utility/TraceGDBRemotePackets.h" 21e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h" 22e8d8bef9SDimitry Andric #include "lldb/lldb-private.h" 23349cc55cSDimitry Andric #include "lldb/lldb-types.h" 24e8d8bef9SDimitry Andric 25e8d8bef9SDimitry Andric namespace lldb_private { 26e8d8bef9SDimitry Andric 27e8d8bef9SDimitry Andric /// \class Trace Trace.h "lldb/Target/Trace.h" 28e8d8bef9SDimitry Andric /// A plug-in interface definition class for trace information. 29e8d8bef9SDimitry Andric /// 30e8d8bef9SDimitry Andric /// Trace plug-ins allow processor trace information to be loaded into LLDB so 31e8d8bef9SDimitry Andric /// that the data can be dumped, used for reverse and forward stepping to allow 32e8d8bef9SDimitry Andric /// introspection into the reason your process crashed or found its way to its 33e8d8bef9SDimitry Andric /// current state. 34e8d8bef9SDimitry Andric /// 35e8d8bef9SDimitry Andric /// Trace information can be loaded into a target without a process to allow 36e8d8bef9SDimitry Andric /// introspection of the trace information during post mortem analysis, such as 37e8d8bef9SDimitry Andric /// when loading core files. 38e8d8bef9SDimitry Andric /// 39e8d8bef9SDimitry Andric /// Processor trace information can also be fetched through the process 40e8d8bef9SDimitry Andric /// interfaces during a live debug session if your process supports gathering 41e8d8bef9SDimitry Andric /// this information. 42e8d8bef9SDimitry Andric /// 43e8d8bef9SDimitry Andric /// In order to support live tracing, the name of the plug-in should match the 44e8d8bef9SDimitry Andric /// name of the tracing type returned by the gdb-remote packet 45fe6060f1SDimitry Andric /// \a jLLDBTraceSupported. 46e8d8bef9SDimitry Andric class Trace : public PluginInterface, 47e8d8bef9SDimitry Andric public std::enable_shared_from_this<Trace> { 48e8d8bef9SDimitry Andric public: 49e8d8bef9SDimitry Andric /// Dump the trace data that this plug-in has access to. 50e8d8bef9SDimitry Andric /// 51e8d8bef9SDimitry Andric /// This function will dump all of the trace data for all threads in a user 52e8d8bef9SDimitry Andric /// readable format. Options for dumping can be added as this API is iterated 53e8d8bef9SDimitry Andric /// on. 54e8d8bef9SDimitry Andric /// 55e8d8bef9SDimitry Andric /// \param[in] s 56e8d8bef9SDimitry Andric /// A stream object to dump the information to. 57e8d8bef9SDimitry Andric virtual void Dump(Stream *s) const = 0; 58e8d8bef9SDimitry Andric 59*753f127fSDimitry Andric /// Save the trace to the specified directory, which will be created if 60*753f127fSDimitry Andric /// needed. This will also create a a file \a <directory>/trace.json with the 61*753f127fSDimitry Andric /// main properties of the trace session, along with others files which 62*753f127fSDimitry Andric /// contain the actual trace data. The trace.json file can be used later as 63*753f127fSDimitry Andric /// input for the "trace load" command to load the trace in LLDB. 64349cc55cSDimitry Andric /// 65349cc55cSDimitry Andric /// \param[in] directory 66349cc55cSDimitry Andric /// The directory where the trace files will be saved. 67349cc55cSDimitry Andric /// 68*753f127fSDimitry Andric /// \param[in] compact 69*753f127fSDimitry Andric /// Try not to save to disk information irrelevant to the traced processes. 70*753f127fSDimitry Andric /// Each trace plug-in implements this in a different fashion. 71*753f127fSDimitry Andric /// 72349cc55cSDimitry Andric /// \return 73*753f127fSDimitry Andric /// A \a FileSpec pointing to the bundle description file, or an \a 74*753f127fSDimitry Andric /// llvm::Error otherwise. 75*753f127fSDimitry Andric virtual llvm::Expected<FileSpec> SaveToDisk(FileSpec directory, 76*753f127fSDimitry Andric bool compact) = 0; 77349cc55cSDimitry Andric 78e8d8bef9SDimitry Andric /// Find a trace plug-in using JSON data. 79e8d8bef9SDimitry Andric /// 80e8d8bef9SDimitry Andric /// When loading trace data from disk, the information for the trace data 81e8d8bef9SDimitry Andric /// can be contained in multiple files and require plug-in specific 82e8d8bef9SDimitry Andric /// information about the CPU. Using data like JSON provides an 83e8d8bef9SDimitry Andric /// easy way to specify all of the settings and information that we will need 84e8d8bef9SDimitry Andric /// to load trace data into LLDB. This structured data can include: 85e8d8bef9SDimitry Andric /// - The plug-in name (this allows a specific plug-in to be selected) 86e8d8bef9SDimitry Andric /// - Architecture or target triple 87e8d8bef9SDimitry Andric /// - one or more paths to the trace data file on disk 8881ad6265SDimitry Andric /// - cpu trace data 89e8d8bef9SDimitry Andric /// - thread events or related information 90e8d8bef9SDimitry Andric /// - shared library load information to use for this trace data that 91e8d8bef9SDimitry Andric /// allows a target to be created so the trace information can be 92e8d8bef9SDimitry Andric /// symbolicated so that the trace information can be displayed to the 93e8d8bef9SDimitry Andric /// user 94e8d8bef9SDimitry Andric /// - shared library path 95e8d8bef9SDimitry Andric /// - load address 96e8d8bef9SDimitry Andric /// - information on how to fetch the shared library 97e8d8bef9SDimitry Andric /// - path to locally cached file on disk 98e8d8bef9SDimitry Andric /// - URL to download the file 99e8d8bef9SDimitry Andric /// - Any information needed to load the trace file 100e8d8bef9SDimitry Andric /// - CPU information 101e8d8bef9SDimitry Andric /// - Custom plug-in information needed to decode the trace information 102e8d8bef9SDimitry Andric /// correctly. 103e8d8bef9SDimitry Andric /// 104e8d8bef9SDimitry Andric /// \param[in] debugger 105e8d8bef9SDimitry Andric /// The debugger instance where new Targets will be created as part of the 106e8d8bef9SDimitry Andric /// JSON data parsing. 107e8d8bef9SDimitry Andric /// 10881ad6265SDimitry Andric /// \param[in] bundle_description 10981ad6265SDimitry Andric /// The trace bundle description object describing the trace session. 110e8d8bef9SDimitry Andric /// 11181ad6265SDimitry Andric /// \param[in] bundle_dir 11281ad6265SDimitry Andric /// The path to the directory that contains the trace bundle. 113e8d8bef9SDimitry Andric static llvm::Expected<lldb::TraceSP> 114fe6060f1SDimitry Andric FindPluginForPostMortemProcess(Debugger &debugger, 11581ad6265SDimitry Andric const llvm::json::Value &bundle_description, 116e8d8bef9SDimitry Andric llvm::StringRef session_file_dir); 117e8d8bef9SDimitry Andric 118fe6060f1SDimitry Andric /// Find a trace plug-in to trace a live process. 119fe6060f1SDimitry Andric /// 120fe6060f1SDimitry Andric /// \param[in] plugin_name 121fe6060f1SDimitry Andric /// Plug-in name to search. 122fe6060f1SDimitry Andric /// 123fe6060f1SDimitry Andric /// \param[in] process 124fe6060f1SDimitry Andric /// Live process to trace. 125fe6060f1SDimitry Andric /// 126fe6060f1SDimitry Andric /// \return 127fe6060f1SDimitry Andric /// A \a TraceSP instance, or an \a llvm::Error if the plug-in name 128fe6060f1SDimitry Andric /// doesn't match any registered plug-ins or tracing couldn't be 129fe6060f1SDimitry Andric /// started. 130fe6060f1SDimitry Andric static llvm::Expected<lldb::TraceSP> 131fe6060f1SDimitry Andric FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process); 132fe6060f1SDimitry Andric 133e8d8bef9SDimitry Andric /// Get the schema of a Trace plug-in given its name. 134e8d8bef9SDimitry Andric /// 135e8d8bef9SDimitry Andric /// \param[in] plugin_name 136e8d8bef9SDimitry Andric /// Name of the trace plugin. 137e8d8bef9SDimitry Andric static llvm::Expected<llvm::StringRef> 138e8d8bef9SDimitry Andric FindPluginSchema(llvm::StringRef plugin_name); 139e8d8bef9SDimitry Andric 14081ad6265SDimitry Andric /// Load a trace from a trace description file and create Targets, 14181ad6265SDimitry Andric /// Processes and Threads based on the contents of such file. 14281ad6265SDimitry Andric /// 14381ad6265SDimitry Andric /// \param[in] debugger 14481ad6265SDimitry Andric /// The debugger instance where new Targets will be created as part of the 14581ad6265SDimitry Andric /// JSON data parsing. 14681ad6265SDimitry Andric /// 14781ad6265SDimitry Andric /// \param[in] trace_description_file 14881ad6265SDimitry Andric /// The file containing the necessary information to load the trace. 14981ad6265SDimitry Andric /// 15081ad6265SDimitry Andric /// \return 15181ad6265SDimitry Andric /// A \a TraceSP instance, or an \a llvm::Error if loading the trace 15281ad6265SDimitry Andric /// fails. 15381ad6265SDimitry Andric static llvm::Expected<lldb::TraceSP> 15481ad6265SDimitry Andric LoadPostMortemTraceFromFile(Debugger &debugger, 15581ad6265SDimitry Andric const FileSpec &trace_description_file); 15681ad6265SDimitry Andric 157fe6060f1SDimitry Andric /// Get the command handle for the "process trace start" command. 158fe6060f1SDimitry Andric virtual lldb::CommandObjectSP 159fe6060f1SDimitry Andric GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0; 160fe6060f1SDimitry Andric 161fe6060f1SDimitry Andric /// Get the command handle for the "thread trace start" command. 162fe6060f1SDimitry Andric virtual lldb::CommandObjectSP 163fe6060f1SDimitry Andric GetThreadTraceStartCommand(CommandInterpreter &interpreter) = 0; 164fe6060f1SDimitry Andric 165e8d8bef9SDimitry Andric /// \return 166e8d8bef9SDimitry Andric /// The JSON schema of this Trace plug-in. 167e8d8bef9SDimitry Andric virtual llvm::StringRef GetSchema() = 0; 168e8d8bef9SDimitry Andric 169fe6060f1SDimitry Andric /// Get a \a TraceCursor for the given thread's trace. 170e8d8bef9SDimitry Andric /// 171e8d8bef9SDimitry Andric /// \return 172fe6060f1SDimitry Andric /// A \a TraceCursorUP. If the thread is not traced or its trace 17381ad6265SDimitry Andric /// information failed to load, an \a llvm::Error is returned. 17481ad6265SDimitry Andric virtual llvm::Expected<lldb::TraceCursorUP> 17581ad6265SDimitry Andric CreateNewCursor(Thread &thread) = 0; 176e8d8bef9SDimitry Andric 177fe6060f1SDimitry Andric /// Dump general info about a given thread's trace. Each Trace plug-in 178fe6060f1SDimitry Andric /// decides which data to show. 179e8d8bef9SDimitry Andric /// 180e8d8bef9SDimitry Andric /// \param[in] thread 181fe6060f1SDimitry Andric /// The thread that owns the trace in question. 182e8d8bef9SDimitry Andric /// 183e8d8bef9SDimitry Andric /// \param[in] s 184fe6060f1SDimitry Andric /// The stream object where the info will be printed printed. 185e8d8bef9SDimitry Andric /// 186fe6060f1SDimitry Andric /// \param[in] verbose 187fe6060f1SDimitry Andric /// If \b true, print detailed info 188fe6060f1SDimitry Andric /// If \b false, print compact info 189*753f127fSDimitry Andric virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, 190*753f127fSDimitry Andric bool json) = 0; 191fe6060f1SDimitry Andric 192fe6060f1SDimitry Andric /// Check if a thread is currently traced by this object. 193e8d8bef9SDimitry Andric /// 194349cc55cSDimitry Andric /// \param[in] tid 195349cc55cSDimitry Andric /// The id of the thread in question. 196e8d8bef9SDimitry Andric /// 197fe6060f1SDimitry Andric /// \return 198fe6060f1SDimitry Andric /// \b true if the thread is traced by this instance, \b false otherwise. 199349cc55cSDimitry Andric virtual bool IsTraced(lldb::tid_t tid) = 0; 200fe6060f1SDimitry Andric 201fe6060f1SDimitry Andric /// \return 202fe6060f1SDimitry Andric /// A description of the parameters to use for the \a Trace::Start method. 203fe6060f1SDimitry Andric virtual const char *GetStartConfigurationHelp() = 0; 204fe6060f1SDimitry Andric 205fe6060f1SDimitry Andric /// Start tracing a live process. 206fe6060f1SDimitry Andric /// 207fe6060f1SDimitry Andric /// \param[in] configuration 208fe6060f1SDimitry Andric /// See \a SBTrace::Start(const lldb::SBStructuredData &) for more 209e8d8bef9SDimitry Andric /// information. 210e8d8bef9SDimitry Andric /// 211e8d8bef9SDimitry Andric /// \return 212fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 213fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 214fe6060f1SDimitry Andric virtual llvm::Error Start( 215fe6060f1SDimitry Andric StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 216e8d8bef9SDimitry Andric 217fe6060f1SDimitry Andric /// Start tracing live threads. 218e8d8bef9SDimitry Andric /// 219fe6060f1SDimitry Andric /// \param[in] tids 220fe6060f1SDimitry Andric /// Threads to trace. This method tries to trace as many threads as 221fe6060f1SDimitry Andric /// possible. 222fe6060f1SDimitry Andric /// 223fe6060f1SDimitry Andric /// \param[in] configuration 224fe6060f1SDimitry Andric /// See \a SBTrace::Start(const lldb::SBThread &, const 225fe6060f1SDimitry Andric /// lldb::SBStructuredData &) for more information. 226e8d8bef9SDimitry Andric /// 227e8d8bef9SDimitry Andric /// \return 228fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 229fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 230fe6060f1SDimitry Andric virtual llvm::Error Start( 231fe6060f1SDimitry Andric llvm::ArrayRef<lldb::tid_t> tids, 232fe6060f1SDimitry Andric StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 233fe6060f1SDimitry Andric 234fe6060f1SDimitry Andric /// Stop tracing live threads. 235fe6060f1SDimitry Andric /// 236fe6060f1SDimitry Andric /// \param[in] tids 237fe6060f1SDimitry Andric /// The threads to stop tracing on. 238fe6060f1SDimitry Andric /// 239fe6060f1SDimitry Andric /// \return 240fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 241fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 242fe6060f1SDimitry Andric llvm::Error Stop(llvm::ArrayRef<lldb::tid_t> tids); 243fe6060f1SDimitry Andric 244fe6060f1SDimitry Andric /// Stop tracing all current and future threads of a live process. 245fe6060f1SDimitry Andric /// 246fe6060f1SDimitry Andric /// \param[in] request 247fe6060f1SDimitry Andric /// The information determining which threads or process to stop tracing. 248fe6060f1SDimitry Andric /// 249fe6060f1SDimitry Andric /// \return 250fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 251fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 252fe6060f1SDimitry Andric llvm::Error Stop(); 253fe6060f1SDimitry Andric 254fe6060f1SDimitry Andric /// \return 255fe6060f1SDimitry Andric /// The stop ID of the live process being traced, or an invalid stop ID 256fe6060f1SDimitry Andric /// if the trace is in an error or invalid state. 257fe6060f1SDimitry Andric uint32_t GetStopID(); 258fe6060f1SDimitry Andric 25981ad6265SDimitry Andric using OnBinaryDataReadCallback = 26081ad6265SDimitry Andric std::function<llvm::Error(llvm::ArrayRef<uint8_t> data)>; 26181ad6265SDimitry Andric using OnCpusBinaryDataReadCallback = std::function<llvm::Error( 26281ad6265SDimitry Andric const llvm::DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> 26381ad6265SDimitry Andric &cpu_to_data)>; 26481ad6265SDimitry Andric 26581ad6265SDimitry Andric /// Fetch binary data associated with a thread, either live or postmortem, and 26681ad6265SDimitry Andric /// pass it to the given callback. The reason of having a callback is to free 26781ad6265SDimitry Andric /// the caller from having to manage the life cycle of the data and to hide 26881ad6265SDimitry Andric /// the different data fetching procedures that exist for live and post mortem 26981ad6265SDimitry Andric /// threads. 27081ad6265SDimitry Andric /// 27181ad6265SDimitry Andric /// The fetched data is not persisted after the callback is invoked. 27281ad6265SDimitry Andric /// 27381ad6265SDimitry Andric /// \param[in] tid 27481ad6265SDimitry Andric /// The tid who owns the data. 27581ad6265SDimitry Andric /// 27681ad6265SDimitry Andric /// \param[in] kind 27781ad6265SDimitry Andric /// The kind of data to read. 27881ad6265SDimitry Andric /// 27981ad6265SDimitry Andric /// \param[in] callback 28081ad6265SDimitry Andric /// The callback to be invoked once the data was successfully read. Its 28181ad6265SDimitry Andric /// return value, which is an \a llvm::Error, is returned by this 28281ad6265SDimitry Andric /// function. 28381ad6265SDimitry Andric /// 28481ad6265SDimitry Andric /// \return 28581ad6265SDimitry Andric /// An \a llvm::Error if the data couldn't be fetched, or the return value 28681ad6265SDimitry Andric /// of the callback, otherwise. 28781ad6265SDimitry Andric llvm::Error OnThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 28881ad6265SDimitry Andric OnBinaryDataReadCallback callback); 28981ad6265SDimitry Andric 29081ad6265SDimitry Andric /// Fetch binary data associated with a cpu, either live or postmortem, and 29181ad6265SDimitry Andric /// pass it to the given callback. The reason of having a callback is to free 29281ad6265SDimitry Andric /// the caller from having to manage the life cycle of the data and to hide 29381ad6265SDimitry Andric /// the different data fetching procedures that exist for live and post mortem 29481ad6265SDimitry Andric /// cpus. 29581ad6265SDimitry Andric /// 29681ad6265SDimitry Andric /// The fetched data is not persisted after the callback is invoked. 29781ad6265SDimitry Andric /// 29881ad6265SDimitry Andric /// \param[in] cpu_id 29981ad6265SDimitry Andric /// The cpu who owns the data. 30081ad6265SDimitry Andric /// 30181ad6265SDimitry Andric /// \param[in] kind 30281ad6265SDimitry Andric /// The kind of data to read. 30381ad6265SDimitry Andric /// 30481ad6265SDimitry Andric /// \param[in] callback 30581ad6265SDimitry Andric /// The callback to be invoked once the data was successfully read. Its 30681ad6265SDimitry Andric /// return value, which is an \a llvm::Error, is returned by this 30781ad6265SDimitry Andric /// function. 30881ad6265SDimitry Andric /// 30981ad6265SDimitry Andric /// \return 31081ad6265SDimitry Andric /// An \a llvm::Error if the data couldn't be fetched, or the return value 31181ad6265SDimitry Andric /// of the callback, otherwise. 31281ad6265SDimitry Andric llvm::Error OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id, llvm::StringRef kind, 31381ad6265SDimitry Andric OnBinaryDataReadCallback callback); 31481ad6265SDimitry Andric 31581ad6265SDimitry Andric /// Similar to \a OnCpuBinaryDataRead but this is able to fetch the same data 31681ad6265SDimitry Andric /// from all cpus at once. 31781ad6265SDimitry Andric llvm::Error OnAllCpusBinaryDataRead(llvm::StringRef kind, 31881ad6265SDimitry Andric OnCpusBinaryDataReadCallback callback); 31981ad6265SDimitry Andric 32081ad6265SDimitry Andric /// \return 32181ad6265SDimitry Andric /// All the currently traced processes. 32281ad6265SDimitry Andric std::vector<Process *> GetAllProcesses(); 32381ad6265SDimitry Andric 32481ad6265SDimitry Andric /// \return 32581ad6265SDimitry Andric /// The list of cpus being traced. Might be empty depending on the 32681ad6265SDimitry Andric /// plugin. 32781ad6265SDimitry Andric llvm::ArrayRef<lldb::cpu_id_t> GetTracedCpus(); 32881ad6265SDimitry Andric 32981ad6265SDimitry Andric /// Helper method for reading a data file and passing its data to the given 33081ad6265SDimitry Andric /// callback. 33181ad6265SDimitry Andric static llvm::Error OnDataFileRead(FileSpec file, 33281ad6265SDimitry Andric OnBinaryDataReadCallback callback); 33381ad6265SDimitry Andric 334fe6060f1SDimitry Andric protected: 33581ad6265SDimitry Andric /// Get the currently traced live process. 33681ad6265SDimitry Andric /// 33781ad6265SDimitry Andric /// \return 33881ad6265SDimitry Andric /// If it's not a live process, return \a nullptr. 33981ad6265SDimitry Andric Process *GetLiveProcess(); 34081ad6265SDimitry Andric 34181ad6265SDimitry Andric /// Get the currently traced postmortem processes. 34281ad6265SDimitry Andric /// 34381ad6265SDimitry Andric /// \return 34481ad6265SDimitry Andric /// If it's not a live process session, return an empty list. 34581ad6265SDimitry Andric llvm::ArrayRef<Process *> GetPostMortemProcesses(); 34681ad6265SDimitry Andric 34781ad6265SDimitry Andric /// Dispatcher for live trace data requests with some additional error 34881ad6265SDimitry Andric /// checking. 34981ad6265SDimitry Andric llvm::Expected<std::vector<uint8_t>> 35081ad6265SDimitry Andric GetLiveTraceBinaryData(const TraceGetBinaryDataRequest &request, 35181ad6265SDimitry Andric uint64_t expected_size); 35281ad6265SDimitry Andric 35381ad6265SDimitry Andric /// Implementation of \a OnThreadBinaryDataRead() for live threads. 35481ad6265SDimitry Andric llvm::Error OnLiveThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 35581ad6265SDimitry Andric OnBinaryDataReadCallback callback); 35681ad6265SDimitry Andric 35781ad6265SDimitry Andric /// Implementation of \a OnLiveBinaryDataRead() for live cpus. 35881ad6265SDimitry Andric llvm::Error OnLiveCpuBinaryDataRead(lldb::cpu_id_t cpu, llvm::StringRef kind, 35981ad6265SDimitry Andric OnBinaryDataReadCallback callback); 36081ad6265SDimitry Andric 36181ad6265SDimitry Andric /// Implementation of \a OnThreadBinaryDataRead() for post mortem threads. 36281ad6265SDimitry Andric llvm::Error 36381ad6265SDimitry Andric OnPostMortemThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 36481ad6265SDimitry Andric OnBinaryDataReadCallback callback); 36581ad6265SDimitry Andric 36681ad6265SDimitry Andric /// Implementation of \a OnCpuBinaryDataRead() for post mortem cpus. 36781ad6265SDimitry Andric llvm::Error OnPostMortemCpuBinaryDataRead(lldb::cpu_id_t cpu_id, 36881ad6265SDimitry Andric llvm::StringRef kind, 36981ad6265SDimitry Andric OnBinaryDataReadCallback callback); 37081ad6265SDimitry Andric 37181ad6265SDimitry Andric /// Get the file path containing data of a postmortem thread given a data 37281ad6265SDimitry Andric /// identifier. 37381ad6265SDimitry Andric /// 37481ad6265SDimitry Andric /// \param[in] tid 37581ad6265SDimitry Andric /// The thread whose data is requested. 37681ad6265SDimitry Andric /// 37781ad6265SDimitry Andric /// \param[in] kind 37881ad6265SDimitry Andric /// The kind of data requested. 37981ad6265SDimitry Andric /// 38081ad6265SDimitry Andric /// \return 38181ad6265SDimitry Andric /// The file spec containing the requested data, or an \a llvm::Error in 38281ad6265SDimitry Andric /// case of failures. 38381ad6265SDimitry Andric llvm::Expected<FileSpec> GetPostMortemThreadDataFile(lldb::tid_t tid, 38481ad6265SDimitry Andric llvm::StringRef kind); 38581ad6265SDimitry Andric 38681ad6265SDimitry Andric /// Get the file path containing data of a postmortem cpu given a data 38781ad6265SDimitry Andric /// identifier. 38881ad6265SDimitry Andric /// 38981ad6265SDimitry Andric /// \param[in] cpu_id 39081ad6265SDimitry Andric /// The cpu whose data is requested. 39181ad6265SDimitry Andric /// 39281ad6265SDimitry Andric /// \param[in] kind 39381ad6265SDimitry Andric /// The kind of data requested. 39481ad6265SDimitry Andric /// 39581ad6265SDimitry Andric /// \return 39681ad6265SDimitry Andric /// The file spec containing the requested data, or an \a llvm::Error in 39781ad6265SDimitry Andric /// case of failures. 39881ad6265SDimitry Andric llvm::Expected<FileSpec> GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, 39981ad6265SDimitry Andric llvm::StringRef kind); 40081ad6265SDimitry Andric 40181ad6265SDimitry Andric /// Associate a given thread with a data file using a data identifier. 40281ad6265SDimitry Andric /// 40381ad6265SDimitry Andric /// \param[in] tid 40481ad6265SDimitry Andric /// The thread associated with the data file. 40581ad6265SDimitry Andric /// 40681ad6265SDimitry Andric /// \param[in] kind 40781ad6265SDimitry Andric /// The kind of data being registered. 40881ad6265SDimitry Andric /// 40981ad6265SDimitry Andric /// \param[in] file_spec 41081ad6265SDimitry Andric /// The path of the data file. 41181ad6265SDimitry Andric void SetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind, 41281ad6265SDimitry Andric FileSpec file_spec); 41381ad6265SDimitry Andric 41481ad6265SDimitry Andric /// Associate a given cpu with a data file using a data identifier. 41581ad6265SDimitry Andric /// 41681ad6265SDimitry Andric /// \param[in] cpu_id 41781ad6265SDimitry Andric /// The cpu associated with the data file. 41881ad6265SDimitry Andric /// 41981ad6265SDimitry Andric /// \param[in] kind 42081ad6265SDimitry Andric /// The kind of data being registered. 42181ad6265SDimitry Andric /// 42281ad6265SDimitry Andric /// \param[in] file_spec 42381ad6265SDimitry Andric /// The path of the data file. 42481ad6265SDimitry Andric void SetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, llvm::StringRef kind, 42581ad6265SDimitry Andric FileSpec file_spec); 42681ad6265SDimitry Andric 427fe6060f1SDimitry Andric /// Get binary data of a live thread given a data identifier. 428fe6060f1SDimitry Andric /// 429fe6060f1SDimitry Andric /// \param[in] tid 430fe6060f1SDimitry Andric /// The thread whose data is requested. 431fe6060f1SDimitry Andric /// 432fe6060f1SDimitry Andric /// \param[in] kind 433fe6060f1SDimitry Andric /// The kind of data requested. 434fe6060f1SDimitry Andric /// 435fe6060f1SDimitry Andric /// \return 436fe6060f1SDimitry Andric /// A vector of bytes with the requested data, or an \a llvm::Error in 437fe6060f1SDimitry Andric /// case of failures. 43881ad6265SDimitry Andric llvm::Expected<std::vector<uint8_t>> 439fe6060f1SDimitry Andric GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind); 440fe6060f1SDimitry Andric 44181ad6265SDimitry Andric /// Get binary data of a live cpu given a data identifier. 44281ad6265SDimitry Andric /// 44381ad6265SDimitry Andric /// \param[in] cpu_id 44481ad6265SDimitry Andric /// The cpu whose data is requested. 44581ad6265SDimitry Andric /// 44681ad6265SDimitry Andric /// \param[in] kind 44781ad6265SDimitry Andric /// The kind of data requested. 44881ad6265SDimitry Andric /// 44981ad6265SDimitry Andric /// \return 45081ad6265SDimitry Andric /// A vector of bytes with the requested data, or an \a llvm::Error in 45181ad6265SDimitry Andric /// case of failures. 45281ad6265SDimitry Andric llvm::Expected<std::vector<uint8_t>> 45381ad6265SDimitry Andric GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind); 45481ad6265SDimitry Andric 455fe6060f1SDimitry Andric /// Get binary data of the current process given a data identifier. 456fe6060f1SDimitry Andric /// 457fe6060f1SDimitry Andric /// \param[in] kind 458fe6060f1SDimitry Andric /// The kind of data requested. 459fe6060f1SDimitry Andric /// 460fe6060f1SDimitry Andric /// \return 461fe6060f1SDimitry Andric /// A vector of bytes with the requested data, or an \a llvm::Error in 462fe6060f1SDimitry Andric /// case of failures. 46381ad6265SDimitry Andric llvm::Expected<std::vector<uint8_t>> 464fe6060f1SDimitry Andric GetLiveProcessBinaryData(llvm::StringRef kind); 465fe6060f1SDimitry Andric 466fe6060f1SDimitry Andric /// Get the size of the data returned by \a GetLiveThreadBinaryData 46781ad6265SDimitry Andric llvm::Optional<uint64_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid, 46881ad6265SDimitry Andric llvm::StringRef kind); 46981ad6265SDimitry Andric 47081ad6265SDimitry Andric /// Get the size of the data returned by \a GetLiveCpuBinaryData 47181ad6265SDimitry Andric llvm::Optional<uint64_t> GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, 472fe6060f1SDimitry Andric llvm::StringRef kind); 473fe6060f1SDimitry Andric 474fe6060f1SDimitry Andric /// Get the size of the data returned by \a GetLiveProcessBinaryData 47581ad6265SDimitry Andric llvm::Optional<uint64_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind); 47681ad6265SDimitry Andric 477fe6060f1SDimitry Andric /// Constructor for post mortem processes 47881ad6265SDimitry Andric Trace(llvm::ArrayRef<lldb::ProcessSP> postmortem_processes, 47981ad6265SDimitry Andric llvm::Optional<std::vector<lldb::cpu_id_t>> postmortem_cpus); 480fe6060f1SDimitry Andric 481fe6060f1SDimitry Andric /// Constructor for a live process 482fe6060f1SDimitry Andric Trace(Process &live_process) : m_live_process(&live_process) {} 483fe6060f1SDimitry Andric 484fe6060f1SDimitry Andric /// Start tracing a live process or its threads. 485fe6060f1SDimitry Andric /// 486fe6060f1SDimitry Andric /// \param[in] request 487fe6060f1SDimitry Andric /// JSON object with the information necessary to start tracing. In the 488fe6060f1SDimitry Andric /// case of gdb-remote processes, this JSON object should conform to the 489fe6060f1SDimitry Andric /// jLLDBTraceStart packet. 490fe6060f1SDimitry Andric /// 491fe6060f1SDimitry Andric /// \return 492fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 493fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 494fe6060f1SDimitry Andric llvm::Error Start(const llvm::json::Value &request); 495fe6060f1SDimitry Andric 496fe6060f1SDimitry Andric /// Get the current tracing state of a live process and its threads. 497fe6060f1SDimitry Andric /// 498fe6060f1SDimitry Andric /// \return 499fe6060f1SDimitry Andric /// A JSON object string with custom data depending on the trace 500fe6060f1SDimitry Andric /// technology, or an \a llvm::Error in case of errors. 501fe6060f1SDimitry Andric llvm::Expected<std::string> GetLiveProcessState(); 502fe6060f1SDimitry Andric 503fe6060f1SDimitry Andric /// Method to be overriden by the plug-in to refresh its own state. 504fe6060f1SDimitry Andric /// 505fe6060f1SDimitry Andric /// This is invoked by RefreshLiveProcessState when a new state is found. 506fe6060f1SDimitry Andric /// 507fe6060f1SDimitry Andric /// \param[in] state 508fe6060f1SDimitry Andric /// The jLLDBTraceGetState response. 509fe6060f1SDimitry Andric /// 51081ad6265SDimitry Andric /// \param[in] json_response 51181ad6265SDimitry Andric /// The original JSON response as a string. It might be useful to redecode 51281ad6265SDimitry Andric /// it if it contains custom data for a specific trace plug-in. 51381ad6265SDimitry Andric /// 51481ad6265SDimitry Andric /// \return 51581ad6265SDimitry Andric /// \b Error::success() if this operation succeedes, or an actual error 51681ad6265SDimitry Andric /// otherwise. 51781ad6265SDimitry Andric virtual llvm::Error 51881ad6265SDimitry Andric DoRefreshLiveProcessState(TraceGetStateResponse state, 51981ad6265SDimitry Andric llvm::StringRef json_response) = 0; 520fe6060f1SDimitry Andric 52181ad6265SDimitry Andric /// Return the list of processes traced by this instance. None of the returned 52281ad6265SDimitry Andric /// pointers are invalid. 52381ad6265SDimitry Andric std::vector<Process *> GetTracedProcesses(); 52481ad6265SDimitry Andric 52581ad6265SDimitry Andric /// Method to be invoked by the plug-in to refresh the live process state. It 52681ad6265SDimitry Andric /// will invoked DoRefreshLiveProcessState at some point, which should be 52781ad6265SDimitry Andric /// implemented by the plug-in for custom state handling. 52881ad6265SDimitry Andric /// 52981ad6265SDimitry Andric /// The result is cached through the same process stop. Even in the case of 53081ad6265SDimitry Andric /// errors, it caches the error. 53181ad6265SDimitry Andric /// 53281ad6265SDimitry Andric /// \return 53381ad6265SDimitry Andric /// An error message if this operation failed, or \b nullptr otherwise. 53481ad6265SDimitry Andric const char *RefreshLiveProcessState(); 53581ad6265SDimitry Andric 53681ad6265SDimitry Andric private: 537fe6060f1SDimitry Andric uint32_t m_stop_id = LLDB_INVALID_STOP_ID; 53881ad6265SDimitry Andric 539fe6060f1SDimitry Andric /// Process traced by this object if doing live tracing. Otherwise it's null. 540fe6060f1SDimitry Andric Process *m_live_process = nullptr; 54181ad6265SDimitry Andric 54281ad6265SDimitry Andric /// We package all the data that can change upon process stops to make sure 54381ad6265SDimitry Andric /// this contract is very visible. 54481ad6265SDimitry Andric /// This variable should only be accessed directly by constructores or live 54581ad6265SDimitry Andric /// process data refreshers. 54681ad6265SDimitry Andric struct Storage { 54781ad6265SDimitry Andric /// Portmortem processes traced by this object if doing non-live tracing. 54881ad6265SDimitry Andric /// Otherwise it's empty. 54981ad6265SDimitry Andric std::vector<Process *> postmortem_processes; 55081ad6265SDimitry Andric 55181ad6265SDimitry Andric /// These data kinds are returned by lldb-server when fetching the state of 55281ad6265SDimitry Andric /// the tracing session. The size in bytes can be used later for fetching 55381ad6265SDimitry Andric /// the data in batches. 55481ad6265SDimitry Andric /// \{ 55581ad6265SDimitry Andric 556fe6060f1SDimitry Andric /// tid -> data kind -> size 55781ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, llvm::DenseMap<ConstString, uint64_t>> 55881ad6265SDimitry Andric live_thread_data; 55981ad6265SDimitry Andric 56081ad6265SDimitry Andric /// cpu id -> data kind -> size 56181ad6265SDimitry Andric llvm::DenseMap<lldb::cpu_id_t, llvm::DenseMap<ConstString, uint64_t>> 56281ad6265SDimitry Andric live_cpu_data_sizes; 56381ad6265SDimitry Andric /// cpu id -> data kind -> bytes 56481ad6265SDimitry Andric llvm::DenseMap<lldb::cpu_id_t, 56581ad6265SDimitry Andric llvm::DenseMap<ConstString, std::vector<uint8_t>>> 56681ad6265SDimitry Andric live_cpu_data; 56781ad6265SDimitry Andric 568fe6060f1SDimitry Andric /// data kind -> size 56981ad6265SDimitry Andric llvm::DenseMap<ConstString, uint64_t> live_process_data; 57081ad6265SDimitry Andric /// \} 57181ad6265SDimitry Andric 57281ad6265SDimitry Andric /// The list of cpus being traced. Might be \b None depending on the 57381ad6265SDimitry Andric /// plug-in. 57481ad6265SDimitry Andric llvm::Optional<std::vector<lldb::cpu_id_t>> cpus; 57581ad6265SDimitry Andric 57681ad6265SDimitry Andric /// Postmortem traces can specific additional data files, which are 57781ad6265SDimitry Andric /// represented in this variable using a data kind identifier for each file. 57881ad6265SDimitry Andric /// \{ 57981ad6265SDimitry Andric 58081ad6265SDimitry Andric /// tid -> data kind -> file 58181ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, llvm::DenseMap<ConstString, FileSpec>> 58281ad6265SDimitry Andric postmortem_thread_data; 58381ad6265SDimitry Andric 58481ad6265SDimitry Andric /// cpu id -> data kind -> file 58581ad6265SDimitry Andric llvm::DenseMap<lldb::cpu_id_t, llvm::DenseMap<ConstString, FileSpec>> 58681ad6265SDimitry Andric postmortem_cpu_data; 58781ad6265SDimitry Andric 58881ad6265SDimitry Andric /// \} 58981ad6265SDimitry Andric 59081ad6265SDimitry Andric llvm::Optional<std::string> live_refresh_error; 59181ad6265SDimitry Andric } m_storage; 59281ad6265SDimitry Andric 59381ad6265SDimitry Andric /// Get the storage after refreshing the data in the case of a live process. 59481ad6265SDimitry Andric Storage &GetUpdatedStorage(); 595e8d8bef9SDimitry Andric }; 596e8d8bef9SDimitry Andric 597e8d8bef9SDimitry Andric } // namespace lldb_private 598e8d8bef9SDimitry Andric 599e8d8bef9SDimitry Andric #endif // LLDB_TARGET_TRACE_H 600