xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1b60736ecSDimitry Andric //===-- CommandObjectTrace.cpp --------------------------------------------===//
2b60736ecSDimitry Andric //
3b60736ecSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b60736ecSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b60736ecSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b60736ecSDimitry Andric //
7b60736ecSDimitry Andric //===----------------------------------------------------------------------===//
8b60736ecSDimitry Andric 
9b60736ecSDimitry Andric #include "CommandObjectTrace.h"
10b60736ecSDimitry Andric 
11b60736ecSDimitry Andric #include "llvm/Support/JSON.h"
12b60736ecSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
13b60736ecSDimitry Andric 
14b60736ecSDimitry Andric #include "lldb/Core/Debugger.h"
15b60736ecSDimitry Andric #include "lldb/Core/PluginManager.h"
16b60736ecSDimitry Andric #include "lldb/Host/OptionParser.h"
17b60736ecSDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
18b60736ecSDimitry Andric #include "lldb/Interpreter/CommandObject.h"
194b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20b60736ecSDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
21b60736ecSDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
22b60736ecSDimitry Andric #include "lldb/Interpreter/OptionGroupFormat.h"
23b60736ecSDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h"
24b60736ecSDimitry Andric #include "lldb/Interpreter/OptionValueLanguage.h"
25b60736ecSDimitry Andric #include "lldb/Interpreter/OptionValueString.h"
26b60736ecSDimitry Andric #include "lldb/Interpreter/Options.h"
27344a3780SDimitry Andric #include "lldb/Target/Process.h"
28b60736ecSDimitry Andric #include "lldb/Target/Trace.h"
29b60736ecSDimitry Andric 
30b60736ecSDimitry Andric using namespace lldb;
31b60736ecSDimitry Andric using namespace lldb_private;
32b60736ecSDimitry Andric using namespace llvm;
33b60736ecSDimitry Andric 
341f917f69SDimitry Andric // CommandObjectTraceSave
351f917f69SDimitry Andric #define LLDB_OPTIONS_trace_save
361f917f69SDimitry Andric #include "CommandOptions.inc"
371f917f69SDimitry Andric 
381f917f69SDimitry Andric #pragma mark CommandObjectTraceSave
391f917f69SDimitry Andric 
401f917f69SDimitry Andric class CommandObjectTraceSave : public CommandObjectParsed {
411f917f69SDimitry Andric public:
421f917f69SDimitry Andric   class CommandOptions : public Options {
431f917f69SDimitry Andric   public:
CommandOptions()441f917f69SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
451f917f69SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)461f917f69SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
471f917f69SDimitry Andric                           ExecutionContext *execution_context) override {
481f917f69SDimitry Andric       Status error;
491f917f69SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
501f917f69SDimitry Andric 
511f917f69SDimitry Andric       switch (short_option) {
521f917f69SDimitry Andric       case 'c': {
531f917f69SDimitry Andric         m_compact = true;
541f917f69SDimitry Andric         break;
551f917f69SDimitry Andric       }
561f917f69SDimitry Andric       default:
571f917f69SDimitry Andric         llvm_unreachable("Unimplemented option");
581f917f69SDimitry Andric       }
591f917f69SDimitry Andric       return error;
601f917f69SDimitry Andric     }
611f917f69SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)621f917f69SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
631f917f69SDimitry Andric       m_compact = false;
641f917f69SDimitry Andric     };
651f917f69SDimitry Andric 
GetDefinitions()661f917f69SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
67e3b55780SDimitry Andric       return llvm::ArrayRef(g_trace_save_options);
681f917f69SDimitry Andric     };
691f917f69SDimitry Andric 
701f917f69SDimitry Andric     bool m_compact;
711f917f69SDimitry Andric   };
721f917f69SDimitry Andric 
GetOptions()731f917f69SDimitry Andric   Options *GetOptions() override { return &m_options; }
741f917f69SDimitry Andric 
CommandObjectTraceSave(CommandInterpreter & interpreter)751f917f69SDimitry Andric   CommandObjectTraceSave(CommandInterpreter &interpreter)
761f917f69SDimitry Andric       : CommandObjectParsed(
771f917f69SDimitry Andric             interpreter, "trace save",
781f917f69SDimitry Andric             "Save the trace of the current target in the specified directory, "
791f917f69SDimitry Andric             "which will be created if needed. "
801f917f69SDimitry Andric             "This directory will contain a trace bundle, with all the "
811f917f69SDimitry Andric             "necessary files the reconstruct the trace session even on a "
821f917f69SDimitry Andric             "different computer. "
831f917f69SDimitry Andric             "Part of this bundle is the bundle description file with the name "
841f917f69SDimitry Andric             "trace.json. This file can be used by the \"trace load\" command "
851f917f69SDimitry Andric             "to load this trace in LLDB."
861f917f69SDimitry Andric             "Note: if the current target contains information of multiple "
871f917f69SDimitry Andric             "processes or targets, they all will be included in the bundle.",
881f917f69SDimitry Andric             "trace save [<cmd-options>] <bundle_directory>",
891f917f69SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
901f917f69SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
911f917f69SDimitry Andric                 eCommandProcessMustBeTraced) {
92ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeDirectoryName);
931f917f69SDimitry Andric   }
941f917f69SDimitry Andric 
951f917f69SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)961f917f69SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
971f917f69SDimitry Andric                            OptionElementVector &opt_element_vector) override {
987fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
997fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1001f917f69SDimitry Andric   }
1011f917f69SDimitry Andric 
1021f917f69SDimitry Andric   ~CommandObjectTraceSave() override = default;
1031f917f69SDimitry Andric 
1041f917f69SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)105b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1061f917f69SDimitry Andric     if (command.size() != 1) {
1071f917f69SDimitry Andric       result.AppendError("a single path to a directory where the trace bundle "
1081f917f69SDimitry Andric                          "will be created is required");
109b1c73532SDimitry Andric       return;
1101f917f69SDimitry Andric     }
1111f917f69SDimitry Andric 
1121f917f69SDimitry Andric     FileSpec bundle_dir(command[0].ref());
1131f917f69SDimitry Andric     FileSystem::Instance().Resolve(bundle_dir);
1141f917f69SDimitry Andric 
1151f917f69SDimitry Andric     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1161f917f69SDimitry Andric 
1171f917f69SDimitry Andric     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1181f917f69SDimitry Andric 
1191f917f69SDimitry Andric     if (llvm::Expected<FileSpec> desc_file =
1201f917f69SDimitry Andric             trace_sp->SaveToDisk(bundle_dir, m_options.m_compact)) {
1211f917f69SDimitry Andric       result.AppendMessageWithFormatv(
1221f917f69SDimitry Andric           "Trace bundle description file written to: {0}", *desc_file);
1231f917f69SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
1241f917f69SDimitry Andric     } else {
1251f917f69SDimitry Andric       result.AppendError(toString(desc_file.takeError()));
1261f917f69SDimitry Andric     }
1271f917f69SDimitry Andric   }
1281f917f69SDimitry Andric 
1291f917f69SDimitry Andric   CommandOptions m_options;
1301f917f69SDimitry Andric };
1311f917f69SDimitry Andric 
132b60736ecSDimitry Andric // CommandObjectTraceLoad
133b60736ecSDimitry Andric #define LLDB_OPTIONS_trace_load
134b60736ecSDimitry Andric #include "CommandOptions.inc"
135b60736ecSDimitry Andric 
136b60736ecSDimitry Andric #pragma mark CommandObjectTraceLoad
137b60736ecSDimitry Andric 
138b60736ecSDimitry Andric class CommandObjectTraceLoad : public CommandObjectParsed {
139b60736ecSDimitry Andric public:
140b60736ecSDimitry Andric   class CommandOptions : public Options {
141b60736ecSDimitry Andric   public:
CommandOptions()1426f8fc217SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
143b60736ecSDimitry Andric 
144b60736ecSDimitry Andric     ~CommandOptions() override = default;
145b60736ecSDimitry Andric 
SetOptionValue(uint32_t option_idx,StringRef option_arg,ExecutionContext * execution_context)146b60736ecSDimitry Andric     Status SetOptionValue(uint32_t option_idx, StringRef option_arg,
147b60736ecSDimitry Andric                           ExecutionContext *execution_context) override {
148b60736ecSDimitry Andric       Status error;
149b60736ecSDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
150b60736ecSDimitry Andric 
151b60736ecSDimitry Andric       switch (short_option) {
152b60736ecSDimitry Andric       case 'v': {
153b60736ecSDimitry Andric         m_verbose = true;
154b60736ecSDimitry Andric         break;
155b60736ecSDimitry Andric       }
156b60736ecSDimitry Andric       default:
157b60736ecSDimitry Andric         llvm_unreachable("Unimplemented option");
158b60736ecSDimitry Andric       }
159b60736ecSDimitry Andric       return error;
160b60736ecSDimitry Andric     }
161b60736ecSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)162b60736ecSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
163b60736ecSDimitry Andric       m_verbose = false;
164b60736ecSDimitry Andric     }
165b60736ecSDimitry Andric 
GetDefinitions()166b60736ecSDimitry Andric     ArrayRef<OptionDefinition> GetDefinitions() override {
167e3b55780SDimitry Andric       return ArrayRef(g_trace_load_options);
168b60736ecSDimitry Andric     }
169b60736ecSDimitry Andric 
170b60736ecSDimitry Andric     bool m_verbose; // Enable verbose logging for debugging purposes.
171b60736ecSDimitry Andric   };
172b60736ecSDimitry Andric 
CommandObjectTraceLoad(CommandInterpreter & interpreter)173b60736ecSDimitry Andric   CommandObjectTraceLoad(CommandInterpreter &interpreter)
174145449b1SDimitry Andric       : CommandObjectParsed(
175145449b1SDimitry Andric             interpreter, "trace load",
176145449b1SDimitry Andric             "Load a post-mortem processor trace session from a trace bundle.",
1771f917f69SDimitry Andric             "trace load <trace_description_file>") {
178ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeFilename);
179145449b1SDimitry Andric   }
180b60736ecSDimitry Andric 
1811f917f69SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1821f917f69SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1831f917f69SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1847fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1857fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1861f917f69SDimitry Andric   }
1871f917f69SDimitry Andric 
188b60736ecSDimitry Andric   ~CommandObjectTraceLoad() override = default;
189b60736ecSDimitry Andric 
GetOptions()190b60736ecSDimitry Andric   Options *GetOptions() override { return &m_options; }
191b60736ecSDimitry Andric 
192b60736ecSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)193b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
194b60736ecSDimitry Andric     if (command.size() != 1) {
195145449b1SDimitry Andric       result.AppendError("a single path to a JSON file containing a the "
196145449b1SDimitry Andric                          "description of the trace bundle is required");
197b1c73532SDimitry Andric       return;
198b60736ecSDimitry Andric     }
199b60736ecSDimitry Andric 
200145449b1SDimitry Andric     const FileSpec trace_description_file(command[0].ref());
201145449b1SDimitry Andric 
202145449b1SDimitry Andric     llvm::Expected<lldb::TraceSP> trace_or_err =
203145449b1SDimitry Andric         Trace::LoadPostMortemTraceFromFile(GetDebugger(),
204145449b1SDimitry Andric                                            trace_description_file);
205145449b1SDimitry Andric 
206145449b1SDimitry Andric     if (!trace_or_err) {
207145449b1SDimitry Andric       result.AppendErrorWithFormat(
208145449b1SDimitry Andric           "%s\n", llvm::toString(trace_or_err.takeError()).c_str());
209b1c73532SDimitry Andric       return;
210b60736ecSDimitry Andric     }
211b60736ecSDimitry Andric 
212145449b1SDimitry Andric     if (m_options.m_verbose) {
213c0981da4SDimitry Andric       result.AppendMessageWithFormatv("loading trace with plugin {0}\n",
214145449b1SDimitry Andric                                       trace_or_err.get()->GetPluginName());
215145449b1SDimitry Andric     }
216b60736ecSDimitry Andric 
217b60736ecSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
218b60736ecSDimitry Andric   }
219b60736ecSDimitry Andric 
220b60736ecSDimitry Andric   CommandOptions m_options;
221b60736ecSDimitry Andric };
222b60736ecSDimitry Andric 
223b60736ecSDimitry Andric // CommandObjectTraceDump
224b60736ecSDimitry Andric #define LLDB_OPTIONS_trace_dump
225b60736ecSDimitry Andric #include "CommandOptions.inc"
226b60736ecSDimitry Andric 
227b60736ecSDimitry Andric #pragma mark CommandObjectTraceDump
228b60736ecSDimitry Andric 
229b60736ecSDimitry Andric class CommandObjectTraceDump : public CommandObjectParsed {
230b60736ecSDimitry Andric public:
231b60736ecSDimitry Andric   class CommandOptions : public Options {
232b60736ecSDimitry Andric   public:
CommandOptions()2336f8fc217SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
234b60736ecSDimitry Andric 
235b60736ecSDimitry Andric     ~CommandOptions() override = default;
236b60736ecSDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)237b60736ecSDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
238b60736ecSDimitry Andric                           ExecutionContext *execution_context) override {
239b60736ecSDimitry Andric       Status error;
240b60736ecSDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
241b60736ecSDimitry Andric 
242b60736ecSDimitry Andric       switch (short_option) {
243b60736ecSDimitry Andric       case 'v': {
244b60736ecSDimitry Andric         m_verbose = true;
245b60736ecSDimitry Andric         break;
246b60736ecSDimitry Andric       }
247b60736ecSDimitry Andric       default:
248b60736ecSDimitry Andric         llvm_unreachable("Unimplemented option");
249b60736ecSDimitry Andric       }
250b60736ecSDimitry Andric       return error;
251b60736ecSDimitry Andric     }
252b60736ecSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)253b60736ecSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
254b60736ecSDimitry Andric       m_verbose = false;
255b60736ecSDimitry Andric     }
256b60736ecSDimitry Andric 
GetDefinitions()257b60736ecSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
258e3b55780SDimitry Andric       return llvm::ArrayRef(g_trace_dump_options);
259b60736ecSDimitry Andric     }
260b60736ecSDimitry Andric 
261b60736ecSDimitry Andric     bool m_verbose; // Enable verbose logging for debugging purposes.
262b60736ecSDimitry Andric   };
263b60736ecSDimitry Andric 
CommandObjectTraceDump(CommandInterpreter & interpreter)264b60736ecSDimitry Andric   CommandObjectTraceDump(CommandInterpreter &interpreter)
265b60736ecSDimitry Andric       : CommandObjectParsed(interpreter, "trace dump",
266b60736ecSDimitry Andric                             "Dump the loaded processor trace data.",
2676f8fc217SDimitry Andric                             "trace dump") {}
268b60736ecSDimitry Andric 
269b60736ecSDimitry Andric   ~CommandObjectTraceDump() override = default;
270b60736ecSDimitry Andric 
GetOptions()271b60736ecSDimitry Andric   Options *GetOptions() override { return &m_options; }
272b60736ecSDimitry Andric 
273b60736ecSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)274b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
275b60736ecSDimitry Andric     Status error;
276b60736ecSDimitry Andric     // TODO: fill in the dumping code here!
277b60736ecSDimitry Andric     if (error.Success()) {
278b60736ecSDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
279b60736ecSDimitry Andric     } else {
280b60736ecSDimitry Andric       result.AppendErrorWithFormat("%s\n", error.AsCString());
281b60736ecSDimitry Andric     }
282b60736ecSDimitry Andric   }
283b60736ecSDimitry Andric 
284b60736ecSDimitry Andric   CommandOptions m_options;
285b60736ecSDimitry Andric };
286b60736ecSDimitry Andric 
287b60736ecSDimitry Andric // CommandObjectTraceSchema
288b60736ecSDimitry Andric #define LLDB_OPTIONS_trace_schema
289b60736ecSDimitry Andric #include "CommandOptions.inc"
290b60736ecSDimitry Andric 
291b60736ecSDimitry Andric #pragma mark CommandObjectTraceSchema
292b60736ecSDimitry Andric 
293b60736ecSDimitry Andric class CommandObjectTraceSchema : public CommandObjectParsed {
294b60736ecSDimitry Andric public:
295b60736ecSDimitry Andric   class CommandOptions : public Options {
296b60736ecSDimitry Andric   public:
CommandOptions()2976f8fc217SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
298b60736ecSDimitry Andric 
299b60736ecSDimitry Andric     ~CommandOptions() override = default;
300b60736ecSDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)301b60736ecSDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
302b60736ecSDimitry Andric                           ExecutionContext *execution_context) override {
303b60736ecSDimitry Andric       Status error;
304b60736ecSDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
305b60736ecSDimitry Andric 
306b60736ecSDimitry Andric       switch (short_option) {
307b60736ecSDimitry Andric       case 'v': {
308b60736ecSDimitry Andric         m_verbose = true;
309b60736ecSDimitry Andric         break;
310b60736ecSDimitry Andric       }
311b60736ecSDimitry Andric       default:
312b60736ecSDimitry Andric         llvm_unreachable("Unimplemented option");
313b60736ecSDimitry Andric       }
314b60736ecSDimitry Andric       return error;
315b60736ecSDimitry Andric     }
316b60736ecSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)317b60736ecSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
318b60736ecSDimitry Andric       m_verbose = false;
319b60736ecSDimitry Andric     }
320b60736ecSDimitry Andric 
GetDefinitions()321b60736ecSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
322e3b55780SDimitry Andric       return llvm::ArrayRef(g_trace_schema_options);
323b60736ecSDimitry Andric     }
324b60736ecSDimitry Andric 
325b60736ecSDimitry Andric     bool m_verbose; // Enable verbose logging for debugging purposes.
326b60736ecSDimitry Andric   };
327b60736ecSDimitry Andric 
CommandObjectTraceSchema(CommandInterpreter & interpreter)328b60736ecSDimitry Andric   CommandObjectTraceSchema(CommandInterpreter &interpreter)
329b60736ecSDimitry Andric       : CommandObjectParsed(interpreter, "trace schema",
330b60736ecSDimitry Andric                             "Show the schema of the given trace plugin.",
331b60736ecSDimitry Andric                             "trace schema <plug-in>. Use the plug-in name "
332145449b1SDimitry Andric                             "\"all\" to see all schemas.\n") {
333ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeNone);
334145449b1SDimitry Andric   }
335b60736ecSDimitry Andric 
336b60736ecSDimitry Andric   ~CommandObjectTraceSchema() override = default;
337b60736ecSDimitry Andric 
GetOptions()338b60736ecSDimitry Andric   Options *GetOptions() override { return &m_options; }
339b60736ecSDimitry Andric 
340b60736ecSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)341b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
342b60736ecSDimitry Andric     Status error;
343b60736ecSDimitry Andric     if (command.empty()) {
344344a3780SDimitry Andric       result.AppendError(
345b60736ecSDimitry Andric           "trace schema cannot be invoked without a plug-in as argument");
346b1c73532SDimitry Andric       return;
347b60736ecSDimitry Andric     }
348b60736ecSDimitry Andric 
349b60736ecSDimitry Andric     StringRef plugin_name(command[0].c_str());
350b60736ecSDimitry Andric     if (plugin_name == "all") {
351b60736ecSDimitry Andric       size_t index = 0;
352b60736ecSDimitry Andric       while (true) {
353b60736ecSDimitry Andric         StringRef schema = PluginManager::GetTraceSchema(index++);
354b60736ecSDimitry Andric         if (schema.empty())
355b60736ecSDimitry Andric           break;
356b60736ecSDimitry Andric 
357b60736ecSDimitry Andric         result.AppendMessage(schema);
358b60736ecSDimitry Andric       }
359b60736ecSDimitry Andric     } else {
360b60736ecSDimitry Andric       if (Expected<StringRef> schemaOrErr =
361b60736ecSDimitry Andric               Trace::FindPluginSchema(plugin_name))
362b60736ecSDimitry Andric         result.AppendMessage(*schemaOrErr);
363b60736ecSDimitry Andric       else
364b60736ecSDimitry Andric         error = schemaOrErr.takeError();
365b60736ecSDimitry Andric     }
366b60736ecSDimitry Andric 
367b60736ecSDimitry Andric     if (error.Success()) {
368b60736ecSDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
369b60736ecSDimitry Andric     } else {
370b60736ecSDimitry Andric       result.AppendErrorWithFormat("%s\n", error.AsCString());
371b60736ecSDimitry Andric     }
372b60736ecSDimitry Andric   }
373b60736ecSDimitry Andric 
374b60736ecSDimitry Andric   CommandOptions m_options;
375b60736ecSDimitry Andric };
376b60736ecSDimitry Andric 
377b60736ecSDimitry Andric // CommandObjectTrace
378b60736ecSDimitry Andric 
CommandObjectTrace(CommandInterpreter & interpreter)379b60736ecSDimitry Andric CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter)
380b60736ecSDimitry Andric     : CommandObjectMultiword(interpreter, "trace",
381b60736ecSDimitry Andric                              "Commands for loading and using processor "
382b60736ecSDimitry Andric                              "trace information.",
383b60736ecSDimitry Andric                              "trace [<sub-command-options>]") {
384b60736ecSDimitry Andric   LoadSubCommand("load",
385b60736ecSDimitry Andric                  CommandObjectSP(new CommandObjectTraceLoad(interpreter)));
386b60736ecSDimitry Andric   LoadSubCommand("dump",
387b60736ecSDimitry Andric                  CommandObjectSP(new CommandObjectTraceDump(interpreter)));
3881f917f69SDimitry Andric   LoadSubCommand("save",
3891f917f69SDimitry Andric                  CommandObjectSP(new CommandObjectTraceSave(interpreter)));
390b60736ecSDimitry Andric   LoadSubCommand("schema",
391b60736ecSDimitry Andric                  CommandObjectSP(new CommandObjectTraceSchema(interpreter)));
392b60736ecSDimitry Andric }
393b60736ecSDimitry Andric 
394b60736ecSDimitry Andric CommandObjectTrace::~CommandObjectTrace() = default;
395344a3780SDimitry Andric 
DoGetProxyCommandObject()396344a3780SDimitry Andric Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() {
397344a3780SDimitry Andric   ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP();
398344a3780SDimitry Andric 
399344a3780SDimitry Andric   if (!process_sp)
400344a3780SDimitry Andric     return createStringError(inconvertibleErrorCode(),
401344a3780SDimitry Andric                              "Process not available.");
402344a3780SDimitry Andric   if (m_live_debug_session_only && !process_sp->IsLiveDebugSession())
403344a3780SDimitry Andric     return createStringError(inconvertibleErrorCode(),
404344a3780SDimitry Andric                              "Process must be alive.");
405344a3780SDimitry Andric 
406344a3780SDimitry Andric   if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate())
407344a3780SDimitry Andric     return GetDelegateCommand(**trace_sp);
408344a3780SDimitry Andric   else
409344a3780SDimitry Andric     return createStringError(inconvertibleErrorCode(),
410344a3780SDimitry Andric                              "Tracing is not supported. %s",
411344a3780SDimitry Andric                              toString(trace_sp.takeError()).c_str());
412344a3780SDimitry Andric }
413344a3780SDimitry Andric 
GetProxyCommandObject()414344a3780SDimitry Andric CommandObject *CommandObjectTraceProxy::GetProxyCommandObject() {
415344a3780SDimitry Andric   if (Expected<CommandObjectSP> delegate = DoGetProxyCommandObject()) {
416344a3780SDimitry Andric     m_delegate_sp = *delegate;
417344a3780SDimitry Andric     m_delegate_error.clear();
418344a3780SDimitry Andric     return m_delegate_sp.get();
419344a3780SDimitry Andric   } else {
420344a3780SDimitry Andric     m_delegate_sp.reset();
421344a3780SDimitry Andric     m_delegate_error = toString(delegate.takeError());
422344a3780SDimitry Andric     return nullptr;
423344a3780SDimitry Andric   }
424344a3780SDimitry Andric }
425