LLDB  mainline
TraceIntelPTMultiCpuDecoder.cpp
Go to the documentation of this file.
1 //===-- TraceIntelPTMultiCpuDecoder.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 
10 
11 #include "TraceIntelPT.h"
12 
13 #include "llvm/Support/Error.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 using namespace lldb_private::trace_intel_pt;
18 using namespace llvm;
19 
20 TraceIntelPTMultiCpuDecoder::TraceIntelPTMultiCpuDecoder(
21  TraceIntelPTSP trace_sp)
22  : m_trace_wp(trace_sp) {
23  for (Process *proc : trace_sp->GetAllProcesses()) {
24  for (ThreadSP thread_sp : proc->GetThreadList().Threads()) {
25  m_tids.insert(thread_sp->GetID());
26  }
27  }
28 }
29 
31  return m_trace_wp.lock();
32 }
33 
35  return m_tids.count(tid);
36 }
37 
38 Expected<DecodedThreadSP> TraceIntelPTMultiCpuDecoder::Decode(Thread &thread) {
40  return std::move(err);
41 
42  TraceIntelPTSP trace_sp = GetTrace();
43 
44  return trace_sp
45  ->GetThreadTimer(thread.GetID())
46  .TimeTask("Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
47  auto it = m_decoded_threads.find(thread.GetID());
48  if (it != m_decoded_threads.end())
49  return it->second;
50 
51  DecodedThreadSP decoded_thread_sp =
52  std::make_shared<DecodedThread>(thread.shared_from_this());
53 
54  Error err = trace_sp->OnAllCpusBinaryDataRead(
56  [&](const DenseMap<cpu_id_t, ArrayRef<uint8_t>> &buffers) -> Error {
57  auto it =
58  m_continuous_executions_per_thread->find(thread.GetID());
59  if (it != m_continuous_executions_per_thread->end())
60  return DecodeSystemWideTraceForThread(
61  *decoded_thread_sp, *trace_sp, buffers, it->second);
62 
63  return Error::success();
64  });
65  if (err)
66  return std::move(err);
67 
68  m_decoded_threads.try_emplace(thread.GetID(), decoded_thread_sp);
69  return decoded_thread_sp;
70  });
71 }
72 
73 static Expected<std::vector<IntelPTThreadSubtrace>>
75  std::vector<IntelPTThreadSubtrace> intel_pt_subtraces;
76  Error err = trace.OnCpuBinaryDataRead(
78  [&](ArrayRef<uint8_t> data) -> Error {
79  Expected<std::vector<IntelPTThreadSubtrace>> split_trace =
81  if (!split_trace)
82  return split_trace.takeError();
83 
84  intel_pt_subtraces = std::move(*split_trace);
85  return Error::success();
86  });
87  if (err)
88  return std::move(err);
89  return intel_pt_subtraces;
90 }
91 
92 Expected<DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>>
94  DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>
95  continuous_executions_per_thread;
96  TraceIntelPTSP trace_sp = GetTrace();
97 
98  Optional<LinuxPerfZeroTscConversion> conv_opt =
99  trace_sp->GetPerfZeroTscConversion();
100  if (!conv_opt)
101  return createStringError(
102  inconvertibleErrorCode(),
103  "TSC to nanoseconds conversion values were not found");
104 
105  LinuxPerfZeroTscConversion tsc_conversion = *conv_opt;
106 
107  for (cpu_id_t cpu_id : trace_sp->GetTracedCpus()) {
108  Expected<std::vector<IntelPTThreadSubtrace>> intel_pt_subtraces =
109  GetIntelPTSubtracesForCpu(*trace_sp, cpu_id);
110  if (!intel_pt_subtraces)
111  return intel_pt_subtraces.takeError();
112 
113  m_total_psb_blocks += intel_pt_subtraces->size();
114  // We'll be iterating through the thread continuous executions and the intel
115  // pt subtraces sorted by time.
116  auto it = intel_pt_subtraces->begin();
117  auto on_new_thread_execution =
118  [&](const ThreadContinuousExecution &thread_execution) {
119  IntelPTThreadContinousExecution execution(thread_execution);
120 
121  for (; it != intel_pt_subtraces->end() &&
122  it->tsc < thread_execution.GetEndTSC();
123  it++) {
124  if (it->tsc > thread_execution.GetStartTSC()) {
125  execution.intelpt_subtraces.push_back(*it);
126  } else {
128  }
129  }
130  continuous_executions_per_thread[thread_execution.tid].push_back(
131  execution);
132  };
133  Error err = trace_sp->OnCpuBinaryDataRead(
135  [&](ArrayRef<uint8_t> data) -> Error {
136  Expected<std::vector<ThreadContinuousExecution>> executions =
137  DecodePerfContextSwitchTrace(data, cpu_id, tsc_conversion);
138  if (!executions)
139  return executions.takeError();
140  for (const ThreadContinuousExecution &exec : *executions)
141  on_new_thread_execution(exec);
142  return Error::success();
143  });
144  if (err)
145  return std::move(err);
146 
147  m_unattributed_psb_blocks += intel_pt_subtraces->end() - it;
148  }
149  // We now sort the executions of each thread to have them ready for
150  // instruction decoding
151  for (auto &tid_executions : continuous_executions_per_thread)
152  std::sort(tid_executions.second.begin(), tid_executions.second.end());
153 
154  return continuous_executions_per_thread;
155 }
156 
158  if (m_setup_error)
159  return createStringError(inconvertibleErrorCode(), m_setup_error->c_str());
160 
162  return Error::success();
163 
164  Error err = GetTrace()->GetGlobalTimer().TimeTask(
165  "Context switch and Intel PT traces correlation", [&]() -> Error {
166  if (auto correlation = DoCorrelateContextSwitchesAndIntelPtTraces()) {
167  m_continuous_executions_per_thread.emplace(std::move(*correlation));
168  return Error::success();
169  } else {
170  return correlation.takeError();
171  }
172  });
173  if (err) {
174  m_setup_error = toString(std::move(err));
175  return createStringError(inconvertibleErrorCode(), m_setup_error->c_str());
176  }
177  return Error::success();
178 }
179 
181  lldb::tid_t tid) const {
183  return 0;
184  auto it = m_continuous_executions_per_thread->find(tid);
185  if (it == m_continuous_executions_per_thread->end())
186  return 0;
187  return it->second.size();
188 }
189 
192  return 0;
193  size_t count = 0;
194  for (const auto &kv : *m_continuous_executions_per_thread)
195  count += kv.second.size();
196  return count;
197 }
198 
199 size_t
202  return 0;
203  size_t count = 0;
204  auto it = m_continuous_executions_per_thread->find(tid);
205  if (it == m_continuous_executions_per_thread->end())
206  return 0;
207  for (const IntelPTThreadContinousExecution &execution : it->second)
208  count += execution.intelpt_subtraces.size();
209  return count;
210 }
211 
214 }
215 
217  return m_total_psb_blocks;
218 }
lldb_private::toString
const char * toString(AppleArm64ExceptionClass EC)
Definition: AppleArm64ExceptionClass.h:38
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GetUnattributedPSBBlocksCount
size_t GetUnattributedPSBBlocksCount() const
Definition: TraceIntelPTMultiCpuDecoder.cpp:212
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::Decode
llvm::Expected< DecodedThreadSP > Decode(Thread &thread)
Definition: TraceIntelPTMultiCpuDecoder.cpp:38
llvm
Definition: Debugger.h:50
lldb_private::Process
Definition: Process.h:338
lldb_private::trace_intel_pt::TraceIntelPT
Definition: TraceIntelPT.h:24
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GetTotalPSBBlocksCount
size_t GetTotalPSBBlocksCount() const
Definition: TraceIntelPTMultiCpuDecoder.cpp:216
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::TracesThread
bool TracesThread(lldb::tid_t tid) const
Definition: TraceIntelPTMultiCpuDecoder.cpp:34
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GePSBBlocksCountForThread
size_t GePSBBlocksCountForThread(lldb::tid_t tid) const
Definition: TraceIntelPTMultiCpuDecoder.cpp:200
lldb_private::trace_intel_pt::DecodePerfContextSwitchTrace
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.
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_decoded_threads
llvm::DenseMap< lldb::tid_t, DecodedThreadSP > m_decoded_threads
Definition: TraceIntelPTMultiCpuDecoder.h:92
lldb_private::trace_intel_pt::IntelPTThreadContinousExecution::intelpt_subtraces
std::vector< IntelPTThreadSubtrace > intelpt_subtraces
Definition: LibiptDecoder.h:35
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GetTotalContinuousExecutionsCount
size_t GetTotalContinuousExecutionsCount() const
Definition: TraceIntelPTMultiCpuDecoder.cpp:190
lldb_private::Thread
Definition: Thread.h:61
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_continuous_executions_per_thread
llvm::Optional< llvm::DenseMap< lldb::tid_t, std::vector< IntelPTThreadContinousExecution > > > m_continuous_executions_per_thread
Definition: TraceIntelPTMultiCpuDecoder.h:91
GetIntelPTSubtracesForCpu
static Expected< std::vector< IntelPTThreadSubtrace > > GetIntelPTSubtracesForCpu(TraceIntelPT &trace, cpu_id_t cpu_id)
Definition: TraceIntelPTMultiCpuDecoder.cpp:74
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GetNumContinuousExecutionsForThread
size_t GetNumContinuousExecutionsForThread(lldb::tid_t tid) const
Definition: TraceIntelPTMultiCpuDecoder.cpp:180
lldb_private::trace_intel_pt::TraceIntelPTSP
std::shared_ptr< TraceIntelPT > TraceIntelPTSP
Definition: forward-declarations.h:20
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::DoCorrelateContextSwitchesAndIntelPtTraces
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 ...
Definition: TraceIntelPTMultiCpuDecoder.cpp:93
lldb_private::IntelPTDataKinds::kIptTrace
static const char * kIptTrace
Definition: TraceIntelPTGDBRemotePackets.h:27
lldb_private::UserID::GetID
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_setup_error
llvm::Optional< std::string > m_setup_error
This variable will be non-None if a severe error happened during the setup of the decoder and we don'...
Definition: TraceIntelPTMultiCpuDecoder.h:95
lldb_private::IntelPTDataKinds::kPerfContextSwitchTrace
static const char * kPerfContextSwitchTrace
Definition: TraceIntelPTGDBRemotePackets.h:28
TraceIntelPTMultiCpuDecoder.h
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_unattributed_psb_blocks
uint64_t m_unattributed_psb_blocks
Definition: TraceIntelPTMultiCpuDecoder.h:96
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::CorrelateContextSwitchesAndIntelPtTraces
llvm::Error CorrelateContextSwitchesAndIntelPtTraces()
Traverse the context switch traces and the basic intel pt continuous subtraces and produce a list of ...
Definition: TraceIntelPTMultiCpuDecoder.cpp:157
uint32_t
lldb_private::LinuxPerfZeroTscConversion
jLLDBTraceGetState gdb-remote packet
Definition: TraceIntelPTGDBRemotePackets.h:89
if
if(APPLE AND LLVM_ENABLE_LOCAL_SUBMODULE_VISIBILITY) remove_module_flags() endif() macro(add_host_subdirectory group) list(APPEND HOST_SOURCES $
Definition: Host/CMakeLists.txt:1
lldb_private::trace_intel_pt::DecodedThreadSP
std::shared_ptr< DecodedThread > DecodedThreadSP
Definition: DecodedThread.h:290
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_trace_wp
std::weak_ptr< TraceIntelPT > m_trace_wp
Definition: TraceIntelPTMultiCpuDecoder.h:87
lldb_private::Trace::OnCpuBinaryDataRead
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...
Definition: Trace.cpp:500
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
lldb_private::trace_intel_pt::ThreadContinuousExecution
This class indicates the time interval in which a thread was running continuously on a cpu core.
Definition: PerfContextSwitchDecoder.h:25
lldb_private::trace_intel_pt::IntelPTThreadContinousExecution
This struct represents a continuous execution of a thread in a cpu, delimited by a context switch in ...
Definition: LibiptDecoder.h:33
lldb_private::trace_intel_pt
Definition: CommandObjectTraceStartIntelPT.h:18
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::GetTrace
TraceIntelPTSP GetTrace()
Definition: TraceIntelPTMultiCpuDecoder.cpp:30
lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions
llvm::Expected< std::vector< IntelPTThreadSubtrace > > SplitTraceInContinuousExecutions(TraceIntelPT &trace_intel_pt, llvm::ArrayRef< uint8_t > buffer)
Given an intel pt trace, split it in chunks delimited by PSB packets.
Definition: LibiptDecoder.cpp:354
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_total_psb_blocks
uint64_t m_total_psb_blocks
Definition: TraceIntelPTMultiCpuDecoder.h:97
lldb
Definition: SBAddress.h:15
TraceIntelPT.h
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86
lldb_private::trace_intel_pt::TraceIntelPTMultiCpuDecoder::m_tids
std::set< lldb::tid_t > m_tids
Definition: TraceIntelPTMultiCpuDecoder.h:88