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 "llvm/Support/JSON.h"
13 
14 #include "lldb/Core/PluginInterface.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/UnimplementedError.h"
17 #include "lldb/lldb-private.h"
18 
19 namespace lldb_private {
20 
21 /// \class Trace Trace.h "lldb/Target/Trace.h"
22 /// A plug-in interface definition class for trace information.
23 ///
24 /// Trace plug-ins allow processor trace information to be loaded into LLDB so
25 /// that the data can be dumped, used for reverse and forward stepping to allow
26 /// introspection into the reason your process crashed or found its way to its
27 /// current state.
28 ///
29 /// Trace information can be loaded into a target without a process to allow
30 /// introspection of the trace information during post mortem analysis, such as
31 /// when loading core files.
32 ///
33 /// Processor trace information can also be fetched through the process
34 /// interfaces during a live debug session if your process supports gathering
35 /// this information.
36 ///
37 /// In order to support live tracing, the name of the plug-in should match the
38 /// name of the tracing type returned by the gdb-remote packet
39 /// \a jLLDBTraceSupportedType.
40 class Trace : public PluginInterface,
41               public std::enable_shared_from_this<Trace> {
42 public:
43   enum class TraceDirection {
44     Forwards = 0,
45     Backwards,
46   };
47 
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   FindPlugin(Debugger &debugger, const llvm::json::Value &trace_session_file,
98              llvm::StringRef session_file_dir);
99 
100   /// Get the schema of a Trace plug-in given its name.
101   ///
102   /// \param[in] plugin_name
103   ///     Name of the trace plugin.
104   static llvm::Expected<llvm::StringRef>
105   FindPluginSchema(llvm::StringRef plugin_name);
106 
107   /// \return
108   ///     The JSON schema of this Trace plug-in.
109   virtual llvm::StringRef GetSchema() = 0;
110 
111   /// Each decoded thread contains a cursor to the current position the user is
112   /// stopped at. When reverse debugging, each operation like reverse-next or
113   /// reverse-continue will move this cursor, which is then picked by any
114   /// subsequent dump or reverse operation.
115   ///
116   /// The initial position for this cursor is the last element of the thread,
117   /// which is the most recent chronologically.
118   ///
119   /// \return
120   ///     The current position of the thread's trace or \b 0 if empty.
121   virtual size_t GetCursorPosition(const Thread &thread) = 0;
122 
123   /// Dump \a count instructions of the given thread's trace ending at the
124   /// given \a end_position position.
125   ///
126   /// The instructions are printed along with their indices or positions, which
127   /// are increasing chronologically. This means that the \a index 0 represents
128   /// the oldest instruction of the trace chronologically.
129   ///
130   /// \param[in] thread
131   ///     The thread whose trace will be dumped.
132   ///
133   /// \param[in] s
134   ///     The stream object where the instructions are printed.
135   ///
136   /// \param[in] count
137   ///     The number of instructions to print.
138   ///
139   /// \param[in] end_position
140   ///     The position of the last instruction to print.
141   ///
142   /// \param[in] raw
143   ///     Dump only instruction addresses without disassembly nor symbol
144   ///     information.
145   void DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
146                              size_t end_position, bool raw);
147 
148   /// Run the provided callback on the instructions of the trace of the given
149   /// thread.
150   ///
151   /// The instructions will be traversed starting at the given \a position
152   /// sequentially until the callback returns \b false, in which case no more
153   /// instructions are inspected.
154   ///
155   /// The purpose of this method is to allow inspecting traced instructions
156   /// without exposing the internal representation of how they are stored on
157   /// memory.
158   ///
159   /// \param[in] thread
160   ///     The thread whose trace will be traversed.
161   ///
162   /// \param[in] position
163   ///     The instruction position to start iterating on.
164   ///
165   /// \param[in] direction
166   ///     If \b TraceDirection::Forwards, then then instructions will be
167   ///     traversed forwards chronologically, i.e. with incrementing indices. If
168   ///     \b TraceDirection::Backwards, the traversal is done backwards
169   ///     chronologically, i.e. with decrementing indices.
170   ///
171   /// \param[in] callback
172   ///     The callback to execute on each instruction. If it returns \b false,
173   ///     the iteration stops.
174   virtual void TraverseInstructions(
175       const Thread &thread, size_t position, TraceDirection direction,
176       std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
177           callback) = 0;
178 
179   /// Stop tracing a live thread
180   ///
181   /// \param[in] thread
182   ///     The thread object to stop tracing.
183   ///
184   /// \return
185   ///     An \a llvm::Error if stopping tracing failed, or \b
186   ///     llvm::Error::success() otherwise.
187   virtual llvm::Error StopTracingThread(const Thread &thread) {
188     return llvm::make_error<UnimplementedError>();
189   }
190 
191   /// Get the number of available instructions in the trace of the given thread.
192   ///
193   /// \param[in] thread
194   ///     The thread whose trace will be inspected.
195   ///
196   /// \return
197   ///     The total number of instructions in the trace.
198   virtual size_t GetInstructionCount(const Thread &thread) = 0;
199 };
200 
201 } // namespace lldb_private
202 
203 #endif // LLDB_TARGET_TRACE_H
204