//===-- DecodedThread.h -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H #include #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "lldb/Target/Trace.h" #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" #include "intel-pt.h" namespace lldb_private { namespace trace_intel_pt { /// Class for representing a libipt decoding error. class IntelPTError : public llvm::ErrorInfo { public: static char ID; /// \param[in] libipt_error_code /// Negative number returned by libipt when decoding the trace and /// signaling errors. /// /// \param[in] address /// Optional instruction address. When decoding an individual instruction, /// its address might be available in the \a pt_insn object, and should be /// passed to this constructor. Other errors don't have an associated /// address. IntelPTError(int libipt_error_code, lldb::addr_t address = LLDB_INVALID_ADDRESS); std::error_code convertToErrorCode() const override { return llvm::errc::not_supported; } void log(llvm::raw_ostream &OS) const override; private: int m_libipt_error_code; lldb::addr_t m_address; }; /// \class IntelPTInstruction /// An instruction obtained from decoding a trace. It is either an actual /// instruction or an error indicating a gap in the trace. /// /// Gaps in the trace can come in a few flavors: /// - tracing gaps (e.g. tracing was paused and then resumed) /// - tracing errors (e.g. buffer overflow) /// - decoding errors (e.g. some memory region couldn't be decoded) /// As mentioned, any gap is represented as an error in this class. class IntelPTInstruction { public: IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp) : m_pt_insn(pt_insn), m_timestamp(timestamp) {} IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {} /// Error constructor /// /// libipt errors should use the underlying \a IntelPTError class. IntelPTInstruction(llvm::Error err); /// Check if this object represents an error (i.e. a gap). /// /// \return /// Whether this object represents an error. bool IsError() const; /// \return /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is /// an error. lldb::addr_t GetLoadAddress() const; /// \return /// An \a llvm::Error object if this class corresponds to an Error, or an /// \a llvm::Error::success otherwise. llvm::Error ToError() const; /// Get the timestamp associated with the current instruction. The timestamp /// is similar to what a rdtsc instruction would return. /// /// \return /// The timestamp or \b llvm::None if not available. llvm::Optional GetTimestampCounter() const; /// Get the \a lldb::TraceInstructionControlFlowType categories of the /// instruction. /// /// \param[in] next_load_address /// The address of the next instruction in the trace or \b /// LLDB_INVALID_ADDRESS if not available. /// /// \return /// The control flow categories, or \b 0 if the instruction is an error. lldb::TraceInstructionControlFlowType GetControlFlowType(lldb::addr_t next_load_address) const; IntelPTInstruction(IntelPTInstruction &&other) = default; private: IntelPTInstruction(const IntelPTInstruction &other) = delete; const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete; pt_insn m_pt_insn; llvm::Optional m_timestamp; std::unique_ptr m_error; }; /// \class DecodedThread /// Class holding the instructions and function call hierarchy obtained from /// decoding a trace, as well as a position cursor used when reverse debugging /// the trace. /// /// Each decoded thread contains a cursor to the current position the user is /// stopped at. See \a Trace::GetCursorPosition for more information. class DecodedThread : public std::enable_shared_from_this { public: DecodedThread(lldb::ThreadSP thread_sp, std::vector &&instructions, size_t raw_trace_size); /// Constructor with a single error signaling a complete failure of the /// decoding process. DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error); /// Get the instructions from the decoded trace. Some of them might indicate /// errors (i.e. gaps) in the trace. /// /// \return /// The instructions of the trace. llvm::ArrayRef GetInstructions() const; /// Get a new cursor for the decoded thread. lldb::TraceCursorUP GetCursor(); /// Get the size in bytes of the corresponding Intel PT raw trace /// /// \return /// The size of the trace. size_t GetRawTraceSize() const; private: lldb::ThreadSP m_thread_sp; std::vector m_instructions; size_t m_raw_trace_size; }; using DecodedThreadSP = std::shared_ptr; } // namespace trace_intel_pt } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H