180814287SRaphael Isemann //===-- CommandObjectLog.cpp ----------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 926cac3afSEugene Zelenko #include "CommandObjectLog.h" 1030fdc8d8SChris Lattner #include "lldb/Core/Debugger.h" 113eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 1230fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 1347cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 14b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 15145d95c9SPavel Labath #include "lldb/Utility/Args.h" 165713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 176f9e6901SZachary Turner #include "lldb/Utility/Log.h" 18bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 1938d0632eSPavel Labath #include "lldb/Utility/Timer.h" 2030fdc8d8SChris Lattner 2130fdc8d8SChris Lattner using namespace lldb; 2230fdc8d8SChris Lattner using namespace lldb_private; 2330fdc8d8SChris Lattner 24ec67e734SRaphael Isemann #define LLDB_OPTIONS_log 25ec67e734SRaphael Isemann #include "CommandOptions.inc" 261f0f5b5bSZachary Turner 276ba63d88SRaphael Isemann /// Common completion logic for log enable/disable. 286ba63d88SRaphael Isemann static void CompleteEnableDisable(CompletionRequest &request) { 296ba63d88SRaphael Isemann size_t arg_index = request.GetCursorIndex(); 306ba63d88SRaphael Isemann if (arg_index == 0) { // We got: log enable/disable x[tab] 316ba63d88SRaphael Isemann for (llvm::StringRef channel : Log::ListChannels()) 326ba63d88SRaphael Isemann request.TryCompleteCurrentArg(channel); 336ba63d88SRaphael Isemann } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab] 346ba63d88SRaphael Isemann llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0); 356ba63d88SRaphael Isemann Log::ForEachChannelCategory( 366ba63d88SRaphael Isemann channel, [&request](llvm::StringRef name, llvm::StringRef desc) { 376ba63d88SRaphael Isemann request.TryCompleteCurrentArg(name, desc); 386ba63d88SRaphael Isemann }); 396ba63d88SRaphael Isemann } 406ba63d88SRaphael Isemann } 416ba63d88SRaphael Isemann 42b9c1b51eSKate Stone class CommandObjectLogEnable : public CommandObjectParsed { 4330fdc8d8SChris Lattner public: 4430fdc8d8SChris Lattner // Constructors and Destructors 45b9c1b51eSKate Stone CommandObjectLogEnable(CommandInterpreter &interpreter) 46b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "log enable", 4730fdc8d8SChris Lattner "Enable logging for a single log channel.", 4826cac3afSEugene Zelenko nullptr), 49b9c1b51eSKate Stone m_options() { 50ceb6b139SCaroline Tice CommandArgumentEntry arg1; 51ceb6b139SCaroline Tice CommandArgumentEntry arg2; 52405fe67fSCaroline Tice CommandArgumentData channel_arg; 53ceb6b139SCaroline Tice CommandArgumentData category_arg; 54405fe67fSCaroline Tice 55405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 56405fe67fSCaroline Tice channel_arg.arg_type = eArgTypeLogChannel; 57405fe67fSCaroline Tice channel_arg.arg_repetition = eArgRepeatPlain; 58405fe67fSCaroline Tice 59b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 60b9c1b51eSKate Stone // argument entry. 61ceb6b139SCaroline Tice arg1.push_back(channel_arg); 62ceb6b139SCaroline Tice 63ceb6b139SCaroline Tice category_arg.arg_type = eArgTypeLogCategory; 64ceb6b139SCaroline Tice category_arg.arg_repetition = eArgRepeatPlus; 65ceb6b139SCaroline Tice 66ceb6b139SCaroline Tice arg2.push_back(category_arg); 67405fe67fSCaroline Tice 68405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 69ceb6b139SCaroline Tice m_arguments.push_back(arg1); 70ceb6b139SCaroline Tice m_arguments.push_back(arg2); 7130fdc8d8SChris Lattner } 7230fdc8d8SChris Lattner 7326cac3afSEugene Zelenko ~CommandObjectLogEnable() override = default; 7430fdc8d8SChris Lattner 75b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 7630fdc8d8SChris Lattner 77b9c1b51eSKate Stone class CommandOptions : public Options { 7830fdc8d8SChris Lattner public: 79b9c1b51eSKate Stone CommandOptions() : Options(), log_file(), log_options(0) {} 8030fdc8d8SChris Lattner 8126cac3afSEugene Zelenko ~CommandOptions() override = default; 8230fdc8d8SChris Lattner 8397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 84b9c1b51eSKate Stone ExecutionContext *execution_context) override { 8597206d57SZachary Turner Status error; 863bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 8730fdc8d8SChris Lattner 88b9c1b51eSKate Stone switch (short_option) { 89b9c1b51eSKate Stone case 'f': 908f3be7a3SJonas Devlieghere log_file.SetFile(option_arg, FileSpec::Style::native); 918f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(log_file); 92b9c1b51eSKate Stone break; 93b9c1b51eSKate Stone case 't': 94b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_THREADSAFE; 95b9c1b51eSKate Stone break; 96b9c1b51eSKate Stone case 'v': 97b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_VERBOSE; 98b9c1b51eSKate Stone break; 99b9c1b51eSKate Stone case 's': 100b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE; 101b9c1b51eSKate Stone break; 102b9c1b51eSKate Stone case 'T': 103b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP; 104b9c1b51eSKate Stone break; 105b9c1b51eSKate Stone case 'p': 106b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD; 107b9c1b51eSKate Stone break; 108b9c1b51eSKate Stone case 'n': 109b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 110b9c1b51eSKate Stone break; 111b9c1b51eSKate Stone case 'S': 112b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_BACKTRACE; 113b9c1b51eSKate Stone break; 114b9c1b51eSKate Stone case 'a': 115b9c1b51eSKate Stone log_options |= LLDB_LOG_OPTION_APPEND; 116b9c1b51eSKate Stone break; 117107d9bbdSPavel Labath case 'F': 118107d9bbdSPavel Labath log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION; 11990505a0aSPavel Labath break; 12030fdc8d8SChris Lattner default: 12136162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner return error; 12530fdc8d8SChris Lattner } 12630fdc8d8SChris Lattner 127b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 128889037d7SGreg Clayton log_file.Clear(); 12930fdc8d8SChris Lattner log_options = 0; 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner 1321f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 13370602439SZachary Turner return llvm::makeArrayRef(g_log_options); 1341f0f5b5bSZachary Turner } 13530fdc8d8SChris Lattner 13630fdc8d8SChris Lattner // Instance variables to hold the values for command options. 13730fdc8d8SChris Lattner 138889037d7SGreg Clayton FileSpec log_file; 13930fdc8d8SChris Lattner uint32_t log_options; 14030fdc8d8SChris Lattner }; 14130fdc8d8SChris Lattner 1426ba63d88SRaphael Isemann void 1436ba63d88SRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 1446ba63d88SRaphael Isemann OptionElementVector &opt_element_vector) override { 1456ba63d88SRaphael Isemann CompleteEnableDisable(request); 1466ba63d88SRaphael Isemann } 1476ba63d88SRaphael Isemann 14830fdc8d8SChris Lattner protected: 149b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 150b9c1b51eSKate Stone if (args.GetArgumentCount() < 2) { 151b9c1b51eSKate Stone result.AppendErrorWithFormat( 152b9c1b51eSKate Stone "%s takes a log channel and one or more log types.\n", 153b9c1b51eSKate Stone m_cmd_name.c_str()); 154434b81d0SRaphael Isemann result.SetStatus(eReturnStatusFailed); 15511eb9c64SZachary Turner return false; 15611eb9c64SZachary Turner } 15711eb9c64SZachary Turner 15811eb9c64SZachary Turner // Store into a std::string since we're about to shift the channel off. 159*adcd0268SBenjamin Kramer const std::string channel = std::string(args[0].ref()); 1605a988416SJim Ingham args.Shift(); // Shift off the channel 161889037d7SGreg Clayton char log_file[PATH_MAX]; 162889037d7SGreg Clayton if (m_options.log_file) 163889037d7SGreg Clayton m_options.log_file.GetPath(log_file, sizeof(log_file)); 164889037d7SGreg Clayton else 165889037d7SGreg Clayton log_file[0] = '\0'; 166775588c0SPavel Labath 167775588c0SPavel Labath std::string error; 168775588c0SPavel Labath llvm::raw_string_ostream error_stream(error); 16957179860SJonas Devlieghere bool success = 17057179860SJonas Devlieghere GetDebugger().EnableLog(channel, args.GetArgumentArrayRef(), log_file, 17157179860SJonas Devlieghere m_options.log_options, error_stream); 172775588c0SPavel Labath result.GetErrorStream() << error_stream.str(); 173775588c0SPavel Labath 1745a988416SJim Ingham if (success) 1755a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1765a988416SJim Ingham else 1775a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 1785a988416SJim Ingham return result.Succeeded(); 1795a988416SJim Ingham } 1805a988416SJim Ingham 18130fdc8d8SChris Lattner CommandOptions m_options; 18230fdc8d8SChris Lattner }; 18330fdc8d8SChris Lattner 184b9c1b51eSKate Stone class CommandObjectLogDisable : public CommandObjectParsed { 18530fdc8d8SChris Lattner public: 18630fdc8d8SChris Lattner // Constructors and Destructors 187b9c1b51eSKate Stone CommandObjectLogDisable(CommandInterpreter &interpreter) 188b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "log disable", 1897149fab4SCaroline Tice "Disable one or more log channel categories.", 190b9c1b51eSKate Stone nullptr) { 1917149fab4SCaroline Tice CommandArgumentEntry arg1; 1927149fab4SCaroline Tice CommandArgumentEntry arg2; 193405fe67fSCaroline Tice CommandArgumentData channel_arg; 1947149fab4SCaroline Tice CommandArgumentData category_arg; 195405fe67fSCaroline Tice 196405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 197405fe67fSCaroline Tice channel_arg.arg_type = eArgTypeLogChannel; 1987149fab4SCaroline Tice channel_arg.arg_repetition = eArgRepeatPlain; 199405fe67fSCaroline Tice 200b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 201b9c1b51eSKate Stone // argument entry. 2027149fab4SCaroline Tice arg1.push_back(channel_arg); 2037149fab4SCaroline Tice 2047149fab4SCaroline Tice category_arg.arg_type = eArgTypeLogCategory; 2057149fab4SCaroline Tice category_arg.arg_repetition = eArgRepeatPlus; 2067149fab4SCaroline Tice 2077149fab4SCaroline Tice arg2.push_back(category_arg); 208405fe67fSCaroline Tice 209405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 2107149fab4SCaroline Tice m_arguments.push_back(arg1); 2117149fab4SCaroline Tice m_arguments.push_back(arg2); 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner 21426cac3afSEugene Zelenko ~CommandObjectLogDisable() override = default; 21530fdc8d8SChris Lattner 2166ba63d88SRaphael Isemann void 2176ba63d88SRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 2186ba63d88SRaphael Isemann OptionElementVector &opt_element_vector) override { 2196ba63d88SRaphael Isemann CompleteEnableDisable(request); 2206ba63d88SRaphael Isemann } 2216ba63d88SRaphael Isemann 2225a988416SJim Ingham protected: 223b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 22411eb9c64SZachary Turner if (args.empty()) { 225b9c1b51eSKate Stone result.AppendErrorWithFormat( 226b9c1b51eSKate Stone "%s takes a log channel and one or more log types.\n", 227b9c1b51eSKate Stone m_cmd_name.c_str()); 228434b81d0SRaphael Isemann result.SetStatus(eReturnStatusFailed); 22911eb9c64SZachary Turner return false; 23011eb9c64SZachary Turner } 23111eb9c64SZachary Turner 232*adcd0268SBenjamin Kramer const std::string channel = std::string(args[0].ref()); 23320ad3c40SCaroline Tice args.Shift(); // Shift off the channel 234fb0d22d6SPavel Labath if (channel == "all") { 235775588c0SPavel Labath Log::DisableAllLogChannels(); 2365fb8af40SPavel Labath result.SetStatus(eReturnStatusSuccessFinishNoResult); 237fb0d22d6SPavel Labath } else { 238775588c0SPavel Labath std::string error; 239775588c0SPavel Labath llvm::raw_string_ostream error_stream(error); 2405e336903SPavel Labath if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(), 241775588c0SPavel Labath error_stream)) 242fb0d22d6SPavel Labath result.SetStatus(eReturnStatusSuccessFinishNoResult); 243775588c0SPavel Labath result.GetErrorStream() << error_stream.str(); 24430fdc8d8SChris Lattner } 24530fdc8d8SChris Lattner return result.Succeeded(); 24630fdc8d8SChris Lattner } 24730fdc8d8SChris Lattner }; 24830fdc8d8SChris Lattner 249b9c1b51eSKate Stone class CommandObjectLogList : public CommandObjectParsed { 25030fdc8d8SChris Lattner public: 25130fdc8d8SChris Lattner // Constructors and Destructors 252b9c1b51eSKate Stone CommandObjectLogList(CommandInterpreter &interpreter) 253b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "log list", 254b9c1b51eSKate Stone "List the log categories for one or more log " 255b9c1b51eSKate Stone "channels. If none specified, lists them all.", 256b9c1b51eSKate Stone nullptr) { 257405fe67fSCaroline Tice CommandArgumentEntry arg; 258405fe67fSCaroline Tice CommandArgumentData channel_arg; 259405fe67fSCaroline Tice 260405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 261405fe67fSCaroline Tice channel_arg.arg_type = eArgTypeLogChannel; 262405fe67fSCaroline Tice channel_arg.arg_repetition = eArgRepeatStar; 263405fe67fSCaroline Tice 264b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 265b9c1b51eSKate Stone // argument entry. 266405fe67fSCaroline Tice arg.push_back(channel_arg); 267405fe67fSCaroline Tice 268405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 269405fe67fSCaroline Tice m_arguments.push_back(arg); 27030fdc8d8SChris Lattner } 27130fdc8d8SChris Lattner 27226cac3afSEugene Zelenko ~CommandObjectLogList() override = default; 27330fdc8d8SChris Lattner 2746ba63d88SRaphael Isemann void 2756ba63d88SRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 2766ba63d88SRaphael Isemann OptionElementVector &opt_element_vector) override { 2776ba63d88SRaphael Isemann for (llvm::StringRef channel : Log::ListChannels()) 2786ba63d88SRaphael Isemann request.TryCompleteCurrentArg(channel); 2796ba63d88SRaphael Isemann } 2806ba63d88SRaphael Isemann 2815a988416SJim Ingham protected: 282b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 283775588c0SPavel Labath std::string output; 284775588c0SPavel Labath llvm::raw_string_ostream output_stream(output); 28511eb9c64SZachary Turner if (args.empty()) { 286775588c0SPavel Labath Log::ListAllLogChannels(output_stream); 28730fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 288b9c1b51eSKate Stone } else { 289fb0d22d6SPavel Labath bool success = true; 290fb0d22d6SPavel Labath for (const auto &entry : args.entries()) 291775588c0SPavel Labath success = 2920d9a201eSRaphael Isemann success && Log::ListChannelCategories(entry.ref(), output_stream); 293fb0d22d6SPavel Labath if (success) 29430fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 29530fdc8d8SChris Lattner } 296775588c0SPavel Labath result.GetOutputStream() << output_stream.str(); 29730fdc8d8SChris Lattner return result.Succeeded(); 29830fdc8d8SChris Lattner } 29930fdc8d8SChris Lattner }; 30030fdc8d8SChris Lattner 301b9c1b51eSKate Stone class CommandObjectLogTimer : public CommandObjectParsed { 30230fdc8d8SChris Lattner public: 30330fdc8d8SChris Lattner // Constructors and Destructors 304b9c1b51eSKate Stone CommandObjectLogTimer(CommandInterpreter &interpreter) 305b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "log timers", 306b9c1b51eSKate Stone "Enable, disable, dump, and reset LLDB internal " 307b9c1b51eSKate Stone "performance timers.", 308b9c1b51eSKate Stone "log timers < enable <depth> | disable | dump | " 309b9c1b51eSKate Stone "increment <bool> | reset >") {} 31030fdc8d8SChris Lattner 31126cac3afSEugene Zelenko ~CommandObjectLogTimer() override = default; 31230fdc8d8SChris Lattner 3135a988416SJim Ingham protected: 314b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 31530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 31630fdc8d8SChris Lattner 31711eb9c64SZachary Turner if (args.GetArgumentCount() == 1) { 3180d9a201eSRaphael Isemann auto sub_command = args[0].ref(); 31930fdc8d8SChris Lattner 32011eb9c64SZachary Turner if (sub_command.equals_lower("enable")) { 32130fdc8d8SChris Lattner Timer::SetDisplayDepth(UINT32_MAX); 32230fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishNoResult); 32311eb9c64SZachary Turner } else if (sub_command.equals_lower("disable")) { 32430fdc8d8SChris Lattner Timer::DumpCategoryTimes(&result.GetOutputStream()); 32530fdc8d8SChris Lattner Timer::SetDisplayDepth(0); 32630fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 32711eb9c64SZachary Turner } else if (sub_command.equals_lower("dump")) { 32830fdc8d8SChris Lattner Timer::DumpCategoryTimes(&result.GetOutputStream()); 32930fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 33011eb9c64SZachary Turner } else if (sub_command.equals_lower("reset")) { 33130fdc8d8SChris Lattner Timer::ResetCategoryTimes(); 33230fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 33330fdc8d8SChris Lattner } 33411eb9c64SZachary Turner } else if (args.GetArgumentCount() == 2) { 3350d9a201eSRaphael Isemann auto sub_command = args[0].ref(); 3360d9a201eSRaphael Isemann auto param = args[1].ref(); 337932725faSJim Ingham 33811eb9c64SZachary Turner if (sub_command.equals_lower("enable")) { 33911eb9c64SZachary Turner uint32_t depth; 34011eb9c64SZachary Turner if (param.consumeInteger(0, depth)) { 341b9c1b51eSKate Stone result.AppendError( 342b9c1b51eSKate Stone "Could not convert enable depth to an unsigned integer."); 34311eb9c64SZachary Turner } else { 34411eb9c64SZachary Turner Timer::SetDisplayDepth(depth); 34511eb9c64SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 346932725faSJim Ingham } 34711eb9c64SZachary Turner } else if (sub_command.equals_lower("increment")) { 348f7f4f501SJim Ingham bool success; 34947cbf4a0SPavel Labath bool increment = OptionArgParser::ToBoolean(param, false, &success); 350b9c1b51eSKate Stone if (success) { 351f7f4f501SJim Ingham Timer::SetQuiet(!increment); 352f7f4f501SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 353b9c1b51eSKate Stone } else 354f7f4f501SJim Ingham result.AppendError("Could not convert increment value to boolean."); 355f7f4f501SJim Ingham } 356932725faSJim Ingham } 357932725faSJim Ingham 358b9c1b51eSKate Stone if (!result.Succeeded()) { 35930fdc8d8SChris Lattner result.AppendError("Missing subcommand"); 36030fdc8d8SChris Lattner result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); 36130fdc8d8SChris Lattner } 36230fdc8d8SChris Lattner return result.Succeeded(); 36330fdc8d8SChris Lattner } 36430fdc8d8SChris Lattner }; 36530fdc8d8SChris Lattner 3667428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter) 367b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "log", 368b9c1b51eSKate Stone "Commands controlling LLDB internal logging.", 369b9c1b51eSKate Stone "log <subcommand> [<command-options>]") { 370b9c1b51eSKate Stone LoadSubCommand("enable", 371b9c1b51eSKate Stone CommandObjectSP(new CommandObjectLogEnable(interpreter))); 372b9c1b51eSKate Stone LoadSubCommand("disable", 373b9c1b51eSKate Stone CommandObjectSP(new CommandObjectLogDisable(interpreter))); 374b9c1b51eSKate Stone LoadSubCommand("list", 375b9c1b51eSKate Stone CommandObjectSP(new CommandObjectLogList(interpreter))); 376b9c1b51eSKate Stone LoadSubCommand("timers", 377b9c1b51eSKate Stone CommandObjectSP(new CommandObjectLogTimer(interpreter))); 37830fdc8d8SChris Lattner } 37930fdc8d8SChris Lattner 38026cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default; 381