146 lines
4.2 KiB
C++
146 lines
4.2 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,
|
|
const Optional<LinuxPerfZeroTscConversion> &tsc_conversion,
|
|
Optional<uint64_t> beginning_of_time_nanos)
|
|
: TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp),
|
|
m_tsc_conversion(tsc_conversion),
|
|
m_beginning_of_time_nanos(beginning_of_time_nanos) {
|
|
Seek(0, lldb::eTraceCursorSeekTypeEnd);
|
|
}
|
|
|
|
void TraceCursorIntelPT::Next() {
|
|
m_pos += IsForwards() ? 1 : -1;
|
|
ClearTimingRangesIfInvalid();
|
|
}
|
|
|
|
void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {
|
|
if (m_tsc_range_calculated) {
|
|
if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) {
|
|
m_tsc_range = None;
|
|
m_tsc_range_calculated = false;
|
|
}
|
|
}
|
|
|
|
if (m_nanoseconds_range_calculated) {
|
|
if (!m_nanoseconds_range || m_pos < 0 ||
|
|
!m_nanoseconds_range->InRange(m_pos)) {
|
|
m_nanoseconds_range = None;
|
|
m_nanoseconds_range_calculated = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
const Optional<DecodedThread::TSCRange> &
|
|
TraceCursorIntelPT::GetTSCRange() const {
|
|
if (!m_tsc_range_calculated) {
|
|
m_tsc_range_calculated = true;
|
|
m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos);
|
|
}
|
|
return m_tsc_range;
|
|
}
|
|
|
|
const Optional<DecodedThread::NanosecondsRange> &
|
|
TraceCursorIntelPT::GetNanosecondsRange() const {
|
|
if (!m_nanoseconds_range_calculated) {
|
|
m_nanoseconds_range_calculated = true;
|
|
m_nanoseconds_range =
|
|
m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos);
|
|
}
|
|
return m_nanoseconds_range;
|
|
}
|
|
|
|
bool TraceCursorIntelPT::Seek(int64_t offset,
|
|
lldb::TraceCursorSeekType origin) {
|
|
switch (origin) {
|
|
case lldb::eTraceCursorSeekTypeBeginning:
|
|
m_pos = offset;
|
|
break;
|
|
case lldb::eTraceCursorSeekTypeEnd:
|
|
m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset;
|
|
break;
|
|
case lldb::eTraceCursorSeekTypeCurrent:
|
|
m_pos += offset;
|
|
}
|
|
|
|
ClearTimingRangesIfInvalid();
|
|
|
|
return HasValue();
|
|
}
|
|
|
|
bool TraceCursorIntelPT::HasValue() const {
|
|
return m_pos >= 0 &&
|
|
static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount();
|
|
}
|
|
|
|
lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const {
|
|
return m_decoded_thread_sp->GetItemKindByIndex(m_pos);
|
|
}
|
|
|
|
const char *TraceCursorIntelPT::GetError() const {
|
|
return m_decoded_thread_sp->GetErrorByIndex(m_pos);
|
|
}
|
|
|
|
lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const {
|
|
return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos);
|
|
}
|
|
|
|
Optional<uint64_t> TraceCursorIntelPT::GetHWClock() const {
|
|
if (const Optional<DecodedThread::TSCRange> &range = GetTSCRange())
|
|
return range->tsc;
|
|
return None;
|
|
}
|
|
|
|
Optional<double> TraceCursorIntelPT::GetWallClockTime() const {
|
|
if (const Optional<DecodedThread::NanosecondsRange> &range =
|
|
GetNanosecondsRange())
|
|
return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos,
|
|
*m_tsc_conversion);
|
|
return None;
|
|
}
|
|
|
|
lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const {
|
|
return m_decoded_thread_sp->GetCPUByIndex(m_pos);
|
|
}
|
|
|
|
lldb::TraceEvent TraceCursorIntelPT::GetEventType() const {
|
|
return m_decoded_thread_sp->GetEventByIndex(m_pos);
|
|
}
|
|
|
|
bool TraceCursorIntelPT::GoToId(user_id_t id) {
|
|
if (!HasId(id))
|
|
return false;
|
|
m_pos = id;
|
|
ClearTimingRangesIfInvalid();
|
|
return true;
|
|
}
|
|
|
|
bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const {
|
|
return id < m_decoded_thread_sp->GetItemsCount();
|
|
}
|
|
|
|
user_id_t TraceCursorIntelPT::GetId() const { return m_pos; }
|
|
|
|
Optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const {
|
|
return formatv("offset = 0x{0:x}",
|
|
m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos))
|
|
.str();
|
|
}
|