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) : m_pt_insn(pt_insn) {} 65 66 /// Error constructor 67 /// 68 /// libipt errors should use the underlying \a IntelPTError class. 69 IntelPTInstruction(llvm::Error err) { 70 llvm::handleAllErrors(std::move(err), 71 [&](std::unique_ptr<llvm::ErrorInfoBase> info) { 72 m_error = std::move(info); 73 }); 74 } 75 76 /// Check if this object represents an error (i.e. a gap). 77 /// 78 /// \return 79 /// Whether this object represents an error. 80 bool IsError() const; 81 82 /// \return 83 /// The instruction pointer address, or an \a llvm::Error if it is an 84 /// error. 85 llvm::Expected<lldb::addr_t> GetLoadAddress() const; 86 87 /// \return 88 /// An \a llvm::Error object if this class corresponds to an Error, or an 89 /// \a llvm::Error::success otherwise. 90 llvm::Error ToError() const; 91 92 IntelPTInstruction(IntelPTInstruction &&other) = default; 93 94 private: 95 IntelPTInstruction(const IntelPTInstruction &other) = delete; 96 const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete; 97 98 pt_insn m_pt_insn; 99 std::unique_ptr<llvm::ErrorInfoBase> m_error; 100 }; 101 102 /// \class DecodedThread 103 /// Class holding the instructions and function call hierarchy obtained from 104 /// decoding a trace, as well as a position cursor used when reverse debugging 105 /// the trace. 106 /// 107 /// Each decoded thread contains a cursor to the current position the user is 108 /// stopped at. See \a Trace::GetCursorPosition for more information. 109 class DecodedThread { 110 public: 111 DecodedThread(std::vector<IntelPTInstruction> &&instructions) 112 : m_instructions(std::move(instructions)), m_position(GetLastPosition()) { 113 } 114 115 /// Constructor with a single error signaling a complete failure of the 116 /// decoding process. 117 DecodedThread(llvm::Error error); 118 119 /// Get the instructions from the decoded trace. Some of them might indicate 120 /// errors (i.e. gaps) in the trace. 121 /// 122 /// \return 123 /// The instructions of the trace. 124 llvm::ArrayRef<IntelPTInstruction> GetInstructions() const; 125 126 /// \return 127 /// The current position of the cursor of this trace, or 0 if there are no 128 /// instructions. 129 size_t GetCursorPosition() const; 130 131 /// Change the position of the cursor of this trace. If this value is to high, 132 /// the new position will be set as the last instruction of the trace. 133 /// 134 /// \return 135 /// The effective new position. 136 size_t SetCursorPosition(size_t new_position); 137 /// \} 138 139 private: 140 /// \return 141 /// The index of the last element of the trace, or 0 if empty. 142 size_t GetLastPosition() const; 143 144 std::vector<IntelPTInstruction> m_instructions; 145 size_t m_position; 146 }; 147 148 } // namespace trace_intel_pt 149 } // namespace lldb_private 150 151 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H 152