Skip to content

Commit f9b4ea0

Browse files
committed
[trace] Add SBTraceCursor bindings
Add bindings for the `TraceCursor` to allow for programatic traversal of traces. This diff adds bindings for all public `TraceCursor` methods except `GetHwClock` and also adds `SBTrace::CreateNewCursor`. A new unittest has been added to TestTraceLoad.py that uses the new `SBTraceCursor` API to test that the sequential and random access APIs of the `TraceCursor` are equivalent. This diff depends on D130925. Test Plan: `ninja lldb-dotest && ./bin/lldb-dotest -p TestTraceLoad` Differential Revision: https://reviews.llvm.org/D130930
1 parent 3dfa562 commit f9b4ea0

File tree

20 files changed

+548
-37
lines changed

20 files changed

+548
-37
lines changed

lldb/bindings/interface/SBTrace.i

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class LLDB_API SBTrace {
1515
public:
1616
SBTrace();
1717

18+
SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread);
19+
1820
const char *GetStartConfigurationHelp();
1921

2022
SBFileSpec SaveToDisk(SBError &error, const SBFileSpec &bundle_dir, bool compact = false);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===-- SWIG Interface for 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+
namespace lldb {
10+
11+
%feature("docstring",
12+
"Represents a trace cursor."
13+
) SBTrace;
14+
class LLDB_API SBTraceCursor {
15+
public:
16+
SBTraceCursor();
17+
18+
SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp);
19+
20+
void SetForwards(bool forwards);
21+
22+
bool IsForwards() const;
23+
24+
void Next();
25+
26+
bool HasValue();
27+
28+
bool GoToId(lldb::user_id_t id);
29+
30+
bool HasId(lldb::user_id_t id) const;
31+
32+
lldb::user_id_t GetId() const;
33+
34+
bool Seek(int64_t offset, lldb::TraceCursorSeekType origin);
35+
36+
lldb::TraceItemKind GetItemKind() const;
37+
38+
bool IsError() const;
39+
40+
const char *GetError() const;
41+
42+
bool IsEvent() const;
43+
44+
lldb::TraceEvent GetEventType() const;
45+
46+
const char *GetEventTypeAsString() const;
47+
48+
bool IsInstruction() const;
49+
50+
lldb::addr_t GetLoadAddress() const;
51+
52+
lldb::cpu_id_t GetCPU() const;
53+
54+
bool IsValid() const;
55+
56+
explicit operator bool() const;
57+
};
58+
} // namespace lldb

lldb/bindings/interfaces.swig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
%include "./interface/SBThreadCollection.i"
7070
%include "./interface/SBThreadPlan.i"
7171
%include "./interface/SBTrace.i"
72+
%include "./interface/SBTraceCursor.i"
7273
%include "./interface/SBType.i"
7374
%include "./interface/SBTypeCategory.i"
7475
%include "./interface/SBTypeEnumMember.i"

lldb/include/lldb/API/SBDefines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class LLDB_API SBThread;
8888
class LLDB_API SBThreadCollection;
8989
class LLDB_API SBThreadPlan;
9090
class LLDB_API SBTrace;
91+
class LLDB_API SBTraceCursor;
9192
class LLDB_API SBType;
9293
class LLDB_API SBTypeCategory;
9394
class LLDB_API SBTypeEnumMember;

lldb/include/lldb/API/SBTrace.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "lldb/API/SBDefines.h"
1313
#include "lldb/API/SBError.h"
14+
#include "lldb/API/SBTraceCursor.h"
1415

1516
namespace lldb {
1617

@@ -25,6 +26,20 @@ class LLDB_API SBTrace {
2526
static SBTrace LoadTraceFromFile(SBError &error, SBDebugger &debugger,
2627
const SBFileSpec &trace_description_file);
2728

29+
/// Get a \a TraceCursor for the given thread's trace.
30+
///
31+
/// \param[out] error
32+
/// This will be set with an error in case of failures.
33+
//
34+
/// \param[in] thread
35+
/// The thread to get a \a TraceCursor for.
36+
//
37+
/// \return
38+
/// A \a SBTraceCursor. If the thread is not traced or its trace
39+
/// information failed to load, an invalid \a SBTraceCursor is returned
40+
/// and the \p error parameter is set.
41+
SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread);
42+
2843
/// Save the trace to the specified directory, which will be created if
2944
/// needed. This will also create a a file \a <directory>/trace.json with the
3045
/// main properties of the trace session, along with others files which

lldb/include/lldb/API/SBTraceCursor.h

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

lldb/include/lldb/Target/TraceCursor.h

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,6 @@ namespace lldb_private {
9292
/// You can read more in the documentation of these methods.
9393
class TraceCursor {
9494
public:
95-
/// Helper enum to indicate the reference point when invoking
96-
/// \a TraceCursor::Seek().
97-
/// The following values are inspired by \a std::istream::seekg.
98-
enum class SeekType {
99-
/// The beginning of the trace, i.e the oldest item.
100-
Beginning = 0,
101-
/// The current position in the trace.
102-
Current,
103-
/// The end of the trace, i.e the most recent item.
104-
End
105-
};
106-
10795
/// Create a cursor that initially points to the end of the trace, i.e. the
10896
/// most recent item.
10997
TraceCursor(lldb::ThreadSP thread_sp);
@@ -208,7 +196,7 @@ class TraceCursor {
208196
///
209197
/// \return
210198
/// \b true if and only if the cursor ends up pointing to a valid item.
211-
virtual bool Seek(int64_t offset, SeekType origin) = 0;
199+
virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin) = 0;
212200

213201
/// \return
214202
/// The \a ExecutionContextRef of the backing thread from the creation time
@@ -235,8 +223,7 @@ class TraceCursor {
235223
bool IsEvent() const;
236224

237225
/// \return
238-
/// The specific kind of event the cursor is pointing at, or \b
239-
/// TraceEvent::eTraceEventNone if the cursor not pointing to an event.
226+
/// The specific kind of event the cursor is pointing at.
240227
virtual lldb::TraceEvent GetEventType() const = 0;
241228

242229
/// \return
@@ -261,9 +248,9 @@ class TraceCursor {
261248
/// whenever an eTraceEventCPUChanged event is fired.
262249
///
263250
/// \return
264-
/// The requested CPU id, or \a llvm::None if this information is
251+
/// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is
265252
/// not available for the current item.
266-
virtual llvm::Optional<lldb::cpu_id_t> GetCPU() const = 0;
253+
virtual lldb::cpu_id_t GetCPU() const = 0;
267254

268255
/// Get the last hardware clock value that was emitted before the current
269256
/// trace item.

lldb/include/lldb/lldb-defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#define LLDB_INVALID_LINE_NUMBER UINT32_MAX
8787
#define LLDB_INVALID_COLUMN_NUMBER 0
8888
#define LLDB_INVALID_QUEUE_ID 0
89+
#define LLDB_INVALID_CPU_ID UINT32_MAX
8990

9091
/// CPU Type definitions
9192
#define LLDB_ARCH_DEFAULT "systemArch"

lldb/include/lldb/lldb-enumerations.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,19 @@ enum TraceItemKind {
11791179
eTraceItemKindInstruction,
11801180
};
11811181

1182+
/// Enum to indicate the reference point when invoking
1183+
/// \a TraceCursor::Seek().
1184+
/// The following values are inspired by \a std::istream::seekg.
1185+
enum TraceCursorSeekType {
1186+
/// The beginning of the trace, i.e the oldest item.
1187+
eTraceCursorSeekTypeBeginning = 0,
1188+
/// The current position in the trace.
1189+
eTraceCursorSeekTypeCurrent,
1190+
/// The end of the trace, i.e the most recent item.
1191+
eTraceCursorSeekTypeEnd
1192+
};
1193+
1194+
11821195
} // namespace lldb
11831196

11841197
#endif // LLDB_LLDB_ENUMERATIONS_H

lldb/source/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
7272
SBThreadCollection.cpp
7373
SBThreadPlan.cpp
7474
SBTrace.cpp
75+
SBTraceCursor.cpp
7576
SBType.cpp
7677
SBTypeCategory.cpp
7778
SBTypeEnumMember.cpp

0 commit comments

Comments
 (0)