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