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