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*be265d25SJonas Devlieghere #include "lldb/Interpreter/OptionValueEnumeration.h"
1509dea546SJonas Devlieghere #include "lldb/Interpreter/OptionValueUInt64.h"
16b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
17145d95c9SPavel Labath #include "lldb/Utility/Args.h"
185713a05bSZachary Turner #include "lldb/Utility/FileSpec.h"
196f9e6901SZachary Turner #include "lldb/Utility/Log.h"
20bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2138d0632eSPavel Labath #include "lldb/Utility/Timer.h"
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner using namespace lldb;
2430fdc8d8SChris Lattner using namespace lldb_private;
2530fdc8d8SChris Lattner 
26*be265d25SJonas Devlieghere static constexpr OptionEnumValueElement g_log_handler_type[] = {
27*be265d25SJonas Devlieghere     {
28*be265d25SJonas Devlieghere         eLogHandlerDefault,
29*be265d25SJonas Devlieghere         "default",
30*be265d25SJonas Devlieghere         "Use the default (stream) log handler",
31*be265d25SJonas Devlieghere     },
32*be265d25SJonas Devlieghere     {
33*be265d25SJonas Devlieghere         eLogHandlerStream,
34*be265d25SJonas Devlieghere         "stream",
35*be265d25SJonas Devlieghere         "Write log messages to the debugger output stream or to a file if one "
36*be265d25SJonas Devlieghere         "is specified. A buffer size (in bytes) can be specified with -b. If "
37*be265d25SJonas Devlieghere         "no buffer size is specified the output is unbuffered.",
38*be265d25SJonas Devlieghere     },
39*be265d25SJonas Devlieghere     {
40*be265d25SJonas Devlieghere         eLogHandlerCircular,
41*be265d25SJonas Devlieghere         "circular",
42*be265d25SJonas Devlieghere         "Write log messages to a fixed size circular buffer. A buffer size "
43*be265d25SJonas Devlieghere         "(number of messages) must be specified with -b.",
44*be265d25SJonas Devlieghere     },
45*be265d25SJonas Devlieghere     {
46*be265d25SJonas Devlieghere         eLogHandlerSystem,
47*be265d25SJonas Devlieghere         "os",
48*be265d25SJonas Devlieghere         "Write log messages to the operating system log.",
49*be265d25SJonas Devlieghere     },
50*be265d25SJonas Devlieghere };
51*be265d25SJonas Devlieghere 
52*be265d25SJonas Devlieghere static constexpr OptionEnumValues LogHandlerType() {
53*be265d25SJonas Devlieghere   return OptionEnumValues(g_log_handler_type);
54*be265d25SJonas Devlieghere }
55*be265d25SJonas Devlieghere 
5609dea546SJonas Devlieghere #define LLDB_OPTIONS_log_enable
57ec67e734SRaphael Isemann #include "CommandOptions.inc"
581f0f5b5bSZachary Turner 
596ba63d88SRaphael Isemann /// Common completion logic for log enable/disable.
606ba63d88SRaphael Isemann static void CompleteEnableDisable(CompletionRequest &request) {
616ba63d88SRaphael Isemann   size_t arg_index = request.GetCursorIndex();
626ba63d88SRaphael Isemann   if (arg_index == 0) { // We got: log enable/disable x[tab]
636ba63d88SRaphael Isemann     for (llvm::StringRef channel : Log::ListChannels())
646ba63d88SRaphael Isemann       request.TryCompleteCurrentArg(channel);
656ba63d88SRaphael Isemann   } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
666ba63d88SRaphael Isemann     llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
676ba63d88SRaphael Isemann     Log::ForEachChannelCategory(
686ba63d88SRaphael Isemann         channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
696ba63d88SRaphael Isemann           request.TryCompleteCurrentArg(name, desc);
706ba63d88SRaphael Isemann         });
716ba63d88SRaphael Isemann   }
726ba63d88SRaphael Isemann }
736ba63d88SRaphael Isemann 
74b9c1b51eSKate Stone class CommandObjectLogEnable : public CommandObjectParsed {
7530fdc8d8SChris Lattner public:
7630fdc8d8SChris Lattner   // Constructors and Destructors
77b9c1b51eSKate Stone   CommandObjectLogEnable(CommandInterpreter &interpreter)
78b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log enable",
7930fdc8d8SChris Lattner                             "Enable logging for a single log channel.",
80abb0ed44SKazu Hirata                             nullptr) {
81ceb6b139SCaroline Tice     CommandArgumentEntry arg1;
82ceb6b139SCaroline Tice     CommandArgumentEntry arg2;
83405fe67fSCaroline Tice     CommandArgumentData channel_arg;
84ceb6b139SCaroline Tice     CommandArgumentData category_arg;
85405fe67fSCaroline Tice 
86405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
87405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
88405fe67fSCaroline Tice     channel_arg.arg_repetition = eArgRepeatPlain;
89405fe67fSCaroline Tice 
90b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
91b9c1b51eSKate Stone     // argument entry.
92ceb6b139SCaroline Tice     arg1.push_back(channel_arg);
93ceb6b139SCaroline Tice 
94ceb6b139SCaroline Tice     category_arg.arg_type = eArgTypeLogCategory;
95ceb6b139SCaroline Tice     category_arg.arg_repetition = eArgRepeatPlus;
96ceb6b139SCaroline Tice 
97ceb6b139SCaroline Tice     arg2.push_back(category_arg);
98405fe67fSCaroline Tice 
99405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
100ceb6b139SCaroline Tice     m_arguments.push_back(arg1);
101ceb6b139SCaroline Tice     m_arguments.push_back(arg2);
10230fdc8d8SChris Lattner   }
10330fdc8d8SChris Lattner 
10426cac3afSEugene Zelenko   ~CommandObjectLogEnable() override = default;
10530fdc8d8SChris Lattner 
106b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
10730fdc8d8SChris Lattner 
108b9c1b51eSKate Stone   class CommandOptions : public Options {
10930fdc8d8SChris Lattner   public:
11024f9a2f5SShafik Yaghmour     CommandOptions() = default;
11130fdc8d8SChris Lattner 
11226cac3afSEugene Zelenko     ~CommandOptions() override = default;
11330fdc8d8SChris Lattner 
11497206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
115b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
11697206d57SZachary Turner       Status error;
1173bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11830fdc8d8SChris Lattner 
119b9c1b51eSKate Stone       switch (short_option) {
120b9c1b51eSKate Stone       case 'f':
1218f3be7a3SJonas Devlieghere         log_file.SetFile(option_arg, FileSpec::Style::native);
1228f3be7a3SJonas Devlieghere         FileSystem::Instance().Resolve(log_file);
123b9c1b51eSKate Stone         break;
124*be265d25SJonas Devlieghere       case 'h':
125*be265d25SJonas Devlieghere         handler = (LogHandlerKind)OptionArgParser::ToOptionEnum(
126*be265d25SJonas Devlieghere             option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
127*be265d25SJonas Devlieghere         if (!error.Success())
128*be265d25SJonas Devlieghere           error.SetErrorStringWithFormat(
129*be265d25SJonas Devlieghere               "unrecognized value for log handler '%s'",
130*be265d25SJonas Devlieghere               option_arg.str().c_str());
131*be265d25SJonas Devlieghere         break;
13209dea546SJonas Devlieghere       case 'b':
13309dea546SJonas Devlieghere         error =
13409dea546SJonas Devlieghere             buffer_size.SetValueFromString(option_arg, eVarSetOperationAssign);
13509dea546SJonas Devlieghere         break;
136b9c1b51eSKate Stone       case 'v':
137b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_VERBOSE;
138b9c1b51eSKate Stone         break;
139b9c1b51eSKate Stone       case 's':
140b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
141b9c1b51eSKate Stone         break;
142b9c1b51eSKate Stone       case 'T':
143b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
144b9c1b51eSKate Stone         break;
145b9c1b51eSKate Stone       case 'p':
146b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
147b9c1b51eSKate Stone         break;
148b9c1b51eSKate Stone       case 'n':
149b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
150b9c1b51eSKate Stone         break;
151b9c1b51eSKate Stone       case 'S':
152b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_BACKTRACE;
153b9c1b51eSKate Stone         break;
154b9c1b51eSKate Stone       case 'a':
155b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_APPEND;
156b9c1b51eSKate Stone         break;
157107d9bbdSPavel Labath       case 'F':
158107d9bbdSPavel Labath         log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
15990505a0aSPavel Labath         break;
16030fdc8d8SChris Lattner       default:
16136162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
16230fdc8d8SChris Lattner       }
16330fdc8d8SChris Lattner 
16430fdc8d8SChris Lattner       return error;
16530fdc8d8SChris Lattner     }
16630fdc8d8SChris Lattner 
167b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
168889037d7SGreg Clayton       log_file.Clear();
16909dea546SJonas Devlieghere       buffer_size.Clear();
170*be265d25SJonas Devlieghere       handler = eLogHandlerStream;
17130fdc8d8SChris Lattner       log_options = 0;
17230fdc8d8SChris Lattner     }
17330fdc8d8SChris Lattner 
1741f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
17509dea546SJonas Devlieghere       return llvm::makeArrayRef(g_log_enable_options);
1761f0f5b5bSZachary Turner     }
17730fdc8d8SChris Lattner 
178889037d7SGreg Clayton     FileSpec log_file;
17909dea546SJonas Devlieghere     OptionValueUInt64 buffer_size;
180*be265d25SJonas Devlieghere     LogHandlerKind handler = eLogHandlerStream;
1819494c510SJonas Devlieghere     uint32_t log_options = 0;
18230fdc8d8SChris Lattner   };
18330fdc8d8SChris Lattner 
1846ba63d88SRaphael Isemann   void
1856ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
1866ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
1876ba63d88SRaphael Isemann     CompleteEnableDisable(request);
1886ba63d88SRaphael Isemann   }
1896ba63d88SRaphael Isemann 
19030fdc8d8SChris Lattner protected:
191b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
192b9c1b51eSKate Stone     if (args.GetArgumentCount() < 2) {
193b9c1b51eSKate Stone       result.AppendErrorWithFormat(
194b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
195b9c1b51eSKate Stone           m_cmd_name.c_str());
19611eb9c64SZachary Turner       return false;
19711eb9c64SZachary Turner     }
19811eb9c64SZachary Turner 
199*be265d25SJonas Devlieghere     if (m_options.handler == eLogHandlerCircular &&
200*be265d25SJonas Devlieghere         m_options.buffer_size.GetCurrentValue() == 0) {
201*be265d25SJonas Devlieghere       result.AppendError(
202*be265d25SJonas Devlieghere           "the circular buffer handler requires a non-zero buffer size.\n");
203*be265d25SJonas Devlieghere       return false;
204*be265d25SJonas Devlieghere     }
205*be265d25SJonas Devlieghere 
20611eb9c64SZachary Turner     // Store into a std::string since we're about to shift the channel off.
207adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
2085a988416SJim Ingham     args.Shift(); // Shift off the channel
209889037d7SGreg Clayton     char log_file[PATH_MAX];
210889037d7SGreg Clayton     if (m_options.log_file)
211889037d7SGreg Clayton       m_options.log_file.GetPath(log_file, sizeof(log_file));
212889037d7SGreg Clayton     else
213889037d7SGreg Clayton       log_file[0] = '\0';
214775588c0SPavel Labath 
215775588c0SPavel Labath     std::string error;
216775588c0SPavel Labath     llvm::raw_string_ostream error_stream(error);
21709dea546SJonas Devlieghere     bool success = GetDebugger().EnableLog(
21809dea546SJonas Devlieghere         channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
219*be265d25SJonas Devlieghere         m_options.buffer_size.GetCurrentValue(), m_options.handler,
220*be265d25SJonas Devlieghere         error_stream);
221775588c0SPavel Labath     result.GetErrorStream() << error_stream.str();
222775588c0SPavel Labath 
2235a988416SJim Ingham     if (success)
2245a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2255a988416SJim Ingham     else
2265a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
2275a988416SJim Ingham     return result.Succeeded();
2285a988416SJim Ingham   }
2295a988416SJim Ingham 
23030fdc8d8SChris Lattner   CommandOptions m_options;
23130fdc8d8SChris Lattner };
23230fdc8d8SChris Lattner 
233b9c1b51eSKate Stone class CommandObjectLogDisable : public CommandObjectParsed {
23430fdc8d8SChris Lattner public:
23530fdc8d8SChris Lattner   // Constructors and Destructors
236b9c1b51eSKate Stone   CommandObjectLogDisable(CommandInterpreter &interpreter)
237b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log disable",
2387149fab4SCaroline Tice                             "Disable one or more log channel categories.",
239b9c1b51eSKate Stone                             nullptr) {
2407149fab4SCaroline Tice     CommandArgumentEntry arg1;
2417149fab4SCaroline Tice     CommandArgumentEntry arg2;
242405fe67fSCaroline Tice     CommandArgumentData channel_arg;
2437149fab4SCaroline Tice     CommandArgumentData category_arg;
244405fe67fSCaroline Tice 
245405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
246405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
2477149fab4SCaroline Tice     channel_arg.arg_repetition = eArgRepeatPlain;
248405fe67fSCaroline Tice 
249b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
250b9c1b51eSKate Stone     // argument entry.
2517149fab4SCaroline Tice     arg1.push_back(channel_arg);
2527149fab4SCaroline Tice 
2537149fab4SCaroline Tice     category_arg.arg_type = eArgTypeLogCategory;
2547149fab4SCaroline Tice     category_arg.arg_repetition = eArgRepeatPlus;
2557149fab4SCaroline Tice 
2567149fab4SCaroline Tice     arg2.push_back(category_arg);
257405fe67fSCaroline Tice 
258405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
2597149fab4SCaroline Tice     m_arguments.push_back(arg1);
2607149fab4SCaroline Tice     m_arguments.push_back(arg2);
26130fdc8d8SChris Lattner   }
26230fdc8d8SChris Lattner 
26326cac3afSEugene Zelenko   ~CommandObjectLogDisable() override = default;
26430fdc8d8SChris Lattner 
2656ba63d88SRaphael Isemann   void
2666ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
2676ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
2686ba63d88SRaphael Isemann     CompleteEnableDisable(request);
2696ba63d88SRaphael Isemann   }
2706ba63d88SRaphael Isemann 
2715a988416SJim Ingham protected:
272b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
27311eb9c64SZachary Turner     if (args.empty()) {
274b9c1b51eSKate Stone       result.AppendErrorWithFormat(
275b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
276b9c1b51eSKate Stone           m_cmd_name.c_str());
27711eb9c64SZachary Turner       return false;
27811eb9c64SZachary Turner     }
27911eb9c64SZachary Turner 
280adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
28120ad3c40SCaroline Tice     args.Shift(); // Shift off the channel
282fb0d22d6SPavel Labath     if (channel == "all") {
283775588c0SPavel Labath       Log::DisableAllLogChannels();
2845fb8af40SPavel Labath       result.SetStatus(eReturnStatusSuccessFinishNoResult);
285fb0d22d6SPavel Labath     } else {
286775588c0SPavel Labath       std::string error;
287775588c0SPavel Labath       llvm::raw_string_ostream error_stream(error);
2885e336903SPavel Labath       if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
289775588c0SPavel Labath                                  error_stream))
290fb0d22d6SPavel Labath         result.SetStatus(eReturnStatusSuccessFinishNoResult);
291775588c0SPavel Labath       result.GetErrorStream() << error_stream.str();
29230fdc8d8SChris Lattner     }
29330fdc8d8SChris Lattner     return result.Succeeded();
29430fdc8d8SChris Lattner   }
29530fdc8d8SChris Lattner };
29630fdc8d8SChris Lattner 
297b9c1b51eSKate Stone class CommandObjectLogList : public CommandObjectParsed {
29830fdc8d8SChris Lattner public:
29930fdc8d8SChris Lattner   // Constructors and Destructors
300b9c1b51eSKate Stone   CommandObjectLogList(CommandInterpreter &interpreter)
301b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log list",
302b9c1b51eSKate Stone                             "List the log categories for one or more log "
303b9c1b51eSKate Stone                             "channels.  If none specified, lists them all.",
304b9c1b51eSKate Stone                             nullptr) {
305405fe67fSCaroline Tice     CommandArgumentEntry arg;
306405fe67fSCaroline Tice     CommandArgumentData channel_arg;
307405fe67fSCaroline Tice 
308405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
309405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
310405fe67fSCaroline Tice     channel_arg.arg_repetition = eArgRepeatStar;
311405fe67fSCaroline Tice 
312b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
313b9c1b51eSKate Stone     // argument entry.
314405fe67fSCaroline Tice     arg.push_back(channel_arg);
315405fe67fSCaroline Tice 
316405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
317405fe67fSCaroline Tice     m_arguments.push_back(arg);
31830fdc8d8SChris Lattner   }
31930fdc8d8SChris Lattner 
32026cac3afSEugene Zelenko   ~CommandObjectLogList() override = default;
32130fdc8d8SChris Lattner 
3226ba63d88SRaphael Isemann   void
3236ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
3246ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
3256ba63d88SRaphael Isemann     for (llvm::StringRef channel : Log::ListChannels())
3266ba63d88SRaphael Isemann       request.TryCompleteCurrentArg(channel);
3276ba63d88SRaphael Isemann   }
3286ba63d88SRaphael Isemann 
3295a988416SJim Ingham protected:
330b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
331775588c0SPavel Labath     std::string output;
332775588c0SPavel Labath     llvm::raw_string_ostream output_stream(output);
33311eb9c64SZachary Turner     if (args.empty()) {
334775588c0SPavel Labath       Log::ListAllLogChannels(output_stream);
33530fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
336b9c1b51eSKate Stone     } else {
337fb0d22d6SPavel Labath       bool success = true;
338fb0d22d6SPavel Labath       for (const auto &entry : args.entries())
339775588c0SPavel Labath         success =
3400d9a201eSRaphael Isemann             success && Log::ListChannelCategories(entry.ref(), output_stream);
341fb0d22d6SPavel Labath       if (success)
34230fdc8d8SChris Lattner         result.SetStatus(eReturnStatusSuccessFinishResult);
34330fdc8d8SChris Lattner     }
344775588c0SPavel Labath     result.GetOutputStream() << output_stream.str();
34530fdc8d8SChris Lattner     return result.Succeeded();
34630fdc8d8SChris Lattner   }
34730fdc8d8SChris Lattner };
34830fdc8d8SChris Lattner 
3491d3b7370SShu Anzai class CommandObjectLogTimerEnable : public CommandObjectParsed {
35030fdc8d8SChris Lattner public:
35130fdc8d8SChris Lattner   // Constructors and Destructors
3521d3b7370SShu Anzai   CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
3531d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers enable",
3541d3b7370SShu Anzai                             "enable LLDB internal performance timers",
3551d3b7370SShu Anzai                             "log timers enable <depth>") {
3561d3b7370SShu Anzai     CommandArgumentEntry arg;
3571d3b7370SShu Anzai     CommandArgumentData depth_arg;
35830fdc8d8SChris Lattner 
3591d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
3601d3b7370SShu Anzai     depth_arg.arg_type = eArgTypeCount;
3611d3b7370SShu Anzai     depth_arg.arg_repetition = eArgRepeatOptional;
3621d3b7370SShu Anzai 
3631d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
3641d3b7370SShu Anzai     // argument entry.
3651d3b7370SShu Anzai     arg.push_back(depth_arg);
3661d3b7370SShu Anzai 
3671d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
3681d3b7370SShu Anzai     m_arguments.push_back(arg);
3691d3b7370SShu Anzai   }
3701d3b7370SShu Anzai 
3711d3b7370SShu Anzai   ~CommandObjectLogTimerEnable() override = default;
37230fdc8d8SChris Lattner 
3735a988416SJim Ingham protected:
374b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
37530fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
37630fdc8d8SChris Lattner 
3771d3b7370SShu Anzai     if (args.GetArgumentCount() == 0) {
37830fdc8d8SChris Lattner       Timer::SetDisplayDepth(UINT32_MAX);
37930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishNoResult);
3801d3b7370SShu Anzai     } else if (args.GetArgumentCount() == 1) {
38111eb9c64SZachary Turner       uint32_t depth;
3821d3b7370SShu Anzai       if (args[0].ref().consumeInteger(0, depth)) {
383b9c1b51eSKate Stone         result.AppendError(
384b9c1b51eSKate Stone             "Could not convert enable depth to an unsigned integer.");
38511eb9c64SZachary Turner       } else {
38611eb9c64SZachary Turner         Timer::SetDisplayDepth(depth);
38711eb9c64SZachary Turner         result.SetStatus(eReturnStatusSuccessFinishNoResult);
388932725faSJim Ingham       }
389932725faSJim Ingham     }
390932725faSJim Ingham 
391b9c1b51eSKate Stone     if (!result.Succeeded()) {
39230fdc8d8SChris Lattner       result.AppendError("Missing subcommand");
39330fdc8d8SChris Lattner       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
39430fdc8d8SChris Lattner     }
39530fdc8d8SChris Lattner     return result.Succeeded();
39630fdc8d8SChris Lattner   }
39730fdc8d8SChris Lattner };
39830fdc8d8SChris Lattner 
3991d3b7370SShu Anzai class CommandObjectLogTimerDisable : public CommandObjectParsed {
4001d3b7370SShu Anzai public:
4011d3b7370SShu Anzai   // Constructors and Destructors
4021d3b7370SShu Anzai   CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
4031d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers disable",
4041d3b7370SShu Anzai                             "disable LLDB internal performance timers",
4051d3b7370SShu Anzai                             nullptr) {}
4061d3b7370SShu Anzai 
4071d3b7370SShu Anzai   ~CommandObjectLogTimerDisable() override = default;
4081d3b7370SShu Anzai 
4091d3b7370SShu Anzai protected:
4101d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4111d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
4121d3b7370SShu Anzai     Timer::SetDisplayDepth(0);
4131d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4141d3b7370SShu Anzai 
4151d3b7370SShu Anzai     if (!result.Succeeded()) {
4161d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4171d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4181d3b7370SShu Anzai     }
4191d3b7370SShu Anzai     return result.Succeeded();
4201d3b7370SShu Anzai   }
4211d3b7370SShu Anzai };
4221d3b7370SShu Anzai 
4231d3b7370SShu Anzai class CommandObjectLogTimerDump : public CommandObjectParsed {
4241d3b7370SShu Anzai public:
4251d3b7370SShu Anzai   // Constructors and Destructors
4261d3b7370SShu Anzai   CommandObjectLogTimerDump(CommandInterpreter &interpreter)
4271d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers dump",
4281d3b7370SShu Anzai                             "dump LLDB internal performance timers", nullptr) {}
4291d3b7370SShu Anzai 
4301d3b7370SShu Anzai   ~CommandObjectLogTimerDump() override = default;
4311d3b7370SShu Anzai 
4321d3b7370SShu Anzai protected:
4331d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4341d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
4351d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4361d3b7370SShu Anzai 
4371d3b7370SShu Anzai     if (!result.Succeeded()) {
4381d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4391d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4401d3b7370SShu Anzai     }
4411d3b7370SShu Anzai     return result.Succeeded();
4421d3b7370SShu Anzai   }
4431d3b7370SShu Anzai };
4441d3b7370SShu Anzai 
4451d3b7370SShu Anzai class CommandObjectLogTimerReset : public CommandObjectParsed {
4461d3b7370SShu Anzai public:
4471d3b7370SShu Anzai   // Constructors and Destructors
4481d3b7370SShu Anzai   CommandObjectLogTimerReset(CommandInterpreter &interpreter)
4491d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers reset",
4501d3b7370SShu Anzai                             "reset LLDB internal performance timers", nullptr) {
4511d3b7370SShu Anzai   }
4521d3b7370SShu Anzai 
4531d3b7370SShu Anzai   ~CommandObjectLogTimerReset() override = default;
4541d3b7370SShu Anzai 
4551d3b7370SShu Anzai protected:
4561d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4571d3b7370SShu Anzai     Timer::ResetCategoryTimes();
4581d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4591d3b7370SShu Anzai 
4601d3b7370SShu Anzai     if (!result.Succeeded()) {
4611d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4621d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4631d3b7370SShu Anzai     }
4641d3b7370SShu Anzai     return result.Succeeded();
4651d3b7370SShu Anzai   }
4661d3b7370SShu Anzai };
4671d3b7370SShu Anzai 
4681d3b7370SShu Anzai class CommandObjectLogTimerIncrement : public CommandObjectParsed {
4691d3b7370SShu Anzai public:
4701d3b7370SShu Anzai   // Constructors and Destructors
4711d3b7370SShu Anzai   CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
4721d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers increment",
4731d3b7370SShu Anzai                             "increment LLDB internal performance timers",
4741d3b7370SShu Anzai                             "log timers increment <bool>") {
4751d3b7370SShu Anzai     CommandArgumentEntry arg;
4761d3b7370SShu Anzai     CommandArgumentData bool_arg;
4771d3b7370SShu Anzai 
4781d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
4791d3b7370SShu Anzai     bool_arg.arg_type = eArgTypeBoolean;
4801d3b7370SShu Anzai     bool_arg.arg_repetition = eArgRepeatPlain;
4811d3b7370SShu Anzai 
4821d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
4831d3b7370SShu Anzai     // argument entry.
4841d3b7370SShu Anzai     arg.push_back(bool_arg);
4851d3b7370SShu Anzai 
4861d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
4871d3b7370SShu Anzai     m_arguments.push_back(arg);
4881d3b7370SShu Anzai   }
4891d3b7370SShu Anzai 
4901d3b7370SShu Anzai   ~CommandObjectLogTimerIncrement() override = default;
4911d3b7370SShu Anzai 
4921d3b7370SShu Anzai   void
4931d3b7370SShu Anzai   HandleArgumentCompletion(CompletionRequest &request,
4941d3b7370SShu Anzai                            OptionElementVector &opt_element_vector) override {
4951d3b7370SShu Anzai     request.TryCompleteCurrentArg("true");
4961d3b7370SShu Anzai     request.TryCompleteCurrentArg("false");
4971d3b7370SShu Anzai   }
4981d3b7370SShu Anzai 
4991d3b7370SShu Anzai protected:
5001d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
5011d3b7370SShu Anzai     result.SetStatus(eReturnStatusFailed);
5021d3b7370SShu Anzai 
5031d3b7370SShu Anzai     if (args.GetArgumentCount() == 1) {
5041d3b7370SShu Anzai       bool success;
5051d3b7370SShu Anzai       bool increment =
5061d3b7370SShu Anzai           OptionArgParser::ToBoolean(args[0].ref(), false, &success);
5071d3b7370SShu Anzai 
5081d3b7370SShu Anzai       if (success) {
5091d3b7370SShu Anzai         Timer::SetQuiet(!increment);
5101d3b7370SShu Anzai         result.SetStatus(eReturnStatusSuccessFinishNoResult);
5111d3b7370SShu Anzai       } else
5121d3b7370SShu Anzai         result.AppendError("Could not convert increment value to boolean.");
5131d3b7370SShu Anzai     }
5141d3b7370SShu Anzai 
5151d3b7370SShu Anzai     if (!result.Succeeded()) {
5161d3b7370SShu Anzai       result.AppendError("Missing subcommand");
5171d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
5181d3b7370SShu Anzai     }
5191d3b7370SShu Anzai     return result.Succeeded();
5201d3b7370SShu Anzai   }
5211d3b7370SShu Anzai };
5221d3b7370SShu Anzai 
5231d3b7370SShu Anzai class CommandObjectLogTimer : public CommandObjectMultiword {
5241d3b7370SShu Anzai public:
5251d3b7370SShu Anzai   CommandObjectLogTimer(CommandInterpreter &interpreter)
5261d3b7370SShu Anzai       : CommandObjectMultiword(interpreter, "log timers",
5271d3b7370SShu Anzai                                "Enable, disable, dump, and reset LLDB internal "
5281d3b7370SShu Anzai                                "performance timers.",
5291d3b7370SShu Anzai                                "log timers < enable <depth> | disable | dump | "
5301d3b7370SShu Anzai                                "increment <bool> | reset >") {
5311d3b7370SShu Anzai     LoadSubCommand("enable", CommandObjectSP(
5321d3b7370SShu Anzai                                  new CommandObjectLogTimerEnable(interpreter)));
5331d3b7370SShu Anzai     LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
5341d3b7370SShu Anzai                                   interpreter)));
5351d3b7370SShu Anzai     LoadSubCommand("dump",
5361d3b7370SShu Anzai                    CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
5371d3b7370SShu Anzai     LoadSubCommand(
5381d3b7370SShu Anzai         "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
5391d3b7370SShu Anzai     LoadSubCommand(
5401d3b7370SShu Anzai         "increment",
5411d3b7370SShu Anzai         CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
5421d3b7370SShu Anzai   }
5431d3b7370SShu Anzai 
5441d3b7370SShu Anzai   ~CommandObjectLogTimer() override = default;
5451d3b7370SShu Anzai };
5461d3b7370SShu Anzai 
5477428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
548b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "log",
549b9c1b51eSKate Stone                              "Commands controlling LLDB internal logging.",
550b9c1b51eSKate Stone                              "log <subcommand> [<command-options>]") {
551b9c1b51eSKate Stone   LoadSubCommand("enable",
552b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
553b9c1b51eSKate Stone   LoadSubCommand("disable",
554b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
555b9c1b51eSKate Stone   LoadSubCommand("list",
556b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogList(interpreter)));
557b9c1b51eSKate Stone   LoadSubCommand("timers",
558b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
55930fdc8d8SChris Lattner }
56030fdc8d8SChris Lattner 
56126cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
562