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