| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| //===-- PTDecoder.cpp -------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // Project includes | ||
| #include "PTDecoder.h" | ||
| #include "Decoder.h" | ||
|
|
||
| using namespace ptdecoder; | ||
| using namespace ptdecoder_private; | ||
|
|
||
| // PTInstruction class member functions definitions | ||
| PTInstruction::PTInstruction() : m_opaque_sp() {} | ||
|
|
||
| PTInstruction::PTInstruction(const PTInstruction &insn) | ||
| : m_opaque_sp(insn.m_opaque_sp) {} | ||
|
|
||
| PTInstruction::PTInstruction( | ||
| const std::shared_ptr<ptdecoder_private::Instruction> &ptr) | ||
| : m_opaque_sp(ptr) {} | ||
|
|
||
| PTInstruction::~PTInstruction() {} | ||
|
|
||
| uint64_t PTInstruction::GetInsnAddress() const { | ||
| return (m_opaque_sp ? m_opaque_sp->GetInsnAddress() : 0); | ||
| } | ||
|
|
||
| size_t PTInstruction::GetRawBytes(void *buf, size_t size) const { | ||
| return (m_opaque_sp ? m_opaque_sp->GetRawBytes(buf, size) : 0); | ||
| } | ||
|
|
||
| std::string PTInstruction::GetError() const { | ||
| return (m_opaque_sp ? m_opaque_sp->GetError() : "null pointer"); | ||
| } | ||
|
|
||
| bool PTInstruction::GetSpeculative() const { | ||
| return (m_opaque_sp ? m_opaque_sp->GetSpeculative() : 0); | ||
| } | ||
|
|
||
| // PTInstructionList class member functions definitions | ||
| PTInstructionList::PTInstructionList() : m_opaque_sp() {} | ||
|
|
||
| PTInstructionList::PTInstructionList(const PTInstructionList &insn_list) | ||
| : m_opaque_sp(insn_list.m_opaque_sp) {} | ||
|
|
||
| PTInstructionList::~PTInstructionList() {} | ||
|
|
||
| size_t PTInstructionList::GetSize() const { | ||
| return (m_opaque_sp ? m_opaque_sp->GetSize() : 0); | ||
| } | ||
|
|
||
| PTInstruction PTInstructionList::GetInstructionAtIndex(uint32_t idx) { | ||
| if (m_opaque_sp) | ||
| return PTInstruction(std::shared_ptr<ptdecoder_private::Instruction>( | ||
| new Instruction(m_opaque_sp->GetInstructionAtIndex(idx)))); | ||
|
|
||
| return PTInstruction(std::shared_ptr<ptdecoder_private::Instruction>( | ||
| new Instruction("invalid instruction"))); | ||
| } | ||
|
|
||
| void PTInstructionList::SetSP( | ||
| const std::shared_ptr<ptdecoder_private::InstructionList> &ptr) { | ||
| m_opaque_sp = ptr; | ||
| } | ||
| void PTInstructionList::Clear() { | ||
| if (!m_opaque_sp) | ||
| return; | ||
| m_opaque_sp.reset(); | ||
| } | ||
|
|
||
| // PTTraceOptions class member functions definitions | ||
| PTTraceOptions::PTTraceOptions() : m_opaque_sp() {} | ||
|
|
||
| PTTraceOptions::PTTraceOptions(const PTTraceOptions &options) | ||
| : m_opaque_sp(options.m_opaque_sp) {} | ||
|
|
||
| PTTraceOptions::~PTTraceOptions() {} | ||
|
|
||
| lldb::TraceType PTTraceOptions::GetType() const { | ||
| return (m_opaque_sp ? m_opaque_sp->getType() | ||
| : lldb::TraceType::eTraceTypeNone); | ||
| } | ||
|
|
||
| uint64_t PTTraceOptions::GetTraceBufferSize() const { | ||
| return (m_opaque_sp ? m_opaque_sp->getTraceBufferSize() : 0); | ||
| } | ||
|
|
||
| uint64_t PTTraceOptions::GetMetaDataBufferSize() const { | ||
| return (m_opaque_sp ? m_opaque_sp->getMetaDataBufferSize() : 0); | ||
| } | ||
|
|
||
| lldb::SBStructuredData PTTraceOptions::GetTraceParams(lldb::SBError &error) { | ||
| if (!m_opaque_sp) | ||
| error.SetErrorString("null pointer"); | ||
| return (m_opaque_sp ? m_opaque_sp->getTraceParams(error) | ||
| : lldb::SBStructuredData()); | ||
| } | ||
|
|
||
| void PTTraceOptions::SetSP( | ||
| const std::shared_ptr<ptdecoder_private::TraceOptions> &ptr) { | ||
| m_opaque_sp = ptr; | ||
| } | ||
|
|
||
| // PTDecoder class member functions definitions | ||
| PTDecoder::PTDecoder(lldb::SBDebugger &sbdebugger) | ||
| : m_opaque_sp(new ptdecoder_private::Decoder(sbdebugger)) {} | ||
|
|
||
| PTDecoder::PTDecoder(const PTDecoder &ptdecoder) | ||
| : m_opaque_sp(ptdecoder.m_opaque_sp) {} | ||
|
|
||
| PTDecoder::~PTDecoder() {} | ||
|
|
||
| void PTDecoder::StartProcessorTrace(lldb::SBProcess &sbprocess, | ||
| lldb::SBTraceOptions &sbtraceoptions, | ||
| lldb::SBError &sberror) { | ||
| if (m_opaque_sp == nullptr) { | ||
| sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); | ||
| return; | ||
| } | ||
|
|
||
| m_opaque_sp->StartProcessorTrace(sbprocess, sbtraceoptions, sberror); | ||
| } | ||
|
|
||
| void PTDecoder::StopProcessorTrace(lldb::SBProcess &sbprocess, | ||
| lldb::SBError &sberror, lldb::tid_t tid) { | ||
| if (m_opaque_sp == nullptr) { | ||
| sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); | ||
| return; | ||
| } | ||
|
|
||
| m_opaque_sp->StopProcessorTrace(sbprocess, sberror, tid); | ||
| } | ||
|
|
||
| void PTDecoder::GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, | ||
| lldb::tid_t tid, uint32_t offset, | ||
| uint32_t count, | ||
| PTInstructionList &result_list, | ||
| lldb::SBError &sberror) { | ||
| if (m_opaque_sp == nullptr) { | ||
| sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); | ||
| return; | ||
| } | ||
|
|
||
| std::shared_ptr<ptdecoder_private::InstructionList> insn_list_ptr( | ||
| new InstructionList()); | ||
| m_opaque_sp->GetInstructionLogAtOffset(sbprocess, tid, offset, count, | ||
| *insn_list_ptr, sberror); | ||
| if (!sberror.Success()) | ||
| return; | ||
|
|
||
| result_list.SetSP(insn_list_ptr); | ||
| } | ||
|
|
||
| void PTDecoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess, | ||
| lldb::tid_t tid, PTTraceOptions &options, | ||
| lldb::SBError &sberror) { | ||
| if (m_opaque_sp == nullptr) { | ||
| sberror.SetErrorStringWithFormat("invalid PTDecoder instance"); | ||
| return; | ||
| } | ||
|
|
||
| std::shared_ptr<ptdecoder_private::TraceOptions> trace_options_ptr( | ||
| new TraceOptions()); | ||
| m_opaque_sp->GetProcessorTraceInfo(sbprocess, tid, *trace_options_ptr, | ||
| sberror); | ||
| if (!sberror.Success()) | ||
| return; | ||
|
|
||
| options.SetSP(trace_options_ptr); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,310 @@ | ||
| //===-- PTDecoder.h ---------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef PTDecoder_h_ | ||
| #define PTDecoder_h_ | ||
|
|
||
| // C/C++ Includes | ||
| #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/SBStructuredData.h" | ||
| #include "lldb/API/SBTraceOptions.h" | ||
| #include "lldb/lldb-enumerations.h" | ||
| #include "lldb/lldb-types.h" | ||
|
|
||
| namespace ptdecoder_private { | ||
| class Instruction; | ||
| class InstructionList; | ||
| class TraceOptions; | ||
| class Decoder; | ||
| } // namespace ptdecoder_private | ||
|
|
||
| namespace ptdecoder { | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| /// @class PTInstruction | ||
| /// @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 PTInstruction { | ||
| public: | ||
| PTInstruction(); | ||
|
|
||
| PTInstruction(const PTInstruction &insn); | ||
|
|
||
| PTInstruction(const std::shared_ptr<ptdecoder_private::Instruction> &ptr); | ||
|
|
||
| ~PTInstruction(); | ||
|
|
||
| // Get instruction address in inferior's memory image | ||
| uint64_t GetInsnAddress() const; | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Get raw bytes of the instruction in the buffer. | ||
| /// | ||
| /// @param[out] buf | ||
| /// The buffer where the raw bytes will be written. This buffer should be | ||
| /// allocated by the caller of this API. Providing an unallocated buffer | ||
| /// is an error. In case of errors, the content of the buffer is not | ||
| /// valid. | ||
| /// | ||
| /// @param[in] size | ||
| /// Number of raw bytes to be written to @buf. Atleast @size bytes of | ||
| /// memory should be allocated to @buf otherwise the behaviour of the API | ||
| /// is undefined. Providing 0 for this argument is an error. | ||
| /// | ||
| /// @return | ||
| /// Number of bytes of the instruction actually written to @buf if API | ||
| /// succeeds. In case of errors, total number of raw bytes of the | ||
| /// instruction is returned. | ||
| //------------------------------------------------------------------ | ||
| size_t GetRawBytes(void *buf, size_t size) const; | ||
|
|
||
| // Get error string if it represents an invalid instruction. For a valid | ||
| // instruction, an empty string is returned | ||
| std::string GetError() const; | ||
|
|
||
| // Instruction was executed speculatively or not | ||
| bool GetSpeculative() const; | ||
|
|
||
| private: | ||
| std::shared_ptr<ptdecoder_private::Instruction> m_opaque_sp; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| /// @class PTInstructionList | ||
| /// @brief Represents a list of assembly instructions. Each instruction is of | ||
| /// type PTInstruction. | ||
| //--------------------------------------------------------------------------- | ||
| class PTInstructionList { | ||
| public: | ||
| PTInstructionList(); | ||
|
|
||
| PTInstructionList(const PTInstructionList &insn_list); | ||
|
|
||
| ~PTInstructionList(); | ||
|
|
||
| // Get number of instructions in the list | ||
| size_t GetSize() const; | ||
|
|
||
| // Get instruction at index | ||
| PTInstruction GetInstructionAtIndex(uint32_t idx); | ||
|
|
||
| void Clear(); | ||
|
|
||
| private: | ||
| friend class PTDecoder; | ||
|
|
||
| void SetSP(const std::shared_ptr<ptdecoder_private::InstructionList> &ptr); | ||
|
|
||
| std::shared_ptr<ptdecoder_private::InstructionList> m_opaque_sp; | ||
| }; | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| /// @class PTTraceOptions | ||
| /// @brief Provides configuration options like trace type, trace buffer size, | ||
| /// meta data buffer size along with other Intel(R) Processor Trace | ||
| /// specific options. | ||
| //---------------------------------------------------------------------- | ||
| class PTTraceOptions { | ||
| public: | ||
| PTTraceOptions(); | ||
|
|
||
| PTTraceOptions(const PTTraceOptions &options); | ||
|
|
||
| ~PTTraceOptions(); | ||
|
|
||
| lldb::TraceType GetType() const; | ||
|
|
||
| uint64_t GetTraceBufferSize() const; | ||
|
|
||
| uint64_t GetMetaDataBufferSize() const; | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Get Intel(R) Processor Trace specific configuration options (apart from | ||
| /// trace buffer size, meta data buffer size and TraceType) formatted as json | ||
| /// text i.e. {"Name":Value,"Name":Value} pairs, where "Value" is a 64-bit | ||
| /// unsigned integer in hex format. For "Name", please refer to | ||
| /// SBProcess::StartTrace API description for setting SBTraceOptions. | ||
| /// | ||
| /// @return | ||
| /// A string formatted as json text {"Name":Value,"Name":Value} | ||
| //------------------------------------------------------------------ | ||
| lldb::SBStructuredData GetTraceParams(lldb::SBError &error); | ||
|
|
||
| private: | ||
| friend class PTDecoder; | ||
|
|
||
| void SetSP(const std::shared_ptr<ptdecoder_private::TraceOptions> &ptr); | ||
|
|
||
| std::shared_ptr<ptdecoder_private::TraceOptions> m_opaque_sp; | ||
| }; | ||
|
|
||
| //---------------------------------------------------------------------- | ||
| /// @class PTDecoder | ||
| /// @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 PTDecoder { | ||
| public: | ||
| PTDecoder(lldb::SBDebugger &sbdebugger); | ||
|
|
||
| PTDecoder(const PTDecoder &ptdecoder); | ||
|
|
||
| ~PTDecoder(); | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Start Intel(R) Processor Trace on a thread or complete process with | ||
| /// Intel(R) Processor Trace specific configuration options | ||
| /// | ||
| /// @param[in] sbprocess | ||
| /// A valid process on which this operation will be performed. An error is | ||
| /// returned in case of an invalid process. | ||
| /// | ||
| /// @param[in] sbtraceoptions | ||
| /// Contains thread id information and configuration options: | ||
| /// | ||
| /// For tracing a single thread, provide a valid thread id. If sbprocess | ||
| /// doesn't contain this thread id, error will be returned. For tracing | ||
| /// complete process, set it to lldb::LLDB_INVALID_THREAD_ID | ||
| /// Configuration options comprises of: | ||
| /// a) trace buffer size, meta data buffer size, TraceType and | ||
| /// b) All other possible Intel(R) Processor Trace specific configuration | ||
| /// options (hereafter collectively referred as CUSTOM_OPTIONS), formatted | ||
| /// as json text i.e. {"Name":Value,"Name":Value,..} inside | ||
| /// sbtraceoptions, where "Value" should be a 64-bit unsigned integer in | ||
| /// hex format. For information regarding what all configuration options | ||
| /// are currently supported by LLDB and detailed information about | ||
| /// CUSTOM_OPTIONS usage, please refer to SBProcess::StartTrace() API | ||
| /// description. To know about all possible configuration options of | ||
| /// Intel(R) Processor Trace, please refer to Intel(R) 64 and IA-32 | ||
| /// Architectures Software Developer's Manual. | ||
| /// | ||
| /// TraceType should be set to lldb::TraceType::eTraceTypeProcessorTrace, | ||
| /// else error is returned. To find out any other requirement to start | ||
| /// tracing successfully, please refer to SBProcess::StartTrace() API | ||
| /// description. LLDB's current implementation of Intel(R) Processor Trace | ||
| /// feature may round off invalid values for configuration options. | ||
| /// Therefore, the configuration options with which the trace was actually | ||
| /// started, might be different to the ones with which trace was asked to | ||
| /// be started by user. The actual used configuration options can be | ||
| /// obtained from GetProcessorTraceInfo() API. | ||
| /// | ||
| /// @param[out] sberror | ||
| /// An error with the failure reason if API fails. Else success. | ||
| //------------------------------------------------------------------ | ||
| void StartProcessorTrace(lldb::SBProcess &sbprocess, | ||
| lldb::SBTraceOptions &sbtraceoptions, | ||
| lldb::SBError &sberror); | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Stop Intel(R) Processor Trace on a thread or complete process. | ||
| /// | ||
| /// @param[in] sbprocess | ||
| /// A valid process on which this operation will be performed. An error is | ||
| /// returned in case of an invalid process. | ||
| /// | ||
| /// @param[in] tid | ||
| /// Case 1: To stop tracing a single thread, provide a valid thread id. If | ||
| /// sbprocess doesn't contain the thread tid, error will be returned. | ||
| /// Case 2: To stop tracing complete process, use | ||
| /// lldb::LLDB_INVALID_THREAD_ID. | ||
| /// | ||
| /// @param[out] sberror | ||
| /// An error with the failure reason if API fails. Else success. | ||
| //------------------------------------------------------------------ | ||
| void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror, | ||
| lldb::tid_t tid = LLDB_INVALID_THREAD_ID); | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Get instruction log containing the execution flow for a thread of a | ||
| /// process in terms of assembly instructions executed. | ||
| /// | ||
| /// @param[in] sbprocess | ||
| /// A valid process on which this operation will be performed. An error is | ||
| /// returned in case of an invalid process. | ||
| /// | ||
| /// @param[in] tid | ||
| /// A valid thread id of the thread for which instruction log is desired. | ||
| /// If sbprocess doesn't contain the thread tid, error will be returned. | ||
| /// | ||
| /// @param[in] count | ||
| /// The number of instructions requested by the user to be returned from | ||
| /// the complete instruction log. Complete instruction log refers to all | ||
| /// the assembly instructions obtained after decoding the complete raw | ||
| /// trace data obtained from LLDB. The length of the complete instruction | ||
| /// log is dependent on the trace buffer size with which processor tracing | ||
| /// was started for this thread. | ||
| /// The number of instructions actually returned are dependent on 'count' | ||
| /// and 'offset' parameters of this API. | ||
| /// | ||
| /// @param[in] offset | ||
| /// The offset in the complete instruction log from where 'count' number | ||
| /// of instructions are requested by the user. offset is counted from the | ||
| /// end of of this complete instruction log (which means the last executed | ||
| /// instruction is at offset 0 (zero)). | ||
| /// | ||
| /// @param[out] result_list | ||
| /// Depending upon 'count' and 'offset' values, list will be overwritten | ||
| /// with the new instructions. | ||
| /// | ||
| /// @param[out] sberror | ||
| /// An error with the failure reason if API fails. Else success. | ||
| //------------------------------------------------------------------ | ||
| void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid, | ||
| uint32_t offset, uint32_t count, | ||
| PTInstructionList &result_list, | ||
| lldb::SBError &sberror); | ||
|
|
||
| //------------------------------------------------------------------ | ||
| /// Get Intel(R) Processor Trace specific information for a thread of a | ||
| /// process. The information contains the actual configuration options with | ||
| /// which the trace was started for this thread. | ||
| /// | ||
| /// @param[in] sbprocess | ||
| /// A valid process on which this operation will be performed. An error is | ||
| /// returned in case of an invalid process. | ||
| /// | ||
| /// @param[in] tid | ||
| /// A valid thread id of the thread for which the trace specific | ||
| /// information is required. If sbprocess doesn't contain the thread tid, | ||
| /// an error will be returned. | ||
| /// | ||
| /// @param[out] options | ||
| /// Contains actual configuration options (they may be different to the | ||
| /// ones with which tracing was asked to be started for this thread during | ||
| /// StartProcessorTrace() API call). | ||
| /// | ||
| /// @param[out] sberror | ||
| /// An error with the failure reason if API fails. Else success. | ||
| //------------------------------------------------------------------ | ||
| void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, | ||
| PTTraceOptions &options, lldb::SBError &sberror); | ||
|
|
||
| private: | ||
| std::shared_ptr<ptdecoder_private::Decoder> m_opaque_sp; | ||
| }; | ||
|
|
||
| } // namespace ptdecoder | ||
| #endif // PTDecoder_h_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| **************************************************************************** | ||
| * README * | ||
| * * | ||
| * This file provides all the information regarding 4 new CLI commands that * | ||
| * enable using Intel(R) Processor Trace Tool from LLDB's CLI. * | ||
| **************************************************************************** | ||
|
|
||
|
|
||
| ============ | ||
| Introduction | ||
| ============ | ||
| A C++ based cli wrapper has been developed to use Intel(R) Processor Trace Tool | ||
| through LLDB's command line. This also provides an idea to all developers on how | ||
| to integrate the Tool into various IDEs providing LLDB as a debugger. | ||
|
|
||
|
|
||
|
|
||
| ============ | ||
| How to Build | ||
| ============ | ||
| The wrapper cli-wrapper-pt.cpp needs to be compiled and linked with the shared | ||
| library of the Intel(R) Processor Trace Tool in order to be used through LLDB's | ||
| CLI. The procedure to build shared library of the Intel(R) Processor Trace Tool | ||
| is given in README_TOOL.txt file. | ||
|
|
||
|
|
||
|
|
||
| ============ | ||
| How to Use | ||
| ============ | ||
| All these commands are available via shared library (lldbIntelFeatures) | ||
| obtained after building intel-features folder from top. Please refer to | ||
| cli-wrapper.cpp and README files of "intel-features" folder for this purpose. | ||
|
|
||
|
|
||
|
|
||
| ============ | ||
| Description | ||
| ============ | ||
| 4 CLI commands have been designed keeping the LLDB's existing CLI command syntax | ||
| in mind. | ||
|
|
||
| 1) processor-trace start [-b <buffer-size>] [<thread-index>] | ||
|
|
||
| Start Intel(R) Processor Trace on a specific thread or on the whole process | ||
|
|
||
| Syntax: processor-trace start <cmd-options> | ||
|
|
||
| cmd-options Usage: | ||
| processor-trace start [-b <buffer-size>] [<thread-index>] | ||
|
|
||
| -b <buffer-size> | ||
| size of the trace buffer to store the trace data. If not specified | ||
| then a default value (=4KB) will be taken | ||
|
|
||
| <thread-index> | ||
| thread index of the thread. If no threads are specified, currently | ||
| selected thread is taken. Use the thread-index 'all' to start | ||
| tracing the whole process | ||
|
|
||
|
|
||
|
|
||
| 2) processor-trace stop [<thread-index>] | ||
|
|
||
| Stop Intel(R) Processor Trace on a specific thread or on the whole process | ||
|
|
||
| Syntax: processor-trace stop <cmd-options> | ||
|
|
||
| cmd-options Usage: | ||
| processor-trace stop [<thread-index>] | ||
|
|
||
| <thread-index> | ||
| thread index of the thread. If no threads are specified, currently | ||
| selected thread is taken. Use the thread-index 'all' to stop | ||
| tracing the whole process | ||
|
|
||
|
|
||
|
|
||
| 3) processor-trace show-trace-options [<thread-index>] | ||
|
|
||
| Display all the information regarding Intel(R) Processor Trace for a specific | ||
| thread or for the whole process. The information contains trace buffer | ||
| size and configuration options of Intel(R) Processor Trace. | ||
|
|
||
| Syntax: processor-trace show-trace-options <cmd-options> | ||
|
|
||
| cmd-options Usage: | ||
| processor-trace show-trace-options [<thread-index>] | ||
|
|
||
| <thread-index> | ||
| thread index of the thread. If no threads are specified, currently | ||
| selected thread is taken. Use the thread-index 'all' to display | ||
| information for all threads of the process | ||
|
|
||
|
|
||
|
|
||
| 4) processor-trace show-instr-log [-o <offset>] [-c <count>] [<thread-index>] | ||
|
|
||
| Display a log of assembly instructions executed for a specific thread or | ||
| for the whole process. The length of the log to be displayed and the | ||
| offset in the whole instruction log from where the log needs to be | ||
| displayed can also be provided. The offset is counted from the end of this | ||
| whole instruction log which means the last executed instruction is at | ||
| offset 0 (zero). | ||
|
|
||
| Syntax: processor-trace show-instr-log <cmd-options> | ||
|
|
||
| cmd-options Usage: | ||
| processor-trace show-instr-log [-o <offset>] [-c <count>] [<thread-index>] | ||
|
|
||
| -c <count> | ||
| number of instructions to be displayed. If not specified then a | ||
| default value (=10) will be taken | ||
|
|
||
| -o <offset> | ||
| offset in the whole instruction log from where the log will be | ||
| displayed. If not specified then default value is calculated as | ||
| offset = count -1 | ||
|
|
||
| <thread-index> | ||
| thread index of the thread. If no threads are specified, currently | ||
| selected thread is taken. Use the thread-index 'all' to show | ||
| instruction log for all the threads of the process |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,311 @@ | ||
| ******************************************************************************* | ||
| * README * | ||
| * * | ||
| * This file provides all the information regarding Intel(R) Processor Trace * | ||
| * Tool. It consists explanation about how Tool internally works, its hardware * | ||
| * and software dependencies, build procedure and usage of the API. * | ||
| ******************************************************************************* | ||
|
|
||
|
|
||
|
|
||
| ============ | ||
| Introduction | ||
| ============ | ||
| The Intel(R) Processor Trace Tool is developed on top of LLDB and provides its | ||
| its users execution trace of the debugged applications. Tool makes use of | ||
| Intel(R) Processor Trace hardware feature implementation inside LLDB for this | ||
| purpose. This hardware feature generates a set of trace packets that | ||
| encapsulates program flow information. These trace packets along with the binary | ||
| of the application can be decoded with the help of a software decoder to | ||
| construct the execution trace of the application. | ||
|
|
||
| More information about Intel(R) Processor Trace feature can be obtained from | ||
| website: https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing | ||
|
|
||
|
|
||
|
|
||
|
|
||
| ========= | ||
| Details | ||
| ========= | ||
| The functionality of the Tool consists three parts: | ||
|
|
||
| 1. Raw Trace Collection from LLDB | ||
| With the help of API of this Tool (given below), Intel(R) Processor Trace | ||
| can be started on the application being debugged with LLDB. The generated | ||
| trace of the application is gathered inside LLDB and is collected by the | ||
| Tool from LLDB through LLDB's public API. | ||
|
|
||
| 2. Raw Trace Decoding | ||
| For decoding the raw trace data, the Tool makes use of "libipt", an | ||
| Intel(R) Processor Trace Decoder Library. The library needs binary of | ||
| the application and information about the cpu on which the application is | ||
| running in order to decode the raw trace. The Tool gathers this | ||
| information from LLDB public API and provide it to "libipt". More | ||
| information about "libipt" can be found at: | ||
| https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing and | ||
| https://github.com/01org/processor-trace | ||
|
|
||
| 3. Decoded Trace Post-processing | ||
| The decoded trace is post-processed to reconstruct the execution flow of | ||
| the application. The execution flow contains the list of assembly | ||
| instructions (called instruction log hereafter). | ||
|
|
||
|
|
||
|
|
||
|
|
||
| ============= | ||
| Dependencies | ||
| ============= | ||
| The Tool has following hardware and software dependencies: | ||
|
|
||
| - Hardware dependency: The Tool makes use of this hardware feature to capture | ||
| raw trace of an application from LLDB. This hardware feature may not be | ||
| present in all processors. The hardware feature is supported on Broadwell | ||
| and other succeeding CPUs such as Skylake etc. In order for Tool to provide | ||
| something meaningful, the target machine on which the application is running | ||
| should have this feature. | ||
|
|
||
| - Software dependency: The Tool has an indirect dependency on the Operating | ||
| System level software support for Intel(R) Processor Trace on the target | ||
| machine where the application is running and being debugged by LLDB. This | ||
| support is required to enable raw trace generation on the target machine. | ||
| Currently, the Tool works for applications running on Linux OS as till now | ||
| the Operating System level support for the feature is present only in Linux | ||
| (more specifically starting from the 4.1 kernel). In Linux, this feature is | ||
| implemented in perf_events subsystem and is usable through perf_event_open | ||
| system call. In the User space level, the Tool has a direct dependency on | ||
| "libipt" to decode the captured raw trace. This library might be | ||
| pre-installed on host systems. If not then the library can be built from | ||
| its sources (available at): https://github.com/01org/processor-trace | ||
|
|
||
|
|
||
|
|
||
|
|
||
| ============ | ||
| How to Build | ||
| ============ | ||
| The Tool has a cmake based build and can be built by specifying some extra flags | ||
| while building LLDB with cmake. The following cmake flags need to be provided to | ||
| build the Tool: | ||
|
|
||
| - LIBIPT_INCLUDE_PATH - The flag specifies the directory where the header | ||
| file of "libipt" resides. If the library is not pre-installed on the host | ||
| system and is built directly from "libipt" project sources then this file | ||
| may either come as a part of the sources itself or will be generated in | ||
| build folder while building library. | ||
|
|
||
| - LIBIPT_LIBRARY_PATH - The flag points to the location of "libipt" shared | ||
| library. | ||
|
|
||
| The Tool currently works successfully with following versions of this library: | ||
| - v1.4, v1.5, v1.6 | ||
|
|
||
|
|
||
|
|
||
| ============ | ||
| How to Use | ||
| ============ | ||
| The Tool's API are exposed as a C++ object oriented interface (file PTDecoder.h) | ||
| in a shared library. The main class that implements the whole functionality is | ||
| PTDecoder. This class makes use of 3 other classes, | ||
| - PTInstruction to represent an assembly instruction | ||
| - PTInstructionList to return instruction log | ||
| - PTTraceOptions to return trace specific information | ||
| The users can use these API to develop their own products. All API are also | ||
| available as python functions through a script bridging interface, allowing | ||
| them to be used directly from python either interactively or to build python | ||
| apps. | ||
|
|
||
| Currently, cli wrapper has been developed on top of the Tool to use it through | ||
| LLDB's command line. Please refer to README_CLI.txt file for command line usage. | ||
|
|
||
|
|
||
| A brief introduction about the classes and their API are given below. | ||
|
|
||
| class PTDecoder | ||
| =============== | ||
| This class makes use of Intel(R) Processor Trace hardware feature | ||
| (implemented 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 | ||
|
|
||
| Corresponding API are explained below: | ||
| a) void StartProcessorTrace(lldb::SBProcess &sbprocess, | ||
| lldb::SBTraceOptions &sbtraceoptions, | ||
| lldb::SBError &sberror) | ||
| ------------------------------------------------------------------------ | ||
| This API allows the user to start trace on a particular thread or on | ||
| the whole process with Intel(R) Processor Trace specific | ||
| configuration options. | ||
|
|
||
| @param[in] sbprocess : A valid process on which this operation | ||
| will be performed. An error is returned in case of an invalid | ||
| process. | ||
|
|
||
| @param[out] sberror : An error with the failure reason if API | ||
| fails. Else success. | ||
|
|
||
| @param[in] sbtraceoptions : Contains thread id information and | ||
| configuration options: | ||
| For tracing a single thread, provide a valid thread id. If | ||
| sbprocess doesn't contain this thread id, error will be returned. | ||
| For tracing complete process, set to lldb::LLDB_INVALID_THREAD_ID | ||
| Configuration options comprises of: | ||
| - trace buffer size, meta data buffer size, TraceType and | ||
| - All other possible Intel(R) Processor Trace specific | ||
| configuration options (hereafter collectively referred as | ||
| CUSTOM_OPTIONS) | ||
|
|
||
| Trace buffer, meant to store the trace data read from target | ||
| machine, inside LLDB is configured as a cyclic buffer. Hence, | ||
| depending upon the trace buffer size provided here, buffer | ||
| overwrites may happen while LLDB writes trace data into it. | ||
| CUSTOM_OPTIONS are formatted as json text i.e. {"Name":Value, | ||
| "Name":Value,...} inside sbtraceoptions, where "Value" should be | ||
| a 64-bit unsigned integer in hex format. For information | ||
| regarding what all configuration options are currently supported | ||
| by LLDB and detailed information about CUSTOM_OPTIONS usage, | ||
| please refer to SBProcess::StartTrace() API description. An | ||
| overview of some of the various CUSTOM_OPTIONS are briefly given | ||
| below. Please refer to "Intel(R) 64 and IA-32 Architectures | ||
| Software Developer's Manual" for more details about them. | ||
| - CYCEn Enable/Disable Cycle Count Packet (CYC) Packet | ||
| - OS Packet generation enabled/disabled if | ||
| Current Privilege Level (CPL)=0 | ||
| - User Packet generation enabled/disabled if CPL>0 | ||
| - CR3Filter Enable/Disable CR3 Filtering | ||
| - MTCEn Enable/disable MTC packets | ||
| - TSCEn Enable/disable TSC packets | ||
| - DisRETC Enable/disable RET Compression | ||
| - BranchEn Enable/disable COFI-based packets | ||
| - MTCFreq Defines MTC Packet Frequency | ||
| - CycThresh CYC Packet threshold | ||
| - PSBFreq Frequency of PSB Packets | ||
|
|
||
| TraceType should be set to | ||
| lldb::TraceType::eTraceTypeProcessorTrace, else error is | ||
| returned. To find out any other requirement to start tracing | ||
| successfully, refer to SBProcess::StartTrace() API description. | ||
| LLDB's current implementation of Intel(R) Processor Trace | ||
| feature may round off invalid values for configuration options. | ||
| Therefore, the configuration options with which the trace was | ||
| actually started, might be different to the ones with which | ||
| trace was asked to be started by user. The actual used | ||
| configuration options can be obtained from | ||
| GetProcessorTraceInfo() API. | ||
|
|
||
|
|
||
|
|
||
| b) void StopProcessorTrace(lldb::SBProcess &sbprocess, | ||
| lldb::SBError &sberror, | ||
| lldb::tid_t tid = LLDB_INVALID_THREAD_ID) | ||
| ------------------------------------------------------------------------ | ||
| This API allows the user to Stop trace on a particular thread or on | ||
| the whole process. | ||
|
|
||
| @param[in] sbprocess : A valid process on which this operation will | ||
| be performed. An error is returned in case of an invalid process. | ||
|
|
||
| @param[in] tid : To stop tracing a single thread, provide a | ||
| valid thread id. If sbprocess doesn't contain the thread tid, | ||
| error will be returned. To stop tracing complete process, use | ||
| lldb::LLDB_INVALID_THREAD_ID | ||
|
|
||
| @param[out] sberror : An error with the failure reason if API fails. | ||
| Else success | ||
|
|
||
|
|
||
|
|
||
| c) void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid, | ||
| uint32_t offset, uint32_t count, | ||
| PTInstructionList &result_list, | ||
| lldb::SBError &sberror) | ||
| ------------------------------------------------------------------------ | ||
| This API provides instruction log that contains the execution flow | ||
| for a thread of a process in terms of assembly instruction executed. | ||
| The API works on only 1 thread at a time. To gather this information | ||
| for whole process, this API needs to be called for each thread. | ||
|
|
||
| @param[in] sbprocess : A valid process on which this operation | ||
| will be performed. An error is returned in case of an invalid | ||
| process. | ||
|
|
||
| @param[in] tid : A valid thread id of the thread for which | ||
| instruction log is desired. If sbprocess doesn't contain the | ||
| thread tid, error will be returned. | ||
|
|
||
| @param[in] count : Number of instructions requested by the | ||
| user to be returned from the complete instruction log. Complete | ||
| instruction log refers to all the assembly instructions obtained | ||
| after decoding the complete raw trace data obtained from LLDB. | ||
| The length of the complete instruction log is dependent on the | ||
| trace buffer size with which processor tracing was started for | ||
| this thread. | ||
| The number of instructions actually returned are dependent on | ||
| 'count' and 'offset' parameters of this API. | ||
|
|
||
| @param[in] offset : The offset in the complete instruction log | ||
| from where 'count' number of instructions are requested by the | ||
| user. offset is counted from the end of of this complete | ||
| instruction log (which means the last executed instruction | ||
| is at offset 0 (zero)). | ||
|
|
||
| @param[out] result_list : Depending upon 'count' and 'offset' values, | ||
| list will be overwritten with the instructions. | ||
|
|
||
| @param[out] sberror : An error with the failure reason if API | ||
| fails. Else success | ||
|
|
||
|
|
||
|
|
||
| d) void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid, | ||
| PTTraceOptions &options, lldb::SBError &sberror) | ||
| ------------------------------------------------------------------------ | ||
| This API provides Intel(R) Processor Trace specific information for | ||
| a thread of a process. The API works on only 1 thread at a time. To | ||
| gather this information for whole process, this API needs to be | ||
| called for each thread. The information contains the actual | ||
| configuration options with which the trace was started for this | ||
| thread. | ||
|
|
||
| @param[in] sbprocess : The valid process on which this operation | ||
| will be performed. An error is returned in case of an invalid | ||
| process. | ||
|
|
||
| @param[in] tid : A valid thread id of the thread for which the | ||
| trace specific information is required. If sbprocess doesn't | ||
| contain the thread tid, an error will be returned. | ||
|
|
||
| @param[out] options : Contains actual configuration options (they | ||
| may be different to the ones with which tracing was asked to be | ||
| started for this thread during StartProcessorTrace() API call). | ||
|
|
||
| @param[out] sberror : An error with the failure reason if API | ||
| fails. Else success | ||
|
|
||
|
|
||
| class PTInstruction | ||
| =================== | ||
| This class represents an assembly instruction containing raw instruction | ||
| bytes, instruction address along with execution flow context and | ||
| Intel(R) Processor Trace context. For more details, please refer to | ||
| PTDecoder.h file. | ||
|
|
||
| class PTInstructionList | ||
| ======================= | ||
| This class represents a list of assembly instructions. Each assembly | ||
| instruction is of type PTInstruction. | ||
|
|
||
| class PTTraceOptions | ||
| ==================== | ||
| This class provides Intel(R) Processor Trace specific configuration | ||
| options like trace type, trace buffer size, meta data buffer size along | ||
| with other trace specific options. For more details, please refer to | ||
| PTDecoder.h file. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| %include "stdint.i" | ||
|
|
||
| %include "lldb/lldb-defines.h" | ||
| %include "lldb/lldb-enumerations.h" | ||
| %include "lldb/lldb-forward.h" | ||
| %include "lldb/lldb-types.h" | ||
|
|
||
| %include "lldb/API/SBDefines.h" | ||
|
|
||
| %include "../PTDecoder.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| file(GLOB_RECURSE SWIG_SOURCES *.swig) | ||
|
|
||
| set(FLAGS | ||
| -c++ | ||
| -shadow | ||
| -python | ||
| -D__STDC_LIMIT_MACROS | ||
| -D__STDC_CONSTANT_MACROS | ||
| ) | ||
|
|
||
| set(INCLUDES | ||
| -I${LLDB_SOURCE_DIR}/include | ||
| -I${LLDB_SOURCE_DIR}/tools/intel-features/intel-pt | ||
| ) | ||
|
|
||
| set(OUTPUT_PYTHON_WRAPPER | ||
| ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp | ||
| ) | ||
|
|
||
| set(OUTPUT_PYTHON_SCRIPT_DIR | ||
| ${CMAKE_CURRENT_BINARY_DIR} | ||
| ) | ||
|
|
||
| find_package(SWIG REQUIRED) | ||
| add_custom_command( | ||
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp | ||
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lldbIntelFeatures.py | ||
| DEPENDS ${SWIG_SOURCES} | ||
| COMMAND ${SWIG_EXECUTABLE} ${FLAGS} ${INCLUDES} -o ${OUTPUT_PYTHON_WRAPPER} -outdir ${OUTPUT_PYTHON_SCRIPT_DIR} ${SWIG_SOURCES} | ||
| COMMENT "Generating python wrapper for features library") | ||
|
|
||
| set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp PROPERTIES GENERATED 1) | ||
| set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lldbIntelFeatures.py PROPERTIES GENERATED 1) | ||
|
|
||
| add_custom_target(intel-features-swig_wrapper ALL | ||
| DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| %module lldbIntelFeatures | ||
|
|
||
| %{ | ||
| #include "lldb/lldb-public.h" | ||
| #include "intel-pt/PTDecoder.h" | ||
| using namespace ptdecoder; | ||
| %} | ||
|
|
||
| /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h */ | ||
| #define __extension__ | ||
|
|
||
| /* Combined python typemap for all features */ | ||
| %include "python-typemaps.txt" | ||
|
|
||
| /* Feature specific python interface files*/ | ||
| %include "../intel-pt/interface/PTDecoder.i" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* Typemap definitions to allow SWIG to properly handle some data types */ | ||
|
|
||
| // typemap for an incoming buffer | ||
| %typemap(in) (void *buf, size_t size) { | ||
| if (PyInt_Check($input)) { | ||
| $2 = PyInt_AsLong($input); | ||
| } else if (PyLong_Check($input)) { | ||
| $2 = PyLong_AsLong($input); | ||
| } else { | ||
| PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object"); | ||
| return NULL; | ||
| } | ||
| if ($2 <= 0) { | ||
| PyErr_SetString(PyExc_ValueError, "Positive integer expected"); | ||
| return NULL; | ||
| } | ||
| $1 = (void *) malloc($2); | ||
| } | ||
|
|
||
| // Return the buffer. Discarding any previous return result | ||
| %typemap(argout) (void *buf, size_t size) { | ||
| Py_XDECREF($result); /* Blow away any previous result */ | ||
| if (result == 0) { | ||
| $result = Py_None; | ||
| Py_INCREF($result); | ||
| } else { | ||
| PyObject *py_bytes = PyBytes_FromStringAndSize(reinterpret_cast<const char*>($1), result); | ||
| $result = py_bytes; | ||
| } | ||
| free($1); | ||
| } |