LLDB  mainline
CommandObjectLog.cpp
Go to the documentation of this file.
1 //===-- CommandObjectLog.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 "CommandObjectLog.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Utility/Args.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Stream.h"
19 #include "lldb/Utility/Timer.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 #define LLDB_OPTIONS_log
25 #include "CommandOptions.inc"
26 
27 /// Common completion logic for log enable/disable.
29  size_t arg_index = request.GetCursorIndex();
30  if (arg_index == 0) { // We got: log enable/disable x[tab]
31  for (llvm::StringRef channel : Log::ListChannels())
32  request.TryCompleteCurrentArg(channel);
33  } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
34  llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
35  Log::ForEachChannelCategory(
36  channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
37  request.TryCompleteCurrentArg(name, desc);
38  });
39  }
40 }
41 
43 public:
44  // Constructors and Destructors
46  : CommandObjectParsed(interpreter, "log enable",
47  "Enable logging for a single log channel.",
48  nullptr),
49  m_options() {
52  CommandArgumentData channel_arg;
53  CommandArgumentData category_arg;
54 
55  // Define the first (and only) variant of this arg.
56  channel_arg.arg_type = eArgTypeLogChannel;
57  channel_arg.arg_repetition = eArgRepeatPlain;
58 
59  // There is only one variant this argument could be; put it into the
60  // argument entry.
61  arg1.push_back(channel_arg);
62 
63  category_arg.arg_type = eArgTypeLogCategory;
64  category_arg.arg_repetition = eArgRepeatPlus;
65 
66  arg2.push_back(category_arg);
67 
68  // Push the data for the first argument into the m_arguments vector.
69  m_arguments.push_back(arg1);
70  m_arguments.push_back(arg2);
71  }
72 
73  ~CommandObjectLogEnable() override = default;
74 
75  Options *GetOptions() override { return &m_options; }
76 
77  class CommandOptions : public Options {
78  public:
79  CommandOptions() : Options(), log_file(), log_options(0) {}
80 
81  ~CommandOptions() override = default;
82 
83  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
84  ExecutionContext *execution_context) override {
85  Status error;
86  const int short_option = m_getopt_table[option_idx].val;
87 
88  switch (short_option) {
89  case 'f':
90  log_file.SetFile(option_arg, FileSpec::Style::native);
91  FileSystem::Instance().Resolve(log_file);
92  break;
93  case 't':
94  log_options |= LLDB_LOG_OPTION_THREADSAFE;
95  break;
96  case 'v':
97  log_options |= LLDB_LOG_OPTION_VERBOSE;
98  break;
99  case 's':
100  log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
101  break;
102  case 'T':
103  log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
104  break;
105  case 'p':
107  break;
108  case 'n':
110  break;
111  case 'S':
112  log_options |= LLDB_LOG_OPTION_BACKTRACE;
113  break;
114  case 'a':
115  log_options |= LLDB_LOG_OPTION_APPEND;
116  break;
117  case 'F':
119  break;
120  default:
121  llvm_unreachable("Unimplemented option");
122  }
123 
124  return error;
125  }
126 
127  void OptionParsingStarting(ExecutionContext *execution_context) override {
128  log_file.Clear();
129  log_options = 0;
130  }
131 
132  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
133  return llvm::makeArrayRef(g_log_options);
134  }
135 
136  // Instance variables to hold the values for command options.
137 
140  };
141 
142  void
144  OptionElementVector &opt_element_vector) override {
145  CompleteEnableDisable(request);
146  }
147 
148 protected:
149  bool DoExecute(Args &args, CommandReturnObject &result) override {
150  if (args.GetArgumentCount() < 2) {
151  result.AppendErrorWithFormat(
152  "%s takes a log channel and one or more log types.\n",
153  m_cmd_name.c_str());
155  return false;
156  }
157 
158  // Store into a std::string since we're about to shift the channel off.
159  const std::string channel = std::string(args[0].ref());
160  args.Shift(); // Shift off the channel
161  char log_file[PATH_MAX];
162  if (m_options.log_file)
163  m_options.log_file.GetPath(log_file, sizeof(log_file));
164  else
165  log_file[0] = '\0';
166 
167  std::string error;
168  llvm::raw_string_ostream error_stream(error);
169  bool success =
170  GetDebugger().EnableLog(channel, args.GetArgumentArrayRef(), log_file,
171  m_options.log_options, error_stream);
172  result.GetErrorStream() << error_stream.str();
173 
174  if (success)
176  else
178  return result.Succeeded();
179  }
180 
182 };
183 
185 public:
186  // Constructors and Destructors
188  : CommandObjectParsed(interpreter, "log disable",
189  "Disable one or more log channel categories.",
190  nullptr) {
193  CommandArgumentData channel_arg;
194  CommandArgumentData category_arg;
195 
196  // Define the first (and only) variant of this arg.
197  channel_arg.arg_type = eArgTypeLogChannel;
198  channel_arg.arg_repetition = eArgRepeatPlain;
199 
200  // There is only one variant this argument could be; put it into the
201  // argument entry.
202  arg1.push_back(channel_arg);
203 
204  category_arg.arg_type = eArgTypeLogCategory;
205  category_arg.arg_repetition = eArgRepeatPlus;
206 
207  arg2.push_back(category_arg);
208 
209  // Push the data for the first argument into the m_arguments vector.
210  m_arguments.push_back(arg1);
211  m_arguments.push_back(arg2);
212  }
213 
214  ~CommandObjectLogDisable() override = default;
215 
216  void
218  OptionElementVector &opt_element_vector) override {
219  CompleteEnableDisable(request);
220  }
221 
222 protected:
223  bool DoExecute(Args &args, CommandReturnObject &result) override {
224  if (args.empty()) {
225  result.AppendErrorWithFormat(
226  "%s takes a log channel and one or more log types.\n",
227  m_cmd_name.c_str());
229  return false;
230  }
231 
232  const std::string channel = std::string(args[0].ref());
233  args.Shift(); // Shift off the channel
234  if (channel == "all") {
235  Log::DisableAllLogChannels();
237  } else {
238  std::string error;
239  llvm::raw_string_ostream error_stream(error);
240  if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
241  error_stream))
243  result.GetErrorStream() << error_stream.str();
244  }
245  return result.Succeeded();
246  }
247 };
248 
250 public:
251  // Constructors and Destructors
253  : CommandObjectParsed(interpreter, "log list",
254  "List the log categories for one or more log "
255  "channels. If none specified, lists them all.",
256  nullptr) {
258  CommandArgumentData channel_arg;
259 
260  // Define the first (and only) variant of this arg.
261  channel_arg.arg_type = eArgTypeLogChannel;
262  channel_arg.arg_repetition = eArgRepeatStar;
263 
264  // There is only one variant this argument could be; put it into the
265  // argument entry.
266  arg.push_back(channel_arg);
267 
268  // Push the data for the first argument into the m_arguments vector.
269  m_arguments.push_back(arg);
270  }
271 
272  ~CommandObjectLogList() override = default;
273 
274  void
276  OptionElementVector &opt_element_vector) override {
277  for (llvm::StringRef channel : Log::ListChannels())
278  request.TryCompleteCurrentArg(channel);
279  }
280 
281 protected:
282  bool DoExecute(Args &args, CommandReturnObject &result) override {
283  std::string output;
284  llvm::raw_string_ostream output_stream(output);
285  if (args.empty()) {
286  Log::ListAllLogChannels(output_stream);
288  } else {
289  bool success = true;
290  for (const auto &entry : args.entries())
291  success =
292  success && Log::ListChannelCategories(entry.ref(), output_stream);
293  if (success)
295  }
296  result.GetOutputStream() << output_stream.str();
297  return result.Succeeded();
298  }
299 };
300 
302 public:
303  // Constructors and Destructors
305  : CommandObjectParsed(interpreter, "log timers enable",
306  "enable LLDB internal performance timers",
307  "log timers enable <depth>") {
309  CommandArgumentData depth_arg;
310 
311  // Define the first (and only) variant of this arg.
312  depth_arg.arg_type = eArgTypeCount;
314 
315  // There is only one variant this argument could be; put it into the
316  // argument entry.
317  arg.push_back(depth_arg);
318 
319  // Push the data for the first argument into the m_arguments vector.
320  m_arguments.push_back(arg);
321  }
322 
323  ~CommandObjectLogTimerEnable() override = default;
324 
325 protected:
326  bool DoExecute(Args &args, CommandReturnObject &result) override {
328 
329  if (args.GetArgumentCount() == 0) {
330  Timer::SetDisplayDepth(UINT32_MAX);
332  } else if (args.GetArgumentCount() == 1) {
333  uint32_t depth;
334  if (args[0].ref().consumeInteger(0, depth)) {
335  result.AppendError(
336  "Could not convert enable depth to an unsigned integer.");
337  } else {
338  Timer::SetDisplayDepth(depth);
340  }
341  }
342 
343  if (!result.Succeeded()) {
344  result.AppendError("Missing subcommand");
345  result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
346  }
347  return result.Succeeded();
348  }
349 };
350 
352 public:
353  // Constructors and Destructors
355  : CommandObjectParsed(interpreter, "log timers disable",
356  "disable LLDB internal performance timers",
357  nullptr) {}
358 
359  ~CommandObjectLogTimerDisable() override = default;
360 
361 protected:
362  bool DoExecute(Args &args, CommandReturnObject &result) override {
363  Timer::DumpCategoryTimes(&result.GetOutputStream());
364  Timer::SetDisplayDepth(0);
366 
367  if (!result.Succeeded()) {
368  result.AppendError("Missing subcommand");
369  result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
370  }
371  return result.Succeeded();
372  }
373 };
374 
376 public:
377  // Constructors and Destructors
379  : CommandObjectParsed(interpreter, "log timers dump",
380  "dump LLDB internal performance timers", nullptr) {}
381 
382  ~CommandObjectLogTimerDump() override = default;
383 
384 protected:
385  bool DoExecute(Args &args, CommandReturnObject &result) override {
386  Timer::DumpCategoryTimes(&result.GetOutputStream());
388 
389  if (!result.Succeeded()) {
390  result.AppendError("Missing subcommand");
391  result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
392  }
393  return result.Succeeded();
394  }
395 };
396 
398 public:
399  // Constructors and Destructors
401  : CommandObjectParsed(interpreter, "log timers reset",
402  "reset LLDB internal performance timers", nullptr) {
403  }
404 
405  ~CommandObjectLogTimerReset() override = default;
406 
407 protected:
408  bool DoExecute(Args &args, CommandReturnObject &result) override {
409  Timer::ResetCategoryTimes();
411 
412  if (!result.Succeeded()) {
413  result.AppendError("Missing subcommand");
414  result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
415  }
416  return result.Succeeded();
417  }
418 };
419 
421 public:
422  // Constructors and Destructors
424  : CommandObjectParsed(interpreter, "log timers increment",
425  "increment LLDB internal performance timers",
426  "log timers increment <bool>") {
428  CommandArgumentData bool_arg;
429 
430  // Define the first (and only) variant of this arg.
431  bool_arg.arg_type = eArgTypeBoolean;
432  bool_arg.arg_repetition = eArgRepeatPlain;
433 
434  // There is only one variant this argument could be; put it into the
435  // argument entry.
436  arg.push_back(bool_arg);
437 
438  // Push the data for the first argument into the m_arguments vector.
439  m_arguments.push_back(arg);
440  }
441 
442  ~CommandObjectLogTimerIncrement() override = default;
443 
444  void
446  OptionElementVector &opt_element_vector) override {
447  request.TryCompleteCurrentArg("true");
448  request.TryCompleteCurrentArg("false");
449  }
450 
451 protected:
452  bool DoExecute(Args &args, CommandReturnObject &result) override {
454 
455  if (args.GetArgumentCount() == 1) {
456  bool success;
457  bool increment =
458  OptionArgParser::ToBoolean(args[0].ref(), false, &success);
459 
460  if (success) {
461  Timer::SetQuiet(!increment);
463  } else
464  result.AppendError("Could not convert increment value to boolean.");
465  }
466 
467  if (!result.Succeeded()) {
468  result.AppendError("Missing subcommand");
469  result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
470  }
471  return result.Succeeded();
472  }
473 };
474 
476 public:
478  : CommandObjectMultiword(interpreter, "log timers",
479  "Enable, disable, dump, and reset LLDB internal "
480  "performance timers.",
481  "log timers < enable <depth> | disable | dump | "
482  "increment <bool> | reset >") {
483  LoadSubCommand("enable", CommandObjectSP(
484  new CommandObjectLogTimerEnable(interpreter)));
485  LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
486  interpreter)));
487  LoadSubCommand("dump",
488  CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
489  LoadSubCommand(
490  "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
491  LoadSubCommand(
492  "increment",
493  CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
494  }
495 
496  ~CommandObjectLogTimer() override = default;
497 };
498 
499 CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
500  : CommandObjectMultiword(interpreter, "log",
501  "Commands controlling LLDB internal logging.",
502  "log <subcommand> [<command-options>]") {
503  LoadSubCommand("enable",
504  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
505  LoadSubCommand("disable",
506  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
507  LoadSubCommand("list",
508  CommandObjectSP(new CommandObjectLogList(interpreter)));
509  LoadSubCommand("timers",
510  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
511 }
512 
std::vector< CommandArgumentData > CommandArgumentEntry
A command line argument class.
Definition: Args.h:33
bool empty() const
Definition: Args.h:118
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
A class that represents a running process on the host machine.
void Shift()
Shifts the first argument C string value of the array off the argument array.
Definition: Args.cpp:278
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:128
static void CompleteEnableDisable(CompletionRequest &request)
Common completion logic for log enable/disable.
CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
bool DoExecute(Args &args, CommandReturnObject &result) override
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
bool DoExecute(Args &args, CommandReturnObject &result) override
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
void OptionParsingStarting(ExecutionContext *execution_context) override
A file utility class.
Definition: FileSpec.h:56
llvm::ArrayRef< const char * > GetArgumentArrayRef() const
Gets the argument as an ArrayRef.
Definition: Args.h:169
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
#define LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION
Definition: Log.h:44
#define LLDB_LOG_OPTION_APPEND
Definition: Log.h:43
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx. ...
Definition: Args.cpp:256
bool DoExecute(Args &args, CommandReturnObject &result) override
"lldb/Utility/ArgCompletionRequest.h"
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
#define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD
Definition: Log.h:40
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:41
CommandObjectLogList(CommandInterpreter &interpreter)
#define UINT32_MAX
Definition: lldb-defines.h:31
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectLogEnable(CommandInterpreter &interpreter)
#define LLDB_LOG_OPTION_PREPEND_THREAD_NAME
Definition: Log.h:41
CommandObjectLogTimerDump(CommandInterpreter &interpreter)
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectLogTimer(CommandInterpreter &interpreter)
#define LLDB_LOG_OPTION_VERBOSE
Definition: Log.h:37
#define LLDB_LOG_OPTION_PREPEND_TIMESTAMP
Definition: Log.h:39
A command line option parsing protocol class.
Definition: Options.h:62
void void AppendError(llvm::StringRef in_string)
bool DoExecute(Args &args, CommandReturnObject &result) override
Options * GetOptions() override
#define LLDB_LOG_OPTION_PREPEND_SEQUENCE
Definition: Log.h:38
Definition: SBAddress.h:15
#define LLDB_LOG_OPTION_THREADSAFE
Definition: Log.h:36
void TryCompleteCurrentArg(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string if the completion would complete the current argument.
CommandObjectLogTimerReset(CommandInterpreter &interpreter)
#define PATH_MAX
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
const Args & GetParsedLine() const
CommandObjectLogDisable(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
void SetStatus(lldb::ReturnStatus status)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
An error handling class.
Definition: Status.h:44
#define LLDB_LOG_OPTION_BACKTRACE
Definition: Log.h:42
bool DoExecute(Args &args, CommandReturnObject &result) override