1 //===-- TraceCursor.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_CURSOR_H 10 #define LLDB_TARGET_TRACE_CURSOR_H 11 12 #include "lldb/lldb-private.h" 13 14 #include "lldb/Target/ExecutionContext.h" 15 16 namespace lldb_private { 17 18 /// Class used for iterating over the instructions of a thread's trace. 19 /// 20 /// This class attempts to be a generic interface for accessing the instructions 21 /// of the trace so that each Trace plug-in can reconstruct, represent and store 22 /// the instruction data in an flexible way that is efficient for the given 23 /// technology. 24 /// 25 /// Live processes: 26 /// In the case of a live process trace, an instance of a \a TraceCursor should 27 /// point to the trace at the moment it was collected. If the process is later 28 /// resumed and new trace data is collected, that should leave that old cursor 29 /// unaffected. 30 /// 31 /// Errors in the trace: 32 /// As there could be errors when reconstructing the instructions of a trace, 33 /// these errors are represented as failed instructions, and the cursor can 34 /// point at them. The consumer should invoke \a TraceCursor::GetError() to 35 /// check if the cursor is pointing to either a valid instruction or an error. 36 /// 37 /// Instructions: 38 /// A \a TraceCursor always points to a specific instruction or error in the 39 /// trace. 40 /// 41 /// Defaults: 42 /// By default, the cursor points at the end item of the trace, moves 43 /// backwards, has a move granularity of \a 44 /// eTraceInstructionControlFlowTypeInstruction (i.e. visit every instruction) 45 /// and stops at every error (the "ignore errors" flag is \b false). See the 46 /// \a TraceCursor::Next() method for more documentation. 47 /// 48 /// Sample usage: 49 /// 50 /// TraceCursorUP cursor = trace.GetTrace(thread); 51 /// 52 /// cursor->SetGranularity(eTraceInstructionControlFlowTypeCall | 53 /// eTraceInstructionControlFlowTypeReturn); 54 /// 55 /// do { 56 /// if (llvm::Error error = cursor->GetError()) 57 /// cout << "error found at: " << llvm::toString(error) << endl; 58 /// else if (cursor->GetInstructionControlFlowType() & 59 /// eTraceInstructionControlFlowTypeCall) 60 /// std::cout << "call found at " << cursor->GetLoadAddress() << 61 /// std::endl; 62 /// else if (cursor->GetInstructionControlFlowType() & 63 /// eTraceInstructionControlFlowTypeReturn) 64 /// std::cout << "return found at " << cursor->GetLoadAddress() << 65 /// std::endl; 66 /// } while(cursor->Next()); 67 /// 68 /// Low level traversal: 69 /// Unlike the \a TraceCursor::Next() API, which uses a given granularity and 70 /// direction to advance the cursor, the \a TraceCursor::Seek() method can be 71 /// used to reposition the cursor to an offset of the end, beginning, or 72 /// current position of the trace. 73 class TraceCursor { 74 public: 75 /// Helper enum to indicate the reference point when invoking 76 /// \a TraceCursor::Seek(). 77 enum class SeekType { 78 /// The beginning of the trace, i.e the oldest item. 79 Set = 0, 80 /// The current position in the trace. 81 Current, 82 /// The end of the trace, i.e the most recent item. 83 End 84 }; 85 86 /// Create a cursor that initially points to the end of the trace, i.e. the 87 /// most recent item. 88 TraceCursor(lldb::ThreadSP thread_sp); 89 90 virtual ~TraceCursor() = default; 91 92 /// Set the granularity to use in the \a TraceCursor::Next() method. 93 void SetGranularity(lldb::TraceInstructionControlFlowType granularity); 94 95 /// Set the "ignore errors" flag to use in the \a TraceCursor::Next() method. 96 void SetIgnoreErrors(bool ignore_errors); 97 98 /// Set the direction to use in the \a TraceCursor::Next() method. 99 /// 100 /// \param[in] forwards 101 /// If \b true, then the traversal will be forwards, otherwise backwards. 102 void SetForwards(bool forwards); 103 104 /// Check if the direction to use in the \a TraceCursor::Next() method is 105 /// forwards. 106 /// 107 /// \return 108 /// \b true if the current direction is forwards, \b false if backwards. 109 bool IsForwards() const; 110 111 /// Move the cursor to the next instruction that matches the current 112 /// granularity. 113 /// 114 /// Direction: 115 /// The traversal is done following the current direction of the trace. If 116 /// it is forwards, the instructions are visited forwards 117 /// chronologically. Otherwise, the traversal is done in 118 /// the opposite direction. By default, a cursor moves backwards unless 119 /// changed with \a TraceCursor::SetForwards(). 120 /// 121 /// Granularity: 122 /// The cursor will traverse the trace looking for the first instruction 123 /// that matches the current granularity. If there aren't any matching 124 /// instructions, the cursor won't move, to give the opportunity of 125 /// changing granularities. 126 /// 127 /// Ignore errors: 128 /// If the "ignore errors" flags is \b false, the traversal will stop as 129 /// soon as it finds an error in the trace and the cursor will point at 130 /// it. 131 /// 132 /// \return 133 /// \b true if the cursor effectively moved, \b false otherwise. 134 virtual bool Next() = 0; 135 136 /// Make the cursor point to an item in the trace based on an origin point and 137 /// an offset. This API doesn't distinguishes instruction types nor errors in 138 /// the trace, unlike the \a TraceCursor::Next() method. 139 /// 140 /// The resulting position of the trace is 141 /// origin + offset 142 /// 143 /// If this resulting position would be out of bounds, it will be adjusted to 144 /// the last or first item in the trace correspondingly. 145 /// 146 /// \param[in] offset 147 /// How many items to move forwards (if positive) or backwards (if 148 /// negative) from the given origin point. 149 /// 150 /// \param[in] origin 151 /// The reference point to use when moving the cursor. 152 /// 153 /// \return 154 /// The number of trace items moved from the origin. 155 virtual size_t Seek(ssize_t offset, SeekType origin) = 0; 156 157 /// \return 158 /// The \a ExecutionContextRef of the backing thread from the creation time 159 /// of this cursor. 160 ExecutionContextRef &GetExecutionContextRef(); 161 162 /// Instruction or error information 163 /// \{ 164 165 /// \return 166 /// Whether the cursor points to an error or not. 167 virtual bool IsError() = 0; 168 169 /// Get the corresponding error message if the cursor points to an error in 170 /// the trace. 171 /// 172 /// \return 173 /// \b llvm::Error::success if the cursor is not pointing to an error in 174 /// the trace. Otherwise return an \a llvm::Error describing the issue. 175 virtual llvm::Error GetError() = 0; 176 177 /// \return 178 /// The load address of the instruction the cursor is pointing at. If the 179 /// cursor points to an error in the trace, return \b 180 /// LLDB_INVALID_ADDRESS. 181 virtual lldb::addr_t GetLoadAddress() = 0; 182 183 /// Get the timestamp counter associated with the current instruction. 184 /// Modern Intel, ARM and AMD processors support this counter. However, a 185 /// trace plugin might decide to use a different time unit instead of an 186 /// actual TSC. 187 /// 188 /// \return 189 /// The timestamp or \b llvm::None if not available. 190 virtual llvm::Optional<uint64_t> GetTimestampCounter() = 0; 191 192 /// \return 193 /// The \a lldb::TraceInstructionControlFlowType categories the 194 /// instruction the cursor is pointing at falls into. If the cursor points 195 /// to an error in the trace, return \b 0. 196 virtual lldb::TraceInstructionControlFlowType 197 GetInstructionControlFlowType() = 0; 198 /// \} 199 200 protected: 201 ExecutionContextRef m_exe_ctx_ref; 202 203 lldb::TraceInstructionControlFlowType m_granularity = 204 lldb::eTraceInstructionControlFlowTypeInstruction; 205 bool m_ignore_errors = false; 206 bool m_forwards = false; 207 }; 208 209 } // namespace lldb_private 210 211 #endif // LLDB_TARGET_TRACE_CURSOR_H 212