diff options
Diffstat (limited to 'lldb/include/lldb/Target/TraceCursor.h')
-rw-r--r-- | lldb/include/lldb/Target/TraceCursor.h | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/lldb/include/lldb/Target/TraceCursor.h b/lldb/include/lldb/Target/TraceCursor.h new file mode 100644 index 000000000000..14fc00d5f95b --- /dev/null +++ b/lldb/include/lldb/Target/TraceCursor.h @@ -0,0 +1,211 @@ +//===-- TraceCursor.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_TRACE_CURSOR_H +#define LLDB_TARGET_TRACE_CURSOR_H + +#include "lldb/lldb-private.h" + +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +/// Class used for iterating over the instructions of a thread's trace. +/// +/// This class attempts to be a generic interface for accessing the instructions +/// of the trace so that each Trace plug-in can reconstruct, represent and store +/// the instruction data in an flexible way that is efficient for the given +/// technology. +/// +/// Live processes: +/// In the case of a live process trace, an instance of a \a TraceCursor should +/// point to the trace at the moment it was collected. If the process is later +/// resumed and new trace data is collected, that should leave that old cursor +/// unaffected. +/// +/// Errors in the trace: +/// As there could be errors when reconstructing the instructions of a trace, +/// these errors are represented as failed instructions, and the cursor can +/// point at them. The consumer should invoke \a TraceCursor::GetError() to +/// check if the cursor is pointing to either a valid instruction or an error. +/// +/// Instructions: +/// A \a TraceCursor always points to a specific instruction or error in the +/// trace. +/// +/// Defaults: +/// By default, the cursor points at the end item of the trace, moves +/// backwards, has a move granularity of \a +/// eTraceInstructionControlFlowTypeInstruction (i.e. visit every instruction) +/// and stops at every error (the "ignore errors" flag is \b false). See the +/// \a TraceCursor::Next() method for more documentation. +/// +/// Sample usage: +/// +/// TraceCursorUP cursor = trace.GetTrace(thread); +/// +/// cursor->SetGranularity(eTraceInstructionControlFlowTypeCall | +/// eTraceInstructionControlFlowTypeReturn); +/// +/// do { +/// if (llvm::Error error = cursor->GetError()) +/// cout << "error found at: " << llvm::toString(error) << endl; +/// else if (cursor->GetInstructionControlFlowType() & +/// eTraceInstructionControlFlowTypeCall) +/// std::cout << "call found at " << cursor->GetLoadAddress() << +/// std::endl; +/// else if (cursor->GetInstructionControlFlowType() & +/// eTraceInstructionControlFlowTypeReturn) +/// std::cout << "return found at " << cursor->GetLoadAddress() << +/// std::endl; +/// } while(cursor->Next()); +/// +/// Low level traversal: +/// Unlike the \a TraceCursor::Next() API, which uses a given granularity and +/// direction to advance the cursor, the \a TraceCursor::Seek() method can be +/// used to reposition the cursor to an offset of the end, beginning, or +/// current position of the trace. +class TraceCursor { +public: + /// Helper enum to indicate the reference point when invoking + /// \a TraceCursor::Seek(). + enum class SeekType { + /// The beginning of the trace, i.e the oldest item. + Set = 0, + /// The current position in the trace. + Current, + /// The end of the trace, i.e the most recent item. + End + }; + + /// Create a cursor that initially points to the end of the trace, i.e. the + /// most recent item. + TraceCursor(lldb::ThreadSP thread_sp); + + virtual ~TraceCursor() = default; + + /// Set the granularity to use in the \a TraceCursor::Next() method. + void SetGranularity(lldb::TraceInstructionControlFlowType granularity); + + /// Set the "ignore errors" flag to use in the \a TraceCursor::Next() method. + void SetIgnoreErrors(bool ignore_errors); + + /// Set the direction to use in the \a TraceCursor::Next() method. + /// + /// \param[in] forwards + /// If \b true, then the traversal will be forwards, otherwise backwards. + void SetForwards(bool forwards); + + /// Check if the direction to use in the \a TraceCursor::Next() method is + /// forwards. + /// + /// \return + /// \b true if the current direction is forwards, \b false if backwards. + bool IsForwards() const; + + /// Move the cursor to the next instruction that matches the current + /// granularity. + /// + /// Direction: + /// The traversal is done following the current direction of the trace. If + /// it is forwards, the instructions are visited forwards + /// chronologically. Otherwise, the traversal is done in + /// the opposite direction. By default, a cursor moves backwards unless + /// changed with \a TraceCursor::SetForwards(). + /// + /// Granularity: + /// The cursor will traverse the trace looking for the first instruction + /// that matches the current granularity. If there aren't any matching + /// instructions, the cursor won't move, to give the opportunity of + /// changing granularities. + /// + /// Ignore errors: + /// If the "ignore errors" flags is \b false, the traversal will stop as + /// soon as it finds an error in the trace and the cursor will point at + /// it. + /// + /// \return + /// \b true if the cursor effectively moved, \b false otherwise. + virtual bool Next() = 0; + + /// Make the cursor point to an item in the trace based on an origin point and + /// an offset. This API doesn't distinguishes instruction types nor errors in + /// the trace, unlike the \a TraceCursor::Next() method. + /// + /// The resulting position of the trace is + /// origin + offset + /// + /// If this resulting position would be out of bounds, it will be adjusted to + /// the last or first item in the trace correspondingly. + /// + /// \param[in] offset + /// How many items to move forwards (if positive) or backwards (if + /// negative) from the given origin point. + /// + /// \param[in] origin + /// The reference point to use when moving the cursor. + /// + /// \return + /// The number of trace items moved from the origin. + virtual size_t Seek(ssize_t offset, SeekType origin) = 0; + + /// \return + /// The \a ExecutionContextRef of the backing thread from the creation time + /// of this cursor. + ExecutionContextRef &GetExecutionContextRef(); + + /// Instruction or error information + /// \{ + + /// \return + /// Whether the cursor points to an error or not. + virtual bool IsError() = 0; + + /// Get the corresponding error message if the cursor points to an error in + /// the trace. + /// + /// \return + /// \b llvm::Error::success if the cursor is not pointing to an error in + /// the trace. Otherwise return an \a llvm::Error describing the issue. + virtual llvm::Error GetError() = 0; + + /// \return + /// The load address of the instruction the cursor is pointing at. If the + /// cursor points to an error in the trace, return \b + /// LLDB_INVALID_ADDRESS. + virtual lldb::addr_t GetLoadAddress() = 0; + + /// Get the timestamp counter associated with the current instruction. + /// Modern Intel, ARM and AMD processors support this counter. However, a + /// trace plugin might decide to use a different time unit instead of an + /// actual TSC. + /// + /// \return + /// The timestamp or \b llvm::None if not available. + virtual llvm::Optional<uint64_t> GetTimestampCounter() = 0; + + /// \return + /// The \a lldb::TraceInstructionControlFlowType categories the + /// instruction the cursor is pointing at falls into. If the cursor points + /// to an error in the trace, return \b 0. + virtual lldb::TraceInstructionControlFlowType + GetInstructionControlFlowType() = 0; + /// \} + +protected: + ExecutionContextRef m_exe_ctx_ref; + + lldb::TraceInstructionControlFlowType m_granularity = + lldb::eTraceInstructionControlFlowTypeInstruction; + bool m_ignore_errors = false; + bool m_forwards = false; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_TRACE_CURSOR_H |