diff options
Diffstat (limited to 'tools/intel-features/intel-pt/cli-wrapper-pt.cpp')
-rw-r--r-- | tools/intel-features/intel-pt/cli-wrapper-pt.cpp | 583 |
1 files changed, 0 insertions, 583 deletions
diff --git a/tools/intel-features/intel-pt/cli-wrapper-pt.cpp b/tools/intel-features/intel-pt/cli-wrapper-pt.cpp deleted file mode 100644 index 1fa236cb0bc7..000000000000 --- a/tools/intel-features/intel-pt/cli-wrapper-pt.cpp +++ /dev/null @@ -1,583 +0,0 @@ -//===-- cli-wrapper-pt.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// CLI Wrapper of PTDecoder Tool to enable it to be used through LLDB's CLI. The -// wrapper provides a new command called processor-trace with 4 child -// subcommands as follows: -// processor-trace start -// processor-trace stop -// processor-trace show-trace-options -// processor-trace show-instr-log -// -//===----------------------------------------------------------------------===// - -#include <cerrno> -#include <cinttypes> -#include <cstring> -#include <string> -#include <vector> - -#include "PTDecoder.h" -#include "cli-wrapper-pt.h" -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBCommandReturnObject.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBProcess.h" -#include "lldb/API/SBStream.h" -#include "lldb/API/SBStructuredData.h" -#include "lldb/API/SBTarget.h" -#include "lldb/API/SBThread.h" - -static bool GetProcess(lldb::SBDebugger &debugger, - lldb::SBCommandReturnObject &result, - lldb::SBProcess &process) { - if (!debugger.IsValid()) { - result.Printf("error: invalid debugger\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - - lldb::SBTarget target = debugger.GetSelectedTarget(); - if (!target.IsValid()) { - result.Printf("error: invalid target inside debugger\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - - process = target.GetProcess(); - if (!process.IsValid() || - (process.GetState() == lldb::StateType::eStateDetached) || - (process.GetState() == lldb::StateType::eStateExited) || - (process.GetState() == lldb::StateType::eStateInvalid)) { - result.Printf("error: invalid process inside debugger's target\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - - return true; -} - -static bool ParseCommandOption(char **command, - lldb::SBCommandReturnObject &result, - uint32_t &index, const std::string &arg, - uint32_t &parsed_result) { - char *endptr; - if (!command[++index]) { - result.Printf("error: option \"%s\" requires an argument\n", arg.c_str()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - - errno = 0; - unsigned long output = strtoul(command[index], &endptr, 0); - if ((errno != 0) || (*endptr != '\0')) { - result.Printf("error: invalid value \"%s\" provided for option \"%s\"\n", - command[index], arg.c_str()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - if (output > UINT32_MAX) { - result.Printf("error: value \"%s\" for option \"%s\" exceeds UINT32_MAX\n", - command[index], arg.c_str()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - parsed_result = (uint32_t)output; - return true; -} - -static bool ParseCommandArgThread(char **command, - lldb::SBCommandReturnObject &result, - lldb::SBProcess &process, uint32_t &index, - lldb::tid_t &thread_id) { - char *endptr; - if (!strcmp(command[index], "all")) - thread_id = LLDB_INVALID_THREAD_ID; - else { - uint32_t thread_index_id; - errno = 0; - unsigned long output = strtoul(command[index], &endptr, 0); - if ((errno != 0) || (*endptr != '\0') || (output > UINT32_MAX)) { - result.Printf("error: invalid thread specification: \"%s\"\n", - command[index]); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_index_id = (uint32_t)output; - - lldb::SBThread thread = process.GetThreadByIndexID(thread_index_id); - if (!thread.IsValid()) { - result.Printf( - "error: process has no thread with thread specification: \"%s\"\n", - command[index]); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_id = thread.GetThreadID(); - } - return true; -} - -class ProcessorTraceStart : public lldb::SBCommandPluginInterface { -public: - ProcessorTraceStart(std::shared_ptr<ptdecoder::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} - - ~ProcessorTraceStart() {} - - virtual bool DoExecute(lldb::SBDebugger debugger, char **command, - lldb::SBCommandReturnObject &result) { - lldb::SBProcess process; - lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) - return false; - - // Default initialize API's arguments - lldb::SBTraceOptions lldb_SBTraceOptions; - uint32_t trace_buffer_size = m_default_trace_buff_size; - lldb::tid_t thread_id; - - // Parse Command line options - bool thread_argument_provided = false; - if (command) { - for (uint32_t i = 0; command[i]; i++) { - if (!strcmp(command[i], "-b")) { - if (!ParseCommandOption(command, result, i, "-b", trace_buffer_size)) - return false; - } else { - thread_argument_provided = true; - if (!ParseCommandArgThread(command, result, process, i, thread_id)) - return false; - } - } - } - - if (!thread_argument_provided) { - thread = process.GetSelectedThread(); - if (!thread.IsValid()) { - result.Printf("error: invalid current selected thread\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_id = thread.GetThreadID(); - } - - if (trace_buffer_size > m_max_trace_buff_size) - trace_buffer_size = m_max_trace_buff_size; - - // Set API's arguments with parsed values - lldb_SBTraceOptions.setType(lldb::TraceType::eTraceTypeProcessorTrace); - lldb_SBTraceOptions.setTraceBufferSize(trace_buffer_size); - lldb_SBTraceOptions.setMetaDataBufferSize(0); - lldb_SBTraceOptions.setThreadID(thread_id); - lldb::SBStream sb_stream; - sb_stream.Printf("{\"trace-tech\":\"intel-pt\"}"); - lldb::SBStructuredData custom_params; - lldb::SBError error = custom_params.SetFromJSON(sb_stream); - if (!error.Success()) { - result.Printf("error: %s\n", error.GetCString()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - lldb_SBTraceOptions.setTraceParams(custom_params); - - // Start trace - pt_decoder_sp->StartProcessorTrace(process, lldb_SBTraceOptions, error); - if (!error.Success()) { - result.Printf("error: %s\n", error.GetCString()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - return true; - } - -private: - std::shared_ptr<ptdecoder::PTDecoder> pt_decoder_sp; - const uint32_t m_max_trace_buff_size = 0x3fff; - const uint32_t m_default_trace_buff_size = 4096; -}; - -class ProcessorTraceInfo : public lldb::SBCommandPluginInterface { -public: - ProcessorTraceInfo(std::shared_ptr<ptdecoder::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} - - ~ProcessorTraceInfo() {} - - virtual bool DoExecute(lldb::SBDebugger debugger, char **command, - lldb::SBCommandReturnObject &result) { - lldb::SBProcess process; - lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) - return false; - - lldb::tid_t thread_id; - - // Parse command line options - bool thread_argument_provided = false; - if (command) { - for (uint32_t i = 0; command[i]; i++) { - thread_argument_provided = true; - if (!ParseCommandArgThread(command, result, process, i, thread_id)) - return false; - } - } - - if (!thread_argument_provided) { - thread = process.GetSelectedThread(); - if (!thread.IsValid()) { - result.Printf("error: invalid current selected thread\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_id = thread.GetThreadID(); - } - - size_t loop_count = 1; - bool entire_process_tracing = false; - if (thread_id == LLDB_INVALID_THREAD_ID) { - entire_process_tracing = true; - loop_count = process.GetNumThreads(); - } - - // Get trace information - lldb::SBError error; - lldb::SBCommandReturnObject res; - for (size_t i = 0; i < loop_count; i++) { - error.Clear(); - res.Clear(); - - if (entire_process_tracing) - thread = process.GetThreadAtIndex(i); - else - thread = process.GetThreadByID(thread_id); - thread_id = thread.GetThreadID(); - - ptdecoder::PTTraceOptions options; - pt_decoder_sp->GetProcessorTraceInfo(process, thread_id, options, error); - if (!error.Success()) { - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", - thread.GetIndexID(), thread_id, error.GetCString()); - result.AppendMessage(res.GetOutput()); - continue; - } - - lldb::SBStructuredData data = options.GetTraceParams(error); - if (!error.Success()) { - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", - thread.GetIndexID(), thread_id, error.GetCString()); - result.AppendMessage(res.GetOutput()); - continue; - } - - lldb::SBStream s; - error = data.GetAsJSON(s); - if (!error.Success()) { - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", - thread.GetIndexID(), thread_id, error.GetCString()); - result.AppendMessage(res.GetOutput()); - continue; - } - - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 - ", trace buffer size=%" PRIu64 ", meta buffer size=%" PRIu64 - ", trace type=%" PRIu32 ", custom trace params=%s", - thread.GetIndexID(), thread_id, options.GetTraceBufferSize(), - options.GetMetaDataBufferSize(), options.GetType(), - s.GetData()); - result.AppendMessage(res.GetOutput()); - } - return true; - } - -private: - std::shared_ptr<ptdecoder::PTDecoder> pt_decoder_sp; -}; - -class ProcessorTraceShowInstrLog : public lldb::SBCommandPluginInterface { -public: - ProcessorTraceShowInstrLog(std::shared_ptr<ptdecoder::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} - - ~ProcessorTraceShowInstrLog() {} - - virtual bool DoExecute(lldb::SBDebugger debugger, char **command, - lldb::SBCommandReturnObject &result) { - lldb::SBProcess process; - lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) - return false; - - // Default initialize API's arguments - uint32_t offset; - bool offset_provided = false; - uint32_t count = m_default_count; - lldb::tid_t thread_id; - - // Parse command line options - bool thread_argument_provided = false; - if (command) { - for (uint32_t i = 0; command[i]; i++) { - if (!strcmp(command[i], "-o")) { - if (!ParseCommandOption(command, result, i, "-o", offset)) - return false; - offset_provided = true; - } else if (!strcmp(command[i], "-c")) { - if (!ParseCommandOption(command, result, i, "-c", count)) - return false; - } else { - thread_argument_provided = true; - if (!ParseCommandArgThread(command, result, process, i, thread_id)) - return false; - } - } - } - - if (!thread_argument_provided) { - thread = process.GetSelectedThread(); - if (!thread.IsValid()) { - result.Printf("error: invalid current selected thread\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_id = thread.GetThreadID(); - } - - size_t loop_count = 1; - bool entire_process_tracing = false; - if (thread_id == LLDB_INVALID_THREAD_ID) { - entire_process_tracing = true; - loop_count = process.GetNumThreads(); - } - - // Get instruction log and disassemble it - lldb::SBError error; - lldb::SBCommandReturnObject res; - for (size_t i = 0; i < loop_count; i++) { - error.Clear(); - res.Clear(); - - if (entire_process_tracing) - thread = process.GetThreadAtIndex(i); - else - thread = process.GetThreadByID(thread_id); - thread_id = thread.GetThreadID(); - - // If offset is not provided then calculate a default offset (to display - // last 'count' number of instructions) - if (!offset_provided) - offset = count - 1; - - // Get the instruction log - ptdecoder::PTInstructionList insn_list; - pt_decoder_sp->GetInstructionLogAtOffset(process, thread_id, offset, - count, insn_list, error); - if (!error.Success()) { - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 ", error: %s", - thread.GetIndexID(), thread_id, error.GetCString()); - result.AppendMessage(res.GetOutput()); - continue; - } - - // Disassemble the instruction log - std::string disassembler_command("dis -c 1 -s "); - res.Printf("thread #%" PRIu32 ": tid=%" PRIu64 "\n", thread.GetIndexID(), - thread_id); - lldb::SBCommandInterpreter sb_cmnd_interpreter( - debugger.GetCommandInterpreter()); - lldb::SBCommandReturnObject result_obj; - for (size_t i = 0; i < insn_list.GetSize(); i++) { - ptdecoder::PTInstruction insn = insn_list.GetInstructionAtIndex(i); - uint64_t addr = insn.GetInsnAddress(); - std::string error = insn.GetError(); - if (!error.empty()) { - res.AppendMessage(error.c_str()); - continue; - } - - result_obj.Clear(); - std::string complete_disassembler_command = - disassembler_command + std::to_string(addr); - sb_cmnd_interpreter.HandleCommand(complete_disassembler_command.c_str(), - result_obj, false); - std::string result_str(result_obj.GetOutput()); - if (result_str.empty()) { - lldb::SBCommandReturnObject output; - output.Printf(" Disassembly not found for address: %" PRIu64, addr); - res.AppendMessage(output.GetOutput()); - continue; - } - - // LLDB's disassemble command displays assembly instructions along with - // the names of the functions they belong to. Parse this result to - // display only the assembly instructions and not the function names - // in an instruction log - std::size_t first_new_line_index = result_str.find_first_of('\n'); - std::size_t last_new_line_index = result_str.find_last_of('\n'); - if (first_new_line_index != last_new_line_index) - res.AppendMessage((result_str.substr(first_new_line_index + 1, - last_new_line_index - - first_new_line_index - 1)) - .c_str()); - else - res.AppendMessage( - (result_str.substr(0, result_str.length() - 1)).c_str()); - } - result.AppendMessage(res.GetOutput()); - } - return true; - } - -private: - std::shared_ptr<ptdecoder::PTDecoder> pt_decoder_sp; - const uint32_t m_default_count = 10; -}; - -class ProcessorTraceStop : public lldb::SBCommandPluginInterface { -public: - ProcessorTraceStop(std::shared_ptr<ptdecoder::PTDecoder> &pt_decoder) - : SBCommandPluginInterface(), pt_decoder_sp(pt_decoder) {} - - ~ProcessorTraceStop() {} - - virtual bool DoExecute(lldb::SBDebugger debugger, char **command, - lldb::SBCommandReturnObject &result) { - lldb::SBProcess process; - lldb::SBThread thread; - if (!GetProcess(debugger, result, process)) - return false; - - lldb::tid_t thread_id; - - // Parse command line options - bool thread_argument_provided = false; - if (command) { - for (uint32_t i = 0; command[i]; i++) { - thread_argument_provided = true; - if (!ParseCommandArgThread(command, result, process, i, thread_id)) - return false; - } - } - - if (!thread_argument_provided) { - thread = process.GetSelectedThread(); - if (!thread.IsValid()) { - result.Printf("error: invalid current selected thread\n"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - thread_id = thread.GetThreadID(); - } - - // Stop trace - lldb::SBError error; - pt_decoder_sp->StopProcessorTrace(process, error, thread_id); - if (!error.Success()) { - result.Printf("error: %s\n", error.GetCString()); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - return true; - } - -private: - std::shared_ptr<ptdecoder::PTDecoder> pt_decoder_sp; -}; - -bool PTPluginInitialize(lldb::SBDebugger &debugger) { - lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter(); - lldb::SBCommand proc_trace = interpreter.AddMultiwordCommand( - "processor-trace", "Intel(R) Processor Trace for thread/process"); - - std::shared_ptr<ptdecoder::PTDecoder> PTDecoderSP( - new ptdecoder::PTDecoder(debugger)); - - lldb::SBCommandPluginInterface *proc_trace_start = - new ProcessorTraceStart(PTDecoderSP); - const char *help_proc_trace_start = "start Intel(R) Processor Trace on a " - "specific thread or on the whole process"; - const char *syntax_proc_trace_start = - "processor-trace start <cmd-options>\n\n" - "\rcmd-options Usage:\n" - "\r processor-trace start [-b <buffer-size>] [<thread-index>]\n\n" - "\t\b-b <buffer-size>\n" - "\t size of the trace buffer to store the trace data. If not " - "specified then a default value will be taken\n\n" - "\t\b<thread-index>\n" - "\t thread index of the thread. If no threads are specified, " - "currently selected thread is taken.\n" - "\t Use the thread-index 'all' to start tracing the whole process\n"; - proc_trace.AddCommand("start", proc_trace_start, help_proc_trace_start, - syntax_proc_trace_start); - - lldb::SBCommandPluginInterface *proc_trace_stop = - new ProcessorTraceStop(PTDecoderSP); - const char *help_proc_trace_stop = - "stop Intel(R) Processor Trace on a specific thread or on whole process"; - const char *syntax_proc_trace_stop = - "processor-trace stop <cmd-options>\n\n" - "\rcmd-options Usage:\n" - "\r processor-trace stop [<thread-index>]\n\n" - "\t\b<thread-index>\n" - "\t thread index of the thread. If no threads are specified, " - "currently selected thread is taken.\n" - "\t Use the thread-index 'all' to stop tracing the whole process\n"; - proc_trace.AddCommand("stop", proc_trace_stop, help_proc_trace_stop, - syntax_proc_trace_stop); - - lldb::SBCommandPluginInterface *proc_trace_show_instr_log = - new ProcessorTraceShowInstrLog(PTDecoderSP); - const char *help_proc_trace_show_instr_log = - "display a log of assembly instructions executed for a specific thread " - "or for the whole process.\n" - "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)"; - const char *syntax_proc_trace_show_instr_log = - "processor-trace show-instr-log <cmd-options>\n\n" - "\rcmd-options Usage:\n" - "\r processor-trace show-instr-log [-o <offset>] [-c <count>] " - "[<thread-index>]\n\n" - "\t\b-o <offset>\n" - "\t offset in the whole instruction log from where the log will be " - "displayed. If not specified then a default value will be taken\n\n" - "\t\b-c <count>\n" - "\t number of instructions to be displayed. If not specified then a " - "default value will be taken\n\n" - "\t\b<thread-index>\n" - "\t thread index of the thread. If no threads are specified, " - "currently selected thread is taken.\n" - "\t Use the thread-index 'all' to show instruction log for all the " - "threads of the process\n"; - proc_trace.AddCommand("show-instr-log", proc_trace_show_instr_log, - help_proc_trace_show_instr_log, - syntax_proc_trace_show_instr_log); - - lldb::SBCommandPluginInterface *proc_trace_options = - new ProcessorTraceInfo(PTDecoderSP); - const char *help_proc_trace_show_options = - "display all the information regarding Intel(R) Processor Trace for a " - "specific thread or for the whole process.\n" - "The information contains trace buffer size and configuration options" - " of Intel(R) Processor Trace."; - const char *syntax_proc_trace_show_options = - "processor-trace show-options <cmd-options>\n\n" - "\rcmd-options Usage:\n" - "\r processor-trace show-options [<thread-index>]\n\n" - "\t\b<thread-index>\n" - "\t thread index of the thread. If no threads are specified, " - "currently selected thread is taken.\n" - "\t Use the thread-index 'all' to display information for all threads " - "of the process\n"; - proc_trace.AddCommand("show-trace-options", proc_trace_options, - help_proc_trace_show_options, - syntax_proc_trace_show_options); - - return true; -} |