147 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TraceCursorIntelPT.h"10#include "DecodedThread.h"11#include "TraceIntelPT.h"12#include <cstdlib>13#include <optional>14 15using namespace lldb;16using namespace lldb_private;17using namespace lldb_private::trace_intel_pt;18using namespace llvm;19 20TraceCursorIntelPT::TraceCursorIntelPT(21 ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp,22 const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion,23 std::optional<uint64_t> beginning_of_time_nanos)24 : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp),25 m_tsc_conversion(tsc_conversion),26 m_beginning_of_time_nanos(beginning_of_time_nanos) {27 Seek(0, lldb::eTraceCursorSeekTypeEnd);28}29 30void TraceCursorIntelPT::Next() {31 m_pos += IsForwards() ? 1 : -1;32 ClearTimingRangesIfInvalid();33}34 35void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {36 if (m_tsc_range_calculated) {37 if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) {38 m_tsc_range = std::nullopt;39 m_tsc_range_calculated = false;40 }41 }42 43 if (m_nanoseconds_range_calculated) {44 if (!m_nanoseconds_range || m_pos < 0 ||45 !m_nanoseconds_range->InRange(m_pos)) {46 m_nanoseconds_range = std::nullopt;47 m_nanoseconds_range_calculated = false;48 }49 }50}51 52const std::optional<DecodedThread::TSCRange> &53TraceCursorIntelPT::GetTSCRange() const {54 if (!m_tsc_range_calculated) {55 m_tsc_range_calculated = true;56 m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos);57 }58 return m_tsc_range;59}60 61const std::optional<DecodedThread::NanosecondsRange> &62TraceCursorIntelPT::GetNanosecondsRange() const {63 if (!m_nanoseconds_range_calculated) {64 m_nanoseconds_range_calculated = true;65 m_nanoseconds_range =66 m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos);67 }68 return m_nanoseconds_range;69}70 71bool TraceCursorIntelPT::Seek(int64_t offset,72 lldb::TraceCursorSeekType origin) {73 switch (origin) {74 case lldb::eTraceCursorSeekTypeBeginning:75 m_pos = offset;76 break;77 case lldb::eTraceCursorSeekTypeEnd:78 m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset;79 break;80 case lldb::eTraceCursorSeekTypeCurrent:81 m_pos += offset;82 }83 84 ClearTimingRangesIfInvalid();85 86 return HasValue();87}88 89bool TraceCursorIntelPT::HasValue() const {90 return m_pos >= 0 &&91 static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount();92}93 94lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const {95 return m_decoded_thread_sp->GetItemKindByIndex(m_pos);96}97 98llvm::StringRef TraceCursorIntelPT::GetError() const {99 return m_decoded_thread_sp->GetErrorByIndex(m_pos);100}101 102lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const {103 return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos);104}105 106std::optional<uint64_t> TraceCursorIntelPT::GetHWClock() const {107 if (const std::optional<DecodedThread::TSCRange> &range = GetTSCRange())108 return range->tsc;109 return std::nullopt;110}111 112std::optional<double> TraceCursorIntelPT::GetWallClockTime() const {113 if (const std::optional<DecodedThread::NanosecondsRange> &range =114 GetNanosecondsRange())115 return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos,116 *m_tsc_conversion);117 return std::nullopt;118}119 120lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const {121 return m_decoded_thread_sp->GetCPUByIndex(m_pos);122}123 124lldb::TraceEvent TraceCursorIntelPT::GetEventType() const {125 return m_decoded_thread_sp->GetEventByIndex(m_pos);126}127 128bool TraceCursorIntelPT::GoToId(user_id_t id) {129 if (!HasId(id))130 return false;131 m_pos = id;132 ClearTimingRangesIfInvalid();133 return true;134}135 136bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const {137 return id < m_decoded_thread_sp->GetItemsCount();138}139 140user_id_t TraceCursorIntelPT::GetId() const { return m_pos; }141 142std::optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const {143 return formatv("offset = 0x{0:x}",144 m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos))145 .str();146}147