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