LLDB  mainline
TraceCursor.h
Go to the documentation of this file.
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 
15 
16 namespace lldb_private {
17 
18 /// Class used for iterating over the instructions of a thread's trace, among
19 /// other kinds of information.
20 ///
21 /// This class attempts to be a generic interface for accessing the instructions
22 /// of the trace so that each Trace plug-in can reconstruct, represent and store
23 /// the instruction data in an flexible way that is efficient for the given
24 /// technology.
25 ///
26 /// Live processes:
27 /// In the case of a live process trace, an instance of a \a TraceCursor
28 /// should point to the trace at the moment it was collected. If the process
29 /// is later resumed and new trace data is collected, then it's up to each
30 /// trace plug-in to decide whether to leave the old cursor unaffected or not.
31 ///
32 /// Cursor items:
33 /// A \a TraceCursor can point at one of the following items:
34 ///
35 /// Errors:
36 /// As there could be errors when reconstructing the instructions of a
37 /// trace, these errors are represented as failed instructions, and the
38 /// cursor can point at them.
39 ///
40 /// Events:
41 /// The cursor can also point at events in the trace, which aren't errors
42 /// nor instructions. An example of an event could be a context switch in
43 /// between two instructions.
44 ///
45 /// Instruction:
46 /// An actual instruction with a memory address.
47 ///
48 /// Defaults:
49 /// By default, the cursor points at the most recent item in the trace and is
50 /// set up to iterate backwards. See the \a TraceCursor::Next() method for
51 /// more documentation.
52 ///
53 /// Sample usage:
54 ///
55 /// TraceCursorSP cursor = trace.GetTrace(thread);
56 ///
57 /// for (; cursor->HasValue(); cursor->Next()) {
58 /// TraceItemKind kind = cursor->GetItemKind();
59 /// switch (cursor->GetItemKind()):
60 /// case eTraceItemKindError:
61 /// cout << "error found: " << cursor->GetError() << endl;
62 /// break;
63 /// case eTraceItemKindEvent:
64 /// cout << "event found: " << cursor->GetEventTypeAsString() << endl;
65 /// break;
66 /// case eTraceItemKindInstruction:
67 /// std::cout << "instructions found at " << cursor->GetLoadAddress() <<
68 /// std::endl; break;
69 /// }
70 /// }
71 ///
72 /// As the trace might be empty or the cursor might have reached the end of the
73 /// trace, you should always invoke \a HasValue() to make sure you don't access
74 /// invalid memory.
75 ///
76 /// Random accesses:
77 ///
78 /// The Trace Cursor offer random acesses in the trace via two APIs:
79 ///
80 /// TraceCursor::Seek():
81 /// Unlike the \a TraceCursor::Next() API, which moves instruction by
82 /// instruction, the \a TraceCursor::Seek() method can be used to
83 /// reposition the cursor to an offset of the end, beginning, or current
84 /// position of the trace.
85 ///
86 /// TraceCursor::GetId() / TraceCursor::SetId(id):
87 /// Each item (error or instruction) in the trace has a numeric identifier
88 /// which is defined by the trace plug-in. It's possible to access the id
89 /// of the current item using GetId(), and to reposition the cursor to a
90 /// given id using SetId(id).
91 ///
92 /// You can read more in the documentation of these methods.
93 class TraceCursor {
94 public:
95  /// Create a cursor that initially points to the end of the trace, i.e. the
96  /// most recent item.
97  TraceCursor(lldb::ThreadSP thread_sp);
98 
99  virtual ~TraceCursor() = default;
100 
101  /// Set the direction to use in the \a TraceCursor::Next() method.
102  ///
103  /// \param[in] forwards
104  /// If \b true, then the traversal will be forwards, otherwise backwards.
105  void SetForwards(bool forwards);
106 
107  /// Check if the direction to use in the \a TraceCursor::Next() method is
108  /// forwards.
109  ///
110  /// \return
111  /// \b true if the current direction is forwards, \b false if backwards.
112  bool IsForwards() const;
113 
114  /// Move the cursor to the next item (instruction or error).
115  ///
116  /// Direction:
117  /// The traversal is done following the current direction of the trace. If
118  /// it is forwards, the instructions are visited forwards
119  /// chronologically. Otherwise, the traversal is done in
120  /// the opposite direction. By default, a cursor moves backwards unless
121  /// changed with \a TraceCursor::SetForwards().
122  virtual void Next() = 0;
123 
124  /// \return
125  /// \b true if the cursor is pointing to a valid item. \b false if the
126  /// cursor has reached the end of the trace.
127  virtual bool HasValue() const = 0;
128 
129  /// Instruction identifiers:
130  ///
131  /// When building complex higher level tools, fast random accesses in the
132  /// trace might be needed, for which each instruction requires a unique
133  /// identifier within its thread trace. For example, a tool might want to
134  /// repeatedly inspect random consecutive portions of a trace. This means that
135  /// it will need to first move quickly to the beginning of each section and
136  /// then start its iteration. Given that the number of instructions can be in
137  /// the order of hundreds of millions, fast random access is necessary.
138  ///
139  /// An example of such a tool could be an inspector of the call graph of a
140  /// trace, where each call is represented with its start and end instructions.
141  /// Inspecting all the instructions of a call requires moving to its first
142  /// instruction and then iterating until the last instruction, which following
143  /// the pattern explained above.
144  ///
145  /// Instead of using 0-based indices as identifiers, each Trace plug-in can
146  /// decide the nature of these identifiers and thus no assumptions can be made
147  /// regarding their ordering and sequentiality. The reason is that an
148  /// instruction might be encoded by the plug-in in a way that hides its actual
149  /// 0-based index in the trace, but it's still possible to efficiently find
150  /// it.
151  ///
152  /// Requirements:
153  /// - For a given thread, no two instructions have the same id.
154  /// - In terms of efficiency, moving the cursor to a given id should be as
155  /// fast as possible, but not necessarily O(1). That's why the recommended
156  /// way to traverse sequential instructions is to use the \a
157  /// TraceCursor::Next() method and only use \a TraceCursor::GoToId(id)
158  /// sparingly.
159 
160  /// Make the cursor point to the item whose identifier is \p id.
161  ///
162  /// \return
163  /// \b true if the given identifier exists and the cursor effectively
164  /// moved to it. Otherwise, \b false is returned and the cursor now points
165  /// to an invalid item, i.e. calling \a HasValue() will return \b false.
166  virtual bool GoToId(lldb::user_id_t id) = 0;
167 
168  /// \return
169  /// \b true if and only if there's an instruction item with the given \p
170  /// id.
171  virtual bool HasId(lldb::user_id_t id) const = 0;
172 
173  /// \return
174  /// A unique identifier for the instruction or error this cursor is
175  /// pointing to.
176  virtual lldb::user_id_t GetId() const = 0;
177  /// \}
178 
179  /// Make the cursor point to an item in the trace based on an origin point and
180  /// an offset.
181  ///
182  /// The resulting position of the trace is
183  /// origin + offset
184  ///
185  /// If this resulting position would be out of bounds, the trace then points
186  /// to an invalid item, i.e. calling \a HasValue() returns \b false.
187  ///
188  /// \param[in] offset
189  /// How many items to move forwards (if positive) or backwards (if
190  /// negative) from the given origin point. For example, if origin is \b
191  /// End, then a negative offset would move backward in the trace, but a
192  /// positive offset would move past the trace to an invalid item.
193  ///
194  /// \param[in] origin
195  /// The reference point to use when moving the cursor.
196  ///
197  /// \return
198  /// \b true if and only if the cursor ends up pointing to a valid item.
199  virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin) = 0;
200 
201  /// \return
202  /// The \a ExecutionContextRef of the backing thread from the creation time
203  /// of this cursor.
205 
206  /// Trace item information (instructions, errors and events)
207  /// \{
208 
209  /// \return
210  /// The kind of item the cursor is pointing at.
211  virtual lldb::TraceItemKind GetItemKind() const = 0;
212 
213  /// \return
214  /// Whether the cursor points to an error or not.
215  bool IsError() const;
216 
217  /// \return
218  /// The error message the cursor is pointing at.
219  virtual const char *GetError() const = 0;
220 
221  /// \return
222  /// Whether the cursor points to an event or not.
223  bool IsEvent() const;
224 
225  /// \return
226  /// The specific kind of event the cursor is pointing at.
227  virtual lldb::TraceEvent GetEventType() const = 0;
228 
229  /// \return
230  /// A human-readable description of the event this cursor is pointing at.
231  const char *GetEventTypeAsString() const;
232 
233  /// \return
234  /// A human-readable description of the given event.
235  static const char *EventKindToString(lldb::TraceEvent event_kind);
236 
237  /// \return
238  /// Whether the cursor points to an instruction.
239  bool IsInstruction() const;
240 
241  /// \return
242  /// The load address of the instruction the cursor is pointing at.
243  virtual lldb::addr_t GetLoadAddress() const = 0;
244 
245  /// Get the CPU associated with the current trace item.
246  ///
247  /// This call might not be O(1), so it's suggested to invoke this method
248  /// whenever an eTraceEventCPUChanged event is fired.
249  ///
250  /// \return
251  /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is
252  /// not available for the current item.
253  virtual lldb::cpu_id_t GetCPU() const = 0;
254 
255  /// Get the last hardware clock value that was emitted before the current
256  /// trace item.
257  ///
258  /// This call might not be O(1), so it's suggested to invoke this method
259  /// whenever an eTraceEventHWClockTick event is fired.
260  ///
261  /// \return
262  /// The requested HW clock value, or \a llvm::None if this information is
263  /// not available for the current item.
264  virtual llvm::Optional<uint64_t> GetHWClock() const = 0;
265 
266  /// Get the approximate wall clock time in nanoseconds at which the current
267  /// trace item was executed. Each trace plug-in has a different definition for
268  /// what time 0 means.
269  ///
270  /// \return
271  /// The approximate wall clock time for the trace item, or \a llvm::None
272  /// if not available.
273  virtual llvm::Optional<double> GetWallClockTime() const = 0;
274 
275  /// Get some metadata associated with a synchronization point event. As
276  /// different trace technologies might have different values for this,
277  /// we return a string for flexibility.
278  ///
279  /// \return
280  /// A string representing some metadata associated with a
281  /// \a eTraceEventSyncPoint event. \b None if no metadata is available.
282  virtual llvm::Optional<std::string> GetSyncPointMetadata() const = 0;
283  /// \}
284 
285 protected:
287  bool m_forwards = false;
288 };
289 } // namespace lldb_private
290 
291 #endif // LLDB_TARGET_TRACE_CURSOR_H
lldb_private::TraceCursor::GoToId
virtual bool GoToId(lldb::user_id_t id)=0
Instruction identifiers:
lldb::TraceItemKind
TraceItemKind
Definition: lldb-enumerations.h:1179
lldb_private::TraceCursor::Seek
virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin)=0
Make the cursor point to an item in the trace based on an origin point and an offset.
lldb_private::TraceCursor::IsForwards
bool IsForwards() const
Check if the direction to use in the TraceCursor::Next() method is forwards.
Definition: TraceCursor.cpp:27
lldb_private::TraceCursor
Class used for iterating over the instructions of a thread's trace, among other kinds of information.
Definition: TraceCursor.h:93
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::TraceCursor::~TraceCursor
virtual ~TraceCursor()=default
lldb_private::TraceCursor::GetError
virtual const char * GetError() const =0
lldb::TraceEvent
TraceEvent
Events that might happen during a trace session.
Definition: lldb-enumerations.h:1163
lldb::TraceCursorSeekType
TraceCursorSeekType
Enum to indicate the reference point when invoking TraceCursor::Seek().
Definition: lldb-enumerations.h:1188
lldb_private::TraceCursor::m_forwards
bool m_forwards
Definition: TraceCursor.h:287
lldb_private::TraceCursor::GetCPU
virtual lldb::cpu_id_t GetCPU() const =0
Get the CPU associated with the current trace item.
lldb_private::TraceCursor::GetItemKind
virtual lldb::TraceItemKind GetItemKind() const =0
Trace item information (instructions, errors and events)
lldb-private.h
lldb_private::TraceCursor::GetSyncPointMetadata
virtual llvm::Optional< std::string > GetSyncPointMetadata() const =0
Get some metadata associated with a synchronization point event.
lldb_private::TraceCursor::GetId
virtual lldb::user_id_t GetId() const =0
lldb_private::TraceCursor::GetEventType
virtual lldb::TraceEvent GetEventType() const =0
lldb_private::TraceCursor::IsInstruction
bool IsInstruction() const
Definition: TraceCursor.cpp:37
uint32_t
lldb_private::TraceCursor::GetEventTypeAsString
const char * GetEventTypeAsString() const
Definition: TraceCursor.cpp:41
lldb_private::TraceCursor::GetHWClock
virtual llvm::Optional< uint64_t > GetHWClock() const =0
Get the last hardware clock value that was emitted before the current trace item.
lldb_private::TraceCursor::IsEvent
bool IsEvent() const
Definition: TraceCursor.cpp:33
lldb_private::TraceCursor::HasValue
virtual bool HasValue() const =0
lldb::user_id_t
uint64_t user_id_t
Definition: lldb-types.h:84
lldb_private::TraceCursor::m_exe_ctx_ref
ExecutionContextRef m_exe_ctx_ref
Definition: TraceCursor.h:286
lldb_private::TraceCursor::IsError
bool IsError() const
Definition: TraceCursor.cpp:29
lldb_private::TraceCursor::TraceCursor
TraceCursor(lldb::ThreadSP thread_sp)
Create a cursor that initially points to the end of the trace, i.e.
Definition: TraceCursor.cpp:18
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::TraceCursor::GetWallClockTime
virtual llvm::Optional< double > GetWallClockTime() const =0
Get the approximate wall clock time in nanoseconds at which the current trace item was executed.
lldb_private::TraceCursor::HasId
virtual bool HasId(lldb::user_id_t id) const =0
lldb_private::TraceCursor::GetLoadAddress
virtual lldb::addr_t GetLoadAddress() const =0
lldb_private::TraceCursor::EventKindToString
static const char * EventKindToString(lldb::TraceEvent event_kind)
Definition: TraceCursor.cpp:45
lldb_private::TraceCursor::Next
virtual void Next()=0
Move the cursor to the next item (instruction or error).
lldb_private::TraceCursor::SetForwards
void SetForwards(bool forwards)
Set the direction to use in the TraceCursor::Next() method.
Definition: TraceCursor.cpp:25
lldb_private::ExecutionContextRef
Execution context objects refer to objects in the execution of the program that is being debugged.
Definition: ExecutionContext.h:72
ExecutionContext.h
lldb_private::TraceCursor::GetExecutionContextRef
ExecutionContextRef & GetExecutionContextRef()
Definition: TraceCursor.cpp:21