xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 //===-- DecodedThread.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_INTEL_PT_DECODEDTHREAD_H
10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
11 
12 #include <vector>
13 
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/Error.h"
16 
17 #include "lldb/Target/Trace.h"
18 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
19 
20 #include "intel-pt.h"
21 
22 namespace lldb_private {
23 namespace trace_intel_pt {
24 
25 /// Class for representing a libipt decoding error.
26 class IntelPTError : public llvm::ErrorInfo<IntelPTError> {
27 public:
28   static char ID;
29 
30   /// \param[in] libipt_error_code
31   ///     Negative number returned by libipt when decoding the trace and
32   ///     signaling errors.
33   ///
34   /// \param[in] address
35   ///     Optional instruction address. When decoding an individual instruction,
36   ///     its address might be available in the \a pt_insn object, and should be
37   ///     passed to this constructor. Other errors don't have an associated
38   ///     address.
39   IntelPTError(int libipt_error_code,
40                lldb::addr_t address = LLDB_INVALID_ADDRESS);
41 
42   std::error_code convertToErrorCode() const override {
43     return llvm::errc::not_supported;
44   }
45 
46   void log(llvm::raw_ostream &OS) const override;
47 
48 private:
49   int m_libipt_error_code;
50   lldb::addr_t m_address;
51 };
52 
53 /// \class IntelPTInstruction
54 /// An instruction obtained from decoding a trace. It is either an actual
55 /// instruction or an error indicating a gap in the trace.
56 ///
57 /// Gaps in the trace can come in a few flavors:
58 ///   - tracing gaps (e.g. tracing was paused and then resumed)
59 ///   - tracing errors (e.g. buffer overflow)
60 ///   - decoding errors (e.g. some memory region couldn't be decoded)
61 /// As mentioned, any gap is represented as an error in this class.
62 class IntelPTInstruction {
63 public:
64   IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp)
65       : m_pt_insn(pt_insn), m_timestamp(timestamp) {}
66 
67   IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {}
68 
69   /// Error constructor
70   ///
71   /// libipt errors should use the underlying \a IntelPTError class.
72   IntelPTInstruction(llvm::Error err);
73 
74   /// Check if this object represents an error (i.e. a gap).
75   ///
76   /// \return
77   ///     Whether this object represents an error.
78   bool IsError() const;
79 
80   /// \return
81   ///     The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is
82   ///     an error.
83   lldb::addr_t GetLoadAddress() const;
84 
85   /// \return
86   ///     An \a llvm::Error object if this class corresponds to an Error, or an
87   ///     \a llvm::Error::success otherwise.
88   llvm::Error ToError() const;
89 
90   /// Get the timestamp associated with the current instruction. The timestamp
91   /// is similar to what a rdtsc instruction would return.
92   ///
93   /// \return
94   ///     The timestamp or \b llvm::None if not available.
95   llvm::Optional<uint64_t> GetTimestampCounter() const;
96 
97   /// Get the \a lldb::TraceInstructionControlFlowType categories of the
98   /// instruction.
99   ///
100   /// \param[in] next_load_address
101   ///     The address of the next instruction in the trace or \b
102   ///     LLDB_INVALID_ADDRESS if not available.
103   ///
104   /// \return
105   ///     The control flow categories, or \b 0 if the instruction is an error.
106   lldb::TraceInstructionControlFlowType
107   GetControlFlowType(lldb::addr_t next_load_address) const;
108 
109   IntelPTInstruction(IntelPTInstruction &&other) = default;
110 
111 private:
112   IntelPTInstruction(const IntelPTInstruction &other) = delete;
113   const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete;
114 
115   pt_insn m_pt_insn;
116   llvm::Optional<uint64_t> m_timestamp;
117   std::unique_ptr<llvm::ErrorInfoBase> m_error;
118 };
119 
120 /// \class DecodedThread
121 /// Class holding the instructions and function call hierarchy obtained from
122 /// decoding a trace, as well as a position cursor used when reverse debugging
123 /// the trace.
124 ///
125 /// Each decoded thread contains a cursor to the current position the user is
126 /// stopped at. See \a Trace::GetCursorPosition for more information.
127 class DecodedThread : public std::enable_shared_from_this<DecodedThread> {
128 public:
129   DecodedThread(lldb::ThreadSP thread_sp,
130                 std::vector<IntelPTInstruction> &&instructions,
131                 size_t raw_trace_size);
132 
133   /// Constructor with a single error signaling a complete failure of the
134   /// decoding process.
135   DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error);
136 
137   /// Get the instructions from the decoded trace. Some of them might indicate
138   /// errors (i.e. gaps) in the trace.
139   ///
140   /// \return
141   ///   The instructions of the trace.
142   llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
143 
144   /// Get a new cursor for the decoded thread.
145   lldb::TraceCursorUP GetCursor();
146 
147   /// Get the size in bytes of the corresponding Intel PT raw trace
148   ///
149   /// \return
150   ///   The size of the trace.
151   size_t GetRawTraceSize() const;
152 
153 private:
154   lldb::ThreadSP m_thread_sp;
155   std::vector<IntelPTInstruction> m_instructions;
156   size_t m_raw_trace_size;
157 };
158 
159 using DecodedThreadSP = std::shared_ptr<DecodedThread>;
160 
161 } // namespace trace_intel_pt
162 } // namespace lldb_private
163 
164 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
165