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