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(ThreadSP thread_sp, 21 DecodedThreadSP decoded_thread_sp) 22 : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) { 23 Seek(0, SeekType::End); 24 } 25 26 int64_t TraceCursorIntelPT::GetItemsCount() const { 27 return m_decoded_thread_sp->GetInstructionsCount(); 28 } 29 30 void TraceCursorIntelPT::CalculateTscRange() { 31 // If we failed, then we look for the exact range 32 if (!m_tsc_range || !m_tsc_range->InRange(m_pos)) 33 m_tsc_range = m_decoded_thread_sp->CalculateTscRange( 34 m_pos, /*hit_range=*/m_tsc_range); 35 } 36 37 void TraceCursorIntelPT::Next() { 38 m_pos += IsForwards() ? 1 : -1; 39 40 // We try to go to a neighbor tsc range that might contain the current pos 41 if (m_tsc_range && !m_tsc_range->InRange(m_pos)) 42 m_tsc_range = IsForwards() ? m_tsc_range->Next() : m_tsc_range->Prev(); 43 44 // If we failed, this call will fix it 45 CalculateTscRange(); 46 } 47 48 bool TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { 49 switch (origin) { 50 case TraceCursor::SeekType::Beginning: 51 m_pos = offset; 52 break; 53 case TraceCursor::SeekType::End: 54 m_pos = GetItemsCount() - 1 + offset; 55 break; 56 case TraceCursor::SeekType::Current: 57 m_pos += offset; 58 } 59 CalculateTscRange(); 60 61 return HasValue(); 62 } 63 64 bool TraceCursorIntelPT::HasValue() const { 65 return m_pos >= 0 && m_pos < GetItemsCount(); 66 } 67 68 bool TraceCursorIntelPT::IsError() { 69 return m_decoded_thread_sp->IsInstructionAnError(m_pos); 70 } 71 72 const char *TraceCursorIntelPT::GetError() { 73 return m_decoded_thread_sp->GetErrorByInstructionIndex(m_pos); 74 } 75 76 lldb::addr_t TraceCursorIntelPT::GetLoadAddress() { 77 return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos); 78 } 79 80 Optional<uint64_t> 81 TraceCursorIntelPT::GetCounter(lldb::TraceCounter counter_type) { 82 switch (counter_type) { 83 case lldb::eTraceCounterTSC: 84 if (m_tsc_range) 85 return m_tsc_range->GetTsc(); 86 else 87 return llvm::None; 88 } 89 } 90 91 lldb::TraceEvents TraceCursorIntelPT::GetEvents() { 92 return m_decoded_thread_sp->GetEvents(m_pos); 93 } 94 95 TraceInstructionControlFlowType 96 TraceCursorIntelPT::GetInstructionControlFlowType() { 97 return m_decoded_thread_sp->GetInstructionControlFlowType(m_pos); 98 } 99 100 bool TraceCursorIntelPT::GoToId(user_id_t id) { 101 if (!HasId(id)) 102 return false; 103 m_pos = id; 104 m_tsc_range = m_decoded_thread_sp->CalculateTscRange(m_pos, m_tsc_range); 105 106 return true; 107 } 108 109 bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const { 110 return id < m_decoded_thread_sp->GetInstructionsCount(); 111 } 112 113 user_id_t TraceCursorIntelPT::GetId() const { return m_pos; } 114