1 //===-- TraceCursorIntelPT.cpp --------------------------------------------===// 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 #include "TraceCursorIntelPT.h" 10 #include "DecodedThread.h" 11 #include "TraceIntelPT.h" 12 #include <cstdlib> 13 14 using namespace lldb; 15 using namespace lldb_private; 16 using namespace lldb_private::trace_intel_pt; 17 using namespace llvm; 18 19 TraceCursorIntelPT::TraceCursorIntelPT( 20 ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp, 21 const Optional<LinuxPerfZeroTscConversion> &tsc_conversion, 22 Optional<uint64_t> beginning_of_time_nanos) 23 : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp), 24 m_tsc_conversion(tsc_conversion), 25 m_beginning_of_time_nanos(beginning_of_time_nanos) { 26 Seek(0, lldb::eTraceCursorSeekTypeEnd); 27 } 28 29 void TraceCursorIntelPT::Next() { 30 m_pos += IsForwards() ? 1 : -1; 31 ClearTimingRangesIfInvalid(); 32 } 33 34 void TraceCursorIntelPT::ClearTimingRangesIfInvalid() { 35 if (m_tsc_range_calculated) { 36 if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) { 37 m_tsc_range = None; 38 m_tsc_range_calculated = false; 39 } 40 } 41 42 if (m_nanoseconds_range_calculated) { 43 if (!m_nanoseconds_range || m_pos < 0 || 44 !m_nanoseconds_range->InRange(m_pos)) { 45 m_nanoseconds_range = None; 46 m_nanoseconds_range_calculated = false; 47 } 48 } 49 } 50 51 const Optional<DecodedThread::TSCRange> & 52 TraceCursorIntelPT::GetTSCRange() const { 53 if (!m_tsc_range_calculated) { 54 m_tsc_range_calculated = true; 55 m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos); 56 } 57 return m_tsc_range; 58 } 59 60 const Optional<DecodedThread::NanosecondsRange> & 61 TraceCursorIntelPT::GetNanosecondsRange() const { 62 if (!m_nanoseconds_range_calculated) { 63 m_nanoseconds_range_calculated = true; 64 m_nanoseconds_range = 65 m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos); 66 } 67 return m_nanoseconds_range; 68 } 69 70 bool TraceCursorIntelPT::Seek(int64_t offset, 71 lldb::TraceCursorSeekType origin) { 72 switch (origin) { 73 case lldb::eTraceCursorSeekTypeBeginning: 74 m_pos = offset; 75 break; 76 case lldb::eTraceCursorSeekTypeEnd: 77 m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset; 78 break; 79 case lldb::eTraceCursorSeekTypeCurrent: 80 m_pos += offset; 81 } 82 83 ClearTimingRangesIfInvalid(); 84 85 return HasValue(); 86 } 87 88 bool TraceCursorIntelPT::HasValue() const { 89 return m_pos >= 0 && 90 static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount(); 91 } 92 93 lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const { 94 return m_decoded_thread_sp->GetItemKindByIndex(m_pos); 95 } 96 97 const char *TraceCursorIntelPT::GetError() const { 98 return m_decoded_thread_sp->GetErrorByIndex(m_pos); 99 } 100 101 lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const { 102 return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos); 103 } 104 105 Optional<uint64_t> TraceCursorIntelPT::GetHWClock() const { 106 if (const Optional<DecodedThread::TSCRange> &range = GetTSCRange()) 107 return range->tsc; 108 return None; 109 } 110 111 Optional<double> TraceCursorIntelPT::GetWallClockTime() const { 112 if (const Optional<DecodedThread::NanosecondsRange> &range = 113 GetNanosecondsRange()) 114 return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos, 115 *m_tsc_conversion); 116 return None; 117 } 118 119 lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const { 120 return m_decoded_thread_sp->GetCPUByIndex(m_pos); 121 } 122 123 lldb::TraceEvent TraceCursorIntelPT::GetEventType() const { 124 return m_decoded_thread_sp->GetEventByIndex(m_pos); 125 } 126 127 bool TraceCursorIntelPT::GoToId(user_id_t id) { 128 if (!HasId(id)) 129 return false; 130 m_pos = id; 131 ClearTimingRangesIfInvalid(); 132 return true; 133 } 134 135 bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const { 136 return id < m_decoded_thread_sp->GetItemsCount(); 137 } 138 139 user_id_t TraceCursorIntelPT::GetId() const { return m_pos; } 140