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 19 #include "intel-pt.h" 20 21 namespace lldb_private { 22 namespace trace_intel_pt { 23 24 /// Class for representing a libipt decoding error. 25 class IntelPTError : public llvm::ErrorInfo<IntelPTError> { 26 public: 27 static char ID; 28 29 /// \param[in] libipt_error_code 30 /// Negative number returned by libipt when decoding the trace and 31 /// signaling errors. 32 /// 33 /// \param[in] address 34 /// Optional instruction address. When decoding an individual instruction, 35 /// its address might be available in the \a pt_insn object, and should be 36 /// passed to this constructor. Other errors don't have an associated 37 /// address. 38 IntelPTError(int libipt_error_code, 39 lldb::addr_t address = LLDB_INVALID_ADDRESS); 40 convertToErrorCode()41 std::error_code convertToErrorCode() const override { 42 return llvm::errc::not_supported; 43 } 44 45 void log(llvm::raw_ostream &OS) const override; 46 47 private: 48 int m_libipt_error_code; 49 lldb::addr_t m_address; 50 }; 51 52 /// \class IntelPTInstruction 53 /// An instruction obtained from decoding a trace. It is either an actual 54 /// instruction or an error indicating a gap in the trace. 55 /// 56 /// Gaps in the trace can come in a few flavors: 57 /// - tracing gaps (e.g. tracing was paused and then resumed) 58 /// - tracing errors (e.g. buffer overflow) 59 /// - decoding errors (e.g. some memory region couldn't be decoded) 60 /// As mentioned, any gap is represented as an error in this class. 61 class IntelPTInstruction { 62 public: IntelPTInstruction(const pt_insn & pt_insn)63 IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {} 64 65 /// Error constructor 66 /// 67 /// libipt errors should use the underlying \a IntelPTError class. IntelPTInstruction(llvm::Error err)68 IntelPTInstruction(llvm::Error err) { 69 llvm::handleAllErrors(std::move(err), 70 [&](std::unique_ptr<llvm::ErrorInfoBase> info) { 71 m_error = std::move(info); 72 }); 73 } 74 75 /// Check if this object represents an error (i.e. a gap). 76 /// 77 /// \return 78 /// Whether this object represents an error. 79 bool IsError() const; 80 81 /// \return 82 /// The instruction pointer address, or an \a llvm::Error if it is an 83 /// error. 84 llvm::Expected<lldb::addr_t> GetLoadAddress() const; 85 86 /// \return 87 /// An \a llvm::Error object if this class corresponds to an Error, or an 88 /// \a llvm::Error::success otherwise. 89 llvm::Error ToError() const; 90 91 IntelPTInstruction(IntelPTInstruction &&other) = default; 92 93 private: 94 IntelPTInstruction(const IntelPTInstruction &other) = delete; 95 const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete; 96 97 pt_insn m_pt_insn; 98 std::unique_ptr<llvm::ErrorInfoBase> m_error; 99 }; 100 101 /// \class DecodedThread 102 /// Class holding the instructions and function call hierarchy obtained from 103 /// decoding a trace, as well as a position cursor used when reverse debugging 104 /// the trace. 105 /// 106 /// Each decoded thread contains a cursor to the current position the user is 107 /// stopped at. See \a Trace::GetCursorPosition for more information. 108 class DecodedThread { 109 public: DecodedThread(std::vector<IntelPTInstruction> && instructions)110 DecodedThread(std::vector<IntelPTInstruction> &&instructions) 111 : m_instructions(std::move(instructions)), m_position(GetLastPosition()) { 112 } 113 114 /// Get the instructions from the decoded trace. Some of them might indicate 115 /// errors (i.e. gaps) in the trace. 116 /// 117 /// \return 118 /// The instructions of the trace. 119 llvm::ArrayRef<IntelPTInstruction> GetInstructions() const; 120 121 /// \return 122 /// The current position of the cursor of this trace, or 0 if there are no 123 /// instructions. 124 size_t GetCursorPosition() const; 125 126 /// Change the position of the cursor of this trace. If this value is to high, 127 /// the new position will be set as the last instruction of the trace. 128 /// 129 /// \return 130 /// The effective new position. 131 size_t SetCursorPosition(size_t new_position); 132 /// \} 133 134 private: 135 /// \return 136 /// The index of the last element of the trace, or 0 if empty. 137 size_t GetLastPosition() const; 138 139 std::vector<IntelPTInstruction> m_instructions; 140 size_t m_position; 141 }; 142 143 } // namespace trace_intel_pt 144 } // namespace lldb_private 145 146 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H 147