xref: /openbsd-src/gnu/llvm/lldb/source/Commands/CommandObjectTrace.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1be691f3bSpatrick //===-- CommandObjectTrace.cpp --------------------------------------------===//
2be691f3bSpatrick //
3be691f3bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4be691f3bSpatrick // See https://llvm.org/LICENSE.txt for license information.
5be691f3bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6be691f3bSpatrick //
7be691f3bSpatrick //===----------------------------------------------------------------------===//
8be691f3bSpatrick 
9be691f3bSpatrick #include "CommandObjectTrace.h"
10be691f3bSpatrick 
11be691f3bSpatrick #include "llvm/Support/JSON.h"
12be691f3bSpatrick #include "llvm/Support/MemoryBuffer.h"
13be691f3bSpatrick 
14be691f3bSpatrick #include "lldb/Core/Debugger.h"
15be691f3bSpatrick #include "lldb/Core/PluginManager.h"
16be691f3bSpatrick #include "lldb/Host/OptionParser.h"
17be691f3bSpatrick #include "lldb/Interpreter/CommandInterpreter.h"
18be691f3bSpatrick #include "lldb/Interpreter/CommandObject.h"
19*f6aab3d8Srobert #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20be691f3bSpatrick #include "lldb/Interpreter/CommandReturnObject.h"
21be691f3bSpatrick #include "lldb/Interpreter/OptionArgParser.h"
22be691f3bSpatrick #include "lldb/Interpreter/OptionGroupFormat.h"
23be691f3bSpatrick #include "lldb/Interpreter/OptionValueBoolean.h"
24be691f3bSpatrick #include "lldb/Interpreter/OptionValueLanguage.h"
25be691f3bSpatrick #include "lldb/Interpreter/OptionValueString.h"
26be691f3bSpatrick #include "lldb/Interpreter/Options.h"
27be691f3bSpatrick #include "lldb/Target/Process.h"
28be691f3bSpatrick #include "lldb/Target/Trace.h"
29be691f3bSpatrick 
30be691f3bSpatrick using namespace lldb;
31be691f3bSpatrick using namespace lldb_private;
32be691f3bSpatrick using namespace llvm;
33be691f3bSpatrick 
34*f6aab3d8Srobert // CommandObjectTraceSave
35*f6aab3d8Srobert #define LLDB_OPTIONS_trace_save
36*f6aab3d8Srobert #include "CommandOptions.inc"
37*f6aab3d8Srobert 
38*f6aab3d8Srobert #pragma mark CommandObjectTraceSave
39*f6aab3d8Srobert 
40*f6aab3d8Srobert class CommandObjectTraceSave : public CommandObjectParsed {
41*f6aab3d8Srobert public:
42*f6aab3d8Srobert   class CommandOptions : public Options {
43*f6aab3d8Srobert   public:
CommandOptions()44*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
45*f6aab3d8Srobert 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)46*f6aab3d8Srobert     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
47*f6aab3d8Srobert                           ExecutionContext *execution_context) override {
48*f6aab3d8Srobert       Status error;
49*f6aab3d8Srobert       const int short_option = m_getopt_table[option_idx].val;
50*f6aab3d8Srobert 
51*f6aab3d8Srobert       switch (short_option) {
52*f6aab3d8Srobert       case 'c': {
53*f6aab3d8Srobert         m_compact = true;
54*f6aab3d8Srobert         break;
55*f6aab3d8Srobert       }
56*f6aab3d8Srobert       default:
57*f6aab3d8Srobert         llvm_unreachable("Unimplemented option");
58*f6aab3d8Srobert       }
59*f6aab3d8Srobert       return error;
60*f6aab3d8Srobert     }
61*f6aab3d8Srobert 
OptionParsingStarting(ExecutionContext * execution_context)62*f6aab3d8Srobert     void OptionParsingStarting(ExecutionContext *execution_context) override {
63*f6aab3d8Srobert       m_compact = false;
64*f6aab3d8Srobert     };
65*f6aab3d8Srobert 
GetDefinitions()66*f6aab3d8Srobert     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
67*f6aab3d8Srobert       return llvm::ArrayRef(g_trace_save_options);
68*f6aab3d8Srobert     };
69*f6aab3d8Srobert 
70*f6aab3d8Srobert     bool m_compact;
71*f6aab3d8Srobert   };
72*f6aab3d8Srobert 
GetOptions()73*f6aab3d8Srobert   Options *GetOptions() override { return &m_options; }
74*f6aab3d8Srobert 
CommandObjectTraceSave(CommandInterpreter & interpreter)75*f6aab3d8Srobert   CommandObjectTraceSave(CommandInterpreter &interpreter)
76*f6aab3d8Srobert       : CommandObjectParsed(
77*f6aab3d8Srobert             interpreter, "trace save",
78*f6aab3d8Srobert             "Save the trace of the current target in the specified directory, "
79*f6aab3d8Srobert             "which will be created if needed. "
80*f6aab3d8Srobert             "This directory will contain a trace bundle, with all the "
81*f6aab3d8Srobert             "necessary files the reconstruct the trace session even on a "
82*f6aab3d8Srobert             "different computer. "
83*f6aab3d8Srobert             "Part of this bundle is the bundle description file with the name "
84*f6aab3d8Srobert             "trace.json. This file can be used by the \"trace load\" command "
85*f6aab3d8Srobert             "to load this trace in LLDB."
86*f6aab3d8Srobert             "Note: if the current target contains information of multiple "
87*f6aab3d8Srobert             "processes or targets, they all will be included in the bundle.",
88*f6aab3d8Srobert             "trace save [<cmd-options>] <bundle_directory>",
89*f6aab3d8Srobert             eCommandRequiresProcess | eCommandTryTargetAPILock |
90*f6aab3d8Srobert                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
91*f6aab3d8Srobert                 eCommandProcessMustBeTraced) {
92*f6aab3d8Srobert     CommandArgumentData bundle_dir{eArgTypeDirectoryName, eArgRepeatPlain};
93*f6aab3d8Srobert     m_arguments.push_back({bundle_dir});
94*f6aab3d8Srobert   }
95*f6aab3d8Srobert 
96*f6aab3d8Srobert   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)97*f6aab3d8Srobert   HandleArgumentCompletion(CompletionRequest &request,
98*f6aab3d8Srobert                            OptionElementVector &opt_element_vector) override {
99*f6aab3d8Srobert     CommandCompletions::InvokeCommonCompletionCallbacks(
100*f6aab3d8Srobert         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
101*f6aab3d8Srobert         request, nullptr);
102*f6aab3d8Srobert   }
103*f6aab3d8Srobert 
104*f6aab3d8Srobert   ~CommandObjectTraceSave() override = default;
105*f6aab3d8Srobert 
106*f6aab3d8Srobert protected:
DoExecute(Args & command,CommandReturnObject & result)107*f6aab3d8Srobert   bool DoExecute(Args &command, CommandReturnObject &result) override {
108*f6aab3d8Srobert     if (command.size() != 1) {
109*f6aab3d8Srobert       result.AppendError("a single path to a directory where the trace bundle "
110*f6aab3d8Srobert                          "will be created is required");
111*f6aab3d8Srobert       return false;
112*f6aab3d8Srobert     }
113*f6aab3d8Srobert 
114*f6aab3d8Srobert     FileSpec bundle_dir(command[0].ref());
115*f6aab3d8Srobert     FileSystem::Instance().Resolve(bundle_dir);
116*f6aab3d8Srobert 
117*f6aab3d8Srobert     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
118*f6aab3d8Srobert 
119*f6aab3d8Srobert     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
120*f6aab3d8Srobert 
121*f6aab3d8Srobert     if (llvm::Expected<FileSpec> desc_file =
122*f6aab3d8Srobert             trace_sp->SaveToDisk(bundle_dir, m_options.m_compact)) {
123*f6aab3d8Srobert       result.AppendMessageWithFormatv(
124*f6aab3d8Srobert           "Trace bundle description file written to: {0}", *desc_file);
125*f6aab3d8Srobert       result.SetStatus(eReturnStatusSuccessFinishResult);
126*f6aab3d8Srobert     } else {
127*f6aab3d8Srobert       result.AppendError(toString(desc_file.takeError()));
128*f6aab3d8Srobert     }
129*f6aab3d8Srobert 
130*f6aab3d8Srobert     return result.Succeeded();
131*f6aab3d8Srobert   }
132*f6aab3d8Srobert 
133*f6aab3d8Srobert   CommandOptions m_options;
134*f6aab3d8Srobert };
135*f6aab3d8Srobert 
136be691f3bSpatrick // CommandObjectTraceLoad
137be691f3bSpatrick #define LLDB_OPTIONS_trace_load
138be691f3bSpatrick #include "CommandOptions.inc"
139be691f3bSpatrick 
140be691f3bSpatrick #pragma mark CommandObjectTraceLoad
141be691f3bSpatrick 
142be691f3bSpatrick class CommandObjectTraceLoad : public CommandObjectParsed {
143be691f3bSpatrick public:
144be691f3bSpatrick   class CommandOptions : public Options {
145be691f3bSpatrick   public:
CommandOptions()146*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
147be691f3bSpatrick 
148be691f3bSpatrick     ~CommandOptions() override = default;
149be691f3bSpatrick 
SetOptionValue(uint32_t option_idx,StringRef option_arg,ExecutionContext * execution_context)150be691f3bSpatrick     Status SetOptionValue(uint32_t option_idx, StringRef option_arg,
151be691f3bSpatrick                           ExecutionContext *execution_context) override {
152be691f3bSpatrick       Status error;
153be691f3bSpatrick       const int short_option = m_getopt_table[option_idx].val;
154be691f3bSpatrick 
155be691f3bSpatrick       switch (short_option) {
156be691f3bSpatrick       case 'v': {
157be691f3bSpatrick         m_verbose = true;
158be691f3bSpatrick         break;
159be691f3bSpatrick       }
160be691f3bSpatrick       default:
161be691f3bSpatrick         llvm_unreachable("Unimplemented option");
162be691f3bSpatrick       }
163be691f3bSpatrick       return error;
164be691f3bSpatrick     }
165be691f3bSpatrick 
OptionParsingStarting(ExecutionContext * execution_context)166be691f3bSpatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
167be691f3bSpatrick       m_verbose = false;
168be691f3bSpatrick     }
169be691f3bSpatrick 
GetDefinitions()170be691f3bSpatrick     ArrayRef<OptionDefinition> GetDefinitions() override {
171*f6aab3d8Srobert       return ArrayRef(g_trace_load_options);
172be691f3bSpatrick     }
173be691f3bSpatrick 
174be691f3bSpatrick     bool m_verbose; // Enable verbose logging for debugging purposes.
175be691f3bSpatrick   };
176be691f3bSpatrick 
CommandObjectTraceLoad(CommandInterpreter & interpreter)177be691f3bSpatrick   CommandObjectTraceLoad(CommandInterpreter &interpreter)
178*f6aab3d8Srobert       : CommandObjectParsed(
179*f6aab3d8Srobert             interpreter, "trace load",
180*f6aab3d8Srobert             "Load a post-mortem processor trace session from a trace bundle.",
181*f6aab3d8Srobert             "trace load <trace_description_file>") {
182*f6aab3d8Srobert     CommandArgumentData session_file_arg{eArgTypeFilename, eArgRepeatPlain};
183*f6aab3d8Srobert     m_arguments.push_back({session_file_arg});
184*f6aab3d8Srobert   }
185*f6aab3d8Srobert 
186*f6aab3d8Srobert   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)187*f6aab3d8Srobert   HandleArgumentCompletion(CompletionRequest &request,
188*f6aab3d8Srobert                            OptionElementVector &opt_element_vector) override {
189*f6aab3d8Srobert     CommandCompletions::InvokeCommonCompletionCallbacks(
190*f6aab3d8Srobert         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
191*f6aab3d8Srobert         request, nullptr);
192*f6aab3d8Srobert   }
193be691f3bSpatrick 
194be691f3bSpatrick   ~CommandObjectTraceLoad() override = default;
195be691f3bSpatrick 
GetOptions()196be691f3bSpatrick   Options *GetOptions() override { return &m_options; }
197be691f3bSpatrick 
198be691f3bSpatrick protected:
DoExecute(Args & command,CommandReturnObject & result)199be691f3bSpatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
200be691f3bSpatrick     if (command.size() != 1) {
201*f6aab3d8Srobert       result.AppendError("a single path to a JSON file containing a the "
202*f6aab3d8Srobert                          "description of the trace bundle is required");
203be691f3bSpatrick       return false;
204be691f3bSpatrick     }
205be691f3bSpatrick 
206*f6aab3d8Srobert     const FileSpec trace_description_file(command[0].ref());
207*f6aab3d8Srobert 
208*f6aab3d8Srobert     llvm::Expected<lldb::TraceSP> trace_or_err =
209*f6aab3d8Srobert         Trace::LoadPostMortemTraceFromFile(GetDebugger(),
210*f6aab3d8Srobert                                            trace_description_file);
211*f6aab3d8Srobert 
212*f6aab3d8Srobert     if (!trace_or_err) {
213*f6aab3d8Srobert       result.AppendErrorWithFormat(
214*f6aab3d8Srobert           "%s\n", llvm::toString(trace_or_err.takeError()).c_str());
215be691f3bSpatrick       return false;
216be691f3bSpatrick     }
217be691f3bSpatrick 
218*f6aab3d8Srobert     if (m_options.m_verbose) {
219*f6aab3d8Srobert       result.AppendMessageWithFormatv("loading trace with plugin {0}\n",
220*f6aab3d8Srobert                                       trace_or_err.get()->GetPluginName());
221*f6aab3d8Srobert     }
222be691f3bSpatrick 
223be691f3bSpatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
224be691f3bSpatrick     return true;
225be691f3bSpatrick   }
226be691f3bSpatrick 
227be691f3bSpatrick   CommandOptions m_options;
228be691f3bSpatrick };
229be691f3bSpatrick 
230be691f3bSpatrick // CommandObjectTraceDump
231be691f3bSpatrick #define LLDB_OPTIONS_trace_dump
232be691f3bSpatrick #include "CommandOptions.inc"
233be691f3bSpatrick 
234be691f3bSpatrick #pragma mark CommandObjectTraceDump
235be691f3bSpatrick 
236be691f3bSpatrick class CommandObjectTraceDump : public CommandObjectParsed {
237be691f3bSpatrick public:
238be691f3bSpatrick   class CommandOptions : public Options {
239be691f3bSpatrick   public:
CommandOptions()240*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
241be691f3bSpatrick 
242be691f3bSpatrick     ~CommandOptions() override = default;
243be691f3bSpatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)244be691f3bSpatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
245be691f3bSpatrick                           ExecutionContext *execution_context) override {
246be691f3bSpatrick       Status error;
247be691f3bSpatrick       const int short_option = m_getopt_table[option_idx].val;
248be691f3bSpatrick 
249be691f3bSpatrick       switch (short_option) {
250be691f3bSpatrick       case 'v': {
251be691f3bSpatrick         m_verbose = true;
252be691f3bSpatrick         break;
253be691f3bSpatrick       }
254be691f3bSpatrick       default:
255be691f3bSpatrick         llvm_unreachable("Unimplemented option");
256be691f3bSpatrick       }
257be691f3bSpatrick       return error;
258be691f3bSpatrick     }
259be691f3bSpatrick 
OptionParsingStarting(ExecutionContext * execution_context)260be691f3bSpatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
261be691f3bSpatrick       m_verbose = false;
262be691f3bSpatrick     }
263be691f3bSpatrick 
GetDefinitions()264be691f3bSpatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
265*f6aab3d8Srobert       return llvm::ArrayRef(g_trace_dump_options);
266be691f3bSpatrick     }
267be691f3bSpatrick 
268be691f3bSpatrick     bool m_verbose; // Enable verbose logging for debugging purposes.
269be691f3bSpatrick   };
270be691f3bSpatrick 
CommandObjectTraceDump(CommandInterpreter & interpreter)271be691f3bSpatrick   CommandObjectTraceDump(CommandInterpreter &interpreter)
272be691f3bSpatrick       : CommandObjectParsed(interpreter, "trace dump",
273be691f3bSpatrick                             "Dump the loaded processor trace data.",
274*f6aab3d8Srobert                             "trace dump") {}
275be691f3bSpatrick 
276be691f3bSpatrick   ~CommandObjectTraceDump() override = default;
277be691f3bSpatrick 
GetOptions()278be691f3bSpatrick   Options *GetOptions() override { return &m_options; }
279be691f3bSpatrick 
280be691f3bSpatrick protected:
DoExecute(Args & command,CommandReturnObject & result)281be691f3bSpatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
282be691f3bSpatrick     Status error;
283be691f3bSpatrick     // TODO: fill in the dumping code here!
284be691f3bSpatrick     if (error.Success()) {
285be691f3bSpatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
286be691f3bSpatrick     } else {
287be691f3bSpatrick       result.AppendErrorWithFormat("%s\n", error.AsCString());
288be691f3bSpatrick     }
289be691f3bSpatrick     return result.Succeeded();
290be691f3bSpatrick   }
291be691f3bSpatrick 
292be691f3bSpatrick   CommandOptions m_options;
293be691f3bSpatrick };
294be691f3bSpatrick 
295be691f3bSpatrick // CommandObjectTraceSchema
296be691f3bSpatrick #define LLDB_OPTIONS_trace_schema
297be691f3bSpatrick #include "CommandOptions.inc"
298be691f3bSpatrick 
299be691f3bSpatrick #pragma mark CommandObjectTraceSchema
300be691f3bSpatrick 
301be691f3bSpatrick class CommandObjectTraceSchema : public CommandObjectParsed {
302be691f3bSpatrick public:
303be691f3bSpatrick   class CommandOptions : public Options {
304be691f3bSpatrick   public:
CommandOptions()305*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
306be691f3bSpatrick 
307be691f3bSpatrick     ~CommandOptions() override = default;
308be691f3bSpatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)309be691f3bSpatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
310be691f3bSpatrick                           ExecutionContext *execution_context) override {
311be691f3bSpatrick       Status error;
312be691f3bSpatrick       const int short_option = m_getopt_table[option_idx].val;
313be691f3bSpatrick 
314be691f3bSpatrick       switch (short_option) {
315be691f3bSpatrick       case 'v': {
316be691f3bSpatrick         m_verbose = true;
317be691f3bSpatrick         break;
318be691f3bSpatrick       }
319be691f3bSpatrick       default:
320be691f3bSpatrick         llvm_unreachable("Unimplemented option");
321be691f3bSpatrick       }
322be691f3bSpatrick       return error;
323be691f3bSpatrick     }
324be691f3bSpatrick 
OptionParsingStarting(ExecutionContext * execution_context)325be691f3bSpatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
326be691f3bSpatrick       m_verbose = false;
327be691f3bSpatrick     }
328be691f3bSpatrick 
GetDefinitions()329be691f3bSpatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
330*f6aab3d8Srobert       return llvm::ArrayRef(g_trace_schema_options);
331be691f3bSpatrick     }
332be691f3bSpatrick 
333be691f3bSpatrick     bool m_verbose; // Enable verbose logging for debugging purposes.
334be691f3bSpatrick   };
335be691f3bSpatrick 
CommandObjectTraceSchema(CommandInterpreter & interpreter)336be691f3bSpatrick   CommandObjectTraceSchema(CommandInterpreter &interpreter)
337be691f3bSpatrick       : CommandObjectParsed(interpreter, "trace schema",
338be691f3bSpatrick                             "Show the schema of the given trace plugin.",
339be691f3bSpatrick                             "trace schema <plug-in>. Use the plug-in name "
340*f6aab3d8Srobert                             "\"all\" to see all schemas.\n") {
341*f6aab3d8Srobert     CommandArgumentData plugin_arg{eArgTypeNone, eArgRepeatPlain};
342*f6aab3d8Srobert     m_arguments.push_back({plugin_arg});
343*f6aab3d8Srobert   }
344be691f3bSpatrick 
345be691f3bSpatrick   ~CommandObjectTraceSchema() override = default;
346be691f3bSpatrick 
GetOptions()347be691f3bSpatrick   Options *GetOptions() override { return &m_options; }
348be691f3bSpatrick 
349be691f3bSpatrick protected:
DoExecute(Args & command,CommandReturnObject & result)350be691f3bSpatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
351be691f3bSpatrick     Status error;
352be691f3bSpatrick     if (command.empty()) {
353be691f3bSpatrick       result.AppendError(
354be691f3bSpatrick           "trace schema cannot be invoked without a plug-in as argument");
355be691f3bSpatrick       return false;
356be691f3bSpatrick     }
357be691f3bSpatrick 
358be691f3bSpatrick     StringRef plugin_name(command[0].c_str());
359be691f3bSpatrick     if (plugin_name == "all") {
360be691f3bSpatrick       size_t index = 0;
361be691f3bSpatrick       while (true) {
362be691f3bSpatrick         StringRef schema = PluginManager::GetTraceSchema(index++);
363be691f3bSpatrick         if (schema.empty())
364be691f3bSpatrick           break;
365be691f3bSpatrick 
366be691f3bSpatrick         result.AppendMessage(schema);
367be691f3bSpatrick       }
368be691f3bSpatrick     } else {
369be691f3bSpatrick       if (Expected<StringRef> schemaOrErr =
370be691f3bSpatrick               Trace::FindPluginSchema(plugin_name))
371be691f3bSpatrick         result.AppendMessage(*schemaOrErr);
372be691f3bSpatrick       else
373be691f3bSpatrick         error = schemaOrErr.takeError();
374be691f3bSpatrick     }
375be691f3bSpatrick 
376be691f3bSpatrick     if (error.Success()) {
377be691f3bSpatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
378be691f3bSpatrick     } else {
379be691f3bSpatrick       result.AppendErrorWithFormat("%s\n", error.AsCString());
380be691f3bSpatrick     }
381be691f3bSpatrick     return result.Succeeded();
382be691f3bSpatrick   }
383be691f3bSpatrick 
384be691f3bSpatrick   CommandOptions m_options;
385be691f3bSpatrick };
386be691f3bSpatrick 
387be691f3bSpatrick // CommandObjectTrace
388be691f3bSpatrick 
CommandObjectTrace(CommandInterpreter & interpreter)389be691f3bSpatrick CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter)
390be691f3bSpatrick     : CommandObjectMultiword(interpreter, "trace",
391be691f3bSpatrick                              "Commands for loading and using processor "
392be691f3bSpatrick                              "trace information.",
393be691f3bSpatrick                              "trace [<sub-command-options>]") {
394be691f3bSpatrick   LoadSubCommand("load",
395be691f3bSpatrick                  CommandObjectSP(new CommandObjectTraceLoad(interpreter)));
396be691f3bSpatrick   LoadSubCommand("dump",
397be691f3bSpatrick                  CommandObjectSP(new CommandObjectTraceDump(interpreter)));
398*f6aab3d8Srobert   LoadSubCommand("save",
399*f6aab3d8Srobert                  CommandObjectSP(new CommandObjectTraceSave(interpreter)));
400be691f3bSpatrick   LoadSubCommand("schema",
401be691f3bSpatrick                  CommandObjectSP(new CommandObjectTraceSchema(interpreter)));
402be691f3bSpatrick }
403be691f3bSpatrick 
404be691f3bSpatrick CommandObjectTrace::~CommandObjectTrace() = default;
405be691f3bSpatrick 
DoGetProxyCommandObject()406be691f3bSpatrick Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() {
407be691f3bSpatrick   ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP();
408be691f3bSpatrick 
409be691f3bSpatrick   if (!process_sp)
410be691f3bSpatrick     return createStringError(inconvertibleErrorCode(),
411be691f3bSpatrick                              "Process not available.");
412be691f3bSpatrick   if (m_live_debug_session_only && !process_sp->IsLiveDebugSession())
413be691f3bSpatrick     return createStringError(inconvertibleErrorCode(),
414be691f3bSpatrick                              "Process must be alive.");
415be691f3bSpatrick 
416be691f3bSpatrick   if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate())
417be691f3bSpatrick     return GetDelegateCommand(**trace_sp);
418be691f3bSpatrick   else
419be691f3bSpatrick     return createStringError(inconvertibleErrorCode(),
420be691f3bSpatrick                              "Tracing is not supported. %s",
421be691f3bSpatrick                              toString(trace_sp.takeError()).c_str());
422be691f3bSpatrick }
423be691f3bSpatrick 
GetProxyCommandObject()424be691f3bSpatrick CommandObject *CommandObjectTraceProxy::GetProxyCommandObject() {
425be691f3bSpatrick   if (Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) {
426be691f3bSpatrick     m_delegate_sp = *delegate;
427be691f3bSpatrick     m_delegate_error.clear();
428be691f3bSpatrick     return m_delegate_sp.get();
429be691f3bSpatrick   } else {
430be691f3bSpatrick     m_delegate_sp.reset();
431be691f3bSpatrick     m_delegate_error = toString(delegate.takeError());
432be691f3bSpatrick     return nullptr;
433be691f3bSpatrick   }
434be691f3bSpatrick }
435