15ffd83dbSDimitry Andric //===-- CommandObjectLog.cpp ----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "CommandObjectLog.h"
100b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
110b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
120b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
130b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
140b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
150b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
160b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
170b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
180b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace lldb;
220b57cec5SDimitry Andric using namespace lldb_private;
230b57cec5SDimitry Andric 
249dba64beSDimitry Andric #define LLDB_OPTIONS_log
259dba64beSDimitry Andric #include "CommandOptions.inc"
269dba64beSDimitry Andric 
279dba64beSDimitry Andric /// Common completion logic for log enable/disable.
CompleteEnableDisable(CompletionRequest & request)289dba64beSDimitry Andric static void CompleteEnableDisable(CompletionRequest &request) {
299dba64beSDimitry Andric   size_t arg_index = request.GetCursorIndex();
309dba64beSDimitry Andric   if (arg_index == 0) { // We got: log enable/disable x[tab]
319dba64beSDimitry Andric     for (llvm::StringRef channel : Log::ListChannels())
329dba64beSDimitry Andric       request.TryCompleteCurrentArg(channel);
339dba64beSDimitry Andric   } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
349dba64beSDimitry Andric     llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
359dba64beSDimitry Andric     Log::ForEachChannelCategory(
369dba64beSDimitry Andric         channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
379dba64beSDimitry Andric           request.TryCompleteCurrentArg(name, desc);
389dba64beSDimitry Andric         });
399dba64beSDimitry Andric   }
409dba64beSDimitry Andric }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric class CommandObjectLogEnable : public CommandObjectParsed {
430b57cec5SDimitry Andric public:
440b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectLogEnable(CommandInterpreter & interpreter)450b57cec5SDimitry Andric   CommandObjectLogEnable(CommandInterpreter &interpreter)
460b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "log enable",
470b57cec5SDimitry Andric                             "Enable logging for a single log channel.",
480b57cec5SDimitry Andric                             nullptr),
490b57cec5SDimitry Andric         m_options() {
500b57cec5SDimitry Andric     CommandArgumentEntry arg1;
510b57cec5SDimitry Andric     CommandArgumentEntry arg2;
520b57cec5SDimitry Andric     CommandArgumentData channel_arg;
530b57cec5SDimitry Andric     CommandArgumentData category_arg;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
560b57cec5SDimitry Andric     channel_arg.arg_type = eArgTypeLogChannel;
570b57cec5SDimitry Andric     channel_arg.arg_repetition = eArgRepeatPlain;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
600b57cec5SDimitry Andric     // argument entry.
610b57cec5SDimitry Andric     arg1.push_back(channel_arg);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric     category_arg.arg_type = eArgTypeLogCategory;
640b57cec5SDimitry Andric     category_arg.arg_repetition = eArgRepeatPlus;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     arg2.push_back(category_arg);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
690b57cec5SDimitry Andric     m_arguments.push_back(arg1);
700b57cec5SDimitry Andric     m_arguments.push_back(arg2);
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   ~CommandObjectLogEnable() override = default;
740b57cec5SDimitry Andric 
GetOptions()750b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   class CommandOptions : public Options {
780b57cec5SDimitry Andric   public:
CommandOptions()79*5f7ddb14SDimitry Andric     CommandOptions() : Options(), log_file() {}
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     ~CommandOptions() override = default;
820b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)830b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
840b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
850b57cec5SDimitry Andric       Status error;
860b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric       switch (short_option) {
890b57cec5SDimitry Andric       case 'f':
900b57cec5SDimitry Andric         log_file.SetFile(option_arg, FileSpec::Style::native);
910b57cec5SDimitry Andric         FileSystem::Instance().Resolve(log_file);
920b57cec5SDimitry Andric         break;
930b57cec5SDimitry Andric       case 't':
940b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_THREADSAFE;
950b57cec5SDimitry Andric         break;
960b57cec5SDimitry Andric       case 'v':
970b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_VERBOSE;
980b57cec5SDimitry Andric         break;
990b57cec5SDimitry Andric       case 's':
1000b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
1010b57cec5SDimitry Andric         break;
1020b57cec5SDimitry Andric       case 'T':
1030b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
1040b57cec5SDimitry Andric         break;
1050b57cec5SDimitry Andric       case 'p':
1060b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
1070b57cec5SDimitry Andric         break;
1080b57cec5SDimitry Andric       case 'n':
1090b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1100b57cec5SDimitry Andric         break;
1110b57cec5SDimitry Andric       case 'S':
1120b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_BACKTRACE;
1130b57cec5SDimitry Andric         break;
1140b57cec5SDimitry Andric       case 'a':
1150b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_APPEND;
1160b57cec5SDimitry Andric         break;
1170b57cec5SDimitry Andric       case 'F':
1180b57cec5SDimitry Andric         log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
1190b57cec5SDimitry Andric         break;
1200b57cec5SDimitry Andric       default:
1219dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
1220b57cec5SDimitry Andric       }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric       return error;
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1270b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1280b57cec5SDimitry Andric       log_file.Clear();
1290b57cec5SDimitry Andric       log_options = 0;
1300b57cec5SDimitry Andric     }
1310b57cec5SDimitry Andric 
GetDefinitions()1320b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1330b57cec5SDimitry Andric       return llvm::makeArrayRef(g_log_options);
1340b57cec5SDimitry Andric     }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     FileSpec log_file;
139*5f7ddb14SDimitry Andric     uint32_t log_options = 0;
1400b57cec5SDimitry Andric   };
1410b57cec5SDimitry Andric 
1429dba64beSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1439dba64beSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1449dba64beSDimitry Andric                            OptionElementVector &opt_element_vector) override {
1459dba64beSDimitry Andric     CompleteEnableDisable(request);
1469dba64beSDimitry Andric   }
1479dba64beSDimitry Andric 
1480b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1490b57cec5SDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
1500b57cec5SDimitry Andric     if (args.GetArgumentCount() < 2) {
1510b57cec5SDimitry Andric       result.AppendErrorWithFormat(
1520b57cec5SDimitry Andric           "%s takes a log channel and one or more log types.\n",
1530b57cec5SDimitry Andric           m_cmd_name.c_str());
1540b57cec5SDimitry Andric       return false;
1550b57cec5SDimitry Andric     }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric     // Store into a std::string since we're about to shift the channel off.
1585ffd83dbSDimitry Andric     const std::string channel = std::string(args[0].ref());
1590b57cec5SDimitry Andric     args.Shift(); // Shift off the channel
1600b57cec5SDimitry Andric     char log_file[PATH_MAX];
1610b57cec5SDimitry Andric     if (m_options.log_file)
1620b57cec5SDimitry Andric       m_options.log_file.GetPath(log_file, sizeof(log_file));
1630b57cec5SDimitry Andric     else
1640b57cec5SDimitry Andric       log_file[0] = '\0';
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     std::string error;
1670b57cec5SDimitry Andric     llvm::raw_string_ostream error_stream(error);
1680b57cec5SDimitry Andric     bool success =
1690b57cec5SDimitry Andric         GetDebugger().EnableLog(channel, args.GetArgumentArrayRef(), log_file,
1700b57cec5SDimitry Andric                                 m_options.log_options, error_stream);
1710b57cec5SDimitry Andric     result.GetErrorStream() << error_stream.str();
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     if (success)
1740b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1750b57cec5SDimitry Andric     else
1760b57cec5SDimitry Andric       result.SetStatus(eReturnStatusFailed);
1770b57cec5SDimitry Andric     return result.Succeeded();
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   CommandOptions m_options;
1810b57cec5SDimitry Andric };
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric class CommandObjectLogDisable : public CommandObjectParsed {
1840b57cec5SDimitry Andric public:
1850b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectLogDisable(CommandInterpreter & interpreter)1860b57cec5SDimitry Andric   CommandObjectLogDisable(CommandInterpreter &interpreter)
1870b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "log disable",
1880b57cec5SDimitry Andric                             "Disable one or more log channel categories.",
1890b57cec5SDimitry Andric                             nullptr) {
1900b57cec5SDimitry Andric     CommandArgumentEntry arg1;
1910b57cec5SDimitry Andric     CommandArgumentEntry arg2;
1920b57cec5SDimitry Andric     CommandArgumentData channel_arg;
1930b57cec5SDimitry Andric     CommandArgumentData category_arg;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
1960b57cec5SDimitry Andric     channel_arg.arg_type = eArgTypeLogChannel;
1970b57cec5SDimitry Andric     channel_arg.arg_repetition = eArgRepeatPlain;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
2000b57cec5SDimitry Andric     // argument entry.
2010b57cec5SDimitry Andric     arg1.push_back(channel_arg);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     category_arg.arg_type = eArgTypeLogCategory;
2040b57cec5SDimitry Andric     category_arg.arg_repetition = eArgRepeatPlus;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     arg2.push_back(category_arg);
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
2090b57cec5SDimitry Andric     m_arguments.push_back(arg1);
2100b57cec5SDimitry Andric     m_arguments.push_back(arg2);
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   ~CommandObjectLogDisable() override = default;
2140b57cec5SDimitry Andric 
2159dba64beSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2169dba64beSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
2179dba64beSDimitry Andric                            OptionElementVector &opt_element_vector) override {
2189dba64beSDimitry Andric     CompleteEnableDisable(request);
2199dba64beSDimitry Andric   }
2209dba64beSDimitry Andric 
2210b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)2220b57cec5SDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
2230b57cec5SDimitry Andric     if (args.empty()) {
2240b57cec5SDimitry Andric       result.AppendErrorWithFormat(
2250b57cec5SDimitry Andric           "%s takes a log channel and one or more log types.\n",
2260b57cec5SDimitry Andric           m_cmd_name.c_str());
2270b57cec5SDimitry Andric       return false;
2280b57cec5SDimitry Andric     }
2290b57cec5SDimitry Andric 
2305ffd83dbSDimitry Andric     const std::string channel = std::string(args[0].ref());
2310b57cec5SDimitry Andric     args.Shift(); // Shift off the channel
2320b57cec5SDimitry Andric     if (channel == "all") {
2330b57cec5SDimitry Andric       Log::DisableAllLogChannels();
2340b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2350b57cec5SDimitry Andric     } else {
2360b57cec5SDimitry Andric       std::string error;
2370b57cec5SDimitry Andric       llvm::raw_string_ostream error_stream(error);
2380b57cec5SDimitry Andric       if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
2390b57cec5SDimitry Andric                                  error_stream))
2400b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
2410b57cec5SDimitry Andric       result.GetErrorStream() << error_stream.str();
2420b57cec5SDimitry Andric     }
2430b57cec5SDimitry Andric     return result.Succeeded();
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric };
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric class CommandObjectLogList : public CommandObjectParsed {
2480b57cec5SDimitry Andric public:
2490b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectLogList(CommandInterpreter & interpreter)2500b57cec5SDimitry Andric   CommandObjectLogList(CommandInterpreter &interpreter)
2510b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "log list",
2520b57cec5SDimitry Andric                             "List the log categories for one or more log "
2530b57cec5SDimitry Andric                             "channels.  If none specified, lists them all.",
2540b57cec5SDimitry Andric                             nullptr) {
2550b57cec5SDimitry Andric     CommandArgumentEntry arg;
2560b57cec5SDimitry Andric     CommandArgumentData channel_arg;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
2590b57cec5SDimitry Andric     channel_arg.arg_type = eArgTypeLogChannel;
2600b57cec5SDimitry Andric     channel_arg.arg_repetition = eArgRepeatStar;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
2630b57cec5SDimitry Andric     // argument entry.
2640b57cec5SDimitry Andric     arg.push_back(channel_arg);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
2670b57cec5SDimitry Andric     m_arguments.push_back(arg);
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   ~CommandObjectLogList() override = default;
2710b57cec5SDimitry Andric 
2729dba64beSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2739dba64beSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
2749dba64beSDimitry Andric                            OptionElementVector &opt_element_vector) override {
2759dba64beSDimitry Andric     for (llvm::StringRef channel : Log::ListChannels())
2769dba64beSDimitry Andric       request.TryCompleteCurrentArg(channel);
2779dba64beSDimitry Andric   }
2789dba64beSDimitry Andric 
2790b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)2800b57cec5SDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
2810b57cec5SDimitry Andric     std::string output;
2820b57cec5SDimitry Andric     llvm::raw_string_ostream output_stream(output);
2830b57cec5SDimitry Andric     if (args.empty()) {
2840b57cec5SDimitry Andric       Log::ListAllLogChannels(output_stream);
2850b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2860b57cec5SDimitry Andric     } else {
2870b57cec5SDimitry Andric       bool success = true;
2880b57cec5SDimitry Andric       for (const auto &entry : args.entries())
2890b57cec5SDimitry Andric         success =
2909dba64beSDimitry Andric             success && Log::ListChannelCategories(entry.ref(), output_stream);
2910b57cec5SDimitry Andric       if (success)
2920b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
2930b57cec5SDimitry Andric     }
2940b57cec5SDimitry Andric     result.GetOutputStream() << output_stream.str();
2950b57cec5SDimitry Andric     return result.Succeeded();
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric };
2980b57cec5SDimitry Andric 
2995ffd83dbSDimitry Andric class CommandObjectLogTimerEnable : public CommandObjectParsed {
3000b57cec5SDimitry Andric public:
3010b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectLogTimerEnable(CommandInterpreter & interpreter)3025ffd83dbSDimitry Andric   CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
3035ffd83dbSDimitry Andric       : CommandObjectParsed(interpreter, "log timers enable",
3045ffd83dbSDimitry Andric                             "enable LLDB internal performance timers",
3055ffd83dbSDimitry Andric                             "log timers enable <depth>") {
3065ffd83dbSDimitry Andric     CommandArgumentEntry arg;
3075ffd83dbSDimitry Andric     CommandArgumentData depth_arg;
3080b57cec5SDimitry Andric 
3095ffd83dbSDimitry Andric     // Define the first (and only) variant of this arg.
3105ffd83dbSDimitry Andric     depth_arg.arg_type = eArgTypeCount;
3115ffd83dbSDimitry Andric     depth_arg.arg_repetition = eArgRepeatOptional;
3125ffd83dbSDimitry Andric 
3135ffd83dbSDimitry Andric     // There is only one variant this argument could be; put it into the
3145ffd83dbSDimitry Andric     // argument entry.
3155ffd83dbSDimitry Andric     arg.push_back(depth_arg);
3165ffd83dbSDimitry Andric 
3175ffd83dbSDimitry Andric     // Push the data for the first argument into the m_arguments vector.
3185ffd83dbSDimitry Andric     m_arguments.push_back(arg);
3195ffd83dbSDimitry Andric   }
3205ffd83dbSDimitry Andric 
3215ffd83dbSDimitry Andric   ~CommandObjectLogTimerEnable() override = default;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)3240b57cec5SDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
3250b57cec5SDimitry Andric     result.SetStatus(eReturnStatusFailed);
3260b57cec5SDimitry Andric 
3275ffd83dbSDimitry Andric     if (args.GetArgumentCount() == 0) {
3280b57cec5SDimitry Andric       Timer::SetDisplayDepth(UINT32_MAX);
3290b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
3305ffd83dbSDimitry Andric     } else if (args.GetArgumentCount() == 1) {
3310b57cec5SDimitry Andric       uint32_t depth;
3325ffd83dbSDimitry Andric       if (args[0].ref().consumeInteger(0, depth)) {
3330b57cec5SDimitry Andric         result.AppendError(
3340b57cec5SDimitry Andric             "Could not convert enable depth to an unsigned integer.");
3350b57cec5SDimitry Andric       } else {
3360b57cec5SDimitry Andric         Timer::SetDisplayDepth(depth);
3370b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
3380b57cec5SDimitry Andric       }
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     if (!result.Succeeded()) {
3420b57cec5SDimitry Andric       result.AppendError("Missing subcommand");
3430b57cec5SDimitry Andric       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3440b57cec5SDimitry Andric     }
3450b57cec5SDimitry Andric     return result.Succeeded();
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric };
3480b57cec5SDimitry Andric 
3495ffd83dbSDimitry Andric class CommandObjectLogTimerDisable : public CommandObjectParsed {
3505ffd83dbSDimitry Andric public:
3515ffd83dbSDimitry Andric   // Constructors and Destructors
CommandObjectLogTimerDisable(CommandInterpreter & interpreter)3525ffd83dbSDimitry Andric   CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
3535ffd83dbSDimitry Andric       : CommandObjectParsed(interpreter, "log timers disable",
3545ffd83dbSDimitry Andric                             "disable LLDB internal performance timers",
3555ffd83dbSDimitry Andric                             nullptr) {}
3565ffd83dbSDimitry Andric 
3575ffd83dbSDimitry Andric   ~CommandObjectLogTimerDisable() override = default;
3585ffd83dbSDimitry Andric 
3595ffd83dbSDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)3605ffd83dbSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
3615ffd83dbSDimitry Andric     Timer::DumpCategoryTimes(&result.GetOutputStream());
3625ffd83dbSDimitry Andric     Timer::SetDisplayDepth(0);
3635ffd83dbSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
3645ffd83dbSDimitry Andric 
3655ffd83dbSDimitry Andric     if (!result.Succeeded()) {
3665ffd83dbSDimitry Andric       result.AppendError("Missing subcommand");
3675ffd83dbSDimitry Andric       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3685ffd83dbSDimitry Andric     }
3695ffd83dbSDimitry Andric     return result.Succeeded();
3705ffd83dbSDimitry Andric   }
3715ffd83dbSDimitry Andric };
3725ffd83dbSDimitry Andric 
3735ffd83dbSDimitry Andric class CommandObjectLogTimerDump : public CommandObjectParsed {
3745ffd83dbSDimitry Andric public:
3755ffd83dbSDimitry Andric   // Constructors and Destructors
CommandObjectLogTimerDump(CommandInterpreter & interpreter)3765ffd83dbSDimitry Andric   CommandObjectLogTimerDump(CommandInterpreter &interpreter)
3775ffd83dbSDimitry Andric       : CommandObjectParsed(interpreter, "log timers dump",
3785ffd83dbSDimitry Andric                             "dump LLDB internal performance timers", nullptr) {}
3795ffd83dbSDimitry Andric 
3805ffd83dbSDimitry Andric   ~CommandObjectLogTimerDump() override = default;
3815ffd83dbSDimitry Andric 
3825ffd83dbSDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)3835ffd83dbSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
3845ffd83dbSDimitry Andric     Timer::DumpCategoryTimes(&result.GetOutputStream());
3855ffd83dbSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
3865ffd83dbSDimitry Andric 
3875ffd83dbSDimitry Andric     if (!result.Succeeded()) {
3885ffd83dbSDimitry Andric       result.AppendError("Missing subcommand");
3895ffd83dbSDimitry Andric       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3905ffd83dbSDimitry Andric     }
3915ffd83dbSDimitry Andric     return result.Succeeded();
3925ffd83dbSDimitry Andric   }
3935ffd83dbSDimitry Andric };
3945ffd83dbSDimitry Andric 
3955ffd83dbSDimitry Andric class CommandObjectLogTimerReset : public CommandObjectParsed {
3965ffd83dbSDimitry Andric public:
3975ffd83dbSDimitry Andric   // Constructors and Destructors
CommandObjectLogTimerReset(CommandInterpreter & interpreter)3985ffd83dbSDimitry Andric   CommandObjectLogTimerReset(CommandInterpreter &interpreter)
3995ffd83dbSDimitry Andric       : CommandObjectParsed(interpreter, "log timers reset",
4005ffd83dbSDimitry Andric                             "reset LLDB internal performance timers", nullptr) {
4015ffd83dbSDimitry Andric   }
4025ffd83dbSDimitry Andric 
4035ffd83dbSDimitry Andric   ~CommandObjectLogTimerReset() override = default;
4045ffd83dbSDimitry Andric 
4055ffd83dbSDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)4065ffd83dbSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
4075ffd83dbSDimitry Andric     Timer::ResetCategoryTimes();
4085ffd83dbSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
4095ffd83dbSDimitry Andric 
4105ffd83dbSDimitry Andric     if (!result.Succeeded()) {
4115ffd83dbSDimitry Andric       result.AppendError("Missing subcommand");
4125ffd83dbSDimitry Andric       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4135ffd83dbSDimitry Andric     }
4145ffd83dbSDimitry Andric     return result.Succeeded();
4155ffd83dbSDimitry Andric   }
4165ffd83dbSDimitry Andric };
4175ffd83dbSDimitry Andric 
4185ffd83dbSDimitry Andric class CommandObjectLogTimerIncrement : public CommandObjectParsed {
4195ffd83dbSDimitry Andric public:
4205ffd83dbSDimitry Andric   // Constructors and Destructors
CommandObjectLogTimerIncrement(CommandInterpreter & interpreter)4215ffd83dbSDimitry Andric   CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
4225ffd83dbSDimitry Andric       : CommandObjectParsed(interpreter, "log timers increment",
4235ffd83dbSDimitry Andric                             "increment LLDB internal performance timers",
4245ffd83dbSDimitry Andric                             "log timers increment <bool>") {
4255ffd83dbSDimitry Andric     CommandArgumentEntry arg;
4265ffd83dbSDimitry Andric     CommandArgumentData bool_arg;
4275ffd83dbSDimitry Andric 
4285ffd83dbSDimitry Andric     // Define the first (and only) variant of this arg.
4295ffd83dbSDimitry Andric     bool_arg.arg_type = eArgTypeBoolean;
4305ffd83dbSDimitry Andric     bool_arg.arg_repetition = eArgRepeatPlain;
4315ffd83dbSDimitry Andric 
4325ffd83dbSDimitry Andric     // There is only one variant this argument could be; put it into the
4335ffd83dbSDimitry Andric     // argument entry.
4345ffd83dbSDimitry Andric     arg.push_back(bool_arg);
4355ffd83dbSDimitry Andric 
4365ffd83dbSDimitry Andric     // Push the data for the first argument into the m_arguments vector.
4375ffd83dbSDimitry Andric     m_arguments.push_back(arg);
4385ffd83dbSDimitry Andric   }
4395ffd83dbSDimitry Andric 
4405ffd83dbSDimitry Andric   ~CommandObjectLogTimerIncrement() override = default;
4415ffd83dbSDimitry Andric 
4425ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4435ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
4445ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
4455ffd83dbSDimitry Andric     request.TryCompleteCurrentArg("true");
4465ffd83dbSDimitry Andric     request.TryCompleteCurrentArg("false");
4475ffd83dbSDimitry Andric   }
4485ffd83dbSDimitry Andric 
4495ffd83dbSDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)4505ffd83dbSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
4515ffd83dbSDimitry Andric     result.SetStatus(eReturnStatusFailed);
4525ffd83dbSDimitry Andric 
4535ffd83dbSDimitry Andric     if (args.GetArgumentCount() == 1) {
4545ffd83dbSDimitry Andric       bool success;
4555ffd83dbSDimitry Andric       bool increment =
4565ffd83dbSDimitry Andric           OptionArgParser::ToBoolean(args[0].ref(), false, &success);
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric       if (success) {
4595ffd83dbSDimitry Andric         Timer::SetQuiet(!increment);
4605ffd83dbSDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4615ffd83dbSDimitry Andric       } else
4625ffd83dbSDimitry Andric         result.AppendError("Could not convert increment value to boolean.");
4635ffd83dbSDimitry Andric     }
4645ffd83dbSDimitry Andric 
4655ffd83dbSDimitry Andric     if (!result.Succeeded()) {
4665ffd83dbSDimitry Andric       result.AppendError("Missing subcommand");
4675ffd83dbSDimitry Andric       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4685ffd83dbSDimitry Andric     }
4695ffd83dbSDimitry Andric     return result.Succeeded();
4705ffd83dbSDimitry Andric   }
4715ffd83dbSDimitry Andric };
4725ffd83dbSDimitry Andric 
4735ffd83dbSDimitry Andric class CommandObjectLogTimer : public CommandObjectMultiword {
4745ffd83dbSDimitry Andric public:
CommandObjectLogTimer(CommandInterpreter & interpreter)4755ffd83dbSDimitry Andric   CommandObjectLogTimer(CommandInterpreter &interpreter)
4765ffd83dbSDimitry Andric       : CommandObjectMultiword(interpreter, "log timers",
4775ffd83dbSDimitry Andric                                "Enable, disable, dump, and reset LLDB internal "
4785ffd83dbSDimitry Andric                                "performance timers.",
4795ffd83dbSDimitry Andric                                "log timers < enable <depth> | disable | dump | "
4805ffd83dbSDimitry Andric                                "increment <bool> | reset >") {
4815ffd83dbSDimitry Andric     LoadSubCommand("enable", CommandObjectSP(
4825ffd83dbSDimitry Andric                                  new CommandObjectLogTimerEnable(interpreter)));
4835ffd83dbSDimitry Andric     LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
4845ffd83dbSDimitry Andric                                   interpreter)));
4855ffd83dbSDimitry Andric     LoadSubCommand("dump",
4865ffd83dbSDimitry Andric                    CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
4875ffd83dbSDimitry Andric     LoadSubCommand(
4885ffd83dbSDimitry Andric         "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
4895ffd83dbSDimitry Andric     LoadSubCommand(
4905ffd83dbSDimitry Andric         "increment",
4915ffd83dbSDimitry Andric         CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
4925ffd83dbSDimitry Andric   }
4935ffd83dbSDimitry Andric 
4945ffd83dbSDimitry Andric   ~CommandObjectLogTimer() override = default;
4955ffd83dbSDimitry Andric };
4965ffd83dbSDimitry Andric 
CommandObjectLog(CommandInterpreter & interpreter)4970b57cec5SDimitry Andric CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
4980b57cec5SDimitry Andric     : CommandObjectMultiword(interpreter, "log",
4990b57cec5SDimitry Andric                              "Commands controlling LLDB internal logging.",
5000b57cec5SDimitry Andric                              "log <subcommand> [<command-options>]") {
5010b57cec5SDimitry Andric   LoadSubCommand("enable",
5020b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
5030b57cec5SDimitry Andric   LoadSubCommand("disable",
5040b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
5050b57cec5SDimitry Andric   LoadSubCommand("list",
5060b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectLogList(interpreter)));
5070b57cec5SDimitry Andric   LoadSubCommand("timers",
5080b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric CommandObjectLog::~CommandObjectLog() = default;
512