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