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