1e8d8bef9SDimitry Andric //===-- CommandObjectTrace.cpp --------------------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #include "CommandObjectTrace.h" 10e8d8bef9SDimitry Andric 11e8d8bef9SDimitry Andric #include "llvm/Support/JSON.h" 12e8d8bef9SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 13e8d8bef9SDimitry Andric 14e8d8bef9SDimitry Andric #include "lldb/Core/Debugger.h" 15e8d8bef9SDimitry Andric #include "lldb/Core/PluginManager.h" 16e8d8bef9SDimitry Andric #include "lldb/Host/OptionParser.h" 17e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 18e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandObject.h" 19fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h" 20e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 21e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 22e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionGroupFormat.h" 23e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h" 24e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueLanguage.h" 25e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueString.h" 26e8d8bef9SDimitry Andric #include "lldb/Interpreter/Options.h" 27fe6060f1SDimitry Andric #include "lldb/Target/Process.h" 28e8d8bef9SDimitry Andric #include "lldb/Target/Trace.h" 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric using namespace lldb; 31e8d8bef9SDimitry Andric using namespace lldb_private; 32e8d8bef9SDimitry Andric using namespace llvm; 33e8d8bef9SDimitry Andric 34753f127fSDimitry Andric // CommandObjectTraceSave 35753f127fSDimitry Andric #define LLDB_OPTIONS_trace_save 36753f127fSDimitry Andric #include "CommandOptions.inc" 37753f127fSDimitry Andric 38753f127fSDimitry Andric #pragma mark CommandObjectTraceSave 39753f127fSDimitry Andric 40753f127fSDimitry Andric class CommandObjectTraceSave : public CommandObjectParsed { 41753f127fSDimitry Andric public: 42753f127fSDimitry Andric class CommandOptions : public Options { 43753f127fSDimitry Andric public: 44753f127fSDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 45753f127fSDimitry Andric 46753f127fSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 47753f127fSDimitry Andric ExecutionContext *execution_context) override { 48753f127fSDimitry Andric Status error; 49753f127fSDimitry Andric const int short_option = m_getopt_table[option_idx].val; 50753f127fSDimitry Andric 51753f127fSDimitry Andric switch (short_option) { 52753f127fSDimitry Andric case 'c': { 53753f127fSDimitry Andric m_compact = true; 54753f127fSDimitry Andric break; 55753f127fSDimitry Andric } 56753f127fSDimitry Andric default: 57753f127fSDimitry Andric llvm_unreachable("Unimplemented option"); 58753f127fSDimitry Andric } 59753f127fSDimitry Andric return error; 60753f127fSDimitry Andric } 61753f127fSDimitry Andric 62753f127fSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 63753f127fSDimitry Andric m_compact = false; 64753f127fSDimitry Andric }; 65753f127fSDimitry Andric 66753f127fSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 67bdd1243dSDimitry Andric return llvm::ArrayRef(g_trace_save_options); 68753f127fSDimitry Andric }; 69753f127fSDimitry Andric 70753f127fSDimitry Andric bool m_compact; 71753f127fSDimitry Andric }; 72753f127fSDimitry Andric 73753f127fSDimitry Andric Options *GetOptions() override { return &m_options; } 74753f127fSDimitry Andric 75753f127fSDimitry Andric CommandObjectTraceSave(CommandInterpreter &interpreter) 76753f127fSDimitry Andric : CommandObjectParsed( 77753f127fSDimitry Andric interpreter, "trace save", 78753f127fSDimitry Andric "Save the trace of the current target in the specified directory, " 79753f127fSDimitry Andric "which will be created if needed. " 80753f127fSDimitry Andric "This directory will contain a trace bundle, with all the " 81753f127fSDimitry Andric "necessary files the reconstruct the trace session even on a " 82753f127fSDimitry Andric "different computer. " 83753f127fSDimitry Andric "Part of this bundle is the bundle description file with the name " 84753f127fSDimitry Andric "trace.json. This file can be used by the \"trace load\" command " 85753f127fSDimitry Andric "to load this trace in LLDB." 86753f127fSDimitry Andric "Note: if the current target contains information of multiple " 87753f127fSDimitry Andric "processes or targets, they all will be included in the bundle.", 88753f127fSDimitry Andric "trace save [<cmd-options>] <bundle_directory>", 89753f127fSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock | 90753f127fSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 91753f127fSDimitry Andric eCommandProcessMustBeTraced) { 92*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeDirectoryName); 93753f127fSDimitry Andric } 94753f127fSDimitry Andric 95753f127fSDimitry Andric void 96753f127fSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 97753f127fSDimitry Andric OptionElementVector &opt_element_vector) override { 9806c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 9906c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 100753f127fSDimitry Andric } 101753f127fSDimitry Andric 102753f127fSDimitry Andric ~CommandObjectTraceSave() override = default; 103753f127fSDimitry Andric 104753f127fSDimitry Andric protected: 1055f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 106753f127fSDimitry Andric if (command.size() != 1) { 107753f127fSDimitry Andric result.AppendError("a single path to a directory where the trace bundle " 108753f127fSDimitry Andric "will be created is required"); 1095f757f3fSDimitry Andric return; 110753f127fSDimitry Andric } 111753f127fSDimitry Andric 112753f127fSDimitry Andric FileSpec bundle_dir(command[0].ref()); 113753f127fSDimitry Andric FileSystem::Instance().Resolve(bundle_dir); 114753f127fSDimitry Andric 115753f127fSDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 116753f127fSDimitry Andric 117753f127fSDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 118753f127fSDimitry Andric 119753f127fSDimitry Andric if (llvm::Expected<FileSpec> desc_file = 120753f127fSDimitry Andric trace_sp->SaveToDisk(bundle_dir, m_options.m_compact)) { 121753f127fSDimitry Andric result.AppendMessageWithFormatv( 122753f127fSDimitry Andric "Trace bundle description file written to: {0}", *desc_file); 123753f127fSDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 124753f127fSDimitry Andric } else { 125753f127fSDimitry Andric result.AppendError(toString(desc_file.takeError())); 126753f127fSDimitry Andric } 127753f127fSDimitry Andric } 128753f127fSDimitry Andric 129753f127fSDimitry Andric CommandOptions m_options; 130753f127fSDimitry Andric }; 131753f127fSDimitry Andric 132e8d8bef9SDimitry Andric // CommandObjectTraceLoad 133e8d8bef9SDimitry Andric #define LLDB_OPTIONS_trace_load 134e8d8bef9SDimitry Andric #include "CommandOptions.inc" 135e8d8bef9SDimitry Andric 136e8d8bef9SDimitry Andric #pragma mark CommandObjectTraceLoad 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric class CommandObjectTraceLoad : public CommandObjectParsed { 139e8d8bef9SDimitry Andric public: 140e8d8bef9SDimitry Andric class CommandOptions : public Options { 141e8d8bef9SDimitry Andric public: 14204eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 143e8d8bef9SDimitry Andric 144e8d8bef9SDimitry Andric ~CommandOptions() override = default; 145e8d8bef9SDimitry Andric 146e8d8bef9SDimitry Andric Status SetOptionValue(uint32_t option_idx, StringRef option_arg, 147e8d8bef9SDimitry Andric ExecutionContext *execution_context) override { 148e8d8bef9SDimitry Andric Status error; 149e8d8bef9SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 150e8d8bef9SDimitry Andric 151e8d8bef9SDimitry Andric switch (short_option) { 152e8d8bef9SDimitry Andric case 'v': { 153e8d8bef9SDimitry Andric m_verbose = true; 154e8d8bef9SDimitry Andric break; 155e8d8bef9SDimitry Andric } 156e8d8bef9SDimitry Andric default: 157e8d8bef9SDimitry Andric llvm_unreachable("Unimplemented option"); 158e8d8bef9SDimitry Andric } 159e8d8bef9SDimitry Andric return error; 160e8d8bef9SDimitry Andric } 161e8d8bef9SDimitry Andric 162e8d8bef9SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 163e8d8bef9SDimitry Andric m_verbose = false; 164e8d8bef9SDimitry Andric } 165e8d8bef9SDimitry Andric 166e8d8bef9SDimitry Andric ArrayRef<OptionDefinition> GetDefinitions() override { 167bdd1243dSDimitry Andric return ArrayRef(g_trace_load_options); 168e8d8bef9SDimitry Andric } 169e8d8bef9SDimitry Andric 170e8d8bef9SDimitry Andric bool m_verbose; // Enable verbose logging for debugging purposes. 171e8d8bef9SDimitry Andric }; 172e8d8bef9SDimitry Andric 173e8d8bef9SDimitry Andric CommandObjectTraceLoad(CommandInterpreter &interpreter) 17481ad6265SDimitry Andric : CommandObjectParsed( 17581ad6265SDimitry Andric interpreter, "trace load", 17681ad6265SDimitry Andric "Load a post-mortem processor trace session from a trace bundle.", 177753f127fSDimitry Andric "trace load <trace_description_file>") { 178*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeFilename); 17981ad6265SDimitry Andric } 180e8d8bef9SDimitry Andric 181753f127fSDimitry Andric void 182753f127fSDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 183753f127fSDimitry Andric OptionElementVector &opt_element_vector) override { 18406c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 18506c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 186753f127fSDimitry Andric } 187753f127fSDimitry Andric 188e8d8bef9SDimitry Andric ~CommandObjectTraceLoad() override = default; 189e8d8bef9SDimitry Andric 190e8d8bef9SDimitry Andric Options *GetOptions() override { return &m_options; } 191e8d8bef9SDimitry Andric 192e8d8bef9SDimitry Andric protected: 1935f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 194e8d8bef9SDimitry Andric if (command.size() != 1) { 19581ad6265SDimitry Andric result.AppendError("a single path to a JSON file containing a the " 19681ad6265SDimitry Andric "description of the trace bundle is required"); 1975f757f3fSDimitry Andric return; 198e8d8bef9SDimitry Andric } 199e8d8bef9SDimitry Andric 20081ad6265SDimitry Andric const FileSpec trace_description_file(command[0].ref()); 20181ad6265SDimitry Andric 20281ad6265SDimitry Andric llvm::Expected<lldb::TraceSP> trace_or_err = 20381ad6265SDimitry Andric Trace::LoadPostMortemTraceFromFile(GetDebugger(), 20481ad6265SDimitry Andric trace_description_file); 20581ad6265SDimitry Andric 20681ad6265SDimitry Andric if (!trace_or_err) { 20781ad6265SDimitry Andric result.AppendErrorWithFormat( 20881ad6265SDimitry Andric "%s\n", llvm::toString(trace_or_err.takeError()).c_str()); 2095f757f3fSDimitry Andric return; 210e8d8bef9SDimitry Andric } 211e8d8bef9SDimitry Andric 21281ad6265SDimitry Andric if (m_options.m_verbose) { 213349cc55cSDimitry Andric result.AppendMessageWithFormatv("loading trace with plugin {0}\n", 21481ad6265SDimitry Andric trace_or_err.get()->GetPluginName()); 21581ad6265SDimitry Andric } 216e8d8bef9SDimitry Andric 217e8d8bef9SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 218e8d8bef9SDimitry Andric } 219e8d8bef9SDimitry Andric 220e8d8bef9SDimitry Andric CommandOptions m_options; 221e8d8bef9SDimitry Andric }; 222e8d8bef9SDimitry Andric 223e8d8bef9SDimitry Andric // CommandObjectTraceDump 224e8d8bef9SDimitry Andric #define LLDB_OPTIONS_trace_dump 225e8d8bef9SDimitry Andric #include "CommandOptions.inc" 226e8d8bef9SDimitry Andric 227e8d8bef9SDimitry Andric #pragma mark CommandObjectTraceDump 228e8d8bef9SDimitry Andric 229e8d8bef9SDimitry Andric class CommandObjectTraceDump : public CommandObjectParsed { 230e8d8bef9SDimitry Andric public: 231e8d8bef9SDimitry Andric class CommandOptions : public Options { 232e8d8bef9SDimitry Andric public: 23304eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 234e8d8bef9SDimitry Andric 235e8d8bef9SDimitry Andric ~CommandOptions() override = default; 236e8d8bef9SDimitry Andric 237e8d8bef9SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 238e8d8bef9SDimitry Andric ExecutionContext *execution_context) override { 239e8d8bef9SDimitry Andric Status error; 240e8d8bef9SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 241e8d8bef9SDimitry Andric 242e8d8bef9SDimitry Andric switch (short_option) { 243e8d8bef9SDimitry Andric case 'v': { 244e8d8bef9SDimitry Andric m_verbose = true; 245e8d8bef9SDimitry Andric break; 246e8d8bef9SDimitry Andric } 247e8d8bef9SDimitry Andric default: 248e8d8bef9SDimitry Andric llvm_unreachable("Unimplemented option"); 249e8d8bef9SDimitry Andric } 250e8d8bef9SDimitry Andric return error; 251e8d8bef9SDimitry Andric } 252e8d8bef9SDimitry Andric 253e8d8bef9SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 254e8d8bef9SDimitry Andric m_verbose = false; 255e8d8bef9SDimitry Andric } 256e8d8bef9SDimitry Andric 257e8d8bef9SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 258bdd1243dSDimitry Andric return llvm::ArrayRef(g_trace_dump_options); 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261e8d8bef9SDimitry Andric bool m_verbose; // Enable verbose logging for debugging purposes. 262e8d8bef9SDimitry Andric }; 263e8d8bef9SDimitry Andric 264e8d8bef9SDimitry Andric CommandObjectTraceDump(CommandInterpreter &interpreter) 265e8d8bef9SDimitry Andric : CommandObjectParsed(interpreter, "trace dump", 266e8d8bef9SDimitry Andric "Dump the loaded processor trace data.", 26704eeddc0SDimitry Andric "trace dump") {} 268e8d8bef9SDimitry Andric 269e8d8bef9SDimitry Andric ~CommandObjectTraceDump() override = default; 270e8d8bef9SDimitry Andric 271e8d8bef9SDimitry Andric Options *GetOptions() override { return &m_options; } 272e8d8bef9SDimitry Andric 273e8d8bef9SDimitry Andric protected: 2745f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 275e8d8bef9SDimitry Andric Status error; 276e8d8bef9SDimitry Andric // TODO: fill in the dumping code here! 277e8d8bef9SDimitry Andric if (error.Success()) { 278e8d8bef9SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 279e8d8bef9SDimitry Andric } else { 280e8d8bef9SDimitry Andric result.AppendErrorWithFormat("%s\n", error.AsCString()); 281e8d8bef9SDimitry Andric } 282e8d8bef9SDimitry Andric } 283e8d8bef9SDimitry Andric 284e8d8bef9SDimitry Andric CommandOptions m_options; 285e8d8bef9SDimitry Andric }; 286e8d8bef9SDimitry Andric 287e8d8bef9SDimitry Andric // CommandObjectTraceSchema 288e8d8bef9SDimitry Andric #define LLDB_OPTIONS_trace_schema 289e8d8bef9SDimitry Andric #include "CommandOptions.inc" 290e8d8bef9SDimitry Andric 291e8d8bef9SDimitry Andric #pragma mark CommandObjectTraceSchema 292e8d8bef9SDimitry Andric 293e8d8bef9SDimitry Andric class CommandObjectTraceSchema : public CommandObjectParsed { 294e8d8bef9SDimitry Andric public: 295e8d8bef9SDimitry Andric class CommandOptions : public Options { 296e8d8bef9SDimitry Andric public: 29704eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); } 298e8d8bef9SDimitry Andric 299e8d8bef9SDimitry Andric ~CommandOptions() override = default; 300e8d8bef9SDimitry Andric 301e8d8bef9SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 302e8d8bef9SDimitry Andric ExecutionContext *execution_context) override { 303e8d8bef9SDimitry Andric Status error; 304e8d8bef9SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 305e8d8bef9SDimitry Andric 306e8d8bef9SDimitry Andric switch (short_option) { 307e8d8bef9SDimitry Andric case 'v': { 308e8d8bef9SDimitry Andric m_verbose = true; 309e8d8bef9SDimitry Andric break; 310e8d8bef9SDimitry Andric } 311e8d8bef9SDimitry Andric default: 312e8d8bef9SDimitry Andric llvm_unreachable("Unimplemented option"); 313e8d8bef9SDimitry Andric } 314e8d8bef9SDimitry Andric return error; 315e8d8bef9SDimitry Andric } 316e8d8bef9SDimitry Andric 317e8d8bef9SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 318e8d8bef9SDimitry Andric m_verbose = false; 319e8d8bef9SDimitry Andric } 320e8d8bef9SDimitry Andric 321e8d8bef9SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 322bdd1243dSDimitry Andric return llvm::ArrayRef(g_trace_schema_options); 323e8d8bef9SDimitry Andric } 324e8d8bef9SDimitry Andric 325e8d8bef9SDimitry Andric bool m_verbose; // Enable verbose logging for debugging purposes. 326e8d8bef9SDimitry Andric }; 327e8d8bef9SDimitry Andric 328e8d8bef9SDimitry Andric CommandObjectTraceSchema(CommandInterpreter &interpreter) 329e8d8bef9SDimitry Andric : CommandObjectParsed(interpreter, "trace schema", 330e8d8bef9SDimitry Andric "Show the schema of the given trace plugin.", 331e8d8bef9SDimitry Andric "trace schema <plug-in>. Use the plug-in name " 33281ad6265SDimitry Andric "\"all\" to see all schemas.\n") { 333*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeNone); 33481ad6265SDimitry Andric } 335e8d8bef9SDimitry Andric 336e8d8bef9SDimitry Andric ~CommandObjectTraceSchema() override = default; 337e8d8bef9SDimitry Andric 338e8d8bef9SDimitry Andric Options *GetOptions() override { return &m_options; } 339e8d8bef9SDimitry Andric 340e8d8bef9SDimitry Andric protected: 3415f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 342e8d8bef9SDimitry Andric Status error; 343e8d8bef9SDimitry Andric if (command.empty()) { 344fe6060f1SDimitry Andric result.AppendError( 345e8d8bef9SDimitry Andric "trace schema cannot be invoked without a plug-in as argument"); 3465f757f3fSDimitry Andric return; 347e8d8bef9SDimitry Andric } 348e8d8bef9SDimitry Andric 349e8d8bef9SDimitry Andric StringRef plugin_name(command[0].c_str()); 350e8d8bef9SDimitry Andric if (plugin_name == "all") { 351e8d8bef9SDimitry Andric size_t index = 0; 352e8d8bef9SDimitry Andric while (true) { 353e8d8bef9SDimitry Andric StringRef schema = PluginManager::GetTraceSchema(index++); 354e8d8bef9SDimitry Andric if (schema.empty()) 355e8d8bef9SDimitry Andric break; 356e8d8bef9SDimitry Andric 357e8d8bef9SDimitry Andric result.AppendMessage(schema); 358e8d8bef9SDimitry Andric } 359e8d8bef9SDimitry Andric } else { 360e8d8bef9SDimitry Andric if (Expected<StringRef> schemaOrErr = 361e8d8bef9SDimitry Andric Trace::FindPluginSchema(plugin_name)) 362e8d8bef9SDimitry Andric result.AppendMessage(*schemaOrErr); 363e8d8bef9SDimitry Andric else 364e8d8bef9SDimitry Andric error = schemaOrErr.takeError(); 365e8d8bef9SDimitry Andric } 366e8d8bef9SDimitry Andric 367e8d8bef9SDimitry Andric if (error.Success()) { 368e8d8bef9SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 369e8d8bef9SDimitry Andric } else { 370e8d8bef9SDimitry Andric result.AppendErrorWithFormat("%s\n", error.AsCString()); 371e8d8bef9SDimitry Andric } 372e8d8bef9SDimitry Andric } 373e8d8bef9SDimitry Andric 374e8d8bef9SDimitry Andric CommandOptions m_options; 375e8d8bef9SDimitry Andric }; 376e8d8bef9SDimitry Andric 377e8d8bef9SDimitry Andric // CommandObjectTrace 378e8d8bef9SDimitry Andric 379e8d8bef9SDimitry Andric CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter) 380e8d8bef9SDimitry Andric : CommandObjectMultiword(interpreter, "trace", 381e8d8bef9SDimitry Andric "Commands for loading and using processor " 382e8d8bef9SDimitry Andric "trace information.", 383e8d8bef9SDimitry Andric "trace [<sub-command-options>]") { 384e8d8bef9SDimitry Andric LoadSubCommand("load", 385e8d8bef9SDimitry Andric CommandObjectSP(new CommandObjectTraceLoad(interpreter))); 386e8d8bef9SDimitry Andric LoadSubCommand("dump", 387e8d8bef9SDimitry Andric CommandObjectSP(new CommandObjectTraceDump(interpreter))); 388753f127fSDimitry Andric LoadSubCommand("save", 389753f127fSDimitry Andric CommandObjectSP(new CommandObjectTraceSave(interpreter))); 390e8d8bef9SDimitry Andric LoadSubCommand("schema", 391e8d8bef9SDimitry Andric CommandObjectSP(new CommandObjectTraceSchema(interpreter))); 392e8d8bef9SDimitry Andric } 393e8d8bef9SDimitry Andric 394e8d8bef9SDimitry Andric CommandObjectTrace::~CommandObjectTrace() = default; 395fe6060f1SDimitry Andric 396fe6060f1SDimitry Andric Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() { 397fe6060f1SDimitry Andric ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP(); 398fe6060f1SDimitry Andric 399fe6060f1SDimitry Andric if (!process_sp) 400fe6060f1SDimitry Andric return createStringError(inconvertibleErrorCode(), 401fe6060f1SDimitry Andric "Process not available."); 402fe6060f1SDimitry Andric if (m_live_debug_session_only && !process_sp->IsLiveDebugSession()) 403fe6060f1SDimitry Andric return createStringError(inconvertibleErrorCode(), 404fe6060f1SDimitry Andric "Process must be alive."); 405fe6060f1SDimitry Andric 406fe6060f1SDimitry Andric if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate()) 407fe6060f1SDimitry Andric return GetDelegateCommand(**trace_sp); 408fe6060f1SDimitry Andric else 409fe6060f1SDimitry Andric return createStringError(inconvertibleErrorCode(), 410fe6060f1SDimitry Andric "Tracing is not supported. %s", 411fe6060f1SDimitry Andric toString(trace_sp.takeError()).c_str()); 412fe6060f1SDimitry Andric } 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric CommandObject *CommandObjectTraceProxy::GetProxyCommandObject() { 415fe6060f1SDimitry Andric if (Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) { 416fe6060f1SDimitry Andric m_delegate_sp = *delegate; 417fe6060f1SDimitry Andric m_delegate_error.clear(); 418fe6060f1SDimitry Andric return m_delegate_sp.get(); 419fe6060f1SDimitry Andric } else { 420fe6060f1SDimitry Andric m_delegate_sp.reset(); 421fe6060f1SDimitry Andric m_delegate_error = toString(delegate.takeError()); 422fe6060f1SDimitry Andric return nullptr; 423fe6060f1SDimitry Andric } 424fe6060f1SDimitry Andric } 425