aboutsummaryrefslogtreecommitdiff
path: root/lldb/include/lldb/Target/TraceCursor.h
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/include/lldb/Target/TraceCursor.h')
-rw-r--r--lldb/include/lldb/Target/TraceCursor.h211
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