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"
14*09dea546SJonas Devlieghere #include "lldb/Interpreter/OptionValueUInt64.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
16145d95c9SPavel Labath #include "lldb/Utility/Args.h"
175713a05bSZachary Turner #include "lldb/Utility/FileSpec.h"
186f9e6901SZachary Turner #include "lldb/Utility/Log.h"
19bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2038d0632eSPavel Labath #include "lldb/Utility/Timer.h"
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner using namespace lldb;
2330fdc8d8SChris Lattner using namespace lldb_private;
2430fdc8d8SChris Lattner 
25*09dea546SJonas Devlieghere #define LLDB_OPTIONS_log_enable
26ec67e734SRaphael Isemann #include "CommandOptions.inc"
271f0f5b5bSZachary Turner 
286ba63d88SRaphael Isemann /// Common completion logic for log enable/disable.
296ba63d88SRaphael Isemann static void CompleteEnableDisable(CompletionRequest &request) {
306ba63d88SRaphael Isemann   size_t arg_index = request.GetCursorIndex();
316ba63d88SRaphael Isemann   if (arg_index == 0) { // We got: log enable/disable x[tab]
326ba63d88SRaphael Isemann     for (llvm::StringRef channel : Log::ListChannels())
336ba63d88SRaphael Isemann       request.TryCompleteCurrentArg(channel);
346ba63d88SRaphael Isemann   } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
356ba63d88SRaphael Isemann     llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
366ba63d88SRaphael Isemann     Log::ForEachChannelCategory(
376ba63d88SRaphael Isemann         channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
386ba63d88SRaphael Isemann           request.TryCompleteCurrentArg(name, desc);
396ba63d88SRaphael Isemann         });
406ba63d88SRaphael Isemann   }
416ba63d88SRaphael Isemann }
426ba63d88SRaphael Isemann 
43b9c1b51eSKate Stone class CommandObjectLogEnable : public CommandObjectParsed {
4430fdc8d8SChris Lattner public:
4530fdc8d8SChris Lattner   // Constructors and Destructors
46b9c1b51eSKate Stone   CommandObjectLogEnable(CommandInterpreter &interpreter)
47b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log enable",
4830fdc8d8SChris Lattner                             "Enable logging for a single log channel.",
49abb0ed44SKazu Hirata                             nullptr) {
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:
7924f9a2f5SShafik Yaghmour     CommandOptions() = default;
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;
93*09dea546SJonas Devlieghere       case 'b':
94*09dea546SJonas Devlieghere         error =
95*09dea546SJonas Devlieghere             buffer_size.SetValueFromString(option_arg, eVarSetOperationAssign);
96*09dea546SJonas Devlieghere         break;
97b9c1b51eSKate Stone       case 't':
98b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_THREADSAFE;
99b9c1b51eSKate Stone         break;
100b9c1b51eSKate Stone       case 'v':
101b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_VERBOSE;
102b9c1b51eSKate Stone         break;
103b9c1b51eSKate Stone       case 's':
104b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
105b9c1b51eSKate Stone         break;
106b9c1b51eSKate Stone       case 'T':
107b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
108b9c1b51eSKate Stone         break;
109b9c1b51eSKate Stone       case 'p':
110b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
111b9c1b51eSKate Stone         break;
112b9c1b51eSKate Stone       case 'n':
113b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
114b9c1b51eSKate Stone         break;
115b9c1b51eSKate Stone       case 'S':
116b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_BACKTRACE;
117b9c1b51eSKate Stone         break;
118b9c1b51eSKate Stone       case 'a':
119b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_APPEND;
120b9c1b51eSKate Stone         break;
121107d9bbdSPavel Labath       case 'F':
122107d9bbdSPavel Labath         log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
12390505a0aSPavel Labath         break;
12430fdc8d8SChris Lattner       default:
12536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12630fdc8d8SChris Lattner       }
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner       return error;
12930fdc8d8SChris Lattner     }
13030fdc8d8SChris Lattner 
131b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
132889037d7SGreg Clayton       log_file.Clear();
133*09dea546SJonas Devlieghere       buffer_size.Clear();
13430fdc8d8SChris Lattner       log_options = 0;
13530fdc8d8SChris Lattner     }
13630fdc8d8SChris Lattner 
1371f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
138*09dea546SJonas Devlieghere       return llvm::makeArrayRef(g_log_enable_options);
1391f0f5b5bSZachary Turner     }
14030fdc8d8SChris Lattner 
141889037d7SGreg Clayton     FileSpec log_file;
142*09dea546SJonas Devlieghere     OptionValueUInt64 buffer_size;
1439494c510SJonas Devlieghere     uint32_t log_options = 0;
14430fdc8d8SChris Lattner   };
14530fdc8d8SChris Lattner 
1466ba63d88SRaphael Isemann   void
1476ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
1486ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
1496ba63d88SRaphael Isemann     CompleteEnableDisable(request);
1506ba63d88SRaphael Isemann   }
1516ba63d88SRaphael Isemann 
15230fdc8d8SChris Lattner protected:
153b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
154b9c1b51eSKate Stone     if (args.GetArgumentCount() < 2) {
155b9c1b51eSKate Stone       result.AppendErrorWithFormat(
156b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
157b9c1b51eSKate Stone           m_cmd_name.c_str());
15811eb9c64SZachary Turner       return false;
15911eb9c64SZachary Turner     }
16011eb9c64SZachary Turner 
16111eb9c64SZachary Turner     // Store into a std::string since we're about to shift the channel off.
162adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
1635a988416SJim Ingham     args.Shift(); // Shift off the channel
164889037d7SGreg Clayton     char log_file[PATH_MAX];
165889037d7SGreg Clayton     if (m_options.log_file)
166889037d7SGreg Clayton       m_options.log_file.GetPath(log_file, sizeof(log_file));
167889037d7SGreg Clayton     else
168889037d7SGreg Clayton       log_file[0] = '\0';
169775588c0SPavel Labath 
170775588c0SPavel Labath     std::string error;
171775588c0SPavel Labath     llvm::raw_string_ostream error_stream(error);
172*09dea546SJonas Devlieghere     bool success = GetDebugger().EnableLog(
173*09dea546SJonas Devlieghere         channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
174*09dea546SJonas Devlieghere         m_options.buffer_size.GetCurrentValue(), error_stream);
175775588c0SPavel Labath     result.GetErrorStream() << error_stream.str();
176775588c0SPavel Labath 
1775a988416SJim Ingham     if (success)
1785a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1795a988416SJim Ingham     else
1805a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
1815a988416SJim Ingham     return result.Succeeded();
1825a988416SJim Ingham   }
1835a988416SJim Ingham 
18430fdc8d8SChris Lattner   CommandOptions m_options;
18530fdc8d8SChris Lattner };
18630fdc8d8SChris Lattner 
187b9c1b51eSKate Stone class CommandObjectLogDisable : public CommandObjectParsed {
18830fdc8d8SChris Lattner public:
18930fdc8d8SChris Lattner   // Constructors and Destructors
190b9c1b51eSKate Stone   CommandObjectLogDisable(CommandInterpreter &interpreter)
191b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log disable",
1927149fab4SCaroline Tice                             "Disable one or more log channel categories.",
193b9c1b51eSKate Stone                             nullptr) {
1947149fab4SCaroline Tice     CommandArgumentEntry arg1;
1957149fab4SCaroline Tice     CommandArgumentEntry arg2;
196405fe67fSCaroline Tice     CommandArgumentData channel_arg;
1977149fab4SCaroline Tice     CommandArgumentData category_arg;
198405fe67fSCaroline Tice 
199405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
200405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
2017149fab4SCaroline Tice     channel_arg.arg_repetition = eArgRepeatPlain;
202405fe67fSCaroline Tice 
203b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
204b9c1b51eSKate Stone     // argument entry.
2057149fab4SCaroline Tice     arg1.push_back(channel_arg);
2067149fab4SCaroline Tice 
2077149fab4SCaroline Tice     category_arg.arg_type = eArgTypeLogCategory;
2087149fab4SCaroline Tice     category_arg.arg_repetition = eArgRepeatPlus;
2097149fab4SCaroline Tice 
2107149fab4SCaroline Tice     arg2.push_back(category_arg);
211405fe67fSCaroline Tice 
212405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
2137149fab4SCaroline Tice     m_arguments.push_back(arg1);
2147149fab4SCaroline Tice     m_arguments.push_back(arg2);
21530fdc8d8SChris Lattner   }
21630fdc8d8SChris Lattner 
21726cac3afSEugene Zelenko   ~CommandObjectLogDisable() override = default;
21830fdc8d8SChris Lattner 
2196ba63d88SRaphael Isemann   void
2206ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
2216ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
2226ba63d88SRaphael Isemann     CompleteEnableDisable(request);
2236ba63d88SRaphael Isemann   }
2246ba63d88SRaphael Isemann 
2255a988416SJim Ingham protected:
226b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
22711eb9c64SZachary Turner     if (args.empty()) {
228b9c1b51eSKate Stone       result.AppendErrorWithFormat(
229b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
230b9c1b51eSKate Stone           m_cmd_name.c_str());
23111eb9c64SZachary Turner       return false;
23211eb9c64SZachary Turner     }
23311eb9c64SZachary Turner 
234adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
23520ad3c40SCaroline Tice     args.Shift(); // Shift off the channel
236fb0d22d6SPavel Labath     if (channel == "all") {
237775588c0SPavel Labath       Log::DisableAllLogChannels();
2385fb8af40SPavel Labath       result.SetStatus(eReturnStatusSuccessFinishNoResult);
239fb0d22d6SPavel Labath     } else {
240775588c0SPavel Labath       std::string error;
241775588c0SPavel Labath       llvm::raw_string_ostream error_stream(error);
2425e336903SPavel Labath       if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
243775588c0SPavel Labath                                  error_stream))
244fb0d22d6SPavel Labath         result.SetStatus(eReturnStatusSuccessFinishNoResult);
245775588c0SPavel Labath       result.GetErrorStream() << error_stream.str();
24630fdc8d8SChris Lattner     }
24730fdc8d8SChris Lattner     return result.Succeeded();
24830fdc8d8SChris Lattner   }
24930fdc8d8SChris Lattner };
25030fdc8d8SChris Lattner 
251b9c1b51eSKate Stone class CommandObjectLogList : public CommandObjectParsed {
25230fdc8d8SChris Lattner public:
25330fdc8d8SChris Lattner   // Constructors and Destructors
254b9c1b51eSKate Stone   CommandObjectLogList(CommandInterpreter &interpreter)
255b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log list",
256b9c1b51eSKate Stone                             "List the log categories for one or more log "
257b9c1b51eSKate Stone                             "channels.  If none specified, lists them all.",
258b9c1b51eSKate Stone                             nullptr) {
259405fe67fSCaroline Tice     CommandArgumentEntry arg;
260405fe67fSCaroline Tice     CommandArgumentData channel_arg;
261405fe67fSCaroline Tice 
262405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
263405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
264405fe67fSCaroline Tice     channel_arg.arg_repetition = eArgRepeatStar;
265405fe67fSCaroline Tice 
266b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
267b9c1b51eSKate Stone     // argument entry.
268405fe67fSCaroline Tice     arg.push_back(channel_arg);
269405fe67fSCaroline Tice 
270405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
271405fe67fSCaroline Tice     m_arguments.push_back(arg);
27230fdc8d8SChris Lattner   }
27330fdc8d8SChris Lattner 
27426cac3afSEugene Zelenko   ~CommandObjectLogList() override = default;
27530fdc8d8SChris Lattner 
2766ba63d88SRaphael Isemann   void
2776ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
2786ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
2796ba63d88SRaphael Isemann     for (llvm::StringRef channel : Log::ListChannels())
2806ba63d88SRaphael Isemann       request.TryCompleteCurrentArg(channel);
2816ba63d88SRaphael Isemann   }
2826ba63d88SRaphael Isemann 
2835a988416SJim Ingham protected:
284b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
285775588c0SPavel Labath     std::string output;
286775588c0SPavel Labath     llvm::raw_string_ostream output_stream(output);
28711eb9c64SZachary Turner     if (args.empty()) {
288775588c0SPavel Labath       Log::ListAllLogChannels(output_stream);
28930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
290b9c1b51eSKate Stone     } else {
291fb0d22d6SPavel Labath       bool success = true;
292fb0d22d6SPavel Labath       for (const auto &entry : args.entries())
293775588c0SPavel Labath         success =
2940d9a201eSRaphael Isemann             success && Log::ListChannelCategories(entry.ref(), output_stream);
295fb0d22d6SPavel Labath       if (success)
29630fdc8d8SChris Lattner         result.SetStatus(eReturnStatusSuccessFinishResult);
29730fdc8d8SChris Lattner     }
298775588c0SPavel Labath     result.GetOutputStream() << output_stream.str();
29930fdc8d8SChris Lattner     return result.Succeeded();
30030fdc8d8SChris Lattner   }
30130fdc8d8SChris Lattner };
30230fdc8d8SChris Lattner 
3031d3b7370SShu Anzai class CommandObjectLogTimerEnable : public CommandObjectParsed {
30430fdc8d8SChris Lattner public:
30530fdc8d8SChris Lattner   // Constructors and Destructors
3061d3b7370SShu Anzai   CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
3071d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers enable",
3081d3b7370SShu Anzai                             "enable LLDB internal performance timers",
3091d3b7370SShu Anzai                             "log timers enable <depth>") {
3101d3b7370SShu Anzai     CommandArgumentEntry arg;
3111d3b7370SShu Anzai     CommandArgumentData depth_arg;
31230fdc8d8SChris Lattner 
3131d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
3141d3b7370SShu Anzai     depth_arg.arg_type = eArgTypeCount;
3151d3b7370SShu Anzai     depth_arg.arg_repetition = eArgRepeatOptional;
3161d3b7370SShu Anzai 
3171d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
3181d3b7370SShu Anzai     // argument entry.
3191d3b7370SShu Anzai     arg.push_back(depth_arg);
3201d3b7370SShu Anzai 
3211d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
3221d3b7370SShu Anzai     m_arguments.push_back(arg);
3231d3b7370SShu Anzai   }
3241d3b7370SShu Anzai 
3251d3b7370SShu Anzai   ~CommandObjectLogTimerEnable() override = default;
32630fdc8d8SChris Lattner 
3275a988416SJim Ingham protected:
328b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
32930fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
33030fdc8d8SChris Lattner 
3311d3b7370SShu Anzai     if (args.GetArgumentCount() == 0) {
33230fdc8d8SChris Lattner       Timer::SetDisplayDepth(UINT32_MAX);
33330fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishNoResult);
3341d3b7370SShu Anzai     } else if (args.GetArgumentCount() == 1) {
33511eb9c64SZachary Turner       uint32_t depth;
3361d3b7370SShu Anzai       if (args[0].ref().consumeInteger(0, depth)) {
337b9c1b51eSKate Stone         result.AppendError(
338b9c1b51eSKate Stone             "Could not convert enable depth to an unsigned integer.");
33911eb9c64SZachary Turner       } else {
34011eb9c64SZachary Turner         Timer::SetDisplayDepth(depth);
34111eb9c64SZachary Turner         result.SetStatus(eReturnStatusSuccessFinishNoResult);
342932725faSJim Ingham       }
343932725faSJim Ingham     }
344932725faSJim Ingham 
345b9c1b51eSKate Stone     if (!result.Succeeded()) {
34630fdc8d8SChris Lattner       result.AppendError("Missing subcommand");
34730fdc8d8SChris Lattner       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
34830fdc8d8SChris Lattner     }
34930fdc8d8SChris Lattner     return result.Succeeded();
35030fdc8d8SChris Lattner   }
35130fdc8d8SChris Lattner };
35230fdc8d8SChris Lattner 
3531d3b7370SShu Anzai class CommandObjectLogTimerDisable : public CommandObjectParsed {
3541d3b7370SShu Anzai public:
3551d3b7370SShu Anzai   // Constructors and Destructors
3561d3b7370SShu Anzai   CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
3571d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers disable",
3581d3b7370SShu Anzai                             "disable LLDB internal performance timers",
3591d3b7370SShu Anzai                             nullptr) {}
3601d3b7370SShu Anzai 
3611d3b7370SShu Anzai   ~CommandObjectLogTimerDisable() override = default;
3621d3b7370SShu Anzai 
3631d3b7370SShu Anzai protected:
3641d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3651d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3661d3b7370SShu Anzai     Timer::SetDisplayDepth(0);
3671d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3681d3b7370SShu Anzai 
3691d3b7370SShu Anzai     if (!result.Succeeded()) {
3701d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3711d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3721d3b7370SShu Anzai     }
3731d3b7370SShu Anzai     return result.Succeeded();
3741d3b7370SShu Anzai   }
3751d3b7370SShu Anzai };
3761d3b7370SShu Anzai 
3771d3b7370SShu Anzai class CommandObjectLogTimerDump : public CommandObjectParsed {
3781d3b7370SShu Anzai public:
3791d3b7370SShu Anzai   // Constructors and Destructors
3801d3b7370SShu Anzai   CommandObjectLogTimerDump(CommandInterpreter &interpreter)
3811d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers dump",
3821d3b7370SShu Anzai                             "dump LLDB internal performance timers", nullptr) {}
3831d3b7370SShu Anzai 
3841d3b7370SShu Anzai   ~CommandObjectLogTimerDump() override = default;
3851d3b7370SShu Anzai 
3861d3b7370SShu Anzai protected:
3871d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3881d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3891d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3901d3b7370SShu Anzai 
3911d3b7370SShu Anzai     if (!result.Succeeded()) {
3921d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3931d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3941d3b7370SShu Anzai     }
3951d3b7370SShu Anzai     return result.Succeeded();
3961d3b7370SShu Anzai   }
3971d3b7370SShu Anzai };
3981d3b7370SShu Anzai 
3991d3b7370SShu Anzai class CommandObjectLogTimerReset : public CommandObjectParsed {
4001d3b7370SShu Anzai public:
4011d3b7370SShu Anzai   // Constructors and Destructors
4021d3b7370SShu Anzai   CommandObjectLogTimerReset(CommandInterpreter &interpreter)
4031d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers reset",
4041d3b7370SShu Anzai                             "reset LLDB internal performance timers", nullptr) {
4051d3b7370SShu Anzai   }
4061d3b7370SShu Anzai 
4071d3b7370SShu Anzai   ~CommandObjectLogTimerReset() override = default;
4081d3b7370SShu Anzai 
4091d3b7370SShu Anzai protected:
4101d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4111d3b7370SShu Anzai     Timer::ResetCategoryTimes();
4121d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4131d3b7370SShu Anzai 
4141d3b7370SShu Anzai     if (!result.Succeeded()) {
4151d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4161d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4171d3b7370SShu Anzai     }
4181d3b7370SShu Anzai     return result.Succeeded();
4191d3b7370SShu Anzai   }
4201d3b7370SShu Anzai };
4211d3b7370SShu Anzai 
4221d3b7370SShu Anzai class CommandObjectLogTimerIncrement : public CommandObjectParsed {
4231d3b7370SShu Anzai public:
4241d3b7370SShu Anzai   // Constructors and Destructors
4251d3b7370SShu Anzai   CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
4261d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers increment",
4271d3b7370SShu Anzai                             "increment LLDB internal performance timers",
4281d3b7370SShu Anzai                             "log timers increment <bool>") {
4291d3b7370SShu Anzai     CommandArgumentEntry arg;
4301d3b7370SShu Anzai     CommandArgumentData bool_arg;
4311d3b7370SShu Anzai 
4321d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
4331d3b7370SShu Anzai     bool_arg.arg_type = eArgTypeBoolean;
4341d3b7370SShu Anzai     bool_arg.arg_repetition = eArgRepeatPlain;
4351d3b7370SShu Anzai 
4361d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
4371d3b7370SShu Anzai     // argument entry.
4381d3b7370SShu Anzai     arg.push_back(bool_arg);
4391d3b7370SShu Anzai 
4401d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
4411d3b7370SShu Anzai     m_arguments.push_back(arg);
4421d3b7370SShu Anzai   }
4431d3b7370SShu Anzai 
4441d3b7370SShu Anzai   ~CommandObjectLogTimerIncrement() override = default;
4451d3b7370SShu Anzai 
4461d3b7370SShu Anzai   void
4471d3b7370SShu Anzai   HandleArgumentCompletion(CompletionRequest &request,
4481d3b7370SShu Anzai                            OptionElementVector &opt_element_vector) override {
4491d3b7370SShu Anzai     request.TryCompleteCurrentArg("true");
4501d3b7370SShu Anzai     request.TryCompleteCurrentArg("false");
4511d3b7370SShu Anzai   }
4521d3b7370SShu Anzai 
4531d3b7370SShu Anzai protected:
4541d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4551d3b7370SShu Anzai     result.SetStatus(eReturnStatusFailed);
4561d3b7370SShu Anzai 
4571d3b7370SShu Anzai     if (args.GetArgumentCount() == 1) {
4581d3b7370SShu Anzai       bool success;
4591d3b7370SShu Anzai       bool increment =
4601d3b7370SShu Anzai           OptionArgParser::ToBoolean(args[0].ref(), false, &success);
4611d3b7370SShu Anzai 
4621d3b7370SShu Anzai       if (success) {
4631d3b7370SShu Anzai         Timer::SetQuiet(!increment);
4641d3b7370SShu Anzai         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4651d3b7370SShu Anzai       } else
4661d3b7370SShu Anzai         result.AppendError("Could not convert increment value to boolean.");
4671d3b7370SShu Anzai     }
4681d3b7370SShu Anzai 
4691d3b7370SShu Anzai     if (!result.Succeeded()) {
4701d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4711d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4721d3b7370SShu Anzai     }
4731d3b7370SShu Anzai     return result.Succeeded();
4741d3b7370SShu Anzai   }
4751d3b7370SShu Anzai };
4761d3b7370SShu Anzai 
4771d3b7370SShu Anzai class CommandObjectLogTimer : public CommandObjectMultiword {
4781d3b7370SShu Anzai public:
4791d3b7370SShu Anzai   CommandObjectLogTimer(CommandInterpreter &interpreter)
4801d3b7370SShu Anzai       : CommandObjectMultiword(interpreter, "log timers",
4811d3b7370SShu Anzai                                "Enable, disable, dump, and reset LLDB internal "
4821d3b7370SShu Anzai                                "performance timers.",
4831d3b7370SShu Anzai                                "log timers < enable <depth> | disable | dump | "
4841d3b7370SShu Anzai                                "increment <bool> | reset >") {
4851d3b7370SShu Anzai     LoadSubCommand("enable", CommandObjectSP(
4861d3b7370SShu Anzai                                  new CommandObjectLogTimerEnable(interpreter)));
4871d3b7370SShu Anzai     LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
4881d3b7370SShu Anzai                                   interpreter)));
4891d3b7370SShu Anzai     LoadSubCommand("dump",
4901d3b7370SShu Anzai                    CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
4911d3b7370SShu Anzai     LoadSubCommand(
4921d3b7370SShu Anzai         "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
4931d3b7370SShu Anzai     LoadSubCommand(
4941d3b7370SShu Anzai         "increment",
4951d3b7370SShu Anzai         CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
4961d3b7370SShu Anzai   }
4971d3b7370SShu Anzai 
4981d3b7370SShu Anzai   ~CommandObjectLogTimer() override = default;
4991d3b7370SShu Anzai };
5001d3b7370SShu Anzai 
5017428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
502b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "log",
503b9c1b51eSKate Stone                              "Commands controlling LLDB internal logging.",
504b9c1b51eSKate Stone                              "log <subcommand> [<command-options>]") {
505b9c1b51eSKate Stone   LoadSubCommand("enable",
506b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
507b9c1b51eSKate Stone   LoadSubCommand("disable",
508b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
509b9c1b51eSKate Stone   LoadSubCommand("list",
510b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogList(interpreter)));
511b9c1b51eSKate Stone   LoadSubCommand("timers",
512b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
51330fdc8d8SChris Lattner }
51430fdc8d8SChris Lattner 
51526cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
516