16423b502SWalter Erquinigo //===-- LibiptDecoder.cpp --======-----------------------------------------===//
26423b502SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
36423b502SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
46423b502SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
56423b502SWalter Erquinigo //
66423b502SWalter Erquinigo //===----------------------------------------------------------------------===//
76423b502SWalter Erquinigo 
86423b502SWalter Erquinigo #include "LibiptDecoder.h"
96423b502SWalter Erquinigo 
106423b502SWalter Erquinigo #include "TraceIntelPT.h"
116423b502SWalter Erquinigo 
126423b502SWalter Erquinigo #include "lldb/Target/Process.h"
136423b502SWalter Erquinigo 
146423b502SWalter Erquinigo using namespace lldb;
156423b502SWalter Erquinigo using namespace lldb_private;
166423b502SWalter Erquinigo using namespace lldb_private::trace_intel_pt;
176423b502SWalter Erquinigo using namespace llvm;
186423b502SWalter Erquinigo 
196423b502SWalter Erquinigo /// Class that decodes a raw buffer for a single thread using the low level
206423b502SWalter Erquinigo /// libipt library.
216423b502SWalter Erquinigo ///
226423b502SWalter Erquinigo /// Throughout this code, the status of the decoder will be used to identify
236423b502SWalter Erquinigo /// events needed to be processed or errors in the decoder. The values can be
246423b502SWalter Erquinigo /// - negative: actual errors
256423b502SWalter Erquinigo /// - positive or zero: not an error, but a list of bits signaling the status
266423b502SWalter Erquinigo /// of the decoder, e.g. whether there are events that need to be decoded or
276423b502SWalter Erquinigo /// not.
286423b502SWalter Erquinigo class LibiptDecoder {
296423b502SWalter Erquinigo public:
306423b502SWalter Erquinigo   /// \param[in] decoder
316423b502SWalter Erquinigo   ///     A well configured decoder. Using the current state of that decoder,
326423b502SWalter Erquinigo   ///     decoding will start at its next valid PSB. It's not assumed that the
336423b502SWalter Erquinigo   ///     decoder is already pointing at a valid PSB.
346423b502SWalter Erquinigo   ///
356423b502SWalter Erquinigo   /// \param[in] decoded_thread
366423b502SWalter Erquinigo   ///     A \a DecodedThread object where the decoded instructions will be
376423b502SWalter Erquinigo   ///     appended to. It might have already some instructions.
LibiptDecoder(pt_insn_decoder & decoder,DecodedThread & decoded_thread)386423b502SWalter Erquinigo   LibiptDecoder(pt_insn_decoder &decoder, DecodedThread &decoded_thread)
396423b502SWalter Erquinigo       : m_decoder(decoder), m_decoded_thread(decoded_thread) {}
406423b502SWalter Erquinigo 
416423b502SWalter Erquinigo   /// Decode all the instructions until the end of the trace.
426423b502SWalter Erquinigo   /// The decoding flow is based on
43a19fcc2bSWalter Erquinigo   /// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop.
DecodeUntilEndOfTrace()446423b502SWalter Erquinigo   void DecodeUntilEndOfTrace() {
45a19fcc2bSWalter Erquinigo     // Multiple loops indicate gaps in the trace, which are found by the inner
46a19fcc2bSWalter Erquinigo     // call to DecodeInstructionsAndEvents.
47a19fcc2bSWalter Erquinigo     while (true) {
48a19fcc2bSWalter Erquinigo       int status = pt_insn_sync_forward(&m_decoder);
49a19fcc2bSWalter Erquinigo 
50a19fcc2bSWalter Erquinigo       if (IsLibiptError(status)) {
51a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendError(IntelPTError(status));
52a19fcc2bSWalter Erquinigo         break;
53a19fcc2bSWalter Erquinigo       }
54a19fcc2bSWalter Erquinigo 
556423b502SWalter Erquinigo       DecodeInstructionsAndEvents(status);
566423b502SWalter Erquinigo     }
576423b502SWalter Erquinigo   }
586423b502SWalter Erquinigo 
59a19fcc2bSWalter Erquinigo   /// Decode all the instructions that belong to the same PSB packet given its
60a19fcc2bSWalter Erquinigo   /// offset.
DecodePSB(uint64_t psb_offset)61a19fcc2bSWalter Erquinigo   void DecodePSB(uint64_t psb_offset) {
62a19fcc2bSWalter Erquinigo     int status = pt_insn_sync_set(&m_decoder, psb_offset);
63a19fcc2bSWalter Erquinigo     if (IsLibiptError(status)) {
64a7d6c3efSWalter Erquinigo       m_decoded_thread.AppendError(IntelPTError(status));
65a19fcc2bSWalter Erquinigo       return;
66a19fcc2bSWalter Erquinigo     }
67a19fcc2bSWalter Erquinigo     DecodeInstructionsAndEvents(status, /*stop_on_psb_change=*/true);
68a19fcc2bSWalter Erquinigo   }
69a19fcc2bSWalter Erquinigo 
706423b502SWalter Erquinigo private:
71a19fcc2bSWalter Erquinigo   /// Decode all the instructions and events until an error is found, the end
72a19fcc2bSWalter Erquinigo   /// of the trace is reached, or optionally a new PSB is reached.
736423b502SWalter Erquinigo   ///
746423b502SWalter Erquinigo   /// \param[in] status
756423b502SWalter Erquinigo   ///   The status that was result of synchronizing to the most recent PSB.
76a19fcc2bSWalter Erquinigo   ///
77a19fcc2bSWalter Erquinigo   /// \param[in] stop_on_psb_change
7867c24051SWalter Erquinigo   ///   If \b true, decoding stops if a different PSB is reached.
DecodeInstructionsAndEvents(int status,bool stop_on_psb_change=false)79a19fcc2bSWalter Erquinigo   void DecodeInstructionsAndEvents(int status,
80a19fcc2bSWalter Erquinigo                                    bool stop_on_psb_change = false) {
81a19fcc2bSWalter Erquinigo     uint64_t psb_offset;
82a19fcc2bSWalter Erquinigo     pt_insn_get_sync_offset(&m_decoder,
83a19fcc2bSWalter Erquinigo                             &psb_offset); // this can't fail because we got here
84a19fcc2bSWalter Erquinigo 
85a7d6c3efSWalter Erquinigo     while (ProcessPTEvents(status)) {
86a19fcc2bSWalter Erquinigo       if (stop_on_psb_change) {
87a19fcc2bSWalter Erquinigo         uint64_t cur_psb_offset;
88a7d6c3efSWalter Erquinigo         // this can't fail because we got here
89a7d6c3efSWalter Erquinigo         pt_insn_get_sync_offset(&m_decoder, &cur_psb_offset);
90a19fcc2bSWalter Erquinigo         if (cur_psb_offset != psb_offset)
91a19fcc2bSWalter Erquinigo           break;
92a19fcc2bSWalter Erquinigo       }
93a19fcc2bSWalter Erquinigo 
94a7d6c3efSWalter Erquinigo       // The status returned by pt_insn_next will need to be processed
95059f39d2SWalter Erquinigo       // by ProcessPTEvents in the next loop if it is not an error.
96a7d6c3efSWalter Erquinigo       pt_insn insn;
97a7d6c3efSWalter Erquinigo       std::memset(&insn, 0, sizeof insn);
98a7d6c3efSWalter Erquinigo       if (IsLibiptError(status =
99a7d6c3efSWalter Erquinigo                             pt_insn_next(&m_decoder, &insn, sizeof(insn)))) {
100a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendError(IntelPTError(status, insn.ip));
1016423b502SWalter Erquinigo         break;
102059f39d2SWalter Erquinigo       }
103a7d6c3efSWalter Erquinigo       m_decoded_thread.AppendInstruction(insn);
1046423b502SWalter Erquinigo     }
1056423b502SWalter Erquinigo   }
1066423b502SWalter Erquinigo 
1076423b502SWalter Erquinigo   /// Move the decoder forward to the next synchronization point (i.e. next PSB
1086423b502SWalter Erquinigo   /// packet).
1096423b502SWalter Erquinigo   ///
1106423b502SWalter Erquinigo   /// Once the decoder is at that synchronization point, it can start decoding
1116423b502SWalter Erquinigo   /// instructions.
1126423b502SWalter Erquinigo   ///
113059f39d2SWalter Erquinigo   /// If errors are found, they will be appended to the trace.
114059f39d2SWalter Erquinigo   ///
1156423b502SWalter Erquinigo   /// \return
1166423b502SWalter Erquinigo   ///   The libipt decoder status after moving to the next PSB. Negative if
1176423b502SWalter Erquinigo   ///   no PSB was found.
FindNextSynchronizationPoint()1186423b502SWalter Erquinigo   int FindNextSynchronizationPoint() {
1196423b502SWalter Erquinigo     // Try to sync the decoder. If it fails, then get the decoder_offset and
1206423b502SWalter Erquinigo     // try to sync again from the next synchronization point. If the
1216423b502SWalter Erquinigo     // new_decoder_offset is same as decoder_offset then we can't move to the
1226423b502SWalter Erquinigo     // next synchronization point. Otherwise, keep resyncing until either end
1236423b502SWalter Erquinigo     // of trace stream (eos) is reached or pt_insn_sync_forward() passes.
1246423b502SWalter Erquinigo     int status = pt_insn_sync_forward(&m_decoder);
1256423b502SWalter Erquinigo 
1266423b502SWalter Erquinigo     // We make this call to record any synchronization errors.
127059f39d2SWalter Erquinigo     if (IsLibiptError(status))
128a7d6c3efSWalter Erquinigo       m_decoded_thread.AppendError(IntelPTError(status));
129059f39d2SWalter Erquinigo 
1306423b502SWalter Erquinigo     return status;
1316423b502SWalter Erquinigo   }
1326423b502SWalter Erquinigo 
1336423b502SWalter Erquinigo   /// Before querying instructions, we need to query the events associated that
1346423b502SWalter Erquinigo   /// instruction e.g. timing events like ptev_tick, or paging events like
1356423b502SWalter Erquinigo   /// ptev_paging.
1366423b502SWalter Erquinigo   ///
137059f39d2SWalter Erquinigo   /// \param[in] status
138059f39d2SWalter Erquinigo   ///   The status gotten from the previous instruction decoding or PSB
139059f39d2SWalter Erquinigo   ///   synchronization.
140059f39d2SWalter Erquinigo   ///
1416423b502SWalter Erquinigo   /// \return
142a7d6c3efSWalter Erquinigo   ///   \b true if no errors were found processing the events.
ProcessPTEvents(int status)143a7d6c3efSWalter Erquinigo   bool ProcessPTEvents(int status) {
1446423b502SWalter Erquinigo     while (status & pts_event_pending) {
1456423b502SWalter Erquinigo       pt_event event;
1466423b502SWalter Erquinigo       status = pt_insn_event(&m_decoder, &event, sizeof(event));
147059f39d2SWalter Erquinigo       if (IsLibiptError(status)) {
148a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendError(IntelPTError(status));
149a7d6c3efSWalter Erquinigo         return false;
1506423b502SWalter Erquinigo       }
1516423b502SWalter Erquinigo 
152a7d6c3efSWalter Erquinigo       if (event.has_tsc)
153a7d6c3efSWalter Erquinigo         m_decoded_thread.NotifyTsc(event.tsc);
154a7d6c3efSWalter Erquinigo 
155059f39d2SWalter Erquinigo       switch (event.type) {
156059f39d2SWalter Erquinigo       case ptev_enabled:
157059f39d2SWalter Erquinigo         // The kernel started or resumed tracing the program.
158059f39d2SWalter Erquinigo         break;
159059f39d2SWalter Erquinigo       case ptev_disabled:
160059f39d2SWalter Erquinigo         // The CPU paused tracing the program, e.g. due to ip filtering.
161a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledHW);
162a7d6c3efSWalter Erquinigo         break;
163059f39d2SWalter Erquinigo       case ptev_async_disabled:
164059f39d2SWalter Erquinigo         // The kernel or user code paused tracing the program, e.g.
165059f39d2SWalter Erquinigo         // a breakpoint or a ioctl invocation pausing the trace, or a
166059f39d2SWalter Erquinigo         // context switch happened.
167a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledSW);
168059f39d2SWalter Erquinigo         break;
169059f39d2SWalter Erquinigo       case ptev_overflow:
170059f39d2SWalter Erquinigo         // The CPU internal buffer had an overflow error and some instructions
171059f39d2SWalter Erquinigo         // were lost.
172a7d6c3efSWalter Erquinigo         m_decoded_thread.AppendError(IntelPTError(-pte_overflow));
173059f39d2SWalter Erquinigo         break;
174059f39d2SWalter Erquinigo       default:
175059f39d2SWalter Erquinigo         break;
176059f39d2SWalter Erquinigo       }
177059f39d2SWalter Erquinigo     }
178059f39d2SWalter Erquinigo 
179a7d6c3efSWalter Erquinigo     return true;
1806423b502SWalter Erquinigo   }
1816423b502SWalter Erquinigo 
1826423b502SWalter Erquinigo private:
1836423b502SWalter Erquinigo   pt_insn_decoder &m_decoder;
1846423b502SWalter Erquinigo   DecodedThread &m_decoded_thread;
1856423b502SWalter Erquinigo };
1866423b502SWalter Erquinigo 
1876423b502SWalter Erquinigo /// Callback used by libipt for reading the process memory.
1886423b502SWalter Erquinigo ///
1896423b502SWalter Erquinigo /// More information can be found in
1906423b502SWalter Erquinigo /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md
ReadProcessMemory(uint8_t * buffer,size_t size,const pt_asid *,uint64_t pc,void * context)1916423b502SWalter Erquinigo static int ReadProcessMemory(uint8_t *buffer, size_t size,
1926423b502SWalter Erquinigo                              const pt_asid * /* unused */, uint64_t pc,
1936423b502SWalter Erquinigo                              void *context) {
1946423b502SWalter Erquinigo   Process *process = static_cast<Process *>(context);
1956423b502SWalter Erquinigo 
1966423b502SWalter Erquinigo   Status error;
1976423b502SWalter Erquinigo   int bytes_read = process->ReadMemory(pc, buffer, size, error);
1986423b502SWalter Erquinigo   if (error.Fail())
1996423b502SWalter Erquinigo     return -pte_nomap;
2006423b502SWalter Erquinigo   return bytes_read;
2016423b502SWalter Erquinigo }
2026423b502SWalter Erquinigo 
2036423b502SWalter Erquinigo // RAII deleter for libipt's decoder
__anonf3d500220102(pt_insn_decoder *decoder) 2046423b502SWalter Erquinigo auto DecoderDeleter = [](pt_insn_decoder *decoder) {
2056423b502SWalter Erquinigo   pt_insn_free_decoder(decoder);
2066423b502SWalter Erquinigo };
2076423b502SWalter Erquinigo 
2086423b502SWalter Erquinigo using PtInsnDecoderUP =
2096423b502SWalter Erquinigo     std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>;
2106423b502SWalter Erquinigo 
2116423b502SWalter Erquinigo static Expected<PtInsnDecoderUP>
CreateInstructionDecoder(TraceIntelPT & trace_intel_pt,ArrayRef<uint8_t> buffer)212a19fcc2bSWalter Erquinigo CreateInstructionDecoder(TraceIntelPT &trace_intel_pt,
213e0cfe20aSWalter Erquinigo                          ArrayRef<uint8_t> buffer) {
2146423b502SWalter Erquinigo   Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
2156423b502SWalter Erquinigo   if (!cpu_info)
2166423b502SWalter Erquinigo     return cpu_info.takeError();
2176423b502SWalter Erquinigo 
2186423b502SWalter Erquinigo   pt_config config;
2196423b502SWalter Erquinigo   pt_config_init(&config);
2206423b502SWalter Erquinigo   config.cpu = *cpu_info;
2216423b502SWalter Erquinigo   int status = pte_ok;
2226423b502SWalter Erquinigo 
2236423b502SWalter Erquinigo   if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu)))
2246423b502SWalter Erquinigo     return make_error<IntelPTError>(status);
2256423b502SWalter Erquinigo 
226e0cfe20aSWalter Erquinigo   // The libipt library does not modify the trace buffer, hence the
227e0cfe20aSWalter Erquinigo   // following casts are safe.
228e0cfe20aSWalter Erquinigo   config.begin = const_cast<uint8_t *>(buffer.data());
229e0cfe20aSWalter Erquinigo   config.end = const_cast<uint8_t *>(buffer.data() + buffer.size());
2306423b502SWalter Erquinigo 
2316423b502SWalter Erquinigo   pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config);
2326423b502SWalter Erquinigo   if (!decoder_ptr)
2336423b502SWalter Erquinigo     return make_error<IntelPTError>(-pte_nomem);
2346423b502SWalter Erquinigo 
235a19fcc2bSWalter Erquinigo   return PtInsnDecoderUP(decoder_ptr, DecoderDeleter);
236a19fcc2bSWalter Erquinigo }
2376423b502SWalter Erquinigo 
SetupMemoryImage(PtInsnDecoderUP & decoder_up,Process & process)238a19fcc2bSWalter Erquinigo static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) {
239a19fcc2bSWalter Erquinigo   pt_image *image = pt_insn_get_image(decoder_up.get());
240a19fcc2bSWalter Erquinigo 
241a19fcc2bSWalter Erquinigo   int status = pte_ok;
2426423b502SWalter Erquinigo   if (IsLibiptError(
243a19fcc2bSWalter Erquinigo           status = pt_image_set_callback(image, ReadProcessMemory, &process)))
2446423b502SWalter Erquinigo     return make_error<IntelPTError>(status);
245a19fcc2bSWalter Erquinigo   return Error::success();
2466423b502SWalter Erquinigo }
2476423b502SWalter Erquinigo 
DecodeSingleTraceForThread(DecodedThread & decoded_thread,TraceIntelPT & trace_intel_pt,ArrayRef<uint8_t> buffer)248a7d6c3efSWalter Erquinigo Error lldb_private::trace_intel_pt::DecodeSingleTraceForThread(
249a7d6c3efSWalter Erquinigo     DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
250e0cfe20aSWalter Erquinigo     ArrayRef<uint8_t> buffer) {
2516423b502SWalter Erquinigo   Expected<PtInsnDecoderUP> decoder_up =
252a19fcc2bSWalter Erquinigo       CreateInstructionDecoder(trace_intel_pt, buffer);
2536423b502SWalter Erquinigo   if (!decoder_up)
254a7d6c3efSWalter Erquinigo     return decoder_up.takeError();
2556423b502SWalter Erquinigo 
256a19fcc2bSWalter Erquinigo   if (Error err = SetupMemoryImage(*decoder_up,
257a19fcc2bSWalter Erquinigo                                    *decoded_thread.GetThread()->GetProcess()))
258a7d6c3efSWalter Erquinigo     return err;
259a19fcc2bSWalter Erquinigo 
2606423b502SWalter Erquinigo   LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread);
2616423b502SWalter Erquinigo   libipt_decoder.DecodeUntilEndOfTrace();
262a7d6c3efSWalter Erquinigo   return Error::success();
2636423b502SWalter Erquinigo }
264a19fcc2bSWalter Erquinigo 
DecodeSystemWideTraceForThread(DecodedThread & decoded_thread,TraceIntelPT & trace_intel_pt,const DenseMap<lldb::cpu_id_t,llvm::ArrayRef<uint8_t>> & buffers,const std::vector<IntelPTThreadContinousExecution> & executions)265a7d6c3efSWalter Erquinigo Error lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread(
266a19fcc2bSWalter Erquinigo     DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
2676a5355e8SWalter Erquinigo     const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers,
268a19fcc2bSWalter Erquinigo     const std::vector<IntelPTThreadContinousExecution> &executions) {
2696a5355e8SWalter Erquinigo   DenseMap<lldb::cpu_id_t, LibiptDecoder> decoders;
2706a5355e8SWalter Erquinigo   for (auto &cpu_id_buffer : buffers) {
271a19fcc2bSWalter Erquinigo     Expected<PtInsnDecoderUP> decoder_up =
2726a5355e8SWalter Erquinigo         CreateInstructionDecoder(trace_intel_pt, cpu_id_buffer.second);
273a19fcc2bSWalter Erquinigo     if (!decoder_up)
274a7d6c3efSWalter Erquinigo       return decoder_up.takeError();
275a19fcc2bSWalter Erquinigo 
276a19fcc2bSWalter Erquinigo     if (Error err = SetupMemoryImage(*decoder_up,
277a19fcc2bSWalter Erquinigo                                      *decoded_thread.GetThread()->GetProcess()))
278a7d6c3efSWalter Erquinigo       return err;
279a19fcc2bSWalter Erquinigo 
2806a5355e8SWalter Erquinigo     decoders.try_emplace(cpu_id_buffer.first,
281a19fcc2bSWalter Erquinigo                          LibiptDecoder(*decoder_up->release(), decoded_thread));
282a19fcc2bSWalter Erquinigo   }
283a19fcc2bSWalter Erquinigo 
284a19fcc2bSWalter Erquinigo   bool has_seen_psbs = false;
285a19fcc2bSWalter Erquinigo   for (size_t i = 0; i < executions.size(); i++) {
286a19fcc2bSWalter Erquinigo     const IntelPTThreadContinousExecution &execution = executions[i];
287a19fcc2bSWalter Erquinigo 
2884a843d92SWalter Erquinigo 
289a19fcc2bSWalter Erquinigo     auto variant = execution.thread_execution.variant;
290*4f676c25SWalter Erquinigo     // We report the TSCs we are sure of
291*4f676c25SWalter Erquinigo     switch (variant) {
292*4f676c25SWalter Erquinigo     case ThreadContinuousExecution::Variant::Complete:
293*4f676c25SWalter Erquinigo       decoded_thread.NotifyTsc(execution.thread_execution.tscs.complete.start);
294*4f676c25SWalter Erquinigo       break;
295*4f676c25SWalter Erquinigo     case ThreadContinuousExecution::Variant::OnlyStart:
296*4f676c25SWalter Erquinigo       decoded_thread.NotifyTsc(
297*4f676c25SWalter Erquinigo           execution.thread_execution.tscs.only_start.start);
298*4f676c25SWalter Erquinigo       break;
299*4f676c25SWalter Erquinigo     default:
300*4f676c25SWalter Erquinigo       break;
301*4f676c25SWalter Erquinigo     }
302*4f676c25SWalter Erquinigo 
303*4f676c25SWalter Erquinigo     decoded_thread.NotifyCPU(execution.thread_execution.cpu_id);
304*4f676c25SWalter Erquinigo 
305a19fcc2bSWalter Erquinigo     // If we haven't seen a PSB yet, then it's fine not to show errors
306a19fcc2bSWalter Erquinigo     if (has_seen_psbs) {
307a19fcc2bSWalter Erquinigo       if (execution.intelpt_subtraces.empty()) {
308a7d6c3efSWalter Erquinigo         decoded_thread.AppendCustomError(
309a7d6c3efSWalter Erquinigo             formatv("Unable to find intel pt data for thread "
310a7d6c3efSWalter Erquinigo                     "execution on cpu id = {0}",
311a7d6c3efSWalter Erquinigo                     execution.thread_execution.cpu_id)
312a7d6c3efSWalter Erquinigo                 .str());
313a19fcc2bSWalter Erquinigo       }
314a19fcc2bSWalter Erquinigo 
315a19fcc2bSWalter Erquinigo       // If the first execution is incomplete because it doesn't have a previous
316*4f676c25SWalter Erquinigo       // context switch in its cpu, all good, otherwise we report the error.
317a19fcc2bSWalter Erquinigo       if (variant == ThreadContinuousExecution::Variant::OnlyEnd ||
318a19fcc2bSWalter Erquinigo           variant == ThreadContinuousExecution::Variant::HintedStart) {
319a7d6c3efSWalter Erquinigo         decoded_thread.AppendCustomError(
320*4f676c25SWalter Erquinigo             formatv("Unable to find the context switch in for the thread "
321*4f676c25SWalter Erquinigo                     "execution starting on cpu id = {0}",
322a7d6c3efSWalter Erquinigo                     execution.thread_execution.cpu_id)
323a7d6c3efSWalter Erquinigo                 .str());
324a19fcc2bSWalter Erquinigo       }
325a19fcc2bSWalter Erquinigo     }
326a19fcc2bSWalter Erquinigo 
327a19fcc2bSWalter Erquinigo     LibiptDecoder &decoder =
3286a5355e8SWalter Erquinigo         decoders.find(execution.thread_execution.cpu_id)->second;
329a19fcc2bSWalter Erquinigo     for (const IntelPTThreadSubtrace &intel_pt_execution :
330a19fcc2bSWalter Erquinigo          execution.intelpt_subtraces) {
331a19fcc2bSWalter Erquinigo       has_seen_psbs = true;
332a19fcc2bSWalter Erquinigo       decoder.DecodePSB(intel_pt_execution.psb_offset);
333a19fcc2bSWalter Erquinigo     }
334a19fcc2bSWalter Erquinigo 
335*4f676c25SWalter Erquinigo     // We report the TSCs we are sure of
336*4f676c25SWalter Erquinigo     switch (variant) {
337*4f676c25SWalter Erquinigo     case ThreadContinuousExecution::Variant::Complete:
338*4f676c25SWalter Erquinigo       decoded_thread.NotifyTsc(execution.thread_execution.tscs.complete.end);
339*4f676c25SWalter Erquinigo       break;
340*4f676c25SWalter Erquinigo     case ThreadContinuousExecution::Variant::OnlyEnd:
341*4f676c25SWalter Erquinigo       decoded_thread.NotifyTsc(execution.thread_execution.tscs.only_end.end);
342*4f676c25SWalter Erquinigo       break;
343*4f676c25SWalter Erquinigo     default:
344*4f676c25SWalter Erquinigo       break;
345*4f676c25SWalter Erquinigo     }
346*4f676c25SWalter Erquinigo 
347a19fcc2bSWalter Erquinigo     // If we haven't seen a PSB yet, then it's fine not to show errors
348a19fcc2bSWalter Erquinigo     if (has_seen_psbs) {
349a19fcc2bSWalter Erquinigo       // If the last execution is incomplete because it doesn't have a following
350a19fcc2bSWalter Erquinigo       // context switch in its cpu, all good.
351a19fcc2bSWalter Erquinigo       if ((variant == ThreadContinuousExecution::Variant::OnlyStart &&
352a19fcc2bSWalter Erquinigo            i + 1 != executions.size()) ||
353a19fcc2bSWalter Erquinigo           variant == ThreadContinuousExecution::Variant::HintedEnd) {
354a7d6c3efSWalter Erquinigo         decoded_thread.AppendCustomError(
355*4f676c25SWalter Erquinigo             formatv("Unable to find the context switch out for the thread "
356*4f676c25SWalter Erquinigo                     "execution on cpu id = {0}",
357a7d6c3efSWalter Erquinigo                     execution.thread_execution.cpu_id)
358a7d6c3efSWalter Erquinigo                 .str());
359a19fcc2bSWalter Erquinigo       }
360a19fcc2bSWalter Erquinigo     }
361a19fcc2bSWalter Erquinigo   }
362a7d6c3efSWalter Erquinigo   return Error::success();
363a19fcc2bSWalter Erquinigo }
364a19fcc2bSWalter Erquinigo 
operator <(const IntelPTThreadContinousExecution & o) const365a19fcc2bSWalter Erquinigo bool IntelPTThreadContinousExecution::operator<(
366a19fcc2bSWalter Erquinigo     const IntelPTThreadContinousExecution &o) const {
367a19fcc2bSWalter Erquinigo   // As the context switch might be incomplete, we look first for the first real
368a19fcc2bSWalter Erquinigo   // PSB packet, which is a valid TSC. Otherwise, We query the thread execution
369a19fcc2bSWalter Erquinigo   // itself for some tsc.
370a19fcc2bSWalter Erquinigo   auto get_tsc = [](const IntelPTThreadContinousExecution &exec) {
371a19fcc2bSWalter Erquinigo     return exec.intelpt_subtraces.empty()
372a19fcc2bSWalter Erquinigo                ? exec.thread_execution.GetLowestKnownTSC()
373a19fcc2bSWalter Erquinigo                : exec.intelpt_subtraces.front().tsc;
374a19fcc2bSWalter Erquinigo   };
375a19fcc2bSWalter Erquinigo 
376a19fcc2bSWalter Erquinigo   return get_tsc(*this) < get_tsc(o);
377a19fcc2bSWalter Erquinigo }
378a19fcc2bSWalter Erquinigo 
379a19fcc2bSWalter Erquinigo Expected<std::vector<IntelPTThreadSubtrace>>
SplitTraceInContinuousExecutions(TraceIntelPT & trace_intel_pt,llvm::ArrayRef<uint8_t> buffer)380a19fcc2bSWalter Erquinigo lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions(
381a19fcc2bSWalter Erquinigo     TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) {
382a19fcc2bSWalter Erquinigo   Expected<PtInsnDecoderUP> decoder_up =
383a19fcc2bSWalter Erquinigo       CreateInstructionDecoder(trace_intel_pt, buffer);
384a19fcc2bSWalter Erquinigo   if (!decoder_up)
385a19fcc2bSWalter Erquinigo     return decoder_up.takeError();
386a19fcc2bSWalter Erquinigo 
387a19fcc2bSWalter Erquinigo   pt_insn_decoder *decoder = decoder_up.get().get();
388a19fcc2bSWalter Erquinigo 
389a19fcc2bSWalter Erquinigo   std::vector<IntelPTThreadSubtrace> executions;
390a19fcc2bSWalter Erquinigo 
391a19fcc2bSWalter Erquinigo   int status = pte_ok;
392a19fcc2bSWalter Erquinigo   while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) {
393a19fcc2bSWalter Erquinigo     uint64_t tsc;
394a19fcc2bSWalter Erquinigo     if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr)))
395a19fcc2bSWalter Erquinigo       return createStringError(inconvertibleErrorCode(),
396a19fcc2bSWalter Erquinigo                                "intel pt trace doesn't have TSC timestamps");
397a19fcc2bSWalter Erquinigo 
398a19fcc2bSWalter Erquinigo     uint64_t psb_offset;
399a19fcc2bSWalter Erquinigo     pt_insn_get_sync_offset(decoder,
400a19fcc2bSWalter Erquinigo                             &psb_offset); // this can't fail because we got here
401a19fcc2bSWalter Erquinigo 
402a19fcc2bSWalter Erquinigo     executions.push_back({
403a19fcc2bSWalter Erquinigo         psb_offset,
40467c24051SWalter Erquinigo         tsc,
405a19fcc2bSWalter Erquinigo     });
406a19fcc2bSWalter Erquinigo   }
407a19fcc2bSWalter Erquinigo   return executions;
408a19fcc2bSWalter Erquinigo }
409*4f676c25SWalter Erquinigo 
410*4f676c25SWalter Erquinigo Expected<Optional<uint64_t>>
FindLowestTSCInTrace(TraceIntelPT & trace_intel_pt,ArrayRef<uint8_t> buffer)411*4f676c25SWalter Erquinigo lldb_private::trace_intel_pt::FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt,
412*4f676c25SWalter Erquinigo                                                    ArrayRef<uint8_t> buffer) {
413*4f676c25SWalter Erquinigo   Expected<PtInsnDecoderUP> decoder_up =
414*4f676c25SWalter Erquinigo       CreateInstructionDecoder(trace_intel_pt, buffer);
415*4f676c25SWalter Erquinigo   if (!decoder_up)
416*4f676c25SWalter Erquinigo     return decoder_up.takeError();
417*4f676c25SWalter Erquinigo 
418*4f676c25SWalter Erquinigo   pt_insn_decoder *decoder = decoder_up.get().get();
419*4f676c25SWalter Erquinigo   int status = pte_ok;
420*4f676c25SWalter Erquinigo   if (IsLibiptError(status = pt_insn_sync_forward(decoder)))
421*4f676c25SWalter Erquinigo     return None;
422*4f676c25SWalter Erquinigo 
423*4f676c25SWalter Erquinigo   uint64_t tsc;
424*4f676c25SWalter Erquinigo   if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr)))
425*4f676c25SWalter Erquinigo     return None;
426*4f676c25SWalter Erquinigo   return tsc;
427*4f676c25SWalter Erquinigo }
428