summaryrefslogtreecommitdiff
path: root/tools/intel-features/intel-pt/Decoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/intel-features/intel-pt/Decoder.h')
-rw-r--r--tools/intel-features/intel-pt/Decoder.h327
1 files changed, 327 insertions, 0 deletions
diff --git a/tools/intel-features/intel-pt/Decoder.h b/tools/intel-features/intel-pt/Decoder.h
new file mode 100644
index 0000000000000..dc2794ac3bc33
--- /dev/null
+++ b/tools/intel-features/intel-pt/Decoder.h
@@ -0,0 +1,327 @@
+//===-- Decoder.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef Decoder_h_
+#define Decoder_h_
+
+// C/C++ Includes
+#include <map>
+#include <mutex>
+#include <string>
+#include <vector>
+
+// Project includes, Other libraries and framework includes
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBTarget.h"
+#include "lldb/API/SBTrace.h"
+#include "lldb/API/SBTraceOptions.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include "intel-pt.h"
+
+namespace ptdecoder_private {
+//----------------------------------------------------------------------
+/// @class Instruction
+/// @brief Represents an assembly instruction containing raw
+/// instruction bytes, instruction address along with information
+/// regarding execution flow context and Intel(R) Processor Trace
+/// context.
+//----------------------------------------------------------------------
+class Instruction {
+public:
+ Instruction() : ip(0), data(), error(), iclass(ptic_error), speculative(0) {}
+
+ Instruction(const Instruction &insn) = default;
+
+ Instruction(const struct pt_insn &insn)
+ : ip(insn.ip), data(), error(insn.size == 0 ? "invalid instruction" : ""),
+ iclass(insn.iclass), speculative(insn.speculative) {
+ if (insn.size != 0)
+ data.assign(insn.raw, insn.raw + insn.size);
+ }
+
+ Instruction(const char *err)
+ : ip(0), data(), error(err ? err : "unknown error"), iclass(ptic_error),
+ speculative(0) {}
+
+ ~Instruction() {}
+
+ uint64_t GetInsnAddress() const { return ip; }
+
+ size_t GetRawBytes(void *buf, size_t size) const {
+ if ((buf == nullptr) || (size == 0))
+ return data.size();
+
+ size_t bytes_to_read = ((size <= data.size()) ? size : data.size());
+ ::memcpy(buf, data.data(), bytes_to_read);
+ return bytes_to_read;
+ }
+
+ const std::string &GetError() const { return error; }
+
+ bool GetSpeculative() const { return speculative; }
+
+private:
+ uint64_t ip; // instruction address in inferior's memory image
+ std::vector<uint8_t> data; // raw bytes
+ std::string error; // Error string if instruction is invalid
+ enum pt_insn_class iclass; // classification of the instruction
+ // A collection of flags giving additional information about instruction
+ uint32_t speculative : 1; // Instruction was executed speculatively or not
+};
+
+//---------------------------------------------------------------------------
+/// @class InstructionList
+/// @brief Represents a list of assembly instructions. Each instruction is of
+/// type Instruction.
+//---------------------------------------------------------------------------
+class InstructionList {
+public:
+ InstructionList() : m_insn_vec() {}
+
+ InstructionList(const InstructionList &insn_list)
+ : m_insn_vec(insn_list.m_insn_vec) {}
+
+ ~InstructionList() {}
+
+ // Get number of instructions in the list
+ size_t GetSize() const { return m_insn_vec.size(); }
+
+ // Get instruction at index
+ Instruction GetInstructionAtIndex(uint32_t idx) {
+ return (idx < m_insn_vec.size() ? m_insn_vec[idx]
+ : Instruction("invalid instruction"));
+ }
+
+ // Append intruction at the end of the list
+ void AppendInstruction(Instruction inst) { m_insn_vec.push_back(inst); }
+
+private:
+ std::vector<Instruction> m_insn_vec;
+};
+
+//----------------------------------------------------------------------
+/// @class TraceOptions
+/// @brief Provides Intel(R) Processor Trace specific configuration options and
+/// other information obtained by decoding and post-processing the trace
+/// data. Currently, this information comprises of the total number of
+/// assembly instructions executed for an inferior.
+//----------------------------------------------------------------------
+class TraceOptions : public lldb::SBTraceOptions {
+public:
+ TraceOptions() : lldb::SBTraceOptions(), m_insn_log_size(0) {}
+
+ ~TraceOptions() {}
+
+ //------------------------------------------------------------------
+ /// Get total number of assembly instructions obtained after decoding the
+ /// complete Intel(R) Processor Trace data obtained from LLDB.
+ ///
+ /// @return
+ /// Total number of instructions.
+ //------------------------------------------------------------------
+ uint32_t getInstructionLogSize() const { return m_insn_log_size; }
+
+ //------------------------------------------------------------------
+ /// Set total number of assembly instructions.
+ ///
+ /// @param[in] size
+ /// Value to be set.
+ //------------------------------------------------------------------
+ void setInstructionLogSize(uint32_t size) { m_insn_log_size = size; }
+
+private:
+ uint32_t m_insn_log_size;
+};
+
+//----------------------------------------------------------------------
+/// @class Decoder
+/// @brief This class makes use of Intel(R) Processor Trace hardware feature
+/// (implememted inside LLDB) to gather trace data for an inferior (being
+/// debugged with LLDB) to provide meaningful information out of it.
+///
+/// Currently the meaningful information comprises of the execution flow
+/// of the inferior (in terms of assembly instructions executed). The class
+/// enables user to:
+/// - start the trace with configuration options for a thread/process,
+/// - stop the trace for a thread/process,
+/// - get the execution flow (assembly instructions) for a thread and
+/// - get trace specific information for a thread
+//----------------------------------------------------------------------
+class Decoder {
+public:
+ typedef std::vector<Instruction> Instructions;
+
+ Decoder(lldb::SBDebugger &sbdebugger)
+ : m_mapProcessUID_mapThreadID_TraceInfo_mutex(),
+ m_mapProcessUID_mapThreadID_TraceInfo(),
+ m_debugger_user_id(sbdebugger.GetID()) {}
+
+ ~Decoder() {}
+
+ void StartProcessorTrace(lldb::SBProcess &sbprocess,
+ lldb::SBTraceOptions &sbtraceoptions,
+ lldb::SBError &sberror);
+
+ void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror,
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID);
+
+ void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+ uint32_t offset, uint32_t count,
+ InstructionList &result_list,
+ lldb::SBError &sberror);
+
+ void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+ TraceOptions &traceinfo, lldb::SBError &sberror);
+
+private:
+ class ThreadTraceInfo;
+ typedef std::vector<uint8_t> Buffer;
+
+ // internal class to manage inferior's read-execute section information
+ class ReadExecuteSectionInfo {
+ public:
+ uint64_t load_address;
+ uint64_t file_offset;
+ uint64_t size;
+ std::string image_path;
+
+ ReadExecuteSectionInfo(const uint64_t addr, const uint64_t offset,
+ const uint64_t sz, const std::string &path)
+ : load_address(addr), file_offset(offset), size(sz), image_path(path) {}
+
+ ReadExecuteSectionInfo(const ReadExecuteSectionInfo &rxsection) = default;
+ };
+
+ typedef struct pt_cpu CPUInfo;
+ typedef std::vector<ReadExecuteSectionInfo> ReadExecuteSectionInfos;
+
+ // Check whether the provided SBProcess belongs to the same SBDebugger with
+ // which Decoder class instance was constructed.
+ void CheckDebuggerID(lldb::SBProcess &sbprocess, lldb::SBError &sberror);
+
+ // Function to remove entries of finished processes/threads in the class
+ void RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess);
+
+ // Parse cpu information from trace configuration received from LLDB
+ void ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s,
+ lldb::SBError &sberror);
+
+ ///------------------------------------------------------------------------
+ /// Function performs following tasks for a given process and thread:
+ /// - Checks if the given thread is registered in the class or not. If not
+ /// then tries to register it if trace was ever started on the entire
+ /// process. Else returns error.
+ /// - fetches trace and other necessary information from LLDB (using
+ /// ReadTraceDataAndImageInfo()) and decodes the trace (using
+ /// DecodeProcessorTrace())
+ ///------------------------------------------------------------------------
+ void FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+ lldb::SBError &sberror,
+ ThreadTraceInfo **threadTraceInfo);
+
+ // Helper function of FetchAndDecode() to get raw trace data and memory image
+ // info of inferior from LLDB
+ void ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+ lldb::SBError &sberror,
+ ThreadTraceInfo &threadTraceInfo);
+
+ // Helper function of FetchAndDecode() to initialize raw trace decoder and
+ // start trace decoding
+ void DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+ lldb::SBError &sberror,
+ ThreadTraceInfo &threadTraceInfo);
+
+ // Helper function of ReadTraceDataAndImageInfo() function for gathering
+ // inferior's memory image info along with all dynamic libraries linked with
+ // it
+ void GetTargetModulesInfo(lldb::SBTarget &sbtarget,
+ ReadExecuteSectionInfos &readExecuteSectionInfos,
+ lldb::SBError &sberror);
+
+ ///------------------------------------------------------------------------
+ /// Helper functions of DecodeProcessorTrace() function for:
+ /// - initializing raw trace decoder (provided by Intel(R) Processor Trace
+ /// Decoding library)
+ /// - start trace decoding
+ ///------------------------------------------------------------------------
+ void InitializePTInstDecoder(
+ struct pt_insn_decoder **decoder, struct pt_config *config,
+ const CPUInfo &pt_cpu, Buffer &pt_buffer,
+ const ReadExecuteSectionInfos &readExecuteSectionInfos,
+ lldb::SBError &sberror) const;
+ void DecodeTrace(struct pt_insn_decoder *decoder,
+ Instructions &instruction_list, lldb::SBError &sberror);
+
+ // Function to diagnose and indicate errors during raw trace decoding
+ void Diagnose(struct pt_insn_decoder *decoder, int errcode,
+ lldb::SBError &sberror, const struct pt_insn *insn = nullptr);
+
+ class ThreadTraceInfo {
+ public:
+ ThreadTraceInfo()
+ : m_pt_buffer(), m_readExecuteSectionInfos(), m_thread_stop_id(0),
+ m_trace(), m_pt_cpu(), m_instruction_log() {}
+
+ ThreadTraceInfo(const ThreadTraceInfo &trace_info) = default;
+
+ ~ThreadTraceInfo() {}
+
+ Buffer &GetPTBuffer() { return m_pt_buffer; }
+
+ void AllocatePTBuffer(uint64_t size) { m_pt_buffer.assign(size, 0); }
+
+ ReadExecuteSectionInfos &GetReadExecuteSectionInfos() {
+ return m_readExecuteSectionInfos;
+ }
+
+ CPUInfo &GetCPUInfo() { return m_pt_cpu; }
+
+ Instructions &GetInstructionLog() { return m_instruction_log; }
+
+ uint32_t GetStopID() const { return m_thread_stop_id; }
+
+ void SetStopID(uint32_t stop_id) { m_thread_stop_id = stop_id; }
+
+ lldb::SBTrace &GetUniqueTraceInstance() { return m_trace; }
+
+ void SetUniqueTraceInstance(lldb::SBTrace &trace) { m_trace = trace; }
+
+ friend class Decoder;
+
+ private:
+ Buffer m_pt_buffer; // raw trace buffer
+ ReadExecuteSectionInfos
+ m_readExecuteSectionInfos; // inferior's memory image info
+ uint32_t m_thread_stop_id; // stop id for thread
+ lldb::SBTrace m_trace; // unique tracing instance of a thread/process
+ CPUInfo m_pt_cpu; // cpu info of the target on which inferior is running
+ Instructions m_instruction_log; // complete instruction log
+ };
+
+ typedef std::map<lldb::user_id_t, ThreadTraceInfo> MapThreadID_TraceInfo;
+ typedef std::map<uint32_t, MapThreadID_TraceInfo>
+ MapProcessUID_MapThreadID_TraceInfo;
+
+ std::mutex m_mapProcessUID_mapThreadID_TraceInfo_mutex;
+ MapProcessUID_MapThreadID_TraceInfo
+ m_mapProcessUID_mapThreadID_TraceInfo; // to store trace information for
+ // each process and its associated
+ // threads
+ lldb::user_id_t m_debugger_user_id; // SBDebugger instance which is associated
+ // to this Decoder instance
+};
+
+} // namespace ptdecoder_private
+#endif // Decoder_h_