xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 //===-- LibiptDecoder.h --======---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H
10 #define LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H
11 
12 #include "DecodedThread.h"
13 #include "PerfContextSwitchDecoder.h"
14 #include "forward-declarations.h"
15 #include "intel-pt.h"
16 #include <optional>
17 
18 namespace lldb_private {
19 namespace trace_intel_pt {
20 
21 /// This struct represents a contiguous section of a trace that starts at a PSB
22 /// and ends right before the next PSB or the end of the trace.
23 struct PSBBlock {
24   /// The memory offset of a PSB packet that is a synchronization point for the
25   /// decoder. A decoder normally looks first for a PSB packet and then it
26   /// starts decoding.
27   uint64_t psb_offset;
28   /// The timestamp associated with the PSB packet above.
29   std::optional<uint64_t> tsc;
30   /// Size in bytes of this block
31   uint64_t size;
32   /// The first ip for this PSB block.
33   /// This is \a std::nullopt if tracing was disabled when the PSB block was
34   /// emitted.  This means that eventually there's be an enablement event that
35   /// will come with an ip.
36   std::optional<lldb::addr_t> starting_ip;
37 };
38 
39 /// This struct represents a continuous execution of a thread in a cpu,
40 /// delimited by a context switch in and out, and a list of Intel PT subtraces
41 /// that belong to this execution.
42 struct IntelPTThreadContinousExecution {
43   ThreadContinuousExecution thread_execution;
44   std::vector<PSBBlock> psb_blocks;
45 
IntelPTThreadContinousExecutionIntelPTThreadContinousExecution46   IntelPTThreadContinousExecution(
47       const ThreadContinuousExecution &thread_execution)
48       : thread_execution(thread_execution) {}
49 
50   /// Comparator by time
51   bool operator<(const IntelPTThreadContinousExecution &o) const;
52 };
53 
54 /// Decode a raw Intel PT trace for a single thread given in \p buffer and
55 /// append the decoded instructions and errors in \p decoded_thread. It uses the
56 /// low level libipt library underneath.
57 ///
58 /// \return
59 ///   An \a llvm::Error if the decoder couldn't be properly set up.
60 llvm::Error DecodeSingleTraceForThread(DecodedThread &decoded_thread,
61                                        TraceIntelPT &trace_intel_pt,
62                                        llvm::ArrayRef<uint8_t> buffer);
63 
64 /// Decode a raw Intel PT trace for a single thread that was collected in a per
65 /// cpu core basis.
66 ///
67 /// \param[out] decoded_thread
68 ///   All decoded instructions, errors and events will be appended to this
69 ///   object.
70 ///
71 /// \param[in] trace_intel_pt
72 ///   The main Trace object that contains all the information related to the
73 ///   trace session.
74 ///
75 /// \param[in] buffers
76 ///   A map from cpu core id to raw intel pt buffers.
77 ///
78 /// \param[in] executions
79 ///   A list of chunks of timed executions of the same given thread. It is used
80 ///   to identify if some executions have missing intel pt data and also to
81 ///   determine in which core a certain part of the execution ocurred.
82 ///
83 /// \return
84 ///   An \a llvm::Error if the decoder couldn't be properly set up, i.e. no
85 ///   instructions were attempted to be decoded.
86 llvm::Error DecodeSystemWideTraceForThread(
87     DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt,
88     const llvm::DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers,
89     const std::vector<IntelPTThreadContinousExecution> &executions);
90 
91 /// Given an intel pt trace, split it in chunks delimited by PSB packets. Each
92 /// of these chunks is guaranteed to have been executed continuously.
93 ///
94 /// \param[in] trace_intel_pt
95 ///   The main Trace object that contains all the information related to the
96 ///   trace session.
97 ///
98 /// \param[in] buffer
99 ///   The intel pt buffer that belongs to a single thread or to a single cpu
100 ///   core.
101 ///
102 /// \param[in] expect_tscs
103 ///   If \b true, an error is return if a packet without TSC is found.
104 ///
105 /// \return
106 ///   A list of continuous executions sorted by time, or an \a llvm::Error in
107 ///   case of failures.
108 llvm::Expected<std::vector<PSBBlock>>
109 SplitTraceIntoPSBBlock(TraceIntelPT &trace_intel_pt,
110                        llvm::ArrayRef<uint8_t> buffer, bool expect_tscs);
111 
112 /// Find the lowest TSC in the given trace.
113 ///
114 /// \return
115 ///     The lowest TSC value in this trace if available, \a std::nullopt if the
116 ///     trace is empty or the trace contains no timing information, or an \a
117 ///     llvm::Error if it was not possible to set up the decoder.
118 llvm::Expected<std::optional<uint64_t>>
119 FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt,
120                      llvm::ArrayRef<uint8_t> buffer);
121 
122 } // namespace trace_intel_pt
123 } // namespace lldb_private
124 
125 #endif // LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H
126