Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp
39645 views
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
#include <optional>
12
13
using namespace lldb;
14
using namespace lldb_private;
15
using namespace lldb_private::trace_intel_pt;
16
using namespace llvm;
17
18
bool IsLibiptError(int status) { return status < 0; }
19
20
bool IsEndOfStream(int status) {
21
assert(status >= 0 && "We can't check if we reached the end of the stream if "
22
"we got a failed status");
23
return status & pts_eos;
24
}
25
26
bool HasEvents(int status) {
27
assert(status >= 0 && "We can't check for events if we got a failed status");
28
return status & pts_event_pending;
29
}
30
31
// RAII deleter for libipt's decoders
32
auto InsnDecoderDeleter = [](pt_insn_decoder *decoder) {
33
pt_insn_free_decoder(decoder);
34
};
35
36
auto QueryDecoderDeleter = [](pt_query_decoder *decoder) {
37
pt_qry_free_decoder(decoder);
38
};
39
40
using PtInsnDecoderUP =
41
std::unique_ptr<pt_insn_decoder, decltype(InsnDecoderDeleter)>;
42
43
using PtQueryDecoderUP =
44
std::unique_ptr<pt_query_decoder, decltype(QueryDecoderDeleter)>;
45
46
/// Create a basic configuration object limited to a given buffer that can be
47
/// used for many different decoders.
48
static Expected<pt_config> CreateBasicLibiptConfig(TraceIntelPT &trace_intel_pt,
49
ArrayRef<uint8_t> buffer) {
50
Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
51
if (!cpu_info)
52
return cpu_info.takeError();
53
54
pt_config config;
55
pt_config_init(&config);
56
config.cpu = *cpu_info;
57
58
int status = pt_cpu_errata(&config.errata, &config.cpu);
59
if (IsLibiptError(status))
60
return make_error<IntelPTError>(status);
61
62
// The libipt library does not modify the trace buffer, hence the
63
// following casts are safe.
64
config.begin = const_cast<uint8_t *>(buffer.data());
65
config.end = const_cast<uint8_t *>(buffer.data() + buffer.size());
66
return config;
67
}
68
69
/// Callback used by libipt for reading the process memory.
70
///
71
/// More information can be found in
72
/// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md
73
static int ReadProcessMemory(uint8_t *buffer, size_t size,
74
const pt_asid * /* unused */, uint64_t pc,
75
void *context) {
76
Process *process = static_cast<Process *>(context);
77
78
Status error;
79
int bytes_read = process->ReadMemory(pc, buffer, size, error);
80
if (error.Fail())
81
return -pte_nomap;
82
return bytes_read;
83
}
84
85
/// Set up the memory image callback for the given decoder.
86
static Error SetupMemoryImage(pt_insn_decoder *decoder, Process &process) {
87
pt_image *image = pt_insn_get_image(decoder);
88
89
int status = pt_image_set_callback(image, ReadProcessMemory, &process);
90
if (IsLibiptError(status))
91
return make_error<IntelPTError>(status);
92
return Error::success();
93
}
94
95
/// Create an instruction decoder for the given buffer and the given process.
96
static Expected<PtInsnDecoderUP>
97
CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer,
98
Process &process) {
99
Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer);
100
if (!config)
101
return config.takeError();
102
103
pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&*config);
104
if (!decoder_ptr)
105
return make_error<IntelPTError>(-pte_nomem);
106
107
PtInsnDecoderUP decoder_up(decoder_ptr, InsnDecoderDeleter);
108
109
if (Error err = SetupMemoryImage(decoder_ptr, process))
110
return std::move(err);
111
112
return decoder_up;
113
}
114
115
/// Create a query decoder for the given buffer. The query decoder is the
116
/// highest level decoder that operates directly on packets and doesn't perform
117
/// actual instruction decoding. That's why it can be useful for inspecting a
118
/// raw trace without pinning it to a particular process.
119
static Expected<PtQueryDecoderUP>
120
CreateQueryDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) {
121
Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer);
122
if (!config)
123
return config.takeError();
124
125
pt_query_decoder *decoder_ptr = pt_qry_alloc_decoder(&*config);
126
if (!decoder_ptr)
127
return make_error<IntelPTError>(-pte_nomem);
128
129
return PtQueryDecoderUP(decoder_ptr, QueryDecoderDeleter);
130
}
131
132
/// Class used to identify anomalies in traces, which should often indicate a
133
/// fatal error in the trace.
134
class PSBBlockAnomalyDetector {
135
public:
136
PSBBlockAnomalyDetector(pt_insn_decoder &decoder,
137
TraceIntelPT &trace_intel_pt,
138
DecodedThread &decoded_thread)
139
: m_decoder(decoder), m_decoded_thread(decoded_thread) {
140
m_infinite_decoding_loop_threshold =
141
trace_intel_pt.GetGlobalProperties()
142
.GetInfiniteDecodingLoopVerificationThreshold();
143
m_extremely_large_decoding_threshold =
144
trace_intel_pt.GetGlobalProperties()
145
.GetExtremelyLargeDecodingThreshold();
146
m_next_infinite_decoding_loop_threshold =
147
m_infinite_decoding_loop_threshold;
148
}
149
150
/// \return
151
/// An \a llvm::Error if an anomaly that includes the last instruction item
152
/// in the trace, or \a llvm::Error::success otherwise.
153
Error DetectAnomaly() {
154
RefreshPacketOffset();
155
uint64_t insn_added_since_last_packet_offset =
156
m_decoded_thread.GetTotalInstructionCount() -
157
m_insn_count_at_last_packet_offset;
158
159
// We want to check if we might have fallen in an infinite loop. As this
160
// check is not a no-op, we want to do it when we have a strong suggestion
161
// that things went wrong. First, we check how many instructions we have
162
// decoded since we processed an Intel PT packet for the last time. This
163
// number should be low, because at some point we should see branches, jumps
164
// or interrupts that require a new packet to be processed. Once we reach
165
// certain threshold we start analyzing the trace.
166
//
167
// We use the number of decoded instructions since the last Intel PT packet
168
// as a proxy because, in fact, we don't expect a single packet to give,
169
// say, 100k instructions. That would mean that there are 100k sequential
170
// instructions without any single branch, which is highly unlikely, or that
171
// we found an infinite loop using direct jumps, e.g.
172
//
173
// 0x0A: nop or pause
174
// 0x0C: jump to 0x0A
175
//
176
// which is indeed code that is found in the kernel. I presume we reach
177
// this kind of code in the decoder because we don't handle self-modified
178
// code in post-mortem kernel traces.
179
//
180
// We are right now only signaling the anomaly as a trace error, but it
181
// would be more conservative to also discard all the trace items found in
182
// this PSB. I prefer not to do that for the time being to give more
183
// exposure to this kind of anomalies and help debugging. Discarding the
184
// trace items would just make investigation harded.
185
//
186
// Finally, if the user wants to see if a specific thread has an anomaly,
187
// it's enough to run the `thread trace dump info` command and look for the
188
// count of this kind of errors.
189
190
if (insn_added_since_last_packet_offset >=
191
m_extremely_large_decoding_threshold) {
192
// In this case, we have decoded a massive amount of sequential
193
// instructions that don't loop. Honestly I wonder if this will ever
194
// happen, but better safe than sorry.
195
return createStringError(
196
inconvertibleErrorCode(),
197
"anomalous trace: possible infinite trace detected");
198
}
199
if (insn_added_since_last_packet_offset ==
200
m_next_infinite_decoding_loop_threshold) {
201
if (std::optional<uint64_t> loop_size = TryIdentifyInfiniteLoop()) {
202
return createStringError(
203
inconvertibleErrorCode(),
204
"anomalous trace: possible infinite loop detected of size %" PRIu64,
205
*loop_size);
206
}
207
m_next_infinite_decoding_loop_threshold *= 2;
208
}
209
return Error::success();
210
}
211
212
private:
213
std::optional<uint64_t> TryIdentifyInfiniteLoop() {
214
// The infinite decoding loops we'll encounter are due to sequential
215
// instructions that repeat themselves due to direct jumps, therefore in a
216
// cycle each individual address will only appear once. We use this
217
// information to detect cycles by finding the last 2 ocurrences of the last
218
// instruction added to the trace. Then we traverse the trace making sure
219
// that these two instructions where the ends of a repeating loop.
220
221
// This is a utility that returns the most recent instruction index given a
222
// position in the trace. If the given position is an instruction, that
223
// position is returned. It skips non-instruction items.
224
auto most_recent_insn_index =
225
[&](uint64_t item_index) -> std::optional<uint64_t> {
226
while (true) {
227
if (m_decoded_thread.GetItemKindByIndex(item_index) ==
228
lldb::eTraceItemKindInstruction) {
229
return item_index;
230
}
231
if (item_index == 0)
232
return std::nullopt;
233
item_index--;
234
}
235
return std::nullopt;
236
};
237
// Similar to most_recent_insn_index but skips the starting position.
238
auto prev_insn_index = [&](uint64_t item_index) -> std::optional<uint64_t> {
239
if (item_index == 0)
240
return std::nullopt;
241
return most_recent_insn_index(item_index - 1);
242
};
243
244
// We first find the most recent instruction.
245
std::optional<uint64_t> last_insn_index_opt =
246
*prev_insn_index(m_decoded_thread.GetItemsCount());
247
if (!last_insn_index_opt)
248
return std::nullopt;
249
uint64_t last_insn_index = *last_insn_index_opt;
250
251
// We then find the most recent previous occurrence of that last
252
// instruction.
253
std::optional<uint64_t> last_insn_copy_index =
254
prev_insn_index(last_insn_index);
255
uint64_t loop_size = 1;
256
while (last_insn_copy_index &&
257
m_decoded_thread.GetInstructionLoadAddress(*last_insn_copy_index) !=
258
m_decoded_thread.GetInstructionLoadAddress(last_insn_index)) {
259
last_insn_copy_index = prev_insn_index(*last_insn_copy_index);
260
loop_size++;
261
}
262
if (!last_insn_copy_index)
263
return std::nullopt;
264
265
// Now we check if the segment between these last positions of the last
266
// instruction address is in fact a repeating loop.
267
uint64_t loop_elements_visited = 1;
268
uint64_t insn_index_a = last_insn_index,
269
insn_index_b = *last_insn_copy_index;
270
while (loop_elements_visited < loop_size) {
271
if (std::optional<uint64_t> prev = prev_insn_index(insn_index_a))
272
insn_index_a = *prev;
273
else
274
return std::nullopt;
275
if (std::optional<uint64_t> prev = prev_insn_index(insn_index_b))
276
insn_index_b = *prev;
277
else
278
return std::nullopt;
279
if (m_decoded_thread.GetInstructionLoadAddress(insn_index_a) !=
280
m_decoded_thread.GetInstructionLoadAddress(insn_index_b))
281
return std::nullopt;
282
loop_elements_visited++;
283
}
284
return loop_size;
285
}
286
287
// Refresh the internal counters if a new packet offset has been visited
288
void RefreshPacketOffset() {
289
lldb::addr_t new_packet_offset;
290
if (!IsLibiptError(pt_insn_get_offset(&m_decoder, &new_packet_offset)) &&
291
new_packet_offset != m_last_packet_offset) {
292
m_last_packet_offset = new_packet_offset;
293
m_next_infinite_decoding_loop_threshold =
294
m_infinite_decoding_loop_threshold;
295
m_insn_count_at_last_packet_offset =
296
m_decoded_thread.GetTotalInstructionCount();
297
}
298
}
299
300
pt_insn_decoder &m_decoder;
301
DecodedThread &m_decoded_thread;
302
lldb::addr_t m_last_packet_offset = LLDB_INVALID_ADDRESS;
303
uint64_t m_insn_count_at_last_packet_offset = 0;
304
uint64_t m_infinite_decoding_loop_threshold;
305
uint64_t m_next_infinite_decoding_loop_threshold;
306
uint64_t m_extremely_large_decoding_threshold;
307
};
308
309
/// Class that decodes a raw buffer for a single PSB block using the low level
310
/// libipt library. It assumes that kernel and user mode instructions are not
311
/// mixed in the same PSB block.
312
///
313
/// Throughout this code, the status of the decoder will be used to identify
314
/// events needed to be processed or errors in the decoder. The values can be
315
/// - negative: actual errors
316
/// - positive or zero: not an error, but a list of bits signaling the status
317
/// of the decoder, e.g. whether there are events that need to be decoded or
318
/// not.
319
class PSBBlockDecoder {
320
public:
321
/// \param[in] decoder
322
/// A decoder configured to start and end within the boundaries of the
323
/// given \p psb_block.
324
///
325
/// \param[in] psb_block
326
/// The PSB block to decode.
327
///
328
/// \param[in] next_block_ip
329
/// The starting ip at the next PSB block of the same thread if available.
330
///
331
/// \param[in] decoded_thread
332
/// A \a DecodedThread object where the decoded instructions will be
333
/// appended to. It might have already some instructions.
334
///
335
/// \param[in] tsc_upper_bound
336
/// Maximum allowed value of TSCs decoded from this PSB block.
337
/// Any of this PSB's data occurring after this TSC will be excluded.
338
PSBBlockDecoder(PtInsnDecoderUP &&decoder_up, const PSBBlock &psb_block,
339
std::optional<lldb::addr_t> next_block_ip,
340
DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
341
std::optional<DecodedThread::TSC> tsc_upper_bound)
342
: m_decoder_up(std::move(decoder_up)), m_psb_block(psb_block),
343
m_next_block_ip(next_block_ip), m_decoded_thread(decoded_thread),
344
m_anomaly_detector(*m_decoder_up, trace_intel_pt, decoded_thread),
345
m_tsc_upper_bound(tsc_upper_bound) {}
346
347
/// \param[in] trace_intel_pt
348
/// The main Trace object that own the PSB block.
349
///
350
/// \param[in] decoder
351
/// A decoder configured to start and end within the boundaries of the
352
/// given \p psb_block.
353
///
354
/// \param[in] psb_block
355
/// The PSB block to decode.
356
///
357
/// \param[in] buffer
358
/// The raw intel pt trace for this block.
359
///
360
/// \param[in] process
361
/// The process to decode. It provides the memory image to use for
362
/// decoding.
363
///
364
/// \param[in] next_block_ip
365
/// The starting ip at the next PSB block of the same thread if available.
366
///
367
/// \param[in] decoded_thread
368
/// A \a DecodedThread object where the decoded instructions will be
369
/// appended to. It might have already some instructions.
370
static Expected<PSBBlockDecoder>
371
Create(TraceIntelPT &trace_intel_pt, const PSBBlock &psb_block,
372
ArrayRef<uint8_t> buffer, Process &process,
373
std::optional<lldb::addr_t> next_block_ip,
374
DecodedThread &decoded_thread,
375
std::optional<DecodedThread::TSC> tsc_upper_bound) {
376
Expected<PtInsnDecoderUP> decoder_up =
377
CreateInstructionDecoder(trace_intel_pt, buffer, process);
378
if (!decoder_up)
379
return decoder_up.takeError();
380
381
return PSBBlockDecoder(std::move(*decoder_up), psb_block, next_block_ip,
382
decoded_thread, trace_intel_pt, tsc_upper_bound);
383
}
384
385
void DecodePSBBlock() {
386
int status = pt_insn_sync_forward(m_decoder_up.get());
387
assert(status >= 0 &&
388
"Synchronization shouldn't fail because this PSB was previously "
389
"decoded correctly.");
390
391
// We emit a TSC before a sync event to more easily associate a timestamp to
392
// the sync event. If present, the current block's TSC would be the first
393
// TSC we'll see when processing events.
394
if (m_psb_block.tsc)
395
m_decoded_thread.NotifyTsc(*m_psb_block.tsc);
396
397
m_decoded_thread.NotifySyncPoint(m_psb_block.psb_offset);
398
399
DecodeInstructionsAndEvents(status);
400
}
401
402
private:
403
/// Append an instruction and return \b false if and only if a serious anomaly
404
/// has been detected.
405
bool AppendInstructionAndDetectAnomalies(const pt_insn &insn) {
406
m_decoded_thread.AppendInstruction(insn);
407
408
if (Error err = m_anomaly_detector.DetectAnomaly()) {
409
m_decoded_thread.AppendCustomError(toString(std::move(err)),
410
/*fatal=*/true);
411
return false;
412
}
413
return true;
414
}
415
/// Decode all the instructions and events of the given PSB block. The
416
/// decoding loop might stop abruptly if an infinite decoding loop is
417
/// detected.
418
void DecodeInstructionsAndEvents(int status) {
419
pt_insn insn;
420
421
while (true) {
422
status = ProcessPTEvents(status);
423
424
if (IsLibiptError(status))
425
return;
426
else if (IsEndOfStream(status))
427
break;
428
429
// The status returned by pt_insn_next will need to be processed
430
// by ProcessPTEvents in the next loop if it is not an error.
431
std::memset(&insn, 0, sizeof insn);
432
status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn));
433
434
if (IsLibiptError(status)) {
435
m_decoded_thread.AppendError(IntelPTError(status, insn.ip));
436
return;
437
} else if (IsEndOfStream(status)) {
438
break;
439
}
440
441
if (!AppendInstructionAndDetectAnomalies(insn))
442
return;
443
}
444
445
// We need to keep querying non-branching instructions until we hit the
446
// starting point of the next PSB. We won't see events at this point. This
447
// is based on
448
// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode
449
if (m_next_block_ip && insn.ip != 0) {
450
while (insn.ip != *m_next_block_ip) {
451
if (!AppendInstructionAndDetectAnomalies(insn))
452
return;
453
454
status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn));
455
456
if (IsLibiptError(status)) {
457
m_decoded_thread.AppendError(IntelPTError(status, insn.ip));
458
return;
459
}
460
}
461
}
462
}
463
464
/// Process the TSC of a decoded PT event. Specifically, check if this TSC
465
/// is below the TSC upper bound for this PSB. If the TSC exceeds the upper
466
/// bound, return an error to abort decoding. Otherwise add the it to the
467
/// underlying DecodedThread and decoding should continue as expected.
468
///
469
/// \param[in] tsc
470
/// The TSC of the a decoded event.
471
Error ProcessPTEventTSC(DecodedThread::TSC tsc) {
472
if (m_tsc_upper_bound && tsc >= *m_tsc_upper_bound) {
473
// This event and all the remaining events of this PSB have a TSC
474
// outside the range of the "owning" ThreadContinuousExecution. For
475
// now we drop all of these events/instructions, future work can
476
// improve upon this by determining the "owning"
477
// ThreadContinuousExecution of the remaining PSB data.
478
std::string err_msg = formatv("decoding truncated: TSC {0} exceeds "
479
"maximum TSC value {1}, will skip decoding"
480
" the remaining data of the PSB",
481
tsc, *m_tsc_upper_bound)
482
.str();
483
484
uint64_t offset;
485
int status = pt_insn_get_offset(m_decoder_up.get(), &offset);
486
if (!IsLibiptError(status)) {
487
err_msg = formatv("{2} (skipping {0} of {1} bytes)", offset,
488
m_psb_block.size, err_msg)
489
.str();
490
}
491
m_decoded_thread.AppendCustomError(err_msg);
492
return createStringError(inconvertibleErrorCode(), err_msg);
493
} else {
494
m_decoded_thread.NotifyTsc(tsc);
495
return Error::success();
496
}
497
}
498
499
/// Before querying instructions, we need to query the events associated with
500
/// that instruction, e.g. timing and trace disablement events.
501
///
502
/// \param[in] status
503
/// The status gotten from the previous instruction decoding or PSB
504
/// synchronization.
505
///
506
/// \return
507
/// The pte_status after decoding events.
508
int ProcessPTEvents(int status) {
509
while (HasEvents(status)) {
510
pt_event event;
511
std::memset(&event, 0, sizeof event);
512
status = pt_insn_event(m_decoder_up.get(), &event, sizeof(event));
513
514
if (IsLibiptError(status)) {
515
m_decoded_thread.AppendError(IntelPTError(status));
516
return status;
517
}
518
519
if (event.has_tsc) {
520
if (Error err = ProcessPTEventTSC(event.tsc)) {
521
consumeError(std::move(err));
522
return -pte_internal;
523
}
524
}
525
526
switch (event.type) {
527
case ptev_disabled:
528
// The CPU paused tracing the program, e.g. due to ip filtering.
529
m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledHW);
530
break;
531
case ptev_async_disabled:
532
// The kernel or user code paused tracing the program, e.g.
533
// a breakpoint or a ioctl invocation pausing the trace, or a
534
// context switch happened.
535
m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledSW);
536
break;
537
case ptev_overflow:
538
// The CPU internal buffer had an overflow error and some instructions
539
// were lost. A OVF packet comes with an FUP packet (harcoded address)
540
// according to the documentation, so we'll continue seeing instructions
541
// after this event.
542
m_decoded_thread.AppendError(IntelPTError(-pte_overflow));
543
break;
544
default:
545
break;
546
}
547
}
548
549
return status;
550
}
551
552
private:
553
PtInsnDecoderUP m_decoder_up;
554
PSBBlock m_psb_block;
555
std::optional<lldb::addr_t> m_next_block_ip;
556
DecodedThread &m_decoded_thread;
557
PSBBlockAnomalyDetector m_anomaly_detector;
558
std::optional<DecodedThread::TSC> m_tsc_upper_bound;
559
};
560
561
Error lldb_private::trace_intel_pt::DecodeSingleTraceForThread(
562
DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
563
ArrayRef<uint8_t> buffer) {
564
Expected<std::vector<PSBBlock>> blocks =
565
SplitTraceIntoPSBBlock(trace_intel_pt, buffer, /*expect_tscs=*/false);
566
if (!blocks)
567
return blocks.takeError();
568
569
for (size_t i = 0; i < blocks->size(); i++) {
570
PSBBlock &block = blocks->at(i);
571
572
Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create(
573
trace_intel_pt, block, buffer.slice(block.psb_offset, block.size),
574
*decoded_thread.GetThread()->GetProcess(),
575
i + 1 < blocks->size() ? blocks->at(i + 1).starting_ip : std::nullopt,
576
decoded_thread, std::nullopt);
577
if (!decoder)
578
return decoder.takeError();
579
580
decoder->DecodePSBBlock();
581
}
582
583
return Error::success();
584
}
585
586
Error lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread(
587
DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
588
const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers,
589
const std::vector<IntelPTThreadContinousExecution> &executions) {
590
bool has_seen_psbs = false;
591
for (size_t i = 0; i < executions.size(); i++) {
592
const IntelPTThreadContinousExecution &execution = executions[i];
593
594
auto variant = execution.thread_execution.variant;
595
596
// We emit the first valid tsc
597
if (execution.psb_blocks.empty()) {
598
decoded_thread.NotifyTsc(execution.thread_execution.GetLowestKnownTSC());
599
} else {
600
assert(execution.psb_blocks.front().tsc &&
601
"per cpu decoding expects TSCs");
602
decoded_thread.NotifyTsc(
603
std::min(execution.thread_execution.GetLowestKnownTSC(),
604
*execution.psb_blocks.front().tsc));
605
}
606
607
// We then emit the CPU, which will be correctly associated with a tsc.
608
decoded_thread.NotifyCPU(execution.thread_execution.cpu_id);
609
610
// If we haven't seen a PSB yet, then it's fine not to show errors
611
if (has_seen_psbs) {
612
if (execution.psb_blocks.empty()) {
613
decoded_thread.AppendCustomError(
614
formatv("Unable to find intel pt data a thread "
615
"execution on cpu id = {0}",
616
execution.thread_execution.cpu_id)
617
.str());
618
}
619
620
// A hinted start is a non-initial execution that doesn't have a switch
621
// in. An only end is an initial execution that doesn't have a switch in.
622
// Any of those cases represent a gap because we have seen a PSB before.
623
if (variant == ThreadContinuousExecution::Variant::HintedStart ||
624
variant == ThreadContinuousExecution::Variant::OnlyEnd) {
625
decoded_thread.AppendCustomError(
626
formatv("Unable to find the context switch in for a thread "
627
"execution on cpu id = {0}",
628
execution.thread_execution.cpu_id)
629
.str());
630
}
631
}
632
633
for (size_t j = 0; j < execution.psb_blocks.size(); j++) {
634
const PSBBlock &psb_block = execution.psb_blocks[j];
635
636
Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create(
637
trace_intel_pt, psb_block,
638
buffers.lookup(execution.thread_execution.cpu_id)
639
.slice(psb_block.psb_offset, psb_block.size),
640
*decoded_thread.GetThread()->GetProcess(),
641
j + 1 < execution.psb_blocks.size()
642
? execution.psb_blocks[j + 1].starting_ip
643
: std::nullopt,
644
decoded_thread, execution.thread_execution.GetEndTSC());
645
if (!decoder)
646
return decoder.takeError();
647
648
has_seen_psbs = true;
649
decoder->DecodePSBBlock();
650
}
651
652
// If we haven't seen a PSB yet, then it's fine not to show errors
653
if (has_seen_psbs) {
654
// A hinted end is a non-ending execution that doesn't have a switch out.
655
// An only start is an ending execution that doesn't have a switch out.
656
// Any of those cases represent a gap if we still have executions to
657
// process and we have seen a PSB before.
658
if (i + 1 != executions.size() &&
659
(variant == ThreadContinuousExecution::Variant::OnlyStart ||
660
variant == ThreadContinuousExecution::Variant::HintedEnd)) {
661
decoded_thread.AppendCustomError(
662
formatv("Unable to find the context switch out for a thread "
663
"execution on cpu id = {0}",
664
execution.thread_execution.cpu_id)
665
.str());
666
}
667
}
668
}
669
return Error::success();
670
}
671
672
bool IntelPTThreadContinousExecution::operator<(
673
const IntelPTThreadContinousExecution &o) const {
674
// As the context switch might be incomplete, we look first for the first real
675
// PSB packet, which is a valid TSC. Otherwise, We query the thread execution
676
// itself for some tsc.
677
auto get_tsc = [](const IntelPTThreadContinousExecution &exec) {
678
return exec.psb_blocks.empty() ? exec.thread_execution.GetLowestKnownTSC()
679
: exec.psb_blocks.front().tsc;
680
};
681
682
return get_tsc(*this) < get_tsc(o);
683
}
684
685
Expected<std::vector<PSBBlock>>
686
lldb_private::trace_intel_pt::SplitTraceIntoPSBBlock(
687
TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer,
688
bool expect_tscs) {
689
// This follows
690
// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode
691
692
Expected<PtQueryDecoderUP> decoder_up =
693
CreateQueryDecoder(trace_intel_pt, buffer);
694
if (!decoder_up)
695
return decoder_up.takeError();
696
697
pt_query_decoder *decoder = decoder_up.get().get();
698
699
std::vector<PSBBlock> executions;
700
701
while (true) {
702
uint64_t maybe_ip = LLDB_INVALID_ADDRESS;
703
int decoding_status = pt_qry_sync_forward(decoder, &maybe_ip);
704
if (IsLibiptError(decoding_status))
705
break;
706
707
uint64_t psb_offset;
708
int offset_status = pt_qry_get_sync_offset(decoder, &psb_offset);
709
assert(offset_status >= 0 &&
710
"This can't fail because we were able to synchronize");
711
712
std::optional<uint64_t> ip;
713
if (!(pts_ip_suppressed & decoding_status))
714
ip = maybe_ip;
715
716
std::optional<uint64_t> tsc;
717
// Now we fetch the first TSC that comes after the PSB.
718
while (HasEvents(decoding_status)) {
719
pt_event event;
720
decoding_status = pt_qry_event(decoder, &event, sizeof(event));
721
if (IsLibiptError(decoding_status))
722
break;
723
if (event.has_tsc) {
724
tsc = event.tsc;
725
break;
726
}
727
}
728
if (IsLibiptError(decoding_status)) {
729
// We continue to the next PSB. This effectively merges this PSB with the
730
// previous one, and that should be fine because this PSB might be the
731
// direct continuation of the previous thread and it's better to show an
732
// error in the decoded thread than to hide it. If this is the first PSB,
733
// we are okay losing it. Besides that, an error at processing events
734
// means that we wouldn't be able to get any instruction out of it.
735
continue;
736
}
737
738
if (expect_tscs && !tsc)
739
return createStringError(inconvertibleErrorCode(),
740
"Found a PSB without TSC.");
741
742
executions.push_back({
743
psb_offset,
744
tsc,
745
0,
746
ip,
747
});
748
}
749
if (!executions.empty()) {
750
// We now adjust the sizes of each block
751
executions.back().size = buffer.size() - executions.back().psb_offset;
752
for (int i = (int)executions.size() - 2; i >= 0; i--) {
753
executions[i].size =
754
executions[i + 1].psb_offset - executions[i].psb_offset;
755
}
756
}
757
return executions;
758
}
759
760
Expected<std::optional<uint64_t>>
761
lldb_private::trace_intel_pt::FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt,
762
ArrayRef<uint8_t> buffer) {
763
Expected<PtQueryDecoderUP> decoder_up =
764
CreateQueryDecoder(trace_intel_pt, buffer);
765
if (!decoder_up)
766
return decoder_up.takeError();
767
768
pt_query_decoder *decoder = decoder_up.get().get();
769
uint64_t ip = LLDB_INVALID_ADDRESS;
770
int status = pt_qry_sync_forward(decoder, &ip);
771
if (IsLibiptError(status))
772
return std::nullopt;
773
774
while (HasEvents(status)) {
775
pt_event event;
776
status = pt_qry_event(decoder, &event, sizeof(event));
777
if (IsLibiptError(status))
778
return std::nullopt;
779
if (event.has_tsc)
780
return event.tsc;
781
}
782
return std::nullopt;
783
}
784
785