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