xref: /llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp (revision a19fcc2bec81989f90700cfc63b89a0dfd330197)
1 //===-- LibiptDecoder.cpp --======-----------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 #include "LibiptDecoder.h"
9 
10 #include "TraceIntelPT.h"
11 
12 #include "lldb/Target/Process.h"
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 using namespace lldb_private::trace_intel_pt;
17 using namespace llvm;
18 
19 // Simple struct used by the decoder to keep the state of the most
20 // recent TSC and a flag indicating whether TSCs are enabled, not enabled
21 // or we just don't yet.
22 struct TscInfo {
23   uint64_t tsc = 0;
24   LazyBool has_tsc = eLazyBoolCalculate;
25 
26   explicit operator bool() const { return has_tsc == eLazyBoolYes; }
27 };
28 
29 /// Class that decodes a raw buffer for a single thread using the low level
30 /// libipt library.
31 ///
32 /// Throughout this code, the status of the decoder will be used to identify
33 /// events needed to be processed or errors in the decoder. The values can be
34 /// - negative: actual errors
35 /// - positive or zero: not an error, but a list of bits signaling the status
36 /// of the decoder, e.g. whether there are events that need to be decoded or
37 /// not.
38 class LibiptDecoder {
39 public:
40   /// \param[in] decoder
41   ///     A well configured decoder. Using the current state of that decoder,
42   ///     decoding will start at its next valid PSB. It's not assumed that the
43   ///     decoder is already pointing at a valid PSB.
44   ///
45   /// \param[in] decoded_thread
46   ///     A \a DecodedThread object where the decoded instructions will be
47   ///     appended to. It might have already some instructions.
48   LibiptDecoder(pt_insn_decoder &decoder, DecodedThread &decoded_thread)
49       : m_decoder(decoder), m_decoded_thread(decoded_thread) {}
50 
51   /// Decode all the instructions until the end of the trace.
52   /// The decoding flow is based on
53   /// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop.
54   void DecodeUntilEndOfTrace() {
55     // Multiple loops indicate gaps in the trace, which are found by the inner
56     // call to DecodeInstructionsAndEvents.
57     while (true) {
58       int status = pt_insn_sync_forward(&m_decoder);
59 
60       if (IsLibiptError(status)) {
61         m_decoded_thread.Append(DecodedInstruction(status));
62         break;
63       }
64 
65       DecodeInstructionsAndEvents(status);
66     }
67   }
68 
69   /// Decode all the instructions that belong to the same PSB packet given its
70   /// offset.
71   void DecodePSB(uint64_t psb_offset) {
72     int status = pt_insn_sync_set(&m_decoder, psb_offset);
73     if (IsLibiptError(status)) {
74       m_decoded_thread.Append(DecodedInstruction(status));
75       return;
76     }
77     DecodeInstructionsAndEvents(status, /*stop_on_psb_change=*/true);
78   }
79 
80 private:
81   /// Invoke the low level function \a pt_insn_next and store the decoded
82   /// instruction in the given \a DecodedInstruction.
83   ///
84   /// \param[out] insn
85   ///   The instruction builder where the pt_insn information will be stored.
86   ///
87   /// \return
88   ///   The status returned by pt_insn_next.
89   int DecodeNextInstruction(DecodedInstruction &insn) {
90     return pt_insn_next(&m_decoder, &insn.pt_insn, sizeof(insn.pt_insn));
91   }
92 
93   /// Decode all the instructions and events until an error is found, the end
94   /// of the trace is reached, or optionally a new PSB is reached.
95   ///
96   /// \param[in] status
97   ///   The status that was result of synchronizing to the most recent PSB.
98   ///
99   /// \param[in] stop_on_psb_change
100   ///   If \b true, decoding
101   ///   An optional offset to a given PSB. Decoding stops if a different PSB is
102   ///   reached.
103   void DecodeInstructionsAndEvents(int status,
104                                    bool stop_on_psb_change = false) {
105     uint64_t psb_offset;
106     pt_insn_get_sync_offset(&m_decoder,
107                             &psb_offset); // this can't fail because we got here
108 
109     while (true) {
110       DecodedInstruction insn = ProcessPTEvents(status);
111       if (!insn) {
112         m_decoded_thread.Append(insn);
113         break;
114       }
115 
116       if (stop_on_psb_change) {
117         uint64_t cur_psb_offset;
118         pt_insn_get_sync_offset(
119             &m_decoder, &cur_psb_offset); // this can't fail because we got here
120         if (cur_psb_offset != psb_offset)
121           break;
122       }
123 
124       // The status returned by DecodeNextInstruction will need to be processed
125       // by ProcessPTEvents in the next loop if it is not an error.
126       if (IsLibiptError(status = DecodeNextInstruction(insn))) {
127         insn.libipt_error = status;
128         m_decoded_thread.Append(insn);
129         break;
130       }
131       m_decoded_thread.Append(insn);
132     }
133   }
134 
135   /// Move the decoder forward to the next synchronization point (i.e. next PSB
136   /// packet).
137   ///
138   /// Once the decoder is at that synchronization point, it can start decoding
139   /// instructions.
140   ///
141   /// If errors are found, they will be appended to the trace.
142   ///
143   /// \return
144   ///   The libipt decoder status after moving to the next PSB. Negative if
145   ///   no PSB was found.
146   int FindNextSynchronizationPoint() {
147     // Try to sync the decoder. If it fails, then get the decoder_offset and
148     // try to sync again from the next synchronization point. If the
149     // new_decoder_offset is same as decoder_offset then we can't move to the
150     // next synchronization point. Otherwise, keep resyncing until either end
151     // of trace stream (eos) is reached or pt_insn_sync_forward() passes.
152     int status = pt_insn_sync_forward(&m_decoder);
153 
154     // We make this call to record any synchronization errors.
155     if (IsLibiptError(status))
156       m_decoded_thread.Append(DecodedInstruction(status));
157 
158     return status;
159   }
160 
161   /// Before querying instructions, we need to query the events associated that
162   /// instruction e.g. timing events like ptev_tick, or paging events like
163   /// ptev_paging.
164   ///
165   /// \param[in] status
166   ///   The status gotten from the previous instruction decoding or PSB
167   ///   synchronization.
168   ///
169   /// \return
170   ///   A \a DecodedInstruction with event, tsc and error information.
171   DecodedInstruction ProcessPTEvents(int status) {
172     DecodedInstruction insn;
173     while (status & pts_event_pending) {
174       pt_event event;
175       status = pt_insn_event(&m_decoder, &event, sizeof(event));
176       if (IsLibiptError(status)) {
177         insn.libipt_error = status;
178         break;
179       }
180 
181       switch (event.type) {
182       case ptev_enabled:
183         // The kernel started or resumed tracing the program.
184         break;
185       case ptev_disabled:
186         // The CPU paused tracing the program, e.g. due to ip filtering.
187       case ptev_async_disabled:
188         // The kernel or user code paused tracing the program, e.g.
189         // a breakpoint or a ioctl invocation pausing the trace, or a
190         // context switch happened.
191 
192         if (m_decoded_thread.GetInstructionsCount() > 0) {
193           // A paused event before the first instruction can be safely
194           // discarded.
195           insn.events |= eTraceEventPaused;
196         }
197         break;
198       case ptev_overflow:
199         // The CPU internal buffer had an overflow error and some instructions
200         // were lost.
201         insn.libipt_error = -pte_overflow;
202         break;
203       default:
204         break;
205       }
206     }
207 
208     // We refresh the TSC that might have changed after processing the events.
209     // See
210     // https://github.com/intel/libipt/blob/master/doc/man/pt_evt_next.3.md
211     RefreshTscInfo();
212     if (m_tsc_info)
213       insn.tsc = m_tsc_info.tsc;
214     return insn;
215   }
216 
217   /// Query the decoder for the most recent TSC timestamp and update
218   /// the inner tsc information accordingly.
219   void RefreshTscInfo() {
220     if (m_tsc_info.has_tsc == eLazyBoolNo)
221       return;
222 
223     uint64_t new_tsc;
224     int tsc_status;
225     if (IsLibiptError(tsc_status = pt_insn_time(&m_decoder, &new_tsc, nullptr,
226                                                 nullptr))) {
227       if (IsTscUnavailable(tsc_status)) {
228         // We now know that the trace doesn't support TSC, so we won't try
229         // again.
230         // See
231         // https://github.com/intel/libipt/blob/master/doc/man/pt_qry_time.3.md
232         m_tsc_info.has_tsc = eLazyBoolNo;
233       } else {
234         // We don't add TSC decoding errors in the decoded trace itself to
235         // prevent creating unnecessary gaps, but we can count how many of
236         // these errors happened. In this case we reuse the previous correct
237         // TSC we saw, as it's better than no TSC at all.
238         m_decoded_thread.RecordTscError(tsc_status);
239       }
240     } else {
241       m_tsc_info.tsc = new_tsc;
242       m_tsc_info.has_tsc = eLazyBoolYes;
243     }
244   }
245 
246 private:
247   pt_insn_decoder &m_decoder;
248   DecodedThread &m_decoded_thread;
249   TscInfo m_tsc_info;
250 };
251 
252 /// Callback used by libipt for reading the process memory.
253 ///
254 /// More information can be found in
255 /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md
256 static int ReadProcessMemory(uint8_t *buffer, size_t size,
257                              const pt_asid * /* unused */, uint64_t pc,
258                              void *context) {
259   Process *process = static_cast<Process *>(context);
260 
261   Status error;
262   int bytes_read = process->ReadMemory(pc, buffer, size, error);
263   if (error.Fail())
264     return -pte_nomap;
265   return bytes_read;
266 }
267 
268 // RAII deleter for libipt's decoder
269 auto DecoderDeleter = [](pt_insn_decoder *decoder) {
270   pt_insn_free_decoder(decoder);
271 };
272 
273 using PtInsnDecoderUP =
274     std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>;
275 
276 static Expected<PtInsnDecoderUP>
277 CreateInstructionDecoder(TraceIntelPT &trace_intel_pt,
278                          ArrayRef<uint8_t> buffer) {
279   Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
280   if (!cpu_info)
281     return cpu_info.takeError();
282 
283   pt_config config;
284   pt_config_init(&config);
285   config.cpu = *cpu_info;
286   int status = pte_ok;
287 
288   if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu)))
289     return make_error<IntelPTError>(status);
290 
291   // The libipt library does not modify the trace buffer, hence the
292   // following casts are safe.
293   config.begin = const_cast<uint8_t *>(buffer.data());
294   config.end = const_cast<uint8_t *>(buffer.data() + buffer.size());
295 
296   pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config);
297   if (!decoder_ptr)
298     return make_error<IntelPTError>(-pte_nomem);
299 
300   return PtInsnDecoderUP(decoder_ptr, DecoderDeleter);
301 }
302 
303 static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) {
304   pt_image *image = pt_insn_get_image(decoder_up.get());
305 
306   int status = pte_ok;
307   if (IsLibiptError(
308           status = pt_image_set_callback(image, ReadProcessMemory, &process)))
309     return make_error<IntelPTError>(status);
310   return Error::success();
311 }
312 
313 void lldb_private::trace_intel_pt::DecodeTrace(DecodedThread &decoded_thread,
314                                                TraceIntelPT &trace_intel_pt,
315                                                ArrayRef<uint8_t> buffer) {
316   Expected<PtInsnDecoderUP> decoder_up =
317       CreateInstructionDecoder(trace_intel_pt, buffer);
318   if (!decoder_up)
319     return decoded_thread.SetAsFailed(decoder_up.takeError());
320 
321   if (Error err = SetupMemoryImage(*decoder_up,
322                                    *decoded_thread.GetThread()->GetProcess()))
323     return decoded_thread.SetAsFailed(std::move(err));
324 
325   LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread);
326   libipt_decoder.DecodeUntilEndOfTrace();
327 }
328 
329 void lldb_private::trace_intel_pt::DecodeTrace(
330     DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
331     const DenseMap<lldb::core_id_t, llvm::ArrayRef<uint8_t>> &buffers,
332     const std::vector<IntelPTThreadContinousExecution> &executions) {
333   DenseMap<lldb::core_id_t, LibiptDecoder> decoders;
334   for (auto &core_id_buffer : buffers) {
335     Expected<PtInsnDecoderUP> decoder_up =
336         CreateInstructionDecoder(trace_intel_pt, core_id_buffer.second);
337     if (!decoder_up)
338       return decoded_thread.SetAsFailed(decoder_up.takeError());
339 
340     if (Error err = SetupMemoryImage(*decoder_up,
341                                      *decoded_thread.GetThread()->GetProcess()))
342       return decoded_thread.SetAsFailed(std::move(err));
343 
344     decoders.try_emplace(core_id_buffer.first,
345                          LibiptDecoder(*decoder_up->release(), decoded_thread));
346   }
347 
348   bool has_seen_psbs = false;
349   for (size_t i = 0; i < executions.size(); i++) {
350     const IntelPTThreadContinousExecution &execution = executions[i];
351 
352     auto variant = execution.thread_execution.variant;
353     // If we haven't seen a PSB yet, then it's fine not to show errors
354     if (has_seen_psbs) {
355       if (execution.intelpt_subtraces.empty()) {
356         decoded_thread.AppendError(createStringError(
357             inconvertibleErrorCode(),
358             formatv("Unable to find intel pt data for thread execution with "
359                     "tsc = {0} on core id = {1}",
360                     execution.thread_execution.GetLowestKnownTSC(),
361                     execution.thread_execution.core_id)));
362       }
363 
364       // If the first execution is incomplete because it doesn't have a previous
365       // context switch in its cpu, all good.
366       if (variant == ThreadContinuousExecution::Variant::OnlyEnd ||
367           variant == ThreadContinuousExecution::Variant::HintedStart) {
368         decoded_thread.AppendError(createStringError(
369             inconvertibleErrorCode(),
370             formatv("Thread execution starting at tsc = {0} on core id = {1} "
371                     "doesn't have a matching context switch in.",
372                     execution.thread_execution.GetLowestKnownTSC(),
373                     execution.thread_execution.core_id)));
374       }
375     }
376 
377     LibiptDecoder &decoder =
378         decoders.find(execution.thread_execution.core_id)->second;
379     for (const IntelPTThreadSubtrace &intel_pt_execution :
380          execution.intelpt_subtraces) {
381       has_seen_psbs = true;
382       decoder.DecodePSB(intel_pt_execution.psb_offset);
383     }
384 
385     // If we haven't seen a PSB yet, then it's fine not to show errors
386     if (has_seen_psbs) {
387       // If the last execution is incomplete because it doesn't have a following
388       // context switch in its cpu, all good.
389       if ((variant == ThreadContinuousExecution::Variant::OnlyStart &&
390            i + 1 != executions.size()) ||
391           variant == ThreadContinuousExecution::Variant::HintedEnd) {
392         decoded_thread.AppendError(createStringError(
393             inconvertibleErrorCode(),
394             formatv("Thread execution starting at tsc = {0} on core id = {1} "
395                     "doesn't have a matching context switch out",
396                     execution.thread_execution.GetLowestKnownTSC(),
397                     execution.thread_execution.core_id)));
398       }
399     }
400   }
401 }
402 
403 bool IntelPTThreadContinousExecution::operator<(
404     const IntelPTThreadContinousExecution &o) const {
405   // As the context switch might be incomplete, we look first for the first real
406   // PSB packet, which is a valid TSC. Otherwise, We query the thread execution
407   // itself for some tsc.
408   auto get_tsc = [](const IntelPTThreadContinousExecution &exec) {
409     return exec.intelpt_subtraces.empty()
410                ? exec.thread_execution.GetLowestKnownTSC()
411                : exec.intelpt_subtraces.front().tsc;
412   };
413 
414   return get_tsc(*this) < get_tsc(o);
415 }
416 
417 Expected<std::vector<IntelPTThreadSubtrace>>
418 lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions(
419     TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) {
420   Expected<PtInsnDecoderUP> decoder_up =
421       CreateInstructionDecoder(trace_intel_pt, buffer);
422   if (!decoder_up)
423     return decoder_up.takeError();
424 
425   pt_insn_decoder *decoder = decoder_up.get().get();
426 
427   std::vector<IntelPTThreadSubtrace> executions;
428 
429   int status = pte_ok;
430   while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) {
431     uint64_t tsc;
432     if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr)))
433       return createStringError(inconvertibleErrorCode(),
434                                "intel pt trace doesn't have TSC timestamps");
435 
436     uint64_t psb_offset;
437     pt_insn_get_sync_offset(decoder,
438                             &psb_offset); // this can't fail because we got here
439 
440     executions.push_back({
441         tsc,
442         psb_offset,
443     });
444   }
445   return executions;
446 }
447