1*e8d8bef9SDimitry Andric //===-- Trace.h -------------------------------------------------*- C++ -*-===// 2*e8d8bef9SDimitry Andric // 3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e8d8bef9SDimitry Andric // 7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8*e8d8bef9SDimitry Andric 9*e8d8bef9SDimitry Andric #ifndef LLDB_TARGET_TRACE_H 10*e8d8bef9SDimitry Andric #define LLDB_TARGET_TRACE_H 11*e8d8bef9SDimitry Andric 12*e8d8bef9SDimitry Andric #include "llvm/Support/JSON.h" 13*e8d8bef9SDimitry Andric 14*e8d8bef9SDimitry Andric #include "lldb/Core/PluginInterface.h" 15*e8d8bef9SDimitry Andric #include "lldb/Utility/ArchSpec.h" 16*e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h" 17*e8d8bef9SDimitry Andric #include "lldb/lldb-private.h" 18*e8d8bef9SDimitry Andric 19*e8d8bef9SDimitry Andric namespace lldb_private { 20*e8d8bef9SDimitry Andric 21*e8d8bef9SDimitry Andric /// \class Trace Trace.h "lldb/Target/Trace.h" 22*e8d8bef9SDimitry Andric /// A plug-in interface definition class for trace information. 23*e8d8bef9SDimitry Andric /// 24*e8d8bef9SDimitry Andric /// Trace plug-ins allow processor trace information to be loaded into LLDB so 25*e8d8bef9SDimitry Andric /// that the data can be dumped, used for reverse and forward stepping to allow 26*e8d8bef9SDimitry Andric /// introspection into the reason your process crashed or found its way to its 27*e8d8bef9SDimitry Andric /// current state. 28*e8d8bef9SDimitry Andric /// 29*e8d8bef9SDimitry Andric /// Trace information can be loaded into a target without a process to allow 30*e8d8bef9SDimitry Andric /// introspection of the trace information during post mortem analysis, such as 31*e8d8bef9SDimitry Andric /// when loading core files. 32*e8d8bef9SDimitry Andric /// 33*e8d8bef9SDimitry Andric /// Processor trace information can also be fetched through the process 34*e8d8bef9SDimitry Andric /// interfaces during a live debug session if your process supports gathering 35*e8d8bef9SDimitry Andric /// this information. 36*e8d8bef9SDimitry Andric /// 37*e8d8bef9SDimitry Andric /// In order to support live tracing, the name of the plug-in should match the 38*e8d8bef9SDimitry Andric /// name of the tracing type returned by the gdb-remote packet 39*e8d8bef9SDimitry Andric /// \a jLLDBTraceSupportedType. 40*e8d8bef9SDimitry Andric class Trace : public PluginInterface, 41*e8d8bef9SDimitry Andric public std::enable_shared_from_this<Trace> { 42*e8d8bef9SDimitry Andric public: 43*e8d8bef9SDimitry Andric enum class TraceDirection { 44*e8d8bef9SDimitry Andric Forwards = 0, 45*e8d8bef9SDimitry Andric Backwards, 46*e8d8bef9SDimitry Andric }; 47*e8d8bef9SDimitry Andric 48*e8d8bef9SDimitry Andric /// Dump the trace data that this plug-in has access to. 49*e8d8bef9SDimitry Andric /// 50*e8d8bef9SDimitry Andric /// This function will dump all of the trace data for all threads in a user 51*e8d8bef9SDimitry Andric /// readable format. Options for dumping can be added as this API is iterated 52*e8d8bef9SDimitry Andric /// on. 53*e8d8bef9SDimitry Andric /// 54*e8d8bef9SDimitry Andric /// \param[in] s 55*e8d8bef9SDimitry Andric /// A stream object to dump the information to. 56*e8d8bef9SDimitry Andric virtual void Dump(Stream *s) const = 0; 57*e8d8bef9SDimitry Andric 58*e8d8bef9SDimitry Andric /// Find a trace plug-in using JSON data. 59*e8d8bef9SDimitry Andric /// 60*e8d8bef9SDimitry Andric /// When loading trace data from disk, the information for the trace data 61*e8d8bef9SDimitry Andric /// can be contained in multiple files and require plug-in specific 62*e8d8bef9SDimitry Andric /// information about the CPU. Using data like JSON provides an 63*e8d8bef9SDimitry Andric /// easy way to specify all of the settings and information that we will need 64*e8d8bef9SDimitry Andric /// to load trace data into LLDB. This structured data can include: 65*e8d8bef9SDimitry Andric /// - The plug-in name (this allows a specific plug-in to be selected) 66*e8d8bef9SDimitry Andric /// - Architecture or target triple 67*e8d8bef9SDimitry Andric /// - one or more paths to the trace data file on disk 68*e8d8bef9SDimitry Andric /// - core trace data 69*e8d8bef9SDimitry Andric /// - thread events or related information 70*e8d8bef9SDimitry Andric /// - shared library load information to use for this trace data that 71*e8d8bef9SDimitry Andric /// allows a target to be created so the trace information can be 72*e8d8bef9SDimitry Andric /// symbolicated so that the trace information can be displayed to the 73*e8d8bef9SDimitry Andric /// user 74*e8d8bef9SDimitry Andric /// - shared library path 75*e8d8bef9SDimitry Andric /// - load address 76*e8d8bef9SDimitry Andric /// - information on how to fetch the shared library 77*e8d8bef9SDimitry Andric /// - path to locally cached file on disk 78*e8d8bef9SDimitry Andric /// - URL to download the file 79*e8d8bef9SDimitry Andric /// - Any information needed to load the trace file 80*e8d8bef9SDimitry Andric /// - CPU information 81*e8d8bef9SDimitry Andric /// - Custom plug-in information needed to decode the trace information 82*e8d8bef9SDimitry Andric /// correctly. 83*e8d8bef9SDimitry Andric /// 84*e8d8bef9SDimitry Andric /// \param[in] debugger 85*e8d8bef9SDimitry Andric /// The debugger instance where new Targets will be created as part of the 86*e8d8bef9SDimitry Andric /// JSON data parsing. 87*e8d8bef9SDimitry Andric /// 88*e8d8bef9SDimitry Andric /// \param[in] trace_session_file 89*e8d8bef9SDimitry Andric /// The contents of the trace session file describing the trace session. 90*e8d8bef9SDimitry Andric /// See \a TraceSessionFileParser::BuildSchema for more information about 91*e8d8bef9SDimitry Andric /// the schema of this JSON file. 92*e8d8bef9SDimitry Andric /// 93*e8d8bef9SDimitry Andric /// \param[in] session_file_dir 94*e8d8bef9SDimitry Andric /// The path to the directory that contains the session file. It's used to 95*e8d8bef9SDimitry Andric /// resolved relative paths in the session file. 96*e8d8bef9SDimitry Andric static llvm::Expected<lldb::TraceSP> 97*e8d8bef9SDimitry Andric FindPlugin(Debugger &debugger, const llvm::json::Value &trace_session_file, 98*e8d8bef9SDimitry Andric llvm::StringRef session_file_dir); 99*e8d8bef9SDimitry Andric 100*e8d8bef9SDimitry Andric /// Get the schema of a Trace plug-in given its name. 101*e8d8bef9SDimitry Andric /// 102*e8d8bef9SDimitry Andric /// \param[in] plugin_name 103*e8d8bef9SDimitry Andric /// Name of the trace plugin. 104*e8d8bef9SDimitry Andric static llvm::Expected<llvm::StringRef> 105*e8d8bef9SDimitry Andric FindPluginSchema(llvm::StringRef plugin_name); 106*e8d8bef9SDimitry Andric 107*e8d8bef9SDimitry Andric /// \return 108*e8d8bef9SDimitry Andric /// The JSON schema of this Trace plug-in. 109*e8d8bef9SDimitry Andric virtual llvm::StringRef GetSchema() = 0; 110*e8d8bef9SDimitry Andric 111*e8d8bef9SDimitry Andric /// Each decoded thread contains a cursor to the current position the user is 112*e8d8bef9SDimitry Andric /// stopped at. When reverse debugging, each operation like reverse-next or 113*e8d8bef9SDimitry Andric /// reverse-continue will move this cursor, which is then picked by any 114*e8d8bef9SDimitry Andric /// subsequent dump or reverse operation. 115*e8d8bef9SDimitry Andric /// 116*e8d8bef9SDimitry Andric /// The initial position for this cursor is the last element of the thread, 117*e8d8bef9SDimitry Andric /// which is the most recent chronologically. 118*e8d8bef9SDimitry Andric /// 119*e8d8bef9SDimitry Andric /// \return 120*e8d8bef9SDimitry Andric /// The current position of the thread's trace or \b 0 if empty. 121*e8d8bef9SDimitry Andric virtual size_t GetCursorPosition(const Thread &thread) = 0; 122*e8d8bef9SDimitry Andric 123*e8d8bef9SDimitry Andric /// Dump \a count instructions of the given thread's trace ending at the 124*e8d8bef9SDimitry Andric /// given \a end_position position. 125*e8d8bef9SDimitry Andric /// 126*e8d8bef9SDimitry Andric /// The instructions are printed along with their indices or positions, which 127*e8d8bef9SDimitry Andric /// are increasing chronologically. This means that the \a index 0 represents 128*e8d8bef9SDimitry Andric /// the oldest instruction of the trace chronologically. 129*e8d8bef9SDimitry Andric /// 130*e8d8bef9SDimitry Andric /// \param[in] thread 131*e8d8bef9SDimitry Andric /// The thread whose trace will be dumped. 132*e8d8bef9SDimitry Andric /// 133*e8d8bef9SDimitry Andric /// \param[in] s 134*e8d8bef9SDimitry Andric /// The stream object where the instructions are printed. 135*e8d8bef9SDimitry Andric /// 136*e8d8bef9SDimitry Andric /// \param[in] count 137*e8d8bef9SDimitry Andric /// The number of instructions to print. 138*e8d8bef9SDimitry Andric /// 139*e8d8bef9SDimitry Andric /// \param[in] end_position 140*e8d8bef9SDimitry Andric /// The position of the last instruction to print. 141*e8d8bef9SDimitry Andric /// 142*e8d8bef9SDimitry Andric /// \param[in] raw 143*e8d8bef9SDimitry Andric /// Dump only instruction addresses without disassembly nor symbol 144*e8d8bef9SDimitry Andric /// information. 145*e8d8bef9SDimitry Andric void DumpTraceInstructions(Thread &thread, Stream &s, size_t count, 146*e8d8bef9SDimitry Andric size_t end_position, bool raw); 147*e8d8bef9SDimitry Andric 148*e8d8bef9SDimitry Andric /// Run the provided callback on the instructions of the trace of the given 149*e8d8bef9SDimitry Andric /// thread. 150*e8d8bef9SDimitry Andric /// 151*e8d8bef9SDimitry Andric /// The instructions will be traversed starting at the given \a position 152*e8d8bef9SDimitry Andric /// sequentially until the callback returns \b false, in which case no more 153*e8d8bef9SDimitry Andric /// instructions are inspected. 154*e8d8bef9SDimitry Andric /// 155*e8d8bef9SDimitry Andric /// The purpose of this method is to allow inspecting traced instructions 156*e8d8bef9SDimitry Andric /// without exposing the internal representation of how they are stored on 157*e8d8bef9SDimitry Andric /// memory. 158*e8d8bef9SDimitry Andric /// 159*e8d8bef9SDimitry Andric /// \param[in] thread 160*e8d8bef9SDimitry Andric /// The thread whose trace will be traversed. 161*e8d8bef9SDimitry Andric /// 162*e8d8bef9SDimitry Andric /// \param[in] position 163*e8d8bef9SDimitry Andric /// The instruction position to start iterating on. 164*e8d8bef9SDimitry Andric /// 165*e8d8bef9SDimitry Andric /// \param[in] direction 166*e8d8bef9SDimitry Andric /// If \b TraceDirection::Forwards, then then instructions will be 167*e8d8bef9SDimitry Andric /// traversed forwards chronologically, i.e. with incrementing indices. If 168*e8d8bef9SDimitry Andric /// \b TraceDirection::Backwards, the traversal is done backwards 169*e8d8bef9SDimitry Andric /// chronologically, i.e. with decrementing indices. 170*e8d8bef9SDimitry Andric /// 171*e8d8bef9SDimitry Andric /// \param[in] callback 172*e8d8bef9SDimitry Andric /// The callback to execute on each instruction. If it returns \b false, 173*e8d8bef9SDimitry Andric /// the iteration stops. 174*e8d8bef9SDimitry Andric virtual void TraverseInstructions( 175*e8d8bef9SDimitry Andric const Thread &thread, size_t position, TraceDirection direction, 176*e8d8bef9SDimitry Andric std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)> 177*e8d8bef9SDimitry Andric callback) = 0; 178*e8d8bef9SDimitry Andric 179*e8d8bef9SDimitry Andric /// Stop tracing a live thread 180*e8d8bef9SDimitry Andric /// 181*e8d8bef9SDimitry Andric /// \param[in] thread 182*e8d8bef9SDimitry Andric /// The thread object to stop tracing. 183*e8d8bef9SDimitry Andric /// 184*e8d8bef9SDimitry Andric /// \return 185*e8d8bef9SDimitry Andric /// An \a llvm::Error if stopping tracing failed, or \b 186*e8d8bef9SDimitry Andric /// llvm::Error::success() otherwise. 187*e8d8bef9SDimitry Andric virtual llvm::Error StopTracingThread(const Thread &thread) { 188*e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 189*e8d8bef9SDimitry Andric } 190*e8d8bef9SDimitry Andric 191*e8d8bef9SDimitry Andric /// Get the number of available instructions in the trace of the given thread. 192*e8d8bef9SDimitry Andric /// 193*e8d8bef9SDimitry Andric /// \param[in] thread 194*e8d8bef9SDimitry Andric /// The thread whose trace will be inspected. 195*e8d8bef9SDimitry Andric /// 196*e8d8bef9SDimitry Andric /// \return 197*e8d8bef9SDimitry Andric /// The total number of instructions in the trace. 198*e8d8bef9SDimitry Andric virtual size_t GetInstructionCount(const Thread &thread) = 0; 199*e8d8bef9SDimitry Andric }; 200*e8d8bef9SDimitry Andric 201*e8d8bef9SDimitry Andric } // namespace lldb_private 202*e8d8bef9SDimitry Andric 203*e8d8bef9SDimitry Andric #endif // LLDB_TARGET_TRACE_H 204