174c93956SWalter Erquinigo //===-- CommandObjectTrace.cpp --------------------------------------------===// 274c93956SWalter Erquinigo // 374c93956SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 474c93956SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information. 574c93956SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 674c93956SWalter Erquinigo // 774c93956SWalter Erquinigo //===----------------------------------------------------------------------===// 874c93956SWalter Erquinigo 974c93956SWalter Erquinigo #include "CommandObjectTrace.h" 1074c93956SWalter Erquinigo 1174c93956SWalter Erquinigo #include "llvm/Support/JSON.h" 1274c93956SWalter Erquinigo #include "llvm/Support/MemoryBuffer.h" 1374c93956SWalter Erquinigo 1474c93956SWalter Erquinigo #include "lldb/Core/Debugger.h" 15ea1f4974SWalter Erquinigo #include "lldb/Core/PluginManager.h" 1674c93956SWalter Erquinigo #include "lldb/Host/OptionParser.h" 1774c93956SWalter Erquinigo #include "lldb/Interpreter/CommandInterpreter.h" 1874c93956SWalter Erquinigo #include "lldb/Interpreter/CommandObject.h" 1974c93956SWalter Erquinigo #include "lldb/Interpreter/CommandReturnObject.h" 2074c93956SWalter Erquinigo #include "lldb/Interpreter/OptionArgParser.h" 2174c93956SWalter Erquinigo #include "lldb/Interpreter/OptionGroupFormat.h" 2274c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueBoolean.h" 2374c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueLanguage.h" 2474c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueString.h" 2574c93956SWalter Erquinigo #include "lldb/Interpreter/Options.h" 260b697561SWalter Erquinigo #include "lldb/Target/Process.h" 2774c93956SWalter Erquinigo #include "lldb/Target/Trace.h" 2874c93956SWalter Erquinigo 2974c93956SWalter Erquinigo using namespace lldb; 3074c93956SWalter Erquinigo using namespace lldb_private; 3174c93956SWalter Erquinigo using namespace llvm; 3274c93956SWalter Erquinigo 3374c93956SWalter Erquinigo // CommandObjectTraceLoad 3474c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_load 3574c93956SWalter Erquinigo #include "CommandOptions.inc" 3674c93956SWalter Erquinigo 3774c93956SWalter Erquinigo #pragma mark CommandObjectTraceLoad 3874c93956SWalter Erquinigo 3974c93956SWalter Erquinigo class CommandObjectTraceLoad : public CommandObjectParsed { 4074c93956SWalter Erquinigo public: 4174c93956SWalter Erquinigo class CommandOptions : public Options { 4274c93956SWalter Erquinigo public: 43abb0ed44SKazu Hirata CommandOptions() { OptionParsingStarting(nullptr); } 4474c93956SWalter Erquinigo 4574c93956SWalter Erquinigo ~CommandOptions() override = default; 4674c93956SWalter Erquinigo 4774c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, StringRef option_arg, 4874c93956SWalter Erquinigo ExecutionContext *execution_context) override { 4974c93956SWalter Erquinigo Status error; 5074c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 5174c93956SWalter Erquinigo 5274c93956SWalter Erquinigo switch (short_option) { 5374c93956SWalter Erquinigo case 'v': { 5474c93956SWalter Erquinigo m_verbose = true; 5574c93956SWalter Erquinigo break; 5674c93956SWalter Erquinigo } 5774c93956SWalter Erquinigo default: 5874c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 5974c93956SWalter Erquinigo } 6074c93956SWalter Erquinigo return error; 6174c93956SWalter Erquinigo } 6274c93956SWalter Erquinigo 6374c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 6474c93956SWalter Erquinigo m_verbose = false; 6574c93956SWalter Erquinigo } 6674c93956SWalter Erquinigo 6774c93956SWalter Erquinigo ArrayRef<OptionDefinition> GetDefinitions() override { 6874c93956SWalter Erquinigo return makeArrayRef(g_trace_load_options); 6974c93956SWalter Erquinigo } 7074c93956SWalter Erquinigo 7174c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 7274c93956SWalter Erquinigo }; 7374c93956SWalter Erquinigo 7474c93956SWalter Erquinigo CommandObjectTraceLoad(CommandInterpreter &interpreter) 75*b8dcd0baSWalter Erquinigo : CommandObjectParsed( 76*b8dcd0baSWalter Erquinigo interpreter, "trace load", 77*b8dcd0baSWalter Erquinigo "Load a post-mortem processor trace session from a trace bundle.", 78abb0ed44SKazu Hirata "trace load") {} 7974c93956SWalter Erquinigo 8074c93956SWalter Erquinigo ~CommandObjectTraceLoad() override = default; 8174c93956SWalter Erquinigo 8274c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 8374c93956SWalter Erquinigo 8474c93956SWalter Erquinigo protected: 8574c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 8674c93956SWalter Erquinigo if (command.size() != 1) { 87*b8dcd0baSWalter Erquinigo result.AppendError("a single path to a JSON file containing a the " 88*b8dcd0baSWalter Erquinigo "description of the trace bundle is required"); 8974c93956SWalter Erquinigo return false; 9074c93956SWalter Erquinigo } 9174c93956SWalter Erquinigo 9250f93679SJakob Johnson const FileSpec trace_description_file(command[0].ref()); 9350f93679SJakob Johnson 9450f93679SJakob Johnson llvm::Expected<lldb::TraceSP> trace_or_err = 9550f93679SJakob Johnson Trace::LoadPostMortemTraceFromFile(GetDebugger(), 9650f93679SJakob Johnson trace_description_file); 9750f93679SJakob Johnson 9850f93679SJakob Johnson if (!trace_or_err) { 9950f93679SJakob Johnson result.AppendErrorWithFormat( 10050f93679SJakob Johnson "%s\n", llvm::toString(trace_or_err.takeError()).c_str()); 10174c93956SWalter Erquinigo return false; 10274c93956SWalter Erquinigo } 10374c93956SWalter Erquinigo 10450f93679SJakob Johnson if (m_options.m_verbose) { 105a3939e15SPavel Labath result.AppendMessageWithFormatv("loading trace with plugin {0}\n", 10650f93679SJakob Johnson trace_or_err.get()->GetPluginName()); 10750f93679SJakob Johnson } 10874c93956SWalter Erquinigo 10974c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 11074c93956SWalter Erquinigo return true; 11174c93956SWalter Erquinigo } 11274c93956SWalter Erquinigo 11374c93956SWalter Erquinigo CommandOptions m_options; 11474c93956SWalter Erquinigo }; 11574c93956SWalter Erquinigo 11674c93956SWalter Erquinigo // CommandObjectTraceDump 11774c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_dump 11874c93956SWalter Erquinigo #include "CommandOptions.inc" 11974c93956SWalter Erquinigo 12074c93956SWalter Erquinigo #pragma mark CommandObjectTraceDump 12174c93956SWalter Erquinigo 12274c93956SWalter Erquinigo class CommandObjectTraceDump : public CommandObjectParsed { 12374c93956SWalter Erquinigo public: 12474c93956SWalter Erquinigo class CommandOptions : public Options { 12574c93956SWalter Erquinigo public: 126abb0ed44SKazu Hirata CommandOptions() { OptionParsingStarting(nullptr); } 12774c93956SWalter Erquinigo 12874c93956SWalter Erquinigo ~CommandOptions() override = default; 12974c93956SWalter Erquinigo 13074c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 13174c93956SWalter Erquinigo ExecutionContext *execution_context) override { 13274c93956SWalter Erquinigo Status error; 13374c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 13474c93956SWalter Erquinigo 13574c93956SWalter Erquinigo switch (short_option) { 13674c93956SWalter Erquinigo case 'v': { 13774c93956SWalter Erquinigo m_verbose = true; 13874c93956SWalter Erquinigo break; 13974c93956SWalter Erquinigo } 14074c93956SWalter Erquinigo default: 14174c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 14274c93956SWalter Erquinigo } 14374c93956SWalter Erquinigo return error; 14474c93956SWalter Erquinigo } 14574c93956SWalter Erquinigo 14674c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 14774c93956SWalter Erquinigo m_verbose = false; 14874c93956SWalter Erquinigo } 14974c93956SWalter Erquinigo 15074c93956SWalter Erquinigo llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 15174c93956SWalter Erquinigo return llvm::makeArrayRef(g_trace_dump_options); 15274c93956SWalter Erquinigo } 15374c93956SWalter Erquinigo 15474c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 15574c93956SWalter Erquinigo }; 15674c93956SWalter Erquinigo 15774c93956SWalter Erquinigo CommandObjectTraceDump(CommandInterpreter &interpreter) 15874c93956SWalter Erquinigo : CommandObjectParsed(interpreter, "trace dump", 15974c93956SWalter Erquinigo "Dump the loaded processor trace data.", 160abb0ed44SKazu Hirata "trace dump") {} 16174c93956SWalter Erquinigo 16274c93956SWalter Erquinigo ~CommandObjectTraceDump() override = default; 16374c93956SWalter Erquinigo 16474c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 16574c93956SWalter Erquinigo 16674c93956SWalter Erquinigo protected: 16774c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 16874c93956SWalter Erquinigo Status error; 16974c93956SWalter Erquinigo // TODO: fill in the dumping code here! 17074c93956SWalter Erquinigo if (error.Success()) { 17174c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 17274c93956SWalter Erquinigo } else { 17374c93956SWalter Erquinigo result.AppendErrorWithFormat("%s\n", error.AsCString()); 17474c93956SWalter Erquinigo } 17574c93956SWalter Erquinigo return result.Succeeded(); 17674c93956SWalter Erquinigo } 17774c93956SWalter Erquinigo 17874c93956SWalter Erquinigo CommandOptions m_options; 17974c93956SWalter Erquinigo }; 18074c93956SWalter Erquinigo 18174c93956SWalter Erquinigo // CommandObjectTraceSchema 18274c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_schema 18374c93956SWalter Erquinigo #include "CommandOptions.inc" 18474c93956SWalter Erquinigo 18574c93956SWalter Erquinigo #pragma mark CommandObjectTraceSchema 18674c93956SWalter Erquinigo 18774c93956SWalter Erquinigo class CommandObjectTraceSchema : public CommandObjectParsed { 18874c93956SWalter Erquinigo public: 18974c93956SWalter Erquinigo class CommandOptions : public Options { 19074c93956SWalter Erquinigo public: 191abb0ed44SKazu Hirata CommandOptions() { OptionParsingStarting(nullptr); } 19274c93956SWalter Erquinigo 19374c93956SWalter Erquinigo ~CommandOptions() override = default; 19474c93956SWalter Erquinigo 19574c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 19674c93956SWalter Erquinigo ExecutionContext *execution_context) override { 19774c93956SWalter Erquinigo Status error; 19874c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 19974c93956SWalter Erquinigo 20074c93956SWalter Erquinigo switch (short_option) { 20174c93956SWalter Erquinigo case 'v': { 20274c93956SWalter Erquinigo m_verbose = true; 20374c93956SWalter Erquinigo break; 20474c93956SWalter Erquinigo } 20574c93956SWalter Erquinigo default: 20674c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 20774c93956SWalter Erquinigo } 20874c93956SWalter Erquinigo return error; 20974c93956SWalter Erquinigo } 21074c93956SWalter Erquinigo 21174c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 21274c93956SWalter Erquinigo m_verbose = false; 21374c93956SWalter Erquinigo } 21474c93956SWalter Erquinigo 21574c93956SWalter Erquinigo llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 21674c93956SWalter Erquinigo return llvm::makeArrayRef(g_trace_schema_options); 21774c93956SWalter Erquinigo } 21874c93956SWalter Erquinigo 21974c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 22074c93956SWalter Erquinigo }; 22174c93956SWalter Erquinigo 22274c93956SWalter Erquinigo CommandObjectTraceSchema(CommandInterpreter &interpreter) 22374c93956SWalter Erquinigo : CommandObjectParsed(interpreter, "trace schema", 22474c93956SWalter Erquinigo "Show the schema of the given trace plugin.", 225ea1f4974SWalter Erquinigo "trace schema <plug-in>. Use the plug-in name " 226abb0ed44SKazu Hirata "\"all\" to see all schemas.\n") {} 22774c93956SWalter Erquinigo 22874c93956SWalter Erquinigo ~CommandObjectTraceSchema() override = default; 22974c93956SWalter Erquinigo 23074c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 23174c93956SWalter Erquinigo 23274c93956SWalter Erquinigo protected: 23374c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 23474c93956SWalter Erquinigo Status error; 23574c93956SWalter Erquinigo if (command.empty()) { 2361b1c8e4aSDavid Spickett result.AppendError( 23774c93956SWalter Erquinigo "trace schema cannot be invoked without a plug-in as argument"); 23874c93956SWalter Erquinigo return false; 23974c93956SWalter Erquinigo } 24074c93956SWalter Erquinigo 24174c93956SWalter Erquinigo StringRef plugin_name(command[0].c_str()); 242ea1f4974SWalter Erquinigo if (plugin_name == "all") { 243ea1f4974SWalter Erquinigo size_t index = 0; 244ea1f4974SWalter Erquinigo while (true) { 245ea1f4974SWalter Erquinigo StringRef schema = PluginManager::GetTraceSchema(index++); 246ea1f4974SWalter Erquinigo if (schema.empty()) 247ea1f4974SWalter Erquinigo break; 24874c93956SWalter Erquinigo 249ea1f4974SWalter Erquinigo result.AppendMessage(schema); 250ea1f4974SWalter Erquinigo } 25174c93956SWalter Erquinigo } else { 252ea1f4974SWalter Erquinigo if (Expected<StringRef> schemaOrErr = 253ea1f4974SWalter Erquinigo Trace::FindPluginSchema(plugin_name)) 254ea1f4974SWalter Erquinigo result.AppendMessage(*schemaOrErr); 255ea1f4974SWalter Erquinigo else 256ea1f4974SWalter Erquinigo error = schemaOrErr.takeError(); 25774c93956SWalter Erquinigo } 25874c93956SWalter Erquinigo 25974c93956SWalter Erquinigo if (error.Success()) { 26074c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 26174c93956SWalter Erquinigo } else { 26274c93956SWalter Erquinigo result.AppendErrorWithFormat("%s\n", error.AsCString()); 26374c93956SWalter Erquinigo } 26474c93956SWalter Erquinigo return result.Succeeded(); 26574c93956SWalter Erquinigo } 26674c93956SWalter Erquinigo 26774c93956SWalter Erquinigo CommandOptions m_options; 26874c93956SWalter Erquinigo }; 26974c93956SWalter Erquinigo 27074c93956SWalter Erquinigo // CommandObjectTrace 27174c93956SWalter Erquinigo 27274c93956SWalter Erquinigo CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter) 27374c93956SWalter Erquinigo : CommandObjectMultiword(interpreter, "trace", 27474c93956SWalter Erquinigo "Commands for loading and using processor " 27574c93956SWalter Erquinigo "trace information.", 27674c93956SWalter Erquinigo "trace [<sub-command-options>]") { 27774c93956SWalter Erquinigo LoadSubCommand("load", 27874c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceLoad(interpreter))); 27974c93956SWalter Erquinigo LoadSubCommand("dump", 28074c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceDump(interpreter))); 28174c93956SWalter Erquinigo LoadSubCommand("schema", 28274c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceSchema(interpreter))); 28374c93956SWalter Erquinigo } 28474c93956SWalter Erquinigo 28574c93956SWalter Erquinigo CommandObjectTrace::~CommandObjectTrace() = default; 2860b697561SWalter Erquinigo 2870b697561SWalter Erquinigo Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() { 2880b697561SWalter Erquinigo ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP(); 2890b697561SWalter Erquinigo 2900b697561SWalter Erquinigo if (!process_sp) 2910b697561SWalter Erquinigo return createStringError(inconvertibleErrorCode(), 2920b697561SWalter Erquinigo "Process not available."); 2930b697561SWalter Erquinigo if (m_live_debug_session_only && !process_sp->IsLiveDebugSession()) 2940b697561SWalter Erquinigo return createStringError(inconvertibleErrorCode(), 2950b697561SWalter Erquinigo "Process must be alive."); 2960b697561SWalter Erquinigo 297bf9f21a2SWalter Erquinigo if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate()) 2980b697561SWalter Erquinigo return GetDelegateCommand(**trace_sp); 2990b697561SWalter Erquinigo else 3000b697561SWalter Erquinigo return createStringError(inconvertibleErrorCode(), 3010b697561SWalter Erquinigo "Tracing is not supported. %s", 3020b697561SWalter Erquinigo toString(trace_sp.takeError()).c_str()); 3030b697561SWalter Erquinigo } 3040b697561SWalter Erquinigo 3050b697561SWalter Erquinigo CommandObject *CommandObjectTraceProxy::GetProxyCommandObject() { 3060b697561SWalter Erquinigo if (Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) { 3070b697561SWalter Erquinigo m_delegate_sp = *delegate; 3080b697561SWalter Erquinigo m_delegate_error.clear(); 3090b697561SWalter Erquinigo return m_delegate_sp.get(); 3100b697561SWalter Erquinigo } else { 3110b697561SWalter Erquinigo m_delegate_sp.reset(); 3120b697561SWalter Erquinigo m_delegate_error = toString(delegate.takeError()); 3130b697561SWalter Erquinigo return nullptr; 3140b697561SWalter Erquinigo } 3150b697561SWalter Erquinigo } 316