xref: /llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp (revision 6a5355e8a159bd9c058d4fbba2a87e0465fe0dc7)
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 stops if a different PSB is reached.
101   void DecodeInstructionsAndEvents(int status,
102                                    bool stop_on_psb_change = false) {
103     uint64_t psb_offset;
104     pt_insn_get_sync_offset(&m_decoder,
105                             &psb_offset); // this can't fail because we got here
106 
107     while (true) {
108       DecodedInstruction insn = ProcessPTEvents(status);
109       if (!insn) {
110         m_decoded_thread.Append(insn);
111         break;
112       }
113 
114       if (stop_on_psb_change) {
115         uint64_t cur_psb_offset;
116         pt_insn_get_sync_offset(
117             &m_decoder, &cur_psb_offset); // this can't fail because we got here
118         if (cur_psb_offset != psb_offset)
119           break;
120       }
121 
122       // The status returned by DecodeNextInstruction will need to be processed
123       // by ProcessPTEvents in the next loop if it is not an error.
124       if (IsLibiptError(status = DecodeNextInstruction(insn))) {
125         insn.libipt_error = status;
126         m_decoded_thread.Append(insn);
127         break;
128       }
129       m_decoded_thread.Append(insn);
130     }
131   }
132 
133   /// Move the decoder forward to the next synchronization point (i.e. next PSB
134   /// packet).
135   ///
136   /// Once the decoder is at that synchronization point, it can start decoding
137   /// instructions.
138   ///
139   /// If errors are found, they will be appended to the trace.
140   ///
141   /// \return
142   ///   The libipt decoder status after moving to the next PSB. Negative if
143   ///   no PSB was found.
144   int FindNextSynchronizationPoint() {
145     // Try to sync the decoder. If it fails, then get the decoder_offset and
146     // try to sync again from the next synchronization point. If the
147     // new_decoder_offset is same as decoder_offset then we can't move to the
148     // next synchronization point. Otherwise, keep resyncing until either end
149     // of trace stream (eos) is reached or pt_insn_sync_forward() passes.
150     int status = pt_insn_sync_forward(&m_decoder);
151 
152     // We make this call to record any synchronization errors.
153     if (IsLibiptError(status))
154       m_decoded_thread.Append(DecodedInstruction(status));
155 
156     return status;
157   }
158 
159   /// Before querying instructions, we need to query the events associated that
160   /// instruction e.g. timing events like ptev_tick, or paging events like
161   /// ptev_paging.
162   ///
163   /// \param[in] status
164   ///   The status gotten from the previous instruction decoding or PSB
165   ///   synchronization.
166   ///
167   /// \return
168   ///   A \a DecodedInstruction with event, tsc and error information.
169   DecodedInstruction ProcessPTEvents(int status) {
170     DecodedInstruction insn;
171     while (status & pts_event_pending) {
172       pt_event event;
173       status = pt_insn_event(&m_decoder, &event, sizeof(event));
174       if (IsLibiptError(status)) {
175         insn.libipt_error = status;
176         break;
177       }
178 
179       switch (event.type) {
180       case ptev_enabled:
181         // The kernel started or resumed tracing the program.
182         break;
183       case ptev_disabled:
184         // The CPU paused tracing the program, e.g. due to ip filtering.
185       case ptev_async_disabled:
186         // The kernel or user code paused tracing the program, e.g.
187         // a breakpoint or a ioctl invocation pausing the trace, or a
188         // context switch happened.
189 
190         if (m_decoded_thread.GetInstructionsCount() > 0) {
191           // A paused event before the first instruction can be safely
192           // discarded.
193           insn.events |= eTraceEventPaused;
194         }
195         break;
196       case ptev_overflow:
197         // The CPU internal buffer had an overflow error and some instructions
198         // were lost.
199         insn.libipt_error = -pte_overflow;
200         break;
201       default:
202         break;
203       }
204     }
205 
206     // We refresh the TSC that might have changed after processing the events.
207     // See
208     // https://github.com/intel/libipt/blob/master/doc/man/pt_evt_next.3.md
209     RefreshTscInfo();
210     if (m_tsc_info)
211       insn.tsc = m_tsc_info.tsc;
212     return insn;
213   }
214 
215   /// Query the decoder for the most recent TSC timestamp and update
216   /// the inner tsc information accordingly.
217   void RefreshTscInfo() {
218     if (m_tsc_info.has_tsc == eLazyBoolNo)
219       return;
220 
221     uint64_t new_tsc;
222     int tsc_status;
223     if (IsLibiptError(tsc_status = pt_insn_time(&m_decoder, &new_tsc, nullptr,
224                                                 nullptr))) {
225       if (IsTscUnavailable(tsc_status)) {
226         // We now know that the trace doesn't support TSC, so we won't try
227         // again.
228         // See
229         // https://github.com/intel/libipt/blob/master/doc/man/pt_qry_time.3.md
230         m_tsc_info.has_tsc = eLazyBoolNo;
231       } else {
232         // We don't add TSC decoding errors in the decoded trace itself to
233         // prevent creating unnecessary gaps, but we can count how many of
234         // these errors happened. In this case we reuse the previous correct
235         // TSC we saw, as it's better than no TSC at all.
236         m_decoded_thread.RecordTscError(tsc_status);
237       }
238     } else {
239       m_tsc_info.tsc = new_tsc;
240       m_tsc_info.has_tsc = eLazyBoolYes;
241     }
242   }
243 
244 private:
245   pt_insn_decoder &m_decoder;
246   DecodedThread &m_decoded_thread;
247   TscInfo m_tsc_info;
248 };
249 
250 /// Callback used by libipt for reading the process memory.
251 ///
252 /// More information can be found in
253 /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md
254 static int ReadProcessMemory(uint8_t *buffer, size_t size,
255                              const pt_asid * /* unused */, uint64_t pc,
256                              void *context) {
257   Process *process = static_cast<Process *>(context);
258 
259   Status error;
260   int bytes_read = process->ReadMemory(pc, buffer, size, error);
261   if (error.Fail())
262     return -pte_nomap;
263   return bytes_read;
264 }
265 
266 // RAII deleter for libipt's decoder
267 auto DecoderDeleter = [](pt_insn_decoder *decoder) {
268   pt_insn_free_decoder(decoder);
269 };
270 
271 using PtInsnDecoderUP =
272     std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>;
273 
274 static Expected<PtInsnDecoderUP>
275 CreateInstructionDecoder(TraceIntelPT &trace_intel_pt,
276                          ArrayRef<uint8_t> buffer) {
277   Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
278   if (!cpu_info)
279     return cpu_info.takeError();
280 
281   pt_config config;
282   pt_config_init(&config);
283   config.cpu = *cpu_info;
284   int status = pte_ok;
285 
286   if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu)))
287     return make_error<IntelPTError>(status);
288 
289   // The libipt library does not modify the trace buffer, hence the
290   // following casts are safe.
291   config.begin = const_cast<uint8_t *>(buffer.data());
292   config.end = const_cast<uint8_t *>(buffer.data() + buffer.size());
293 
294   pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config);
295   if (!decoder_ptr)
296     return make_error<IntelPTError>(-pte_nomem);
297 
298   return PtInsnDecoderUP(decoder_ptr, DecoderDeleter);
299 }
300 
301 static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) {
302   pt_image *image = pt_insn_get_image(decoder_up.get());
303 
304   int status = pte_ok;
305   if (IsLibiptError(
306           status = pt_image_set_callback(image, ReadProcessMemory, &process)))
307     return make_error<IntelPTError>(status);
308   return Error::success();
309 }
310 
311 void lldb_private::trace_intel_pt::DecodeSingleTraceForThread(DecodedThread &decoded_thread,
312                                                TraceIntelPT &trace_intel_pt,
313                                                ArrayRef<uint8_t> buffer) {
314   Expected<PtInsnDecoderUP> decoder_up =
315       CreateInstructionDecoder(trace_intel_pt, buffer);
316   if (!decoder_up)
317     return decoded_thread.SetAsFailed(decoder_up.takeError());
318 
319   if (Error err = SetupMemoryImage(*decoder_up,
320                                    *decoded_thread.GetThread()->GetProcess()))
321     return decoded_thread.SetAsFailed(std::move(err));
322 
323   LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread);
324   libipt_decoder.DecodeUntilEndOfTrace();
325 }
326 
327 void lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread(
328     DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
329     const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers,
330     const std::vector<IntelPTThreadContinousExecution> &executions) {
331   DenseMap<lldb::cpu_id_t, LibiptDecoder> decoders;
332   for (auto &cpu_id_buffer : buffers) {
333     Expected<PtInsnDecoderUP> decoder_up =
334         CreateInstructionDecoder(trace_intel_pt, cpu_id_buffer.second);
335     if (!decoder_up)
336       return decoded_thread.SetAsFailed(decoder_up.takeError());
337 
338     if (Error err = SetupMemoryImage(*decoder_up,
339                                      *decoded_thread.GetThread()->GetProcess()))
340       return decoded_thread.SetAsFailed(std::move(err));
341 
342     decoders.try_emplace(cpu_id_buffer.first,
343                          LibiptDecoder(*decoder_up->release(), decoded_thread));
344   }
345 
346   bool has_seen_psbs = false;
347   for (size_t i = 0; i < executions.size(); i++) {
348     const IntelPTThreadContinousExecution &execution = executions[i];
349 
350     auto variant = execution.thread_execution.variant;
351     // If we haven't seen a PSB yet, then it's fine not to show errors
352     if (has_seen_psbs) {
353       if (execution.intelpt_subtraces.empty()) {
354         decoded_thread.AppendError(createStringError(
355             inconvertibleErrorCode(),
356             formatv("Unable to find intel pt data for thread execution with "
357                     "tsc = {0} on cpu id = {1}",
358                     execution.thread_execution.GetLowestKnownTSC(),
359                     execution.thread_execution.cpu_id)));
360       }
361 
362       // If the first execution is incomplete because it doesn't have a previous
363       // context switch in its cpu, all good.
364       if (variant == ThreadContinuousExecution::Variant::OnlyEnd ||
365           variant == ThreadContinuousExecution::Variant::HintedStart) {
366         decoded_thread.AppendError(createStringError(
367             inconvertibleErrorCode(),
368             formatv("Thread execution starting at tsc = {0} on cpu id = {1} "
369                     "doesn't have a matching context switch in.",
370                     execution.thread_execution.GetLowestKnownTSC(),
371                     execution.thread_execution.cpu_id)));
372       }
373     }
374 
375     LibiptDecoder &decoder =
376         decoders.find(execution.thread_execution.cpu_id)->second;
377     for (const IntelPTThreadSubtrace &intel_pt_execution :
378          execution.intelpt_subtraces) {
379       has_seen_psbs = true;
380       decoder.DecodePSB(intel_pt_execution.psb_offset);
381     }
382 
383     // If we haven't seen a PSB yet, then it's fine not to show errors
384     if (has_seen_psbs) {
385       // If the last execution is incomplete because it doesn't have a following
386       // context switch in its cpu, all good.
387       if ((variant == ThreadContinuousExecution::Variant::OnlyStart &&
388            i + 1 != executions.size()) ||
389           variant == ThreadContinuousExecution::Variant::HintedEnd) {
390         decoded_thread.AppendError(createStringError(
391             inconvertibleErrorCode(),
392             formatv("Thread execution starting at tsc = {0} on cpu id = {1} "
393                     "doesn't have a matching context switch out",
394                     execution.thread_execution.GetLowestKnownTSC(),
395                     execution.thread_execution.cpu_id)));
396       }
397     }
398   }
399 }
400 
401 bool IntelPTThreadContinousExecution::operator<(
402     const IntelPTThreadContinousExecution &o) const {
403   // As the context switch might be incomplete, we look first for the first real
404   // PSB packet, which is a valid TSC. Otherwise, We query the thread execution
405   // itself for some tsc.
406   auto get_tsc = [](const IntelPTThreadContinousExecution &exec) {
407     return exec.intelpt_subtraces.empty()
408                ? exec.thread_execution.GetLowestKnownTSC()
409                : exec.intelpt_subtraces.front().tsc;
410   };
411 
412   return get_tsc(*this) < get_tsc(o);
413 }
414 
415 Expected<std::vector<IntelPTThreadSubtrace>>
416 lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions(
417     TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) {
418   Expected<PtInsnDecoderUP> decoder_up =
419       CreateInstructionDecoder(trace_intel_pt, buffer);
420   if (!decoder_up)
421     return decoder_up.takeError();
422 
423   pt_insn_decoder *decoder = decoder_up.get().get();
424 
425   std::vector<IntelPTThreadSubtrace> executions;
426 
427   int status = pte_ok;
428   while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) {
429     uint64_t tsc;
430     if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr)))
431       return createStringError(inconvertibleErrorCode(),
432                                "intel pt trace doesn't have TSC timestamps");
433 
434     uint64_t psb_offset;
435     pt_insn_get_sync_offset(decoder,
436                             &psb_offset); // this can't fail because we got here
437 
438     executions.push_back({
439         psb_offset,
440         tsc,
441     });
442   }
443   return executions;
444 }
445