LLDB  mainline
DecodedThread.cpp
Go to the documentation of this file.
1 //===-- DecodedThread.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 
9 #include "DecodedThread.h"
10 
11 #include <intel-pt.h>
12 
13 #include "TraceCursorIntelPT.h"
14 
15 #include <memory>
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 using namespace lldb_private::trace_intel_pt;
20 using namespace llvm;
21 
23  return libipt_status < 0;
24 }
25 
27  return libipt_status == -pte_eos;
28 }
29 
31  return libipt_status == -pte_no_time;
32 }
33 
34 char IntelPTError::ID;
35 
36 IntelPTError::IntelPTError(int libipt_error_code, lldb::addr_t address)
37  : m_libipt_error_code(libipt_error_code), m_address(address) {
38  assert(libipt_error_code < 0);
39 }
40 
41 void IntelPTError::log(llvm::raw_ostream &OS) const {
42  OS << pt_errstr(pt_errcode(m_libipt_error_code));
44  OS << formatv(": {0:x+16}", m_address);
45 }
46 
48  return static_cast<int64_t>(m_item_kinds.size());
49 }
50 
52  return m_item_data[item_index].load_address;
53 }
54 
55 ThreadSP DecodedThread::GetThread() { return m_thread_sp; }
56 
59  m_item_kinds.push_back(kind);
60  m_item_data.emplace_back();
61  return m_item_data.back();
62 }
63 
64 void DecodedThread::NotifyTsc(uint64_t tsc) {
65  if (!m_last_tsc || *m_last_tsc != tsc) {
66  m_timestamps.emplace(m_item_kinds.size(), tsc);
67  m_last_tsc = tsc;
68  }
69 }
70 
72  if (!m_last_cpu || *m_last_cpu != cpu_id) {
73  m_cpus.emplace(m_item_kinds.size(), cpu_id);
74  m_last_cpu = cpu_id;
76  }
77 }
78 
79 Optional<lldb::cpu_id_t>
80 DecodedThread::GetCPUByIndex(uint64_t insn_index) const {
81  // Could possibly optimize the search
82  auto it = m_cpus.upper_bound(insn_index);
83  if (it == m_cpus.begin())
84  return None;
85  return prev(it)->second;
86 }
87 
91 }
92 
93 void DecodedThread::AppendInstruction(const pt_insn &insn) {
95 }
96 
98  // End of stream shouldn't be a public error
99  if (IsEndOfStream(error.GetLibiptErrorCode()))
100  return;
102  ConstString(error.message()).AsCString();
103 }
104 
105 void DecodedThread::AppendCustomError(StringRef err) {
107  ConstString(err).AsCString();
108 }
109 
111  return m_item_data[item_index].event;
112 }
113 
115  libipt_errors_counts[pt_errstr(pt_errcode(libipt_error_code))]++;
116  total_count++;
117 }
118 
119 void DecodedThread::RecordTscError(int libipt_error_code) {
120  m_tsc_errors_stats.RecordError(libipt_error_code);
121 }
122 
125  return m_tsc_errors_stats;
126 }
127 
129  return m_events_stats;
130 }
131 
133  events_counts[event]++;
134  total_count++;
135 }
136 
137 Optional<DecodedThread::TscRange> DecodedThread::CalculateTscRange(
138  size_t insn_index,
139  const Optional<DecodedThread::TscRange> &hint_range) const {
140  // We first try to check the given hint range in case we are traversing the
141  // trace in short jumps. If that fails, then we do the more expensive
142  // arbitrary lookup.
143  if (hint_range) {
144  Optional<TscRange> candidate_range;
145  if (insn_index < hint_range->GetStartInstructionIndex())
146  candidate_range = hint_range->Prev();
147  else if (insn_index > hint_range->GetEndInstructionIndex())
148  candidate_range = hint_range->Next();
149  else
150  candidate_range = hint_range;
151 
152  if (candidate_range && candidate_range->InRange(insn_index))
153  return candidate_range;
154  }
155  // Now we do a more expensive lookup
156  auto it = m_timestamps.upper_bound(insn_index);
157  if (it == m_timestamps.begin())
158  return None;
159 
160  return TscRange(--it, *this);
161 }
162 
164  return static_cast<lldb::TraceItemKind>(m_item_kinds[item_index]);
165 }
166 
167 const char *DecodedThread::GetErrorByIndex(size_t item_index) const {
168  return m_item_data[item_index].error;
169 }
170 
171 DecodedThread::DecodedThread(ThreadSP thread_sp) : m_thread_sp(thread_sp) {}
172 
173 lldb::TraceCursorUP DecodedThread::CreateNewCursor() {
174  return std::make_unique<TraceCursorIntelPT>(m_thread_sp, shared_from_this());
175 }
176 
178  return sizeof(TraceItemStorage) * m_item_data.size() +
179  sizeof(uint8_t) * m_item_kinds.size() +
180  (sizeof(size_t) + sizeof(uint64_t)) * m_timestamps.size() +
181  (sizeof(size_t) + sizeof(lldb::cpu_id_t)) * m_cpus.size();
182 }
183 
184 DecodedThread::TscRange::TscRange(std::map<size_t, uint64_t>::const_iterator it,
185  const DecodedThread &decoded_thread)
186  : m_it(it), m_decoded_thread(&decoded_thread) {
187  auto next_it = m_it;
188  ++next_it;
189  m_end_index = (next_it == m_decoded_thread->m_timestamps.end())
190  ? std::numeric_limits<uint64_t>::max()
191  : next_it->first - 1;
192 }
193 
194 size_t DecodedThread::TscRange::GetTsc() const { return m_it->second; }
195 
197  return m_it->first;
198 }
199 
201  return m_end_index;
202 }
203 
204 bool DecodedThread::TscRange::InRange(size_t insn_index) const {
205  return GetStartInstructionIndex() <= insn_index &&
206  insn_index <= GetEndInstructionIndex();
207 }
208 
209 Optional<DecodedThread::TscRange> DecodedThread::TscRange::Next() const {
210  auto next_it = m_it;
211  ++next_it;
212  if (next_it == m_decoded_thread->m_timestamps.end())
213  return None;
214  return TscRange(next_it, *m_decoded_thread);
215 }
216 
217 Optional<DecodedThread::TscRange> DecodedThread::TscRange::Prev() const {
218  if (m_it == m_decoded_thread->m_timestamps.begin())
219  return None;
220  auto prev_it = m_it;
221  --prev_it;
222  return TscRange(prev_it, *m_decoded_thread);
223 }
lldb_private::trace_intel_pt::DecodedThread::TscRange::TscRange
TscRange(std::map< size_t, uint64_t >::const_iterator it, const DecodedThread &decoded_thread)
Definition: DecodedThread.cpp:184
lldb::TraceItemKind
TraceItemKind
Definition: lldb-enumerations.h:1180
llvm
Definition: Debugger.h:50
lldb_private::trace_intel_pt::DecodedThread::DecodedThread
DecodedThread(lldb::ThreadSP thread_sp)
lldb_private::trace_intel_pt::DecodedThread::CreateNewCursor
lldb::TraceCursorUP CreateNewCursor()
Get a new cursor for the decoded thread.
Definition: DecodedThread.cpp:173
lldb::eTraceItemKindError
@ eTraceItemKindError
Definition: lldb-enumerations.h:1181
lldb::eTraceItemKindInstruction
@ eTraceItemKindInstruction
Definition: lldb-enumerations.h:1183
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::libipt_errors_counts
llvm::DenseMap< const char *, int > libipt_errors_counts
Definition: DecodedThread.h:117
lldb_private::trace_intel_pt::IntelPTError::m_libipt_error_code
int m_libipt_error_code
Definition: DecodedThread.h:61
lldb_private::trace_intel_pt::DecodedThread::GetErrorByIndex
const char * GetErrorByIndex(size_t item_index) const
Definition: DecodedThread.cpp:167
lldb_private::trace_intel_pt::DecodedThread::CreateNewTraceItem
DecodedThread::TraceItemStorage & CreateNewTraceItem(lldb::TraceItemKind kind)
Create a new trace item.
Definition: DecodedThread.cpp:58
lldb_private::trace_intel_pt::DecodedThread::TscRange::Next
llvm::Optional< TscRange > Next() const
Get the next range chronologically.
Definition: DecodedThread.cpp:209
lldb_private::trace_intel_pt::IntelPTError::m_address
lldb::addr_t m_address
Definition: DecodedThread.h:62
TraceCursorIntelPT.h
lldb_private::trace_intel_pt::DecodedThread::AppendEvent
void AppendEvent(lldb::TraceEvent)
Append an event.
Definition: DecodedThread.cpp:88
lldb_private::ConstString::AsCString
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:193
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats
Definition: DecodedThread.h:115
lldb_private::trace_intel_pt::DecodedThread::TscRange::m_it
std::map< size_t, uint64_t >::const_iterator m_it
The iterator pointing to the beginning of the range.
Definition: DecodedThread.h:107
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::trace_intel_pt::DecodedThread::GetItemsCount
int64_t GetItemsCount() const
Get the total number of instruction, errors and events from the decoded trace.
Definition: DecodedThread.cpp:47
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage
We use a union to optimize the memory usage for the different kinds of trace items.
Definition: DecodedThread.h:242
lldb_private::trace_intel_pt::DecodedThread::TscRange::GetEndInstructionIndex
size_t GetEndInstructionIndex() const
Get the largest instruction index that has this TSC.
Definition: DecodedThread.cpp:200
lldb_private::trace_intel_pt::DecodedThread::GetItemKindByIndex
lldb::TraceItemKind GetItemKindByIndex(size_t item_index) const
Definition: DecodedThread.cpp:163
lldb_private::trace_intel_pt::DecodedThread::CalculateTscRange
llvm::Optional< TscRange > CalculateTscRange(size_t insn_index, const llvm::Optional< DecodedThread::TscRange > &hint_range) const
Construct the TSC range that covers the given instruction index.
Definition: DecodedThread.cpp:137
lldb_private::trace_intel_pt::DecodedThread::m_last_tsc
llvm::Optional< uint64_t > m_last_tsc
This is the chronologically last TSC that has been added.
Definition: DecodedThread.h:273
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::RecordError
void RecordError(int libipt_error_code)
Definition: DecodedThread.cpp:114
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb::TraceEvent
TraceEvent
Events that might happen during a trace session.
Definition: lldb-enumerations.h:1169
ID
static char ID
Definition: IRDynamicChecks.cpp:33
lldb_private::trace_intel_pt::DecodedThread::m_item_data
std::vector< TraceItemStorage > m_item_data
Most of the trace data is stored here.
Definition: DecodedThread.h:260
lldb_private::trace_intel_pt::DecodedThread::AppendError
void AppendError(const IntelPTError &error)
Append a decoding error.
Definition: DecodedThread.cpp:97
lldb_private::trace_intel_pt::DecodedThread::TscRange::Prev
llvm::Optional< TscRange > Prev() const
Get the previous range chronologically.
Definition: DecodedThread.cpp:217
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::error
const char * error
The string message of this item if it's an error.
Definition: DecodedThread.h:250
DecodedThread.h
lldb::eTraceItemKindEvent
@ eTraceItemKindEvent
Definition: lldb-enumerations.h:1182
lldb_private::trace_intel_pt::DecodedThread::GetEventsStats
const EventsStats & GetEventsStats() const
Return an object with statistics of the trace events that happened.
Definition: DecodedThread.cpp:128
lldb_private::trace_intel_pt::DecodedThread::AppendInstruction
void AppendInstruction(const pt_insn &insn)
Append an instruction.
Definition: DecodedThread.cpp:93
lldb_private::trace_intel_pt::DecodedThread::TscRange::m_decoded_thread
const DecodedThread * m_decoded_thread
Definition: DecodedThread.h:111
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::total_count
size_t total_count
Definition: DecodedThread.h:118
lldb_private::trace_intel_pt::DecodedThread::TscRange::GetStartInstructionIndex
size_t GetStartInstructionIndex() const
Get the smallest instruction index that has this TSC.
Definition: DecodedThread.cpp:196
lldb_private::trace_intel_pt::DecodedThread::TscRange
Definition: DecodedThread.h:82
lldb_private::trace_intel_pt::DecodedThread::NotifyTsc
void NotifyTsc(uint64_t tsc)
Notify this object that a new tsc has been seen.
Definition: DecodedThread.cpp:64
lldb_private::trace_intel_pt::DecodedThread::RecordTscError
void RecordTscError(int libipt_error_code)
Record an error decoding a TSC timestamp.
Definition: DecodedThread.cpp:119
lldb_private::trace_intel_pt::IntelPTError
Class for representing a libipt decoding error.
Definition: DecodedThread.h:36
lldb_private::trace_intel_pt::IntelPTError::log
void log(llvm::raw_ostream &OS) const override
Definition: DecodedThread.cpp:41
uint32_t
lldb_private::trace_intel_pt::DecodedThread::m_thread_sp
lldb::ThreadSP m_thread_sp
When adding new members to this class, make sure to update CalculateApproximateMemoryUsage() accordin...
Definition: DecodedThread.h:238
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::event
lldb::TraceEvent event
The event kind of this item if it's an event.
Definition: DecodedThread.h:247
lldb_private::trace_intel_pt::DecodedThread::EventsStats::RecordEvent
void RecordEvent(lldb::TraceEvent event)
Definition: DecodedThread.cpp:132
lldb::eTraceEventCPUChanged
@ eTraceEventCPUChanged
Event due to CPU change for a thread.
Definition: lldb-enumerations.h:1176
lldb_private::trace_intel_pt::DecodedThread::GetTscErrorsStats
const LibiptErrorsStats & GetTscErrorsStats() const
Return an object with statistics of the TSC decoding errors that happened.
Definition: DecodedThread.cpp:124
lldb_private::trace_intel_pt::DecodedThread::TscRange::InRange
bool InRange(size_t insn_index) const
Check if this TSC range includes the given instruction index.
Definition: DecodedThread.cpp:204
lldb_private::trace_intel_pt::DecodedThread::CalculateApproximateMemoryUsage
size_t CalculateApproximateMemoryUsage() const
The approximate size in bytes used by this instance, including all the already decoded instructions.
Definition: DecodedThread.cpp:177
lldb_private::trace_intel_pt::DecodedThread::EventsStats
Definition: DecodedThread.h:124
lldb_private::trace_intel_pt::DecodedThread::GetCPUByIndex
llvm::Optional< lldb::cpu_id_t > GetCPUByIndex(uint64_t item_index) const
Get the most recent CPU id before or at the given trace item index.
Definition: DecodedThread.cpp:80
lldb_private::trace_intel_pt::DecodedThread::GetThread
lldb::ThreadSP GetThread()
Definition: DecodedThread.cpp:55
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::trace_intel_pt::DecodedThread::NotifyCPU
void NotifyCPU(lldb::cpu_id_t cpu_id)
Notify this object that a CPU has been seen.
Definition: DecodedThread.cpp:71
lldb_private::trace_intel_pt::DecodedThread::TscRange::m_end_index
size_t m_end_index
The largest instruction index that has this TSC.
Definition: DecodedThread.h:109
lldb_private::trace_intel_pt::DecodedThread::m_cpus
std::map< uint64_t, lldb::cpu_id_t > m_cpus
Definition: DecodedThread.h:278
lldb_private::trace_intel_pt::DecodedThread::m_tsc_errors_stats
LibiptErrorsStats m_tsc_errors_stats
Statistics of libipt errors when decoding TSCs.
Definition: DecodedThread.h:285
lldb_private::trace_intel_pt::IsLibiptError
bool IsLibiptError(int libipt_status)
libipt status utils
Definition: DecodedThread.cpp:22
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::trace_intel_pt::DecodedThread::TscRange::GetTsc
size_t GetTsc() const
Get the TSC value.
Definition: DecodedThread.cpp:194
lldb_private::trace_intel_pt::IsEndOfStream
bool IsEndOfStream(int libipt_status)
Definition: DecodedThread.cpp:26
lldb_private::trace_intel_pt::IsTscUnavailable
bool IsTscUnavailable(int libipt_status)
Definition: DecodedThread.cpp:30
lldb_private::trace_intel_pt::DecodedThread
Definition: DecodedThread.h:72
lldb_private::trace_intel_pt
Definition: CommandObjectTraceStartIntelPT.h:18
lldb_private::trace_intel_pt::DecodedThread::m_item_kinds
std::vector< uint8_t > m_item_kinds
The TraceItemKind for each trace item encoded as uint8_t.
Definition: DecodedThread.h:263
lldb_private::trace_intel_pt::DecodedThread::GetInstructionLoadAddress
lldb::addr_t GetInstructionLoadAddress(size_t item_index) const
Definition: DecodedThread.cpp:51
lldb_private::trace_intel_pt::DecodedThread::m_timestamps
std::map< uint64_t, uint64_t > m_timestamps
This map contains the TSCs of the decoded instructions.
Definition: DecodedThread.h:271
lldb_private::trace_intel_pt::DecodedThread::AppendCustomError
void AppendCustomError(llvm::StringRef error)
Append a custom decoding.
Definition: DecodedThread.cpp:105
lldb
Definition: SBAddress.h:15
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::load_address
uint64_t load_address
The load addresses of this item if it's an instruction.
Definition: DecodedThread.h:244
lldb_private::trace_intel_pt::DecodedThread::m_last_cpu
llvm::Optional< uint64_t > m_last_cpu
This is the chronologically last CPU ID.
Definition: DecodedThread.h:280
lldb_private::trace_intel_pt::DecodedThread::m_events_stats
EventsStats m_events_stats
Statistics of all tracing events.
Definition: DecodedThread.h:283
lldb_private::trace_intel_pt::DecodedThread::GetEventByIndex
lldb::TraceEvent GetEventByIndex(int item_index) const
Definition: DecodedThread.cpp:110
lldb_private::LLDBLog::OS
@ OS