LLDB  mainline
DecodedThread.h
Go to the documentation of this file.
1 //===-- DecodedThread.h -----------------------------------------*- C++ -*-===//
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 #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
11 
12 #include <utility>
13 #include <vector>
14 
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 
18 #include "lldb/Target/Trace.h"
20 
21 #include "intel-pt.h"
22 
23 namespace lldb_private {
24 namespace trace_intel_pt {
25 
26 /// libipt status utils
27 /// \{
28 bool IsLibiptError(int libipt_status);
29 
30 bool IsEndOfStream(int libipt_status);
31 
32 bool IsTscUnavailable(int libipt_status);
33 /// \}
34 
35 /// Class for representing a libipt decoding error.
36 class IntelPTError : public llvm::ErrorInfo<IntelPTError> {
37 public:
38  static char ID;
39 
40  /// \param[in] libipt_error_code
41  /// Negative number returned by libipt when decoding the trace and
42  /// signaling errors.
43  ///
44  /// \param[in] address
45  /// Optional instruction address. When decoding an individual instruction,
46  /// its address might be available in the \a pt_insn object, and should be
47  /// passed to this constructor. Other errors don't have an associated
48  /// address.
49  IntelPTError(int libipt_error_code,
51 
52  std::error_code convertToErrorCode() const override {
53  return llvm::errc::not_supported;
54  }
55 
56  void log(llvm::raw_ostream &OS) const override;
57 
58 private:
61 };
62 
63 /// Helper struct for building an instruction or error from the decoder.
64 /// It holds associated events and timing information.
68  libipt_error = pte_ok;
69  }
70 
71  DecodedInstruction(int libipt_error_code) : DecodedInstruction() {
72  libipt_error = libipt_error_code;
73  }
74 
75  /// \return \b true if and only if this struct holds a libipt error.
76  explicit operator bool() const;
77 
79  lldb::TraceEvents events = (lldb::TraceEvents)0;
80  llvm::Optional<uint64_t> tsc = llvm::None;
82 };
83 
84 /// \class DecodedThread
85 /// Class holding the instructions and function call hierarchy obtained from
86 /// decoding a trace, as well as a position cursor used when reverse debugging
87 /// the trace.
88 ///
89 /// Each decoded thread contains a cursor to the current position the user is
90 /// stopped at. See \a Trace::GetCursorPosition for more information.
91 class DecodedThread : public std::enable_shared_from_this<DecodedThread> {
92 public:
93  /// \class TscRange
94  /// Class that represents the trace range associated with a given TSC.
95  /// It provides efficient iteration to the previous or next TSC range in the
96  /// decoded trace.
97  ///
98  /// TSC timestamps are emitted by the decoder infrequently, which means
99  /// that each TSC covers a range of instruction indices, which can be used to
100  /// speed up TSC lookups.
101  class TscRange {
102  public:
103  /// Check if this TSC range includes the given instruction index.
104  bool InRange(size_t insn_index) const;
105 
106  /// Get the next range chronologically.
107  llvm::Optional<TscRange> Next() const;
108 
109  /// Get the previous range chronologically.
110  llvm::Optional<TscRange> Prev() const;
111 
112  /// Get the TSC value.
113  size_t GetTsc() const;
114  /// Get the smallest instruction index that has this TSC.
115  size_t GetStartInstructionIndex() const;
116  /// Get the largest instruction index that has this TSC.
117  size_t GetEndInstructionIndex() const;
118 
119  private:
120  friend class DecodedThread;
121 
122  TscRange(std::map<size_t, uint64_t>::const_iterator it,
123  const DecodedThread &decoded_thread);
124 
125  /// The iterator pointing to the beginning of the range.
126  std::map<size_t, uint64_t>::const_iterator m_it;
127  /// The largest instruction index that has this TSC.
128  size_t m_end_index;
129 
131  };
132 
133  // Struct holding counts for libipts errors;
135  // libipt error -> count
136  llvm::DenseMap<const char *, int> libipt_errors_counts;
137  size_t total_count = 0;
138 
139  void RecordError(int libipt_error_code);
140  };
141 
142  // Struct holding counts for events;
143  struct EventsStats {
144  /// A count for each individual event kind. We use an unordered map instead
145  /// of a DenseMap because DenseMap can't understand enums.
146  std::unordered_map<lldb::TraceEvents, size_t> events_counts;
147  size_t total_count = 0;
149 
150  void RecordEventsForInstruction(lldb::TraceEvents events);
151  };
152 
153  DecodedThread(lldb::ThreadSP thread_sp);
154 
155  /// Utility constructor that initializes the trace with a provided error.
156  DecodedThread(lldb::ThreadSP thread_sp, llvm::Error &&err);
157 
158  /// Append an instruction or a libipt error.
159  void Append(const DecodedInstruction &insn);
160 
161  /// Append an error signaling that decoding completely failed.
162  void SetAsFailed(llvm::Error &&error);
163 
164  /// Get a bitmask with the events that happened chronologically right before
165  /// the instruction pointed by the given instruction index, but after the
166  /// previous instruction.
167  lldb::TraceEvents GetEvents(int insn_index);
168 
169  /// Get the total number of instruction pointers from the decoded trace.
170  /// This will include instructions that indicate errors (or gaps) in the
171  /// trace. For an instruction error, you can access its underlying error
172  /// message with the \a GetErrorByInstructionIndex() method.
173  size_t GetInstructionsCount() const;
174 
175  /// \return
176  /// The load address of the instruction at the given index, or \a
177  /// LLDB_INVALID_ADDRESS if it is an error.
178  lldb::addr_t GetInstructionLoadAddress(size_t insn_index) const;
179 
180  /// Get the \a lldb::TraceInstructionControlFlowType categories of the
181  /// instruction.
182  ///
183  /// \return
184  /// The control flow categories, or \b 0 if the instruction is an error.
185  lldb::TraceInstructionControlFlowType
186  GetInstructionControlFlowType(size_t insn_index) const;
187 
188  /// Construct the TSC range that covers the given instruction index.
189  /// This operation is O(logn) and should be used sparingly.
190  /// If the trace was collected with TSC support, all the instructions of
191  /// the trace will have associated TSCs. This means that this method will
192  /// only return \b llvm::None if there are no TSCs whatsoever in the trace.
193  ///
194  /// \param[in] insn_index
195  /// The instruction index in question.
196  ///
197  /// \param[in] hint_range
198  /// An optional range that might include the given index or might be a
199  /// neighbor of it. It might help speed it traversals of the trace with
200  /// short jumps.
201  llvm::Optional<TscRange> CalculateTscRange(
202  size_t insn_index,
203  const llvm::Optional<DecodedThread::TscRange> &hint_range) const;
204 
205  /// Check if an instruction given by its index is an error.
206  bool IsInstructionAnError(size_t insn_idx) const;
207 
208  /// Get the error associated with a given instruction index.
209  ///
210  /// \return
211  /// The error message of \b nullptr if the given index
212  /// points to a valid instruction.
213  const char *GetErrorByInstructionIndex(size_t ins_idx);
214 
215  /// Get a new cursor for the decoded thread.
216  lldb::TraceCursorUP GetCursor();
217 
218  /// Return an object with statistics of the TSC decoding errors that happened.
219  /// A TSC error is not a fatal error and doesn't create gaps in the trace.
220  /// Instead we only keep track of them as statistics.
221  ///
222  /// \return
223  /// An object with the statistics of TSC decoding errors.
224  const LibiptErrorsStats &GetTscErrorsStats() const;
225 
226  /// Return an object with statistics of the trace events that happened.
227  ///
228  /// \return
229  /// The stats object of all the events.
230  const EventsStats &GetEventsStats() const;
231 
232  /// Record an error decoding a TSC timestamp.
233  ///
234  /// See \a GetTscErrors() for more documentation.
235  ///
236  /// \param[in] libipt_error_code
237  /// An error returned by the libipt library.
238  void RecordTscError(int libipt_error_code);
239 
240  /// The approximate size in bytes used by this instance,
241  /// including all the already decoded instructions.
242  size_t CalculateApproximateMemoryUsage() const;
243 
244  lldb::ThreadSP GetThread();
245 
246 private:
247  /// Append a decoding error given an llvm::Error.
248  void AppendError(llvm::Error &&error);
249 
250  /// Notify this class that the last added instruction or error has
251  /// an associated TSC.
252  void RecordTscForLastInstruction(uint64_t tsc);
253 
254  /// When adding new members to this class, make sure
255  /// to update \a CalculateApproximateMemoryUsage() accordingly.
256  lldb::ThreadSP m_thread_sp;
257  /// The low level storage of all instruction addresses. Each instruction has
258  /// an index in this vector and it will be used in other parts of the code.
259  std::vector<lldb::addr_t> m_instruction_ips;
260  /// The size in bytes of each instruction.
261  std::vector<uint8_t> m_instruction_sizes;
262  /// The libipt instruction class for each instruction.
263  std::vector<pt_insn_class> m_instruction_classes;
264 
265  /// This map contains the TSCs of the decoded instructions. It maps
266  /// `instruction index -> TSC`, where `instruction index` is the first index
267  /// at which the mapped TSC appears. We use this representation because TSCs
268  /// are sporadic and we can think of them as ranges. If TSCs are present in
269  /// the trace, all instructions will have an associated TSC, including the
270  /// first one. Otherwise, this map will be empty.
271  std::map<uint64_t, uint64_t> m_instruction_timestamps;
272  /// This is the chronologically last TSC that has been added.
273  llvm::Optional<uint64_t> m_last_tsc = llvm::None;
274  // This variables stores the messages of all the error instructions in the
275  // trace. It maps `instruction index -> error message`.
276  llvm::DenseMap<uint64_t, std::string> m_errors;
277  /// This variable stores the bitmask of events that happened right before
278  /// the instruction given as a key. It maps `instruction index -> events`.
279  llvm::DenseMap<uint64_t, lldb::TraceEvents> m_events;
280 
281  /// Statistics of all tracing events.
283  /// Statistics of libipt errors when decoding TSCs.
285  /// Total amount of time spent decoding.
286  std::chrono::milliseconds m_total_decoding_time{0};
287 };
288 
289 using DecodedThreadSP = std::shared_ptr<DecodedThread>;
290 
291 } // namespace trace_intel_pt
292 } // namespace lldb_private
293 
294 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
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:243
lldb_private::trace_intel_pt::DecodedThread::DecodedThread
DecodedThread(lldb::ThreadSP thread_sp)
lldb_private::trace_intel_pt::IntelPTError::ID
static char ID
Definition: DecodedThread.h:38
lldb_private::trace_intel_pt::DecodedInstruction::tsc
llvm::Optional< uint64_t > tsc
Definition: DecodedThread.h:80
lldb_private::trace_intel_pt::DecodedThread::IsInstructionAnError
bool IsInstructionAnError(size_t insn_idx) const
Check if an instruction given by its index is an error.
Definition: DecodedThread.cpp:208
lldb_private::trace_intel_pt::DecodedThread::EventsStats::total_count
size_t total_count
Definition: DecodedThread.h:147
lldb_private::trace_intel_pt::DecodedThread::GetCursor
lldb::TraceCursorUP GetCursor()
Get a new cursor for the decoded thread.
Definition: DecodedThread.cpp:227
lldb_private::trace_intel_pt::DecodedThread::m_events
llvm::DenseMap< uint64_t, lldb::TraceEvents > m_events
This variable stores the bitmask of events that happened right before the instruction given as a key.
Definition: DecodedThread.h:279
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::libipt_errors_counts
llvm::DenseMap< const char *, int > libipt_errors_counts
Definition: DecodedThread.h:136
lldb_private::trace_intel_pt::IntelPTError::m_libipt_error_code
int m_libipt_error_code
Definition: DecodedThread.h:59
lldb_private::trace_intel_pt::DecodedThread::SetAsFailed
void SetAsFailed(llvm::Error &&error)
Append an error signaling that decoding completely failed.
Definition: DecodedThread.cpp:141
lldb_private::trace_intel_pt::DecodedThread::AppendError
void AppendError(llvm::Error &&error)
Append a decoding error given an llvm::Error.
Definition: DecodedThread.cpp:134
lldb_private::trace_intel_pt::DecodedThread::m_instruction_sizes
std::vector< uint8_t > m_instruction_sizes
The size in bytes of each instruction.
Definition: DecodedThread.h:261
lldb_private::trace_intel_pt::DecodedThread::TscRange::Next
llvm::Optional< TscRange > Next() const
Get the next range chronologically.
Definition: DecodedThread.cpp:268
lldb_private::trace_intel_pt::IntelPTError::m_address
lldb::addr_t m_address
Definition: DecodedThread.h:60
lldb_private::trace_intel_pt::DecodedThread::GetEvents
lldb::TraceEvents GetEvents(int insn_index)
Get a bitmask with the events that happened chronologically right before the instruction pointed by t...
Definition: DecodedThread.cpp:145
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats
Definition: DecodedThread.h:134
Trace.h
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:126
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::trace_intel_pt::DecodedThread::TscRange::GetEndInstructionIndex
size_t GetEndInstructionIndex() const
Get the largest instruction index that has this TSC.
Definition: DecodedThread.cpp:259
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:182
lldb_private::trace_intel_pt::DecodedThread::Append
void Append(const DecodedInstruction &insn)
Append an instruction or a libipt error.
Definition: DecodedThread.cpp:112
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:152
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::trace_intel_pt::DecodedThread::m_errors
llvm::DenseMap< uint64_t, std::string > m_errors
Definition: DecodedThread.h:276
lldb_private::trace_intel_pt::IntelPTError::IntelPTError
IntelPTError(int libipt_error_code, lldb::addr_t address=LLDB_INVALID_ADDRESS)
Definition: DecodedThread.cpp:36
lldb_private::trace_intel_pt::DecodedThread::RecordTscForLastInstruction
void RecordTscForLastInstruction(uint64_t tsc)
Notify this class that the last added instruction or error has an associated TSC.
Definition: DecodedThread.cpp:100
lldb_private::trace_intel_pt::DecodedInstruction::pt_insn
pt_insn pt_insn
Definition: DecodedThread.h:81
TraceIntelPTGDBRemotePackets.h
lldb_private::trace_intel_pt::DecodedThread::GetInstructionLoadAddress
lldb::addr_t GetInstructionLoadAddress(size_t insn_index) const
Definition: DecodedThread.cpp:58
lldb_private::trace_intel_pt::DecodedThread::TscRange::Prev
llvm::Optional< TscRange > Prev() const
Get the previous range chronologically.
Definition: DecodedThread.cpp:276
lldb_private::trace_intel_pt::DecodedThread::m_instruction_timestamps
std::map< uint64_t, uint64_t > m_instruction_timestamps
This map contains the TSCs of the decoded instructions.
Definition: DecodedThread.h:271
lldb_private::trace_intel_pt::DecodedInstruction::DecodedInstruction
DecodedInstruction()
Definition: DecodedThread.h:66
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:166
lldb_private::trace_intel_pt::DecodedThread::m_total_decoding_time
std::chrono::milliseconds m_total_decoding_time
Total amount of time spent decoding.
Definition: DecodedThread.h:286
lldb_private::trace_intel_pt::DecodedThread::TscRange::m_decoded_thread
const DecodedThread * m_decoded_thread
Definition: DecodedThread.h:130
lldb_private::trace_intel_pt::DecodedThread::GetInstructionsCount
size_t GetInstructionsCount() const
Get the total number of instruction pointers from the decoded trace.
Definition: DecodedThread.cpp:54
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::total_count
size_t total_count
Definition: DecodedThread.h:137
lldb_private::trace_intel_pt::IntelPTError::convertToErrorCode
std::error_code convertToErrorCode() const override
Definition: DecodedThread.h:52
lldb_private::trace_intel_pt::DecodedThread::m_instruction_classes
std::vector< pt_insn_class > m_instruction_classes
The libipt instruction class for each instruction.
Definition: DecodedThread.h:263
lldb_private::trace_intel_pt::DecodedThread::TscRange::GetStartInstructionIndex
size_t GetStartInstructionIndex() const
Get the smallest instruction index that has this TSC.
Definition: DecodedThread.cpp:255
lldb_private::trace_intel_pt::DecodedInstruction
Helper struct for building an instruction or error from the decoder.
Definition: DecodedThread.h:65
lldb_private::trace_intel_pt::DecodedThread::TscRange
Definition: DecodedThread.h:101
lldb_private::trace_intel_pt::DecodedThread::EventsStats::total_instructions_with_events
size_t total_instructions_with_events
Definition: DecodedThread.h:148
lldb_private::trace_intel_pt::DecodedThread::GetInstructionControlFlowType
lldb::TraceInstructionControlFlowType GetInstructionControlFlowType(size_t insn_index) const
Get the lldb::TraceInstructionControlFlowType categories of the instruction.
Definition: DecodedThread.cpp:63
lldb_private::trace_intel_pt::DecodedThread::EventsStats::RecordEventsForInstruction
void RecordEventsForInstruction(lldb::TraceEvents events)
Definition: DecodedThread.cpp:170
lldb_private::trace_intel_pt::DecodedThread::RecordTscError
void RecordTscError(int libipt_error_code)
Record an error decoding a TSC timestamp.
Definition: DecodedThread.cpp:157
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
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:256
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:162
lldb_private::trace_intel_pt::DecodedInstruction::DecodedInstruction
DecodedInstruction(int libipt_error_code)
Definition: DecodedThread.h:71
lldb_private::trace_intel_pt::DecodedInstruction::libipt_error
int libipt_error
Definition: DecodedThread.h:78
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:263
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:235
lldb_private::trace_intel_pt::DecodedThread::EventsStats
Definition: DecodedThread.h:143
lldb_private::trace_intel_pt::DecodedThread::GetThread
lldb::ThreadSP GetThread()
Definition: DecodedThread.cpp:98
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
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:128
lldb_private::trace_intel_pt::DecodedThreadSP
std::shared_ptr< DecodedThread > DecodedThreadSP
Definition: DecodedThread.h:289
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:284
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:253
lldb_private::trace_intel_pt::DecodedThread::GetErrorByInstructionIndex
const char * GetErrorByInstructionIndex(size_t ins_idx)
Get the error associated with a given instruction index.
Definition: DecodedThread.cpp:212
lldb_private::trace_intel_pt::IsEndOfStream
bool IsEndOfStream(int libipt_status)
Definition: DecodedThread.cpp:26
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
lldb_private::trace_intel_pt::IsTscUnavailable
bool IsTscUnavailable(int libipt_status)
Definition: DecodedThread.cpp:30
lldb_private::trace_intel_pt::DecodedThread
Definition: DecodedThread.h:91
lldb_private::trace_intel_pt::DecodedThread::EventsStats::events_counts
std::unordered_map< lldb::TraceEvents, size_t > events_counts
A count for each individual event kind.
Definition: DecodedThread.h:146
lldb_private::trace_intel_pt::DecodedInstruction::events
lldb::TraceEvents events
Definition: DecodedThread.h:79
lldb_private::trace_intel_pt::DecodedThread::m_instruction_ips
std::vector< lldb::addr_t > m_instruction_ips
The low level storage of all instruction addresses.
Definition: DecodedThread.h:259
lldb_private::trace_intel_pt::DecodedThread::m_events_stats
EventsStats m_events_stats
Statistics of all tracing events.
Definition: DecodedThread.h:282