1b0aa7076SWalter Erquinigo //===-- TraceCursorIntelPT.cpp --------------------------------------------===//
2b0aa7076SWalter Erquinigo //
3b0aa7076SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b0aa7076SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
5b0aa7076SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b0aa7076SWalter Erquinigo //
7b0aa7076SWalter Erquinigo //===----------------------------------------------------------------------===//
8b0aa7076SWalter Erquinigo
9b0aa7076SWalter Erquinigo #include "TraceCursorIntelPT.h"
10b0aa7076SWalter Erquinigo #include "DecodedThread.h"
11b0aa7076SWalter Erquinigo #include "TraceIntelPT.h"
12b0aa7076SWalter Erquinigo #include <cstdlib>
13f190ce62SKazu Hirata #include <optional>
14b0aa7076SWalter Erquinigo
15b0aa7076SWalter Erquinigo using namespace lldb;
16b0aa7076SWalter Erquinigo using namespace lldb_private;
17b0aa7076SWalter Erquinigo using namespace lldb_private::trace_intel_pt;
18b0aa7076SWalter Erquinigo using namespace llvm;
19b0aa7076SWalter Erquinigo
TraceCursorIntelPT(ThreadSP thread_sp,DecodedThreadSP decoded_thread_sp,const std::optional<LinuxPerfZeroTscConversion> & tsc_conversion,std::optional<uint64_t> beginning_of_time_nanos)204f676c25SWalter Erquinigo TraceCursorIntelPT::TraceCursorIntelPT(
214f676c25SWalter Erquinigo ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp,
222fe83274SKazu Hirata const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion,
232fe83274SKazu Hirata std::optional<uint64_t> beginning_of_time_nanos)
244f676c25SWalter Erquinigo : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp),
254f676c25SWalter Erquinigo m_tsc_conversion(tsc_conversion),
264f676c25SWalter Erquinigo m_beginning_of_time_nanos(beginning_of_time_nanos) {
27f9b4ea0cSJakob Johnson Seek(0, lldb::eTraceCursorSeekTypeEnd);
28b0aa7076SWalter Erquinigo }
29b0aa7076SWalter Erquinigo
Next()30f91d8281SWalter Erquinigo void TraceCursorIntelPT::Next() {
31b0aa7076SWalter Erquinigo m_pos += IsForwards() ? 1 : -1;
324f676c25SWalter Erquinigo ClearTimingRangesIfInvalid();
334f676c25SWalter Erquinigo }
34ca922a35SAlisamar Husain
ClearTimingRangesIfInvalid()354f676c25SWalter Erquinigo void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {
364f676c25SWalter Erquinigo if (m_tsc_range_calculated) {
374f676c25SWalter Erquinigo if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) {
38*a50ea2f7SNicholas Mosier m_tsc_range = std::nullopt;
394f676c25SWalter Erquinigo m_tsc_range_calculated = false;
404f676c25SWalter Erquinigo }
414f676c25SWalter Erquinigo }
42ca922a35SAlisamar Husain
434f676c25SWalter Erquinigo if (m_nanoseconds_range_calculated) {
444f676c25SWalter Erquinigo if (!m_nanoseconds_range || m_pos < 0 ||
454f676c25SWalter Erquinigo !m_nanoseconds_range->InRange(m_pos)) {
46*a50ea2f7SNicholas Mosier m_nanoseconds_range = std::nullopt;
474f676c25SWalter Erquinigo m_nanoseconds_range_calculated = false;
484f676c25SWalter Erquinigo }
494f676c25SWalter Erquinigo }
504f676c25SWalter Erquinigo }
514f676c25SWalter Erquinigo
522fe83274SKazu Hirata const std::optional<DecodedThread::TSCRange> &
GetTSCRange() const534f676c25SWalter Erquinigo TraceCursorIntelPT::GetTSCRange() const {
544f676c25SWalter Erquinigo if (!m_tsc_range_calculated) {
554f676c25SWalter Erquinigo m_tsc_range_calculated = true;
564f676c25SWalter Erquinigo m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos);
574f676c25SWalter Erquinigo }
584f676c25SWalter Erquinigo return m_tsc_range;
594f676c25SWalter Erquinigo }
604f676c25SWalter Erquinigo
612fe83274SKazu Hirata const std::optional<DecodedThread::NanosecondsRange> &
GetNanosecondsRange() const624f676c25SWalter Erquinigo TraceCursorIntelPT::GetNanosecondsRange() const {
634f676c25SWalter Erquinigo if (!m_nanoseconds_range_calculated) {
644f676c25SWalter Erquinigo m_nanoseconds_range_calculated = true;
654f676c25SWalter Erquinigo m_nanoseconds_range =
664f676c25SWalter Erquinigo m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos);
674f676c25SWalter Erquinigo }
684f676c25SWalter Erquinigo return m_nanoseconds_range;
69b0aa7076SWalter Erquinigo }
70b0aa7076SWalter Erquinigo
Seek(int64_t offset,lldb::TraceCursorSeekType origin)71f9b4ea0cSJakob Johnson bool TraceCursorIntelPT::Seek(int64_t offset,
72f9b4ea0cSJakob Johnson lldb::TraceCursorSeekType origin) {
73b0aa7076SWalter Erquinigo switch (origin) {
74f9b4ea0cSJakob Johnson case lldb::eTraceCursorSeekTypeBeginning:
75f91d8281SWalter Erquinigo m_pos = offset;
76f91d8281SWalter Erquinigo break;
77f9b4ea0cSJakob Johnson case lldb::eTraceCursorSeekTypeEnd:
78a7d6c3efSWalter Erquinigo m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset;
79f91d8281SWalter Erquinigo break;
80f9b4ea0cSJakob Johnson case lldb::eTraceCursorSeekTypeCurrent:
81f91d8281SWalter Erquinigo m_pos += offset;
82b0aa7076SWalter Erquinigo }
834f676c25SWalter Erquinigo
844f676c25SWalter Erquinigo ClearTimingRangesIfInvalid();
85ca922a35SAlisamar Husain
86f91d8281SWalter Erquinigo return HasValue();
87f91d8281SWalter Erquinigo }
88f91d8281SWalter Erquinigo
HasValue() const89f91d8281SWalter Erquinigo bool TraceCursorIntelPT::HasValue() const {
904f676c25SWalter Erquinigo return m_pos >= 0 &&
914f676c25SWalter Erquinigo static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount();
92b0aa7076SWalter Erquinigo }
93b0aa7076SWalter Erquinigo
GetItemKind() const94a7d6c3efSWalter Erquinigo lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const {
95a7d6c3efSWalter Erquinigo return m_decoded_thread_sp->GetItemKindByIndex(m_pos);
96b0aa7076SWalter Erquinigo }
97b0aa7076SWalter Erquinigo
GetError() const984bae7066SAlex Langford llvm::StringRef TraceCursorIntelPT::GetError() const {
99a7d6c3efSWalter Erquinigo return m_decoded_thread_sp->GetErrorByIndex(m_pos);
100b0aa7076SWalter Erquinigo }
101b0aa7076SWalter Erquinigo
GetLoadAddress() const102a7d6c3efSWalter Erquinigo lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const {
103d8499590SAlisamar Husain return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos);
104b0aa7076SWalter Erquinigo }
105b0aa7076SWalter Erquinigo
GetHWClock() const1061da3a795SFangrui Song std::optional<uint64_t> TraceCursorIntelPT::GetHWClock() const {
1072fe83274SKazu Hirata if (const std::optional<DecodedThread::TSCRange> &range = GetTSCRange())
1084f676c25SWalter Erquinigo return range->tsc;
109d920ab4aSKazu Hirata return std::nullopt;
11004195843SWalter Erquinigo }
1114f676c25SWalter Erquinigo
GetWallClockTime() const1122fe83274SKazu Hirata std::optional<double> TraceCursorIntelPT::GetWallClockTime() const {
1132fe83274SKazu Hirata if (const std::optional<DecodedThread::NanosecondsRange> &range =
1144f676c25SWalter Erquinigo GetNanosecondsRange())
1154f676c25SWalter Erquinigo return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos,
1164f676c25SWalter Erquinigo *m_tsc_conversion);
117d920ab4aSKazu Hirata return std::nullopt;
11822077627SJakob Johnson }
11904195843SWalter Erquinigo
GetCPU() const120f9b4ea0cSJakob Johnson lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const {
1214a843d92SWalter Erquinigo return m_decoded_thread_sp->GetCPUByIndex(m_pos);
1224a843d92SWalter Erquinigo }
1234a843d92SWalter Erquinigo
GetEventType() const124a7d6c3efSWalter Erquinigo lldb::TraceEvent TraceCursorIntelPT::GetEventType() const {
125a7d6c3efSWalter Erquinigo return m_decoded_thread_sp->GetEventByIndex(m_pos);
126b0aa7076SWalter Erquinigo }
12705b4bf25SWalter Erquinigo
GoToId(user_id_t id)12805b4bf25SWalter Erquinigo bool TraceCursorIntelPT::GoToId(user_id_t id) {
129efbfde0dSWalter Erquinigo if (!HasId(id))
13005b4bf25SWalter Erquinigo return false;
13105b4bf25SWalter Erquinigo m_pos = id;
1324f676c25SWalter Erquinigo ClearTimingRangesIfInvalid();
13305b4bf25SWalter Erquinigo return true;
13405b4bf25SWalter Erquinigo }
13505b4bf25SWalter Erquinigo
HasId(lldb::user_id_t id) const136efbfde0dSWalter Erquinigo bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const {
1374f676c25SWalter Erquinigo return id < m_decoded_thread_sp->GetItemsCount();
138efbfde0dSWalter Erquinigo }
139efbfde0dSWalter Erquinigo
GetId() const14005b4bf25SWalter Erquinigo user_id_t TraceCursorIntelPT::GetId() const { return m_pos; }
141e17cae07SWalter Erquinigo
GetSyncPointMetadata() const1421da3a795SFangrui Song std::optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const {
143e17cae07SWalter Erquinigo return formatv("offset = 0x{0:x}",
144e17cae07SWalter Erquinigo m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos))
145e17cae07SWalter Erquinigo .str();
146e17cae07SWalter Erquinigo }
147