11#include "llvm/Support/Error.h"
21 : m_trace_wp(trace_sp) {
22 for (
Process *proc : trace_sp->GetAllProcesses()) {
23 for (
ThreadSP thread_sp : proc->GetThreadList().Threads()) {
24 m_tids.insert(thread_sp->GetID());
38 std::optional<uint64_t> lowest_tsc;
43 [&](
const DenseMap<
cpu_id_t, ArrayRef<uint8_t>> &buffers) ->
Error {
44 for (
auto &cpu_id_to_buffer : buffers) {
45 Expected<std::optional<uint64_t>> tsc =
48 return tsc.takeError();
49 if (*tsc && (!lowest_tsc || *lowest_tsc > **tsc))
52 return Error::success();
55 return std::move(err);
61 return std::move(err);
65 return trace_sp->GetThreadTimer(thread.
GetID())
66 .TimeTask(
"Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
72 thread.shared_from_this(), trace_sp->GetPerfZeroTscConversion());
74 Error err = trace_sp->OnAllCpusBinaryDataRead(
76 [&](
const DenseMap<
cpu_id_t, ArrayRef<uint8_t>> &buffers) ->
Error {
78 m_continuous_executions_per_thread->find(thread.GetID());
79 if (it != m_continuous_executions_per_thread->end())
80 return DecodeSystemWideTraceForThread(
81 *decoded_thread_sp, *trace_sp, buffers, it->second);
83 return Error::success();
86 return std::move(err);
89 return decoded_thread_sp;
95 std::vector<PSBBlock> psb_blocks;
98 [&](ArrayRef<uint8_t> data) ->
Error {
99 Expected<std::vector<PSBBlock>> split_trace =
102 return split_trace.takeError();
104 psb_blocks = std::move(*split_trace);
105 return Error::success();
108 return std::move(err);
112Expected<DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>>
114 DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>
115 continuous_executions_per_thread;
118 std::optional<LinuxPerfZeroTscConversion> conv_opt =
119 trace_sp->GetPerfZeroTscConversion();
121 return createStringError(
122 inconvertibleErrorCode(),
123 "TSC to nanoseconds conversion values were not found");
127 for (
cpu_id_t cpu_id : trace_sp->GetTracedCpus()) {
128 Expected<std::vector<PSBBlock>> psb_blocks =
131 return psb_blocks.takeError();
136 auto it = psb_blocks->begin();
137 auto on_new_thread_execution =
141 for (; it != psb_blocks->end() &&
142 *it->tsc < thread_execution.GetEndTSC();
144 if (*it->tsc > thread_execution.GetStartTSC()) {
150 continuous_executions_per_thread[thread_execution.tid].push_back(
153 Error err = trace_sp->OnCpuBinaryDataRead(
155 [&](ArrayRef<uint8_t> data) ->
Error {
156 Expected<std::vector<ThreadContinuousExecution>> executions =
159 return executions.takeError();
161 on_new_thread_execution(exec);
162 return Error::success();
165 return std::move(err);
171 for (
auto &tid_executions : continuous_executions_per_thread)
172 std::sort(tid_executions.second.begin(), tid_executions.second.end());
174 return continuous_executions_per_thread;
179 return createStringError(inconvertibleErrorCode(),
m_setup_error->c_str());
182 return Error::success();
185 "Context switch and Intel PT traces correlation", [&]() ->
Error {
188 return Error::success();
190 return correlation.takeError();
195 return createStringError(inconvertibleErrorCode(),
m_setup_error->c_str());
197 return Error::success();
207 return it->second.size();
215 count += kv.second.size();
static Expected< std::vector< PSBBlock > > GetPSBBlocksForCPU(TraceIntelPT &trace, cpu_id_t cpu_id)
A plug-in interface definition class for debugging a process.
llvm::Error OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id, llvm::StringRef kind, OnBinaryDataReadCallback callback)
Fetch binary data associated with a cpu, either live or postmortem, and pass it to the given callback...
llvm::Expected< llvm::DenseMap< lldb::tid_t, std::vector< IntelPTThreadContinousExecution > > > DoCorrelateContextSwitchesAndIntelPtTraces()
Produce a mapping from thread ids to the list of continuos executions with their associated intel pt ...
std::set< lldb::tid_t > m_tids
llvm::Expected< DecodedThreadSP > Decode(Thread &thread)
llvm::DenseMap< lldb::tid_t, DecodedThreadSP > m_decoded_threads
uint64_t m_unattributed_psb_blocks
uint64_t m_total_psb_blocks
size_t GetTotalContinuousExecutionsCount() const
size_t GetUnattributedPSBBlocksCount() const
llvm::Expected< std::optional< uint64_t > > FindLowestTSC()
size_t GePSBBlocksCountForThread(lldb::tid_t tid) const
size_t GetNumContinuousExecutionsForThread(lldb::tid_t tid) const
size_t GetTotalPSBBlocksCount() const
std::optional< std::string > m_setup_error
This variable will not be std::nullopt if a severe error happened during the setup of the decoder and...
TraceIntelPTSP GetTrace()
llvm::Error CorrelateContextSwitchesAndIntelPtTraces()
Traverse the context switch traces and the basic intel pt continuous subtraces and produce a list of ...
std::weak_ptr< TraceIntelPT > m_trace_wp
bool TracesThread(lldb::tid_t tid) const
std::optional< llvm::DenseMap< lldb::tid_t, std::vector< IntelPTThreadContinousExecution > > > m_continuous_executions_per_thread
TraceIntelPTMultiCpuDecoder(TraceIntelPTSP trace_sp)
llvm::Expected< std::vector< PSBBlock > > SplitTraceIntoPSBBlock(TraceIntelPT &trace_intel_pt, llvm::ArrayRef< uint8_t > buffer, bool expect_tscs)
Given an intel pt trace, split it in chunks delimited by PSB packets.
std::shared_ptr< DecodedThread > DecodedThreadSP
llvm::Expected< std::vector< ThreadContinuousExecution > > DecodePerfContextSwitchTrace(llvm::ArrayRef< uint8_t > data, lldb::cpu_id_t cpu_id, const LinuxPerfZeroTscConversion &tsc_conversion)
Decodes a context switch trace collected with perf_event_open.
std::shared_ptr< TraceIntelPT > TraceIntelPTSP
llvm::Expected< std::optional< uint64_t > > FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, llvm::ArrayRef< uint8_t > buffer)
Find the lowest TSC in the given trace.
A class that represents a running process on the host machine.
const char * toString(AppleArm64ExceptionClass EC)
std::shared_ptr< lldb_private::Thread > ThreadSP
static const char * kIptTrace
static const char * kPerfContextSwitchTrace
jLLDBTraceGetState gdb-remote packet
lldb::user_id_t GetID() const
Get accessor for the user ID.
This struct represents a continuous execution of a thread in a cpu, delimited by a context switch in ...
std::vector< PSBBlock > psb_blocks
This class indicates the time interval in which a thread was running continuously on a cpu core.