wallace updated this revision to Diff 352872.
wallace marked 2 inline comments as done.
wallace added a comment.
Herald added a subscriber: mgorny.

address comments:

- now simply pointing to the last instruction of the trace by default
- removed the GetInstructionSize, as it's really not needed
- made sure that the target lldbCore builds correctly
- improved documentation
- some other small fixes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104422/new/

https://reviews.llvm.org/D104422

Files:
  lldb/include/lldb/Target/Trace.h
  lldb/include/lldb/Target/TraceCursor.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/include/lldb/lldb-forward.h
  lldb/source/Target/CMakeLists.txt
  lldb/source/Target/Trace.cpp
  lldb/source/Target/TraceCursor.cpp

Index: lldb/source/Target/TraceCursor.cpp
===================================================================
--- /dev/null
+++ lldb/source/Target/TraceCursor.cpp
@@ -0,0 +1,15 @@
+//===-- TraceCursor.cpp -----------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/TraceCursor.h"
+
+#include "lldb/Target/Trace.h"
+
+using namespace lldb_private;
+
+bool TraceCursor::IsStale() { return m_stop_id != m_trace_sp->GetStopID(); }
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -473,3 +473,8 @@
 
   DoRefreshLiveProcessState(std::move(live_process_state));
 }
+
+uint32_t Trace::GetStopID() {
+  RefreshLiveProcessState();
+  return m_stop_id;
+}
Index: lldb/source/Target/CMakeLists.txt
===================================================================
--- lldb/source/Target/CMakeLists.txt
+++ lldb/source/Target/CMakeLists.txt
@@ -68,6 +68,7 @@
   ThreadSpec.cpp
   ThreadPostMortemTrace.cpp
   Trace.cpp
+  TraceCursor.cpp
   TraceSessionFileParser.cpp
   UnixSignals.cpp
   UnwindAssembly.cpp
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -229,6 +229,7 @@
 class ThreadSpec;
 class ThreadPostMortemTrace;
 class Trace;
+class TraceCursor;
 class TraceSessionFileParser;
 class Type;
 class TypeAndOrName;
@@ -441,6 +442,7 @@
 typedef std::weak_ptr<lldb_private::ThreadPlan> ThreadPlanWP;
 typedef std::shared_ptr<lldb_private::ThreadPlanTracer> ThreadPlanTracerSP;
 typedef std::shared_ptr<lldb_private::Trace> TraceSP;
+typedef std::unique_ptr<lldb_private::TraceCursor> TraceCursorUP;
 typedef std::shared_ptr<lldb_private::Type> TypeSP;
 typedef std::weak_ptr<lldb_private::Type> TypeWP;
 typedef std::shared_ptr<lldb_private::TypeCategoryImpl> TypeCategoryImplSP;
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -958,6 +958,25 @@
   eExpressionEvaluationComplete
 };
 
+/// Architecture-agnostic categorization of instructions for traversing the
+/// control flow of a trace.
+///
+/// A single instruction can match one or more of these categories.
+FLAGS_ENUM(TraceInstructionControlFlowType){
+    /// Any instruction.
+    eTraceInstructionControlFlowTypeInstruction = (1u << 1),
+    /// A conditional or unconditional branch/jump.
+    eTraceInstructionControlFlowTypeBranch = (1u << 2),
+    /// A conditional or unconditional branch/jump that changed
+    /// the control flow of the program.
+    eTraceInstructionControlFlowTypeTakenBranch = (1u << 3),
+    /// A call to a function.
+    eTraceInstructionControlFlowTypeCall = (1u << 4),
+    /// A return from a function.
+    eTraceInstructionControlFlowTypeReturn = (1u << 5)};
+
+LLDB_MARK_AS_BITMASK_ENUM(TraceInstructionControlFlowType)
+
 /// Watchpoint Kind.
 ///
 /// Indicates what types of events cause the watchpoint to fire. Used by Native
Index: lldb/include/lldb/Target/TraceCursor.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Target/TraceCursor.h
@@ -0,0 +1,136 @@
+//===-- 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"
+
+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.
+///
+///  The Trace initially points to the last item in the trace.
+///
+/// Sample usage:
+///
+///  TraceCursorUP cursor = trace.GetTrace(thread);
+///
+///  auto granularity = 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->Prev(granularity));
+class TraceCursor {
+public:
+  virtual ~TraceCursor() = default;
+
+  /// Move the cursor to the next instruction more recent chronologically in the
+  /// trace given the provided granularity. If such instruction is not found,
+  /// the cursor doesn't move.
+  ///
+  /// \param[in] granularity
+  ///     Bitmask granularity filter. The cursor stops at the next
+  ///     instruction that matches the specified granularity.
+  ///
+  /// \param[in] ignore_errors
+  ///     If \b false, the cursor stops as soon as it finds a failure in the
+  ///     trace and points at it.
+  ///
+  /// \return
+  ///     \b true if the cursor moved, \b false otherwise.
+  virtual bool Next(lldb::TraceInstructionControlFlowType granularity =
+                        lldb::eTraceInstructionControlFlowTypeInstruction,
+                    bool ignore_errors = false) = 0;
+
+  /// Similar to \a TraceCursor::Next(), but moves backwards chronologically.
+  virtual bool Prev(lldb::TraceInstructionControlFlowType granularity =
+                        lldb::eTraceInstructionControlFlowTypeInstruction,
+                    bool ignore_errors = false) = 0;
+
+  /// Force the cursor to point to the end of the trace, i.e. the most recent
+  /// item.
+  virtual void SeekToEnd() = 0;
+
+  /// Force the cursor to point to the beginning of the trace, i.e. the oldest
+  /// item.
+  virtual void SeekToBegin() = 0;
+
+  /// \return
+  ///   \b true if the trace corresponds to a live process who has resumed after
+  ///   the trace cursor was created. Otherwise, including the case in which the
+  ///   process is a post-mortem one, return \b false.
+  bool IsStale();
+
+  /// Instruction or error information
+  /// \{
+
+  /// 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;
+
+  /// \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;
+
+  /// \}
+
+private:
+  /// The stop ID when the cursor was created.
+  uint32_t m_stop_id = 0;
+  /// The trace that owns this cursor.
+  lldb::TraceSP m_trace_sp;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_TRACE_CURSOR_H
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -15,6 +15,7 @@
 
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Target/TraceCursor.h"
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/TraceGDBRemotePackets.h"
 #include "lldb/Utility/UnimplementedError.h"
@@ -204,6 +205,14 @@
       std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
           callback) = 0;
 
+  /// Get a \a TraceCursor for the given thread's trace.
+  ///
+  /// \return
+  ///     A \a TraceCursorUP. If the thread is not traced or its trace
+  ///     information failed to load, the corresponding error is embedded in the
+  ///     trace.
+  virtual lldb::TraceCursorUP GetCursor(Thread &thread) = 0;
+
   /// Get the number of available instructions in the trace of the given thread.
   ///
   /// \param[in] thread
@@ -279,6 +288,11 @@
   /// Get the trace file of the given post mortem thread.
   llvm::Expected<const FileSpec &> GetPostMortemTraceFile(lldb::tid_t tid);
 
+  /// \return
+  ///     The stop ID of the live process being traced, or \b 0 if this is a
+  ///     post-mortem trace session.
+  uint32_t GetStopID();
+
 protected:
   /// Get binary data of a live thread given a data identifier.
   ///
@@ -350,8 +364,8 @@
   /// The result is cached through the same process stop.
   void RefreshLiveProcessState();
 
+  uint32_t m_stop_id = 0;
   /// Process traced by this object if doing live tracing. Otherwise it's null.
-  int64_t m_stop_id = -1;
   Process *m_live_process = nullptr;
   /// tid -> data kind -> size
   std::map<lldb::tid_t, std::unordered_map<std::string, size_t>>
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to