xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp (revision 297eecfb02bb25902531dbb5c3b9a88caf8adf29)
1fe6060f1SDimitry Andric //===-- TraceCursorIntelPT.cpp --------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #include "TraceCursorIntelPT.h"
10fe6060f1SDimitry Andric #include "DecodedThread.h"
11fe6060f1SDimitry Andric #include "TraceIntelPT.h"
12fe6060f1SDimitry Andric #include <cstdlib>
13bdd1243dSDimitry Andric #include <optional>
14fe6060f1SDimitry Andric 
15fe6060f1SDimitry Andric using namespace lldb;
16fe6060f1SDimitry Andric using namespace lldb_private;
17fe6060f1SDimitry Andric using namespace lldb_private::trace_intel_pt;
18fe6060f1SDimitry Andric using namespace llvm;
19fe6060f1SDimitry Andric 
TraceCursorIntelPT(ThreadSP thread_sp,DecodedThreadSP decoded_thread_sp,const std::optional<LinuxPerfZeroTscConversion> & tsc_conversion,std::optional<uint64_t> beginning_of_time_nanos)20972a253aSDimitry Andric TraceCursorIntelPT::TraceCursorIntelPT(
21972a253aSDimitry Andric     ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp,
22bdd1243dSDimitry Andric     const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion,
23bdd1243dSDimitry Andric     std::optional<uint64_t> beginning_of_time_nanos)
24972a253aSDimitry Andric     : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp),
25972a253aSDimitry Andric       m_tsc_conversion(tsc_conversion),
26972a253aSDimitry Andric       m_beginning_of_time_nanos(beginning_of_time_nanos) {
27bdd1243dSDimitry Andric   Seek(0, lldb::eTraceCursorSeekTypeEnd);
28fe6060f1SDimitry Andric }
29fe6060f1SDimitry Andric 
Next()3081ad6265SDimitry Andric void TraceCursorIntelPT::Next() {
31fe6060f1SDimitry Andric   m_pos += IsForwards() ? 1 : -1;
32972a253aSDimitry Andric   ClearTimingRangesIfInvalid();
33972a253aSDimitry Andric }
3481ad6265SDimitry Andric 
ClearTimingRangesIfInvalid()35972a253aSDimitry Andric void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {
36972a253aSDimitry Andric   if (m_tsc_range_calculated) {
37972a253aSDimitry Andric     if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) {
38*297eecfbSDimitry Andric       m_tsc_range = std::nullopt;
39972a253aSDimitry Andric       m_tsc_range_calculated = false;
40972a253aSDimitry Andric     }
41972a253aSDimitry Andric   }
4281ad6265SDimitry Andric 
43972a253aSDimitry Andric   if (m_nanoseconds_range_calculated) {
44972a253aSDimitry Andric     if (!m_nanoseconds_range || m_pos < 0 ||
45972a253aSDimitry Andric         !m_nanoseconds_range->InRange(m_pos)) {
46*297eecfbSDimitry Andric       m_nanoseconds_range = std::nullopt;
47972a253aSDimitry Andric       m_nanoseconds_range_calculated = false;
48972a253aSDimitry Andric     }
49972a253aSDimitry Andric   }
50972a253aSDimitry Andric }
51972a253aSDimitry Andric 
52bdd1243dSDimitry Andric const std::optional<DecodedThread::TSCRange> &
GetTSCRange() const53972a253aSDimitry Andric TraceCursorIntelPT::GetTSCRange() const {
54972a253aSDimitry Andric   if (!m_tsc_range_calculated) {
55972a253aSDimitry Andric     m_tsc_range_calculated = true;
56972a253aSDimitry Andric     m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos);
57972a253aSDimitry Andric   }
58972a253aSDimitry Andric   return m_tsc_range;
59972a253aSDimitry Andric }
60972a253aSDimitry Andric 
61bdd1243dSDimitry Andric const std::optional<DecodedThread::NanosecondsRange> &
GetNanosecondsRange() const62972a253aSDimitry Andric TraceCursorIntelPT::GetNanosecondsRange() const {
63972a253aSDimitry Andric   if (!m_nanoseconds_range_calculated) {
64972a253aSDimitry Andric     m_nanoseconds_range_calculated = true;
65972a253aSDimitry Andric     m_nanoseconds_range =
66972a253aSDimitry Andric         m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos);
67972a253aSDimitry Andric   }
68972a253aSDimitry Andric   return m_nanoseconds_range;
69fe6060f1SDimitry Andric }
70fe6060f1SDimitry Andric 
Seek(int64_t offset,lldb::TraceCursorSeekType origin)71bdd1243dSDimitry Andric bool TraceCursorIntelPT::Seek(int64_t offset,
72bdd1243dSDimitry Andric                               lldb::TraceCursorSeekType origin) {
73fe6060f1SDimitry Andric   switch (origin) {
74bdd1243dSDimitry Andric   case lldb::eTraceCursorSeekTypeBeginning:
7581ad6265SDimitry Andric     m_pos = offset;
7681ad6265SDimitry Andric     break;
77bdd1243dSDimitry Andric   case lldb::eTraceCursorSeekTypeEnd:
7881ad6265SDimitry Andric     m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset;
7981ad6265SDimitry Andric     break;
80bdd1243dSDimitry Andric   case lldb::eTraceCursorSeekTypeCurrent:
8181ad6265SDimitry Andric     m_pos += offset;
8281ad6265SDimitry Andric   }
83972a253aSDimitry Andric 
84972a253aSDimitry Andric   ClearTimingRangesIfInvalid();
8581ad6265SDimitry Andric 
8681ad6265SDimitry Andric   return HasValue();
8781ad6265SDimitry Andric }
8881ad6265SDimitry Andric 
HasValue() const8981ad6265SDimitry Andric bool TraceCursorIntelPT::HasValue() const {
90972a253aSDimitry Andric   return m_pos >= 0 &&
91972a253aSDimitry Andric          static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount();
9281ad6265SDimitry Andric }
9381ad6265SDimitry Andric 
GetItemKind() const9481ad6265SDimitry Andric lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const {
9581ad6265SDimitry Andric   return m_decoded_thread_sp->GetItemKindByIndex(m_pos);
9681ad6265SDimitry Andric }
9781ad6265SDimitry Andric 
GetError() const9806c3fb27SDimitry Andric llvm::StringRef TraceCursorIntelPT::GetError() const {
9981ad6265SDimitry Andric   return m_decoded_thread_sp->GetErrorByIndex(m_pos);
10081ad6265SDimitry Andric }
10181ad6265SDimitry Andric 
GetLoadAddress() const10281ad6265SDimitry Andric lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const {
10381ad6265SDimitry Andric   return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos);
10481ad6265SDimitry Andric }
10581ad6265SDimitry Andric 
GetHWClock() const106bdd1243dSDimitry Andric std::optional<uint64_t> TraceCursorIntelPT::GetHWClock() const {
107bdd1243dSDimitry Andric   if (const std::optional<DecodedThread::TSCRange> &range = GetTSCRange())
108972a253aSDimitry Andric     return range->tsc;
109bdd1243dSDimitry Andric   return std::nullopt;
110fe6060f1SDimitry Andric }
111972a253aSDimitry Andric 
GetWallClockTime() const112bdd1243dSDimitry Andric std::optional<double> TraceCursorIntelPT::GetWallClockTime() const {
113bdd1243dSDimitry Andric   if (const std::optional<DecodedThread::NanosecondsRange> &range =
114972a253aSDimitry Andric           GetNanosecondsRange())
115972a253aSDimitry Andric     return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos,
116972a253aSDimitry Andric                                       *m_tsc_conversion);
117bdd1243dSDimitry Andric   return std::nullopt;
118fe6060f1SDimitry Andric }
119fe6060f1SDimitry Andric 
GetCPU() const120bdd1243dSDimitry Andric lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const {
121753f127fSDimitry Andric   return m_decoded_thread_sp->GetCPUByIndex(m_pos);
122753f127fSDimitry Andric }
123753f127fSDimitry Andric 
GetEventType() const12481ad6265SDimitry Andric lldb::TraceEvent TraceCursorIntelPT::GetEventType() const {
12581ad6265SDimitry Andric   return m_decoded_thread_sp->GetEventByIndex(m_pos);
126fe6060f1SDimitry Andric }
127fe6060f1SDimitry Andric 
GoToId(user_id_t id)12881ad6265SDimitry Andric bool TraceCursorIntelPT::GoToId(user_id_t id) {
12981ad6265SDimitry Andric   if (!HasId(id))
13081ad6265SDimitry Andric     return false;
13181ad6265SDimitry Andric   m_pos = id;
132972a253aSDimitry Andric   ClearTimingRangesIfInvalid();
13381ad6265SDimitry Andric   return true;
134fe6060f1SDimitry Andric }
135fe6060f1SDimitry Andric 
HasId(lldb::user_id_t id) const13681ad6265SDimitry Andric bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const {
137972a253aSDimitry Andric   return id < m_decoded_thread_sp->GetItemsCount();
138fe6060f1SDimitry Andric }
139fe6060f1SDimitry Andric 
GetId() const14081ad6265SDimitry Andric user_id_t TraceCursorIntelPT::GetId() const { return m_pos; }
141bdd1243dSDimitry Andric 
GetSyncPointMetadata() const142bdd1243dSDimitry Andric std::optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const {
143bdd1243dSDimitry Andric   return formatv("offset = 0x{0:x}",
144bdd1243dSDimitry Andric                  m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos))
145bdd1243dSDimitry Andric       .str();
146bdd1243dSDimitry Andric }
147