1 | //===-- SBTraceCursor.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_API_SBTRACECURSOR_H |
10 | #define LLDB_API_SBTRACECURSOR_H |
11 | |
12 | #include "lldb/API/SBDefines.h" |
13 | #include "lldb/API/SBError.h" |
14 | #include "lldb/API/SBExecutionContext.h" |
15 | |
16 | namespace lldb { |
17 | |
18 | class LLDB_API SBTraceCursor { |
19 | public: |
20 | /// Default constructor for an invalid \a SBTraceCursor object. |
21 | SBTraceCursor(); |
22 | |
23 | /// Set the direction to use in the \a SBTraceCursor::Next() method. |
24 | /// |
25 | /// \param[in] forwards |
26 | /// If \b true, then the traversal will be forwards, otherwise backwards. |
27 | void SetForwards(bool forwards); |
28 | |
29 | /// Check if the direction to use in the \a SBTraceCursor::Next() method is |
30 | /// forwards. |
31 | /// |
32 | /// \return |
33 | /// \b true if the current direction is forwards, \b false if backwards. |
34 | bool IsForwards() const; |
35 | |
36 | /// Move the cursor to the next item (instruction or error). |
37 | /// |
38 | /// Direction: |
39 | /// The traversal is done following the current direction of the trace. If |
40 | /// it is forwards, the instructions are visited forwards |
41 | /// chronologically. Otherwise, the traversal is done in |
42 | /// the opposite direction. By default, a cursor moves backwards unless |
43 | /// changed with \a SBTraceCursor::SetForwards(). |
44 | void Next(); |
45 | |
46 | /// \return |
47 | /// \b true if the cursor is pointing to a valid item. \b false if the |
48 | /// cursor has reached the end of the trace. |
49 | bool HasValue() const; |
50 | |
51 | /// Instruction identifiers: |
52 | /// |
53 | /// When building complex higher level tools, fast random accesses in the |
54 | /// trace might be needed, for which each instruction requires a unique |
55 | /// identifier within its thread trace. For example, a tool might want to |
56 | /// repeatedly inspect random consecutive portions of a trace. This means that |
57 | /// it will need to first move quickly to the beginning of each section and |
58 | /// then start its iteration. Given that the number of instructions can be in |
59 | /// the order of hundreds of millions, fast random access is necessary. |
60 | /// |
61 | /// An example of such a tool could be an inspector of the call graph of a |
62 | /// trace, where each call is represented with its start and end instructions. |
63 | /// Inspecting all the instructions of a call requires moving to its first |
64 | /// instruction and then iterating until the last instruction, which following |
65 | /// the pattern explained above. |
66 | /// |
67 | /// Instead of using 0-based indices as identifiers, each Trace plug-in can |
68 | /// decide the nature of these identifiers and thus no assumptions can be made |
69 | /// regarding their ordering and sequentiality. The reason is that an |
70 | /// instruction might be encoded by the plug-in in a way that hides its actual |
71 | /// 0-based index in the trace, but it's still possible to efficiently find |
72 | /// it. |
73 | /// |
74 | /// Requirements: |
75 | /// - For a given thread, no two instructions have the same id. |
76 | /// - In terms of efficiency, moving the cursor to a given id should be as |
77 | /// fast as possible, but not necessarily O(1). That's why the recommended |
78 | /// way to traverse sequential instructions is to use the \a |
79 | /// SBTraceCursor::Next() method and only use \a SBTraceCursor::GoToId(id) |
80 | /// sparingly. |
81 | |
82 | /// Make the cursor point to the item whose identifier is \p id. |
83 | /// |
84 | /// \return |
85 | /// \b true if the given identifier exists and the cursor effectively |
86 | /// moved to it. Otherwise, \b false is returned and the cursor now points |
87 | /// to an invalid item, i.e. calling \a HasValue() will return \b false. |
88 | bool GoToId(lldb::user_id_t id); |
89 | |
90 | /// \return |
91 | /// \b true if and only if there's an instruction item with the given \p |
92 | /// id. |
93 | bool HasId(lldb::user_id_t id) const; |
94 | |
95 | /// \return |
96 | /// A unique identifier for the instruction or error this cursor is |
97 | /// pointing to. |
98 | lldb::user_id_t GetId() const; |
99 | /// \} |
100 | |
101 | /// Make the cursor point to an item in the trace based on an origin point and |
102 | /// an offset. |
103 | /// |
104 | /// The resulting position of the trace is |
105 | /// origin + offset |
106 | /// |
107 | /// If this resulting position would be out of bounds, the trace then points |
108 | /// to an invalid item, i.e. calling \a HasValue() returns \b false. |
109 | /// |
110 | /// \param[in] offset |
111 | /// How many items to move forwards (if positive) or backwards (if |
112 | /// negative) from the given origin point. For example, if origin is \b |
113 | /// End, then a negative offset would move backward in the trace, but a |
114 | /// positive offset would move past the trace to an invalid item. |
115 | /// |
116 | /// \param[in] origin |
117 | /// The reference point to use when moving the cursor. |
118 | /// |
119 | /// \return |
120 | /// \b true if and only if the cursor ends up pointing to a valid item. |
121 | bool Seek(int64_t offset, lldb::TraceCursorSeekType origin); |
122 | |
123 | /// Trace item information (instructions, errors and events) |
124 | /// \{ |
125 | |
126 | /// \return |
127 | /// The kind of item the cursor is pointing at. |
128 | lldb::TraceItemKind GetItemKind() const; |
129 | |
130 | /// \return |
131 | /// Whether the cursor points to an error or not. |
132 | bool IsError() const; |
133 | |
134 | /// \return |
135 | /// The error message the cursor is pointing at. |
136 | const char *GetError() const; |
137 | |
138 | /// \return |
139 | /// Whether the cursor points to an event or not. |
140 | bool IsEvent() const; |
141 | |
142 | /// \return |
143 | /// The specific kind of event the cursor is pointing at. |
144 | lldb::TraceEvent GetEventType() const; |
145 | |
146 | /// \return |
147 | /// A human-readable description of the event this cursor is pointing at. |
148 | const char *GetEventTypeAsString() const; |
149 | |
150 | /// \return |
151 | /// Whether the cursor points to an instruction. |
152 | bool IsInstruction() const; |
153 | |
154 | /// \return |
155 | /// The load address of the instruction the cursor is pointing at. |
156 | lldb::addr_t GetLoadAddress() const; |
157 | |
158 | /// \return |
159 | /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is |
160 | /// not available for the current item. |
161 | lldb::cpu_id_t GetCPU() const; |
162 | |
163 | bool IsValid() const; |
164 | |
165 | explicit operator bool() const; |
166 | |
167 | protected: |
168 | friend class SBTrace; |
169 | |
170 | /// Create a cursor that initially points to the end of the trace, i.e. the |
171 | /// most recent item. |
172 | SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp); |
173 | |
174 | lldb::TraceCursorSP m_opaque_sp; |
175 | }; |
176 | } // namespace lldb |
177 | |
178 | #endif // LLDB_API_SBTRACECURSOR_H |
179 | |