LLDB  mainline
LibiptDecoder.cpp
Go to the documentation of this file.
1 //===-- LibiptDecoder.cpp --======-----------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 #include "LibiptDecoder.h"
9 #include "TraceIntelPT.h"
10 #include "lldb/Target/Process.h"
11 
12 using namespace lldb;
13 using namespace lldb_private;
14 using namespace lldb_private::trace_intel_pt;
15 using namespace llvm;
16 
17 bool IsLibiptError(int status) { return status < 0; }
18 
19 bool IsEndOfStream(int status) {
20  assert(status >= 0 && "We can't check if we reached the end of the stream if "
21  "we got a failed status");
22  return status & pts_eos;
23 }
24 
25 bool HasEvents(int status) {
26  assert(status >= 0 && "We can't check for events if we got a failed status");
27  return status & pts_event_pending;
28 }
29 
30 // RAII deleter for libipt's decoders
31 auto InsnDecoderDeleter = [](pt_insn_decoder *decoder) {
32  pt_insn_free_decoder(decoder);
33 };
34 
35 auto QueryDecoderDeleter = [](pt_query_decoder *decoder) {
36  pt_qry_free_decoder(decoder);
37 };
38 
39 using PtInsnDecoderUP =
40  std::unique_ptr<pt_insn_decoder, decltype(InsnDecoderDeleter)>;
41 
42 using PtQueryDecoderUP =
43  std::unique_ptr<pt_query_decoder, decltype(QueryDecoderDeleter)>;
44 
45 /// Create a basic configuration object limited to a given buffer that can be
46 /// used for many different decoders.
47 static Expected<pt_config> CreateBasicLibiptConfig(TraceIntelPT &trace_intel_pt,
48  ArrayRef<uint8_t> buffer) {
49  Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
50  if (!cpu_info)
51  return cpu_info.takeError();
52 
53  pt_config config;
54  pt_config_init(&config);
55  config.cpu = *cpu_info;
56 
57  int status = pt_cpu_errata(&config.errata, &config.cpu);
58  if (IsLibiptError(status))
59  return make_error<IntelPTError>(status);
60 
61  // The libipt library does not modify the trace buffer, hence the
62  // following casts are safe.
63  config.begin = const_cast<uint8_t *>(buffer.data());
64  config.end = const_cast<uint8_t *>(buffer.data() + buffer.size());
65  return config;
66 }
67 
68 /// Callback used by libipt for reading the process memory.
69 ///
70 /// More information can be found in
71 /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md
72 static int ReadProcessMemory(uint8_t *buffer, size_t size,
73  const pt_asid * /* unused */, uint64_t pc,
74  void *context) {
75  Process *process = static_cast<Process *>(context);
76 
77  Status error;
78  int bytes_read = process->ReadMemory(pc, buffer, size, error);
79  if (error.Fail())
80  return -pte_nomap;
81  return bytes_read;
82 }
83 
84 /// Set up the memory image callback for the given decoder.
85 static Error SetupMemoryImage(pt_insn_decoder *decoder, Process &process) {
86  pt_image *image = pt_insn_get_image(decoder);
87 
88  int status = pt_image_set_callback(image, ReadProcessMemory, &process);
89  if (IsLibiptError(status))
90  return make_error<IntelPTError>(status);
91  return Error::success();
92 }
93 
94 /// Create an instruction decoder for the given buffer and the given process.
95 static Expected<PtInsnDecoderUP>
96 CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer,
97  Process &process) {
98  Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer);
99  if (!config)
100  return config.takeError();
101 
102  pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&*config);
103  if (!decoder_ptr)
104  return make_error<IntelPTError>(-pte_nomem);
105 
106  PtInsnDecoderUP decoder_up(decoder_ptr, InsnDecoderDeleter);
107 
108  if (Error err = SetupMemoryImage(decoder_ptr, process))
109  return std::move(err);
110 
111  return decoder_up;
112 }
113 
114 /// Create a query decoder for the given buffer. The query decoder is the
115 /// highest level decoder that operates directly on packets and doesn't perform
116 /// actual instruction decoding. That's why it can be useful for inspecting a
117 /// raw trace without pinning it to a particular process.
118 static Expected<PtQueryDecoderUP>
119 CreateQueryDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) {
120  Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer);
121  if (!config)
122  return config.takeError();
123 
124  pt_query_decoder *decoder_ptr = pt_qry_alloc_decoder(&*config);
125  if (!decoder_ptr)
126  return make_error<IntelPTError>(-pte_nomem);
127 
128  return PtQueryDecoderUP(decoder_ptr, QueryDecoderDeleter);
129 }
130 
131 /// Class that decodes a raw buffer for a single PSB block using the low level
132 /// libipt library. It assumes that kernel and user mode instructions are not
133 /// mixed in the same PSB block.
134 ///
135 /// Throughout this code, the status of the decoder will be used to identify
136 /// events needed to be processed or errors in the decoder. The values can be
137 /// - negative: actual errors
138 /// - positive or zero: not an error, but a list of bits signaling the status
139 /// of the decoder, e.g. whether there are events that need to be decoded or
140 /// not.
142 public:
143  /// \param[in] decoder
144  /// A decoder configured to start and end within the boundaries of the
145  /// given \p psb_block.
146  ///
147  /// \param[in] psb_block
148  /// The PSB block to decode.
149  ///
150  /// \param[in] next_block_ip
151  /// The starting ip at the next PSB block of the same thread if available.
152  ///
153  /// \param[in] decoded_thread
154  /// A \a DecodedThread object where the decoded instructions will be
155  /// appended to. It might have already some instructions.
156  PSBBlockDecoder(PtInsnDecoderUP &&decoder_up, const PSBBlock &psb_block,
157  Optional<lldb::addr_t> next_block_ip,
158  DecodedThread &decoded_thread)
159  : m_decoder_up(std::move(decoder_up)), m_psb_block(psb_block),
160  m_next_block_ip(next_block_ip), m_decoded_thread(decoded_thread) {}
161 
162  /// \param[in] trace_intel_pt
163  /// The main Trace object that own the PSB block.
164  ///
165  /// \param[in] decoder
166  /// A decoder configured to start and end within the boundaries of the
167  /// given \p psb_block.
168  ///
169  /// \param[in] psb_block
170  /// The PSB block to decode.
171  ///
172  /// \param[in] buffer
173  /// The raw intel pt trace for this block.
174  ///
175  /// \param[in] process
176  /// The process to decode. It provides the memory image to use for
177  /// decoding.
178  ///
179  /// \param[in] next_block_ip
180  /// The starting ip at the next PSB block of the same thread if available.
181  ///
182  /// \param[in] decoded_thread
183  /// A \a DecodedThread object where the decoded instructions will be
184  /// appended to. It might have already some instructions.
185  static Expected<PSBBlockDecoder>
186  Create(TraceIntelPT &trace_intel_pt, const PSBBlock &psb_block,
187  ArrayRef<uint8_t> buffer, Process &process,
188  Optional<lldb::addr_t> next_block_ip, DecodedThread &decoded_thread) {
189  Expected<PtInsnDecoderUP> decoder_up =
190  CreateInstructionDecoder(trace_intel_pt, buffer, process);
191  if (!decoder_up)
192  return decoder_up.takeError();
193 
194  return PSBBlockDecoder(std::move(*decoder_up), psb_block, next_block_ip,
195  decoded_thread);
196  }
197 
198  void DecodePSBBlock() {
199  int status = pt_insn_sync_forward(m_decoder_up.get());
200  assert(status >= 0 &&
201  "Synchronization shouldn't fail because this PSB was previously "
202  "decoded correctly.");
203 
204  // We emit a TSC before a sync event to more easily associate a timestamp to
205  // the sync event. If present, the current block's TSC would be the first
206  // TSC we'll see when processing events.
207  if (m_psb_block.tsc)
208  m_decoded_thread.NotifyTsc(*m_psb_block.tsc);
209 
210  m_decoded_thread.NotifySyncPoint(m_psb_block.psb_offset);
211 
212  DecodeInstructionsAndEvents(status);
213  }
214 
215 private:
216  /// Decode all the instructions and events of the given PSB block.
217  ///
218  /// \param[in] status
219  /// The status that was result of synchronizing to the most recent PSB.
220  void DecodeInstructionsAndEvents(int status) {
221  pt_insn insn;
222  while (true) {
223  status = ProcessPTEvents(status);
224 
225  if (IsLibiptError(status))
226  return;
227  else if (IsEndOfStream(status))
228  break;
229 
230  // The status returned by pt_insn_next will need to be processed
231  // by ProcessPTEvents in the next loop if it is not an error.
232  std::memset(&insn, 0, sizeof insn);
233  status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn));
234 
235  if (IsLibiptError(status)) {
236  m_decoded_thread.AppendError(IntelPTError(status, insn.ip));
237  return;
238  } else if (IsEndOfStream(status)) {
239  break;
240  }
241  m_decoded_thread.AppendInstruction(insn);
242  }
243 
244  // We need to keep querying non-branching instructions until we hit the
245  // starting point of the next PSB. We won't see events at this point. This
246  // is based on
247  // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode
248  if (m_next_block_ip && insn.ip != 0) {
249  while (insn.ip != *m_next_block_ip) {
250  m_decoded_thread.AppendInstruction(insn);
251 
252  status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn));
253 
254  if (IsLibiptError(status)) {
255  m_decoded_thread.AppendError(IntelPTError(status, insn.ip));
256  return;
257  }
258  }
259  }
260  }
261 
262  /// Before querying instructions, we need to query the events associated with
263  /// that instruction, e.g. timing and trace disablement events.
264  ///
265  /// \param[in] status
266  /// The status gotten from the previous instruction decoding or PSB
267  /// synchronization.
268  ///
269  /// \return
270  /// The pte_status after decoding events.
271  int ProcessPTEvents(int status) {
272  while (HasEvents(status)) {
273  pt_event event;
274  std::memset(&event, 0, sizeof event);
275  status = pt_insn_event(m_decoder_up.get(), &event, sizeof(event));
276 
277  if (IsLibiptError(status)) {
278  m_decoded_thread.AppendError(IntelPTError(status));
279  return status;
280  }
281 
282  if (event.has_tsc)
283  m_decoded_thread.NotifyTsc(event.tsc);
284 
285  switch (event.type) {
286  case ptev_disabled:
287  // The CPU paused tracing the program, e.g. due to ip filtering.
288  m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledHW);
289  break;
290  case ptev_async_disabled:
291  // The kernel or user code paused tracing the program, e.g.
292  // a breakpoint or a ioctl invocation pausing the trace, or a
293  // context switch happened.
294  m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledSW);
295  break;
296  case ptev_overflow:
297  // The CPU internal buffer had an overflow error and some instructions
298  // were lost.
299  m_decoded_thread.AppendError(IntelPTError(-pte_overflow));
300  break;
301  default:
302  break;
303  }
304  }
305 
306  return status;
307  }
308 
309 private:
312  Optional<lldb::addr_t> m_next_block_ip;
314 };
315 
317  DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
318  ArrayRef<uint8_t> buffer) {
319  Expected<std::vector<PSBBlock>> blocks =
320  SplitTraceIntoPSBBlock(trace_intel_pt, buffer, /*expect_tscs=*/false);
321  if (!blocks)
322  return blocks.takeError();
323 
324  for (size_t i = 0; i < blocks->size(); i++) {
325  PSBBlock &block = blocks->at(i);
326 
327  Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create(
328  trace_intel_pt, block, buffer.slice(block.psb_offset, block.size),
329  *decoded_thread.GetThread()->GetProcess(),
330  i + 1 < blocks->size() ? blocks->at(i + 1).starting_ip : None,
331  decoded_thread);
332  if (!decoder)
333  return decoder.takeError();
334 
335  decoder->DecodePSBBlock();
336  }
337 
338  return Error::success();
339 }
340 
342  DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
343  const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers,
344  const std::vector<IntelPTThreadContinousExecution> &executions) {
345  bool has_seen_psbs = false;
346  for (size_t i = 0; i < executions.size(); i++) {
347  const IntelPTThreadContinousExecution &execution = executions[i];
348 
349  auto variant = execution.thread_execution.variant;
350 
351  // We emit the first valid tsc
352  if (execution.psb_blocks.empty()) {
353  decoded_thread.NotifyTsc(execution.thread_execution.GetLowestKnownTSC());
354  } else {
355  assert(execution.psb_blocks.front().tsc &&
356  "per cpu decoding expects TSCs");
357  decoded_thread.NotifyTsc(
358  std::min(execution.thread_execution.GetLowestKnownTSC(),
359  *execution.psb_blocks.front().tsc));
360  }
361 
362  // We then emit the CPU, which will be correctly associated with a tsc.
363  decoded_thread.NotifyCPU(execution.thread_execution.cpu_id);
364 
365  // If we haven't seen a PSB yet, then it's fine not to show errors
366  if (has_seen_psbs) {
367  if (execution.psb_blocks.empty()) {
368  decoded_thread.AppendCustomError(
369  formatv("Unable to find intel pt data a thread "
370  "execution on cpu id = {0}",
371  execution.thread_execution.cpu_id)
372  .str());
373  }
374 
375  // A hinted start is a non-initial execution that doesn't have a switch
376  // in. An only end is an initial execution that doesn't have a switch in.
377  // Any of those cases represent a gap because we have seen a PSB before.
378  if (variant == ThreadContinuousExecution::Variant::HintedStart ||
379  variant == ThreadContinuousExecution::Variant::OnlyEnd) {
380  decoded_thread.AppendCustomError(
381  formatv("Unable to find the context switch in for a thread "
382  "execution on cpu id = {0}",
383  execution.thread_execution.cpu_id)
384  .str());
385  }
386  }
387 
388  for (size_t j = 0; j < execution.psb_blocks.size(); j++) {
389  const PSBBlock &psb_block = execution.psb_blocks[j];
390 
391  Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create(
392  trace_intel_pt, psb_block,
393  buffers.lookup(executions[i].thread_execution.cpu_id)
394  .slice(psb_block.psb_offset, psb_block.size),
395  *decoded_thread.GetThread()->GetProcess(),
396  j + 1 < execution.psb_blocks.size()
397  ? execution.psb_blocks[j + 1].starting_ip
398  : None,
399  decoded_thread);
400  if (!decoder)
401  return decoder.takeError();
402 
403  has_seen_psbs = true;
404  decoder->DecodePSBBlock();
405  }
406 
407  // If we haven't seen a PSB yet, then it's fine not to show errors
408  if (has_seen_psbs) {
409  // A hinted end is a non-ending execution that doesn't have a switch out.
410  // An only start is an ending execution that doesn't have a switch out.
411  // Any of those cases represent a gap if we still have executions to
412  // process and we have seen a PSB before.
413  if (i + 1 != executions.size() &&
414  (variant == ThreadContinuousExecution::Variant::OnlyStart ||
415  variant == ThreadContinuousExecution::Variant::HintedEnd)) {
416  decoded_thread.AppendCustomError(
417  formatv("Unable to find the context switch out for a thread "
418  "execution on cpu id = {0}",
419  execution.thread_execution.cpu_id)
420  .str());
421  }
422  }
423  }
424  return Error::success();
425 }
426 
428  const IntelPTThreadContinousExecution &o) const {
429  // As the context switch might be incomplete, we look first for the first real
430  // PSB packet, which is a valid TSC. Otherwise, We query the thread execution
431  // itself for some tsc.
432  auto get_tsc = [](const IntelPTThreadContinousExecution &exec) {
433  return exec.psb_blocks.empty() ? exec.thread_execution.GetLowestKnownTSC()
434  : exec.psb_blocks.front().tsc;
435  };
436 
437  return get_tsc(*this) < get_tsc(o);
438 }
439 
440 Expected<std::vector<PSBBlock>>
442  TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer,
443  bool expect_tscs) {
444  // This follows
445  // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode
446 
447  Expected<PtQueryDecoderUP> decoder_up =
448  CreateQueryDecoder(trace_intel_pt, buffer);
449  if (!decoder_up)
450  return decoder_up.takeError();
451 
452  pt_query_decoder *decoder = decoder_up.get().get();
453 
454  std::vector<PSBBlock> executions;
455 
456  while (true) {
457  uint64_t maybe_ip = LLDB_INVALID_ADDRESS;
458  int decoding_status = pt_qry_sync_forward(decoder, &maybe_ip);
459  if (IsLibiptError(decoding_status))
460  break;
461 
462  uint64_t psb_offset;
463  int offset_status = pt_qry_get_sync_offset(decoder, &psb_offset);
464  assert(offset_status >= 0 &&
465  "This can't fail because we were able to synchronize");
466 
467  Optional<uint64_t> ip;
468  if (!(pts_ip_suppressed & decoding_status))
469  ip = maybe_ip;
470 
471  Optional<uint64_t> tsc;
472  // Now we fetch the first TSC that comes after the PSB.
473  while (HasEvents(decoding_status)) {
474  pt_event event;
475  decoding_status = pt_qry_event(decoder, &event, sizeof(event));
476  if (IsLibiptError(decoding_status))
477  break;
478  if (event.has_tsc) {
479  tsc = event.tsc;
480  break;
481  }
482  }
483  if (IsLibiptError(decoding_status)) {
484  // We continue to the next PSB. This effectively merges this PSB with the
485  // previous one, and that should be fine because this PSB might be the
486  // direct continuation of the previous thread and it's better to show an
487  // error in the decoded thread than to hide it. If this is the first PSB,
488  // we are okay losing it. Besides that, an error at processing events
489  // means that we wouldn't be able to get any instruction out of it.
490  continue;
491  }
492 
493  if (expect_tscs && !tsc)
494  return createStringError(inconvertibleErrorCode(),
495  "Found a PSB without TSC.");
496 
497  executions.push_back({
498  psb_offset,
499  tsc,
500  0,
501  ip,
502  });
503  }
504  if (!executions.empty()) {
505  // We now adjust the sizes of each block
506  executions.back().size = buffer.size() - executions.back().psb_offset;
507  for (int i = (int)executions.size() - 2; i >= 0; i--) {
508  executions[i].size =
509  executions[i + 1].psb_offset - executions[i].psb_offset;
510  }
511  }
512  return executions;
513 }
514 
515 Expected<Optional<uint64_t>>
517  ArrayRef<uint8_t> buffer) {
518  Expected<PtQueryDecoderUP> decoder_up =
519  CreateQueryDecoder(trace_intel_pt, buffer);
520  if (!decoder_up)
521  return decoder_up.takeError();
522 
523  pt_query_decoder *decoder = decoder_up.get().get();
524  uint64_t ip = LLDB_INVALID_ADDRESS;
525  int status = pt_qry_sync_forward(decoder, &ip);
526  if (IsLibiptError(status))
527  return None;
528 
529  while (HasEvents(status)) {
530  pt_event event;
531  status = pt_qry_event(decoder, &event, sizeof(event));
532  if (IsLibiptError(status))
533  return None;
534  if (event.has_tsc)
535  return event.tsc;
536  }
537  return None;
538 }
InsnDecoderDeleter
auto InsnDecoderDeleter
Definition: LibiptDecoder.cpp:31
llvm
Definition: Debugger.h:50
PtInsnDecoderUP
std::unique_ptr< pt_insn_decoder, decltype(InsnDecoderDeleter)> PtInsnDecoderUP
Definition: LibiptDecoder.cpp:40
lldb_private::trace_intel_pt::ThreadContinuousExecution::GetLowestKnownTSC
uint64_t GetLowestKnownTSC() const
Definition: PerfContextSwitchDecoder.cpp:100
lldb_private::Process::ReadMemory
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
Definition: Process.cpp:1922
lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread
llvm::Error DecodeSystemWideTraceForThread(DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, const llvm::DenseMap< lldb::cpu_id_t, llvm::ArrayRef< uint8_t >> &buffers, const std::vector< IntelPTThreadContinousExecution > &executions)
Decode a raw Intel PT trace for a single thread that was collected in a per cpu core basis.
PSBBlockDecoder::m_decoded_thread
DecodedThread & m_decoded_thread
Definition: LibiptDecoder.cpp:313
lldb_private::trace_intel_pt::IntelPTThreadContinousExecution::thread_execution
ThreadContinuousExecution thread_execution
Definition: LibiptDecoder.h:42
PSBBlockDecoder::DecodePSBBlock
void DecodePSBBlock()
Definition: LibiptDecoder.cpp:198
IsEndOfStream
bool IsEndOfStream(int status)
Definition: LibiptDecoder.cpp:19
lldb_private::Process
Definition: Process.h:338
LibiptDecoder.h
lldb_private::trace_intel_pt::SplitTraceIntoPSBBlock
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.
Definition: LibiptDecoder.cpp:441
lldb_private::trace_intel_pt::TraceIntelPT
Definition: TraceIntelPT.h:23
PSBBlockDecoder::DecodeInstructionsAndEvents
void DecodeInstructionsAndEvents(int status)
Decode all the instructions and events of the given PSB block.
Definition: LibiptDecoder.cpp:220
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
Process.h
lldb_private::trace_intel_pt::ThreadContinuousExecution::cpu_id
lldb::cpu_id_t cpu_id
Definition: PerfContextSwitchDecoder.h:110
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::trace_intel_pt::ThreadContinuousExecution::variant
enum lldb_private::trace_intel_pt::ThreadContinuousExecution::Variant variant
lldb_private::trace_intel_pt::PSBBlock::psb_offset
uint64_t psb_offset
The memory offset of a PSB packet that is a synchronization point for the decoder.
Definition: LibiptDecoder.h:26
PSBBlockDecoder::m_decoder_up
PtInsnDecoderUP m_decoder_up
Definition: LibiptDecoder.cpp:310
CreateQueryDecoder
static Expected< PtQueryDecoderUP > CreateQueryDecoder(TraceIntelPT &trace_intel_pt, ArrayRef< uint8_t > buffer)
Create a query decoder for the given buffer.
Definition: LibiptDecoder.cpp:119
PSBBlockDecoder::Create
static Expected< PSBBlockDecoder > Create(TraceIntelPT &trace_intel_pt, const PSBBlock &psb_block, ArrayRef< uint8_t > buffer, Process &process, Optional< lldb::addr_t > next_block_ip, DecodedThread &decoded_thread)
Definition: LibiptDecoder.cpp:186
PSBBlockDecoder
Class that decodes a raw buffer for a single PSB block using the low level libipt library.
Definition: LibiptDecoder.cpp:141
SetupMemoryImage
static Error SetupMemoryImage(pt_insn_decoder *decoder, Process &process)
Set up the memory image callback for the given decoder.
Definition: LibiptDecoder.cpp:85
lldb_private::trace_intel_pt::IntelPTError
Class for representing a libipt decoding error.
Definition: DecodedThread.h:24
PSBBlockDecoder::ProcessPTEvents
int ProcessPTEvents(int status)
Before querying instructions, we need to query the events associated with that instruction,...
Definition: LibiptDecoder.cpp:271
lldb_private::Status
Definition: Status.h:44
uint32_t
lldb_private::trace_intel_pt::DecodedThread::NotifyTsc
void NotifyTsc(TSC tsc)
Notify this object that a new tsc has been seen.
Definition: DecodedThread.cpp:117
PSBBlockDecoder::PSBBlockDecoder
PSBBlockDecoder(PtInsnDecoderUP &&decoder_up, const PSBBlock &psb_block, Optional< lldb::addr_t > next_block_ip, DecodedThread &decoded_thread)
Definition: LibiptDecoder.cpp:156
lldb::eTraceEventDisabledHW
@ eTraceEventDisabledHW
Tracing was disable for some time due to a hardware trigger.
Definition: lldb-enumerations.h:1167
lldb_private::trace_intel_pt::IntelPTThreadContinousExecution::psb_blocks
std::vector< PSBBlock > psb_blocks
Definition: LibiptDecoder.h:43
QueryDecoderDeleter
auto QueryDecoderDeleter
Definition: LibiptDecoder.cpp:35
lldb_private::trace_intel_pt::PSBBlock
This struct represents a contiguous section of a trace that starts at a PSB and ends right before the...
Definition: LibiptDecoder.h:22
lldb_private::operator<
bool operator<(const Address &lhs, const Address &rhs)
Definition: Address.cpp:985
IsLibiptError
bool IsLibiptError(int status)
Definition: LibiptDecoder.cpp:17
lldb_private::trace_intel_pt::DecodedThread::GetThread
lldb::ThreadSP GetThread()
Definition: DecodedThread.cpp:99
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:144
HasEvents
bool HasEvents(int status)
Definition: LibiptDecoder.cpp:25
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
CreateBasicLibiptConfig
static Expected< pt_config > CreateBasicLibiptConfig(TraceIntelPT &trace_intel_pt, ArrayRef< uint8_t > buffer)
Create a basic configuration object limited to a given buffer that can be used for many different dec...
Definition: LibiptDecoder.cpp:47
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
PSBBlockDecoder::m_psb_block
PSBBlock m_psb_block
Definition: LibiptDecoder.cpp:311
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:41
lldb_private::trace_intel_pt::TraceIntelPT::GetCPUInfo
llvm::Expected< pt_cpu > GetCPUInfo()
Get or fetch the cpu information from, for example, /proc/cpuinfo.
Definition: TraceIntelPT.cpp:459
lldb_private::trace_intel_pt::PSBBlock::size
uint64_t size
Size in bytes of this block.
Definition: LibiptDecoder.h:30
lldb_private::trace_intel_pt::DecodedThread
Definition: DecodedThread.h:60
lldb_private::trace_intel_pt
Definition: CommandObjectTraceStartIntelPT.h:18
lldb_private::trace_intel_pt::FindLowestTSCInTrace
llvm::Expected< llvm::Optional< uint64_t > > FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, llvm::ArrayRef< uint8_t > buffer)
Find the lowest TSC in the given trace.
PSBBlockDecoder::m_next_block_ip
Optional< lldb::addr_t > m_next_block_ip
Definition: LibiptDecoder.cpp:312
lldb_private::trace_intel_pt::DecodedThread::AppendCustomError
void AppendCustomError(llvm::StringRef error)
Append a custom decoding.
Definition: DecodedThread.cpp:187
lldb::eTraceEventDisabledSW
@ eTraceEventDisabledSW
Tracing was disabled for some time due to a software trigger.
Definition: lldb-enumerations.h:1165
PtQueryDecoderUP
std::unique_ptr< pt_query_decoder, decltype(QueryDecoderDeleter)> PtQueryDecoderUP
Definition: LibiptDecoder.cpp:43
ReadProcessMemory
static int ReadProcessMemory(uint8_t *buffer, size_t size, const pt_asid *, uint64_t pc, void *context)
Callback used by libipt for reading the process memory.
Definition: LibiptDecoder.cpp:72
lldb
Definition: SBAddress.h:15
TraceIntelPT.h
lldb_private::trace_intel_pt::DecodeSingleTraceForThread
llvm::Error DecodeSingleTraceForThread(DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, llvm::ArrayRef< uint8_t > buffer)
Decode a raw Intel PT trace for a single thread given in buffer and append the decoded instructions a...
CreateInstructionDecoder
static Expected< PtInsnDecoderUP > CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, ArrayRef< uint8_t > buffer, Process &process)
Create an instruction decoder for the given buffer and the given process.
Definition: LibiptDecoder.cpp:96