1 //===-- TraceCursorIntelPT.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "TraceCursorIntelPT.h"
10 #include "DecodedThread.h"
11 #include "TraceIntelPT.h"
16 using namespace lldb_private
;
17 using namespace lldb_private::trace_intel_pt
;
20 TraceCursorIntelPT::TraceCursorIntelPT(
21 ThreadSP thread_sp
, DecodedThreadSP decoded_thread_sp
,
22 const std::optional
<LinuxPerfZeroTscConversion
> &tsc_conversion
,
23 std::optional
<uint64_t> beginning_of_time_nanos
)
24 : TraceCursor(thread_sp
), m_decoded_thread_sp(decoded_thread_sp
),
25 m_tsc_conversion(tsc_conversion
),
26 m_beginning_of_time_nanos(beginning_of_time_nanos
) {
27 Seek(0, lldb::eTraceCursorSeekTypeEnd
);
30 void TraceCursorIntelPT::Next() {
31 m_pos
+= IsForwards() ? 1 : -1;
32 ClearTimingRangesIfInvalid();
35 void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {
36 if (m_tsc_range_calculated
) {
37 if (!m_tsc_range
|| m_pos
< 0 || !m_tsc_range
->InRange(m_pos
)) {
39 m_tsc_range_calculated
= false;
43 if (m_nanoseconds_range_calculated
) {
44 if (!m_nanoseconds_range
|| m_pos
< 0 ||
45 !m_nanoseconds_range
->InRange(m_pos
)) {
46 m_nanoseconds_range
= None
;
47 m_nanoseconds_range_calculated
= false;
52 const std::optional
<DecodedThread::TSCRange
> &
53 TraceCursorIntelPT::GetTSCRange() const {
54 if (!m_tsc_range_calculated
) {
55 m_tsc_range_calculated
= true;
56 m_tsc_range
= m_decoded_thread_sp
->GetTSCRangeByIndex(m_pos
);
61 const std::optional
<DecodedThread::NanosecondsRange
> &
62 TraceCursorIntelPT::GetNanosecondsRange() const {
63 if (!m_nanoseconds_range_calculated
) {
64 m_nanoseconds_range_calculated
= true;
66 m_decoded_thread_sp
->GetNanosecondsRangeByIndex(m_pos
);
68 return m_nanoseconds_range
;
71 bool TraceCursorIntelPT::Seek(int64_t offset
,
72 lldb::TraceCursorSeekType origin
) {
74 case lldb::eTraceCursorSeekTypeBeginning
:
77 case lldb::eTraceCursorSeekTypeEnd
:
78 m_pos
= m_decoded_thread_sp
->GetItemsCount() - 1 + offset
;
80 case lldb::eTraceCursorSeekTypeCurrent
:
84 ClearTimingRangesIfInvalid();
89 bool TraceCursorIntelPT::HasValue() const {
91 static_cast<uint64_t>(m_pos
) < m_decoded_thread_sp
->GetItemsCount();
94 lldb::TraceItemKind
TraceCursorIntelPT::GetItemKind() const {
95 return m_decoded_thread_sp
->GetItemKindByIndex(m_pos
);
98 llvm::StringRef
TraceCursorIntelPT::GetError() const {
99 return m_decoded_thread_sp
->GetErrorByIndex(m_pos
);
102 lldb::addr_t
TraceCursorIntelPT::GetLoadAddress() const {
103 return m_decoded_thread_sp
->GetInstructionLoadAddress(m_pos
);
106 std::optional
<uint64_t> TraceCursorIntelPT::GetHWClock() const {
107 if (const std::optional
<DecodedThread::TSCRange
> &range
= GetTSCRange())
112 std::optional
<double> TraceCursorIntelPT::GetWallClockTime() const {
113 if (const std::optional
<DecodedThread::NanosecondsRange
> &range
=
114 GetNanosecondsRange())
115 return range
->GetInterpolatedTime(m_pos
, *m_beginning_of_time_nanos
,
120 lldb::cpu_id_t
TraceCursorIntelPT::GetCPU() const {
121 return m_decoded_thread_sp
->GetCPUByIndex(m_pos
);
124 lldb::TraceEvent
TraceCursorIntelPT::GetEventType() const {
125 return m_decoded_thread_sp
->GetEventByIndex(m_pos
);
128 bool TraceCursorIntelPT::GoToId(user_id_t id
) {
132 ClearTimingRangesIfInvalid();
136 bool TraceCursorIntelPT::HasId(lldb::user_id_t id
) const {
137 return id
< m_decoded_thread_sp
->GetItemsCount();
140 user_id_t
TraceCursorIntelPT::GetId() const { return m_pos
; }
142 std::optional
<std::string
> TraceCursorIntelPT::GetSyncPointMetadata() const {
143 return formatv("offset = 0x{0:x}",
144 m_decoded_thread_sp
->GetSyncPointOffsetByIndex(m_pos
))