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 13 #include <cstdlib> 14 15 using namespace lldb; 16 using namespace lldb_private; 17 using namespace lldb_private::trace_intel_pt; 18 using namespace llvm; 19 20 TraceCursorIntelPT::TraceCursorIntelPT( 21 ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp, 22 const Optional<LinuxPerfZeroTscConversion> &tsc_conversion, 23 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, SeekType::End); 28 } 29 30 void TraceCursorIntelPT::Next() { 31 m_pos += IsForwards() ? 1 : -1; 32 ClearTimingRangesIfInvalid(); 33 } 34 35 void TraceCursorIntelPT::ClearTimingRangesIfInvalid() { 36 if (m_tsc_range_calculated) { 37 if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) { 38 m_tsc_range = None; 39 m_tsc_range_calculated = false; 40 } 41 } 42 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; 48 } 49 } 50 } 51 52 const 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); 57 } 58 return m_tsc_range; 59 } 60 61 const Optional<DecodedThread::NanosecondsRange> & 62 TraceCursorIntelPT::GetNanosecondsRange() const { 63 if (!m_nanoseconds_range_calculated) { 64 m_nanoseconds_range_calculated = true; 65 m_nanoseconds_range = 66 m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos); 67 } 68 return m_nanoseconds_range; 69 } 70 71 bool TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { 72 switch (origin) { 73 case TraceCursor::SeekType::Beginning: 74 m_pos = offset; 75 break; 76 case TraceCursor::SeekType::End: 77 m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset; 78 break; 79 case TraceCursor::SeekType::Current: 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 Optional<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