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 assert(!m_decoded_thread_sp->GetInstructions().empty() && 24 "a trace should have at least one instruction or error"); 25 m_pos = m_decoded_thread_sp->GetInstructions().size() - 1; 26 } 27 28 size_t TraceCursorIntelPT::GetInternalInstructionSize() { 29 return m_decoded_thread_sp->GetInstructions().size(); 30 } 31 32 bool TraceCursorIntelPT::Next() { 33 auto canMoveOne = [&]() { 34 if (IsForwards()) 35 return m_pos + 1 < GetInternalInstructionSize(); 36 return m_pos > 0; 37 }; 38 39 size_t initial_pos = m_pos; 40 41 while (canMoveOne()) { 42 m_pos += IsForwards() ? 1 : -1; 43 if (!m_ignore_errors && IsError()) 44 return true; 45 if (GetInstructionControlFlowType() & m_granularity) 46 return true; 47 } 48 49 // Didn't find any matching instructions 50 m_pos = initial_pos; 51 return false; 52 } 53 54 size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { 55 int64_t last_index = GetInternalInstructionSize() - 1; 56 57 auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t { 58 return std::min(std::max((int64_t)0, raw_pos), last_index); 59 }; 60 61 switch (origin) { 62 case TraceCursor::SeekType::Set: 63 m_pos = fitPosToBounds(offset); 64 return m_pos; 65 case TraceCursor::SeekType::End: 66 m_pos = fitPosToBounds(offset + last_index); 67 return last_index - m_pos; 68 case TraceCursor::SeekType::Current: 69 int64_t new_pos = fitPosToBounds(offset + m_pos); 70 int64_t dist = m_pos - new_pos; 71 m_pos = new_pos; 72 return std::abs(dist); 73 } 74 } 75 76 bool TraceCursorIntelPT::IsError() { 77 return m_decoded_thread_sp->GetInstructions()[m_pos].IsError(); 78 } 79 80 Error TraceCursorIntelPT::GetError() { 81 return m_decoded_thread_sp->GetInstructions()[m_pos].ToError(); 82 } 83 84 lldb::addr_t TraceCursorIntelPT::GetLoadAddress() { 85 return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress(); 86 } 87 88 Optional<uint64_t> TraceCursorIntelPT::GetTimestampCounter() { 89 return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter(); 90 } 91 92 TraceInstructionControlFlowType 93 TraceCursorIntelPT::GetInstructionControlFlowType() { 94 lldb::addr_t next_load_address = 95 m_pos + 1 < GetInternalInstructionSize() 96 ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress() 97 : LLDB_INVALID_ADDRESS; 98 return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType( 99 next_load_address); 100 } 101