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