diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h @@ -51,61 +51,6 @@ 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) - : m_pt_insn(pt_insn), m_is_error(false) {} - - /// Error constructor - IntelPTInstruction(); - - /// 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; - - /// Get the size in bytes of an instance of this class - static size_t GetMemoryUsage(); - - /// 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; - - // When adding new members to this class, make sure to update - // IntelPTInstruction::GetMemoryUsage() if needed. - pt_insn m_pt_insn; - bool m_is_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 @@ -178,14 +123,32 @@ /// Append a decoding error (i.e. an instruction that failed to be decoded). void AppendError(llvm::Error &&error); - /// Get the instructions from the decoded trace. Some of them might indicate - /// errors (i.e. gaps) in the trace. For an instruction error, you can access - /// its underlying error message with the \a GetErrorByInstructionIndex() - /// method. + /// Get the instruction pointers from the decoded trace. Some of them might + /// indicate errors (i.e. gaps) in the trace. For an instruction error, you + /// can access its underlying error message with the \a + /// GetErrorByInstructionIndex() method. /// /// \return /// The instructions of the trace. - llvm::ArrayRef GetInstructions() const; + llvm::ArrayRef GetInstructions() const; + + /// \return + /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is + /// an error. + lldb::addr_t GetInstructionLoadAddress(size_t insn_index) 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 + GetInstructionControlFlowType(size_t insn_index, + lldb::addr_t next_load_address) const; /// Construct the TSC range that covers the given instruction index. /// This operation is O(logn) and should be used sparingly. @@ -251,7 +214,7 @@ lldb::ThreadSP m_thread_sp; /// The low level storage of all instruction addresses. Each instruction has /// an index in this vector and it will be used in other parts of the code. - std::vector m_instructions; + std::vector m_instructions; /// This map contains the TSCs of the decoded instructions. It maps /// `instruction index -> TSC`, where `instruction index` is the first index /// at which the mapped TSC appears. We use this representation because TSCs diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -35,38 +35,29 @@ OS << "error: " << libipt_error_message; } -IntelPTInstruction::IntelPTInstruction() { - m_pt_insn.ip = LLDB_INVALID_ADDRESS; - m_pt_insn.iclass = ptic_error; - m_is_error = true; -} - -bool IntelPTInstruction::IsError() const { return m_is_error; } - -lldb::addr_t IntelPTInstruction::GetLoadAddress() const { return m_pt_insn.ip; } - -size_t IntelPTInstruction::GetMemoryUsage() { - return sizeof(IntelPTInstruction); -} - Optional DecodedThread::GetRawTraceSize() const { return m_raw_trace_size; } -TraceInstructionControlFlowType -IntelPTInstruction::GetControlFlowType(lldb::addr_t next_load_address) const { - if (IsError()) +lldb::addr_t DecodedThread::GetInstructionLoadAddress(size_t insn_index) const { + m_instructions[insn_index]->ip; +} + +TraceInstructionControlFlowType DecodedThread::GetInstructionControlFlowType( + size_t insn_index, lldb::addr_t next_load_address) const { + if (IsInstructionAnError(insn_index)) return (TraceInstructionControlFlowType)0; TraceInstructionControlFlowType mask = eTraceInstructionControlFlowTypeInstruction; - switch (m_pt_insn.iclass) { + pt_insn insn = *m_instructions[insn_index]; + switch (insn.iclass) { case ptic_cond_jump: case ptic_jump: case ptic_far_jump: mask |= eTraceInstructionControlFlowTypeBranch; - if (m_pt_insn.ip + m_pt_insn.size != next_load_address) + if (insn.ip + insn.size != next_load_address) mask |= eTraceInstructionControlFlowTypeTakenBranch; break; case ptic_return: @@ -99,7 +90,7 @@ } void DecodedThread::AppendInstruction(const pt_insn &insn) { - m_instructions.emplace_back(insn); + m_instructions.emplace_back(&insn); } void DecodedThread::AppendInstruction(const pt_insn &insn, uint64_t tsc) { @@ -130,7 +121,7 @@ return m_tsc_errors; } -ArrayRef DecodedThread::GetInstructions() const { +ArrayRef DecodedThread::GetInstructions() const { return makeArrayRef(m_instructions); } @@ -144,7 +135,7 @@ } bool DecodedThread::IsInstructionAnError(size_t insn_idx) const { - return m_instructions[insn_idx].IsError(); + return m_instructions[insn_idx]->ip == LLDB_INVALID_ADDRESS; } const char *DecodedThread::GetErrorByInstructionIndex(size_t insn_idx) { @@ -173,8 +164,7 @@ } size_t DecodedThread::CalculateApproximateMemoryUsage() const { - return IntelPTInstruction::GetMemoryUsage() * m_instructions.size() + - m_errors.getMemorySize(); + return sizeof(pt_insn *) * m_instructions.size() + m_errors.getMemorySize(); } DecodedThread::TscRange::TscRange(std::map::const_iterator it, diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp --- a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -78,8 +78,8 @@ return std::abs(dist); } }; - - int64_t dist = FindDistanceAndSetPos(); + + int64_t dist = FindDistanceAndSetPos(); m_tsc_range = m_decoded_thread_sp->CalculateTscRange(m_pos); return dist; } @@ -93,7 +93,7 @@ } lldb::addr_t TraceCursorIntelPT::GetLoadAddress() { - return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress(); + return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos); } Optional @@ -111,8 +111,8 @@ TraceCursorIntelPT::GetInstructionControlFlowType() { lldb::addr_t next_load_address = m_pos + 1 < GetInternalInstructionSize() - ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress() + ? m_decoded_thread_sp->GetInstructionLoadAddress(m_pos + 1) : LLDB_INVALID_ADDRESS; - return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType( - next_load_address); + return m_decoded_thread_sp->GetInstructionControlFlowType(m_pos, + next_load_address); }