101 lines
3.0 KiB
C++
101 lines
3.0 KiB
C++
//===-- TraceCursorIntelPT.cpp --------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "TraceCursorIntelPT.h"
|
|
#include "DecodedThread.h"
|
|
#include "TraceIntelPT.h"
|
|
|
|
#include <cstdlib>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::trace_intel_pt;
|
|
using namespace llvm;
|
|
|
|
TraceCursorIntelPT::TraceCursorIntelPT(ThreadSP thread_sp,
|
|
DecodedThreadSP decoded_thread_sp)
|
|
: TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) {
|
|
assert(!m_decoded_thread_sp->GetInstructions().empty() &&
|
|
"a trace should have at least one instruction or error");
|
|
m_pos = m_decoded_thread_sp->GetInstructions().size() - 1;
|
|
}
|
|
|
|
size_t TraceCursorIntelPT::GetInternalInstructionSize() {
|
|
return m_decoded_thread_sp->GetInstructions().size();
|
|
}
|
|
|
|
bool TraceCursorIntelPT::Next() {
|
|
auto canMoveOne = [&]() {
|
|
if (IsForwards())
|
|
return m_pos + 1 < GetInternalInstructionSize();
|
|
return m_pos > 0;
|
|
};
|
|
|
|
size_t initial_pos = m_pos;
|
|
|
|
while (canMoveOne()) {
|
|
m_pos += IsForwards() ? 1 : -1;
|
|
if (!m_ignore_errors && IsError())
|
|
return true;
|
|
if (GetInstructionControlFlowType() & m_granularity)
|
|
return true;
|
|
}
|
|
|
|
// Didn't find any matching instructions
|
|
m_pos = initial_pos;
|
|
return false;
|
|
}
|
|
|
|
size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) {
|
|
int64_t last_index = GetInternalInstructionSize() - 1;
|
|
|
|
auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t {
|
|
return std::min(std::max((int64_t)0, raw_pos), last_index);
|
|
};
|
|
|
|
switch (origin) {
|
|
case TraceCursor::SeekType::Set:
|
|
m_pos = fitPosToBounds(offset);
|
|
return m_pos;
|
|
case TraceCursor::SeekType::End:
|
|
m_pos = fitPosToBounds(offset + last_index);
|
|
return last_index - m_pos;
|
|
case TraceCursor::SeekType::Current:
|
|
int64_t new_pos = fitPosToBounds(offset + m_pos);
|
|
int64_t dist = m_pos - new_pos;
|
|
m_pos = new_pos;
|
|
return std::abs(dist);
|
|
}
|
|
}
|
|
|
|
bool TraceCursorIntelPT::IsError() {
|
|
return m_decoded_thread_sp->GetInstructions()[m_pos].IsError();
|
|
}
|
|
|
|
Error TraceCursorIntelPT::GetError() {
|
|
return m_decoded_thread_sp->GetInstructions()[m_pos].ToError();
|
|
}
|
|
|
|
lldb::addr_t TraceCursorIntelPT::GetLoadAddress() {
|
|
return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress();
|
|
}
|
|
|
|
Optional<uint64_t> TraceCursorIntelPT::GetTimestampCounter() {
|
|
return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter();
|
|
}
|
|
|
|
TraceInstructionControlFlowType
|
|
TraceCursorIntelPT::GetInstructionControlFlowType() {
|
|
lldb::addr_t next_load_address =
|
|
m_pos + 1 < GetInternalInstructionSize()
|
|
? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress()
|
|
: LLDB_INVALID_ADDRESS;
|
|
return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType(
|
|
next_load_address);
|
|
}
|