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:
79*9494c510SJonas Devlieghere     CommandOptions() : Options(), log_file() {}
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;
139*9494c510SJonas Devlieghere     uint32_t log_options = 0;
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.
159adcd0268SBenjamin 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 
232adcd0268SBenjamin 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 
3011d3b7370SShu Anzai class CommandObjectLogTimerEnable : public CommandObjectParsed {
30230fdc8d8SChris Lattner public:
30330fdc8d8SChris Lattner   // Constructors and Destructors
3041d3b7370SShu Anzai   CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
3051d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers enable",
3061d3b7370SShu Anzai                             "enable LLDB internal performance timers",
3071d3b7370SShu Anzai                             "log timers enable <depth>") {
3081d3b7370SShu Anzai     CommandArgumentEntry arg;
3091d3b7370SShu Anzai     CommandArgumentData depth_arg;
31030fdc8d8SChris Lattner 
3111d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
3121d3b7370SShu Anzai     depth_arg.arg_type = eArgTypeCount;
3131d3b7370SShu Anzai     depth_arg.arg_repetition = eArgRepeatOptional;
3141d3b7370SShu Anzai 
3151d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
3161d3b7370SShu Anzai     // argument entry.
3171d3b7370SShu Anzai     arg.push_back(depth_arg);
3181d3b7370SShu Anzai 
3191d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
3201d3b7370SShu Anzai     m_arguments.push_back(arg);
3211d3b7370SShu Anzai   }
3221d3b7370SShu Anzai 
3231d3b7370SShu Anzai   ~CommandObjectLogTimerEnable() override = default;
32430fdc8d8SChris Lattner 
3255a988416SJim Ingham protected:
326b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
32730fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
32830fdc8d8SChris Lattner 
3291d3b7370SShu Anzai     if (args.GetArgumentCount() == 0) {
33030fdc8d8SChris Lattner       Timer::SetDisplayDepth(UINT32_MAX);
33130fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishNoResult);
3321d3b7370SShu Anzai     } else if (args.GetArgumentCount() == 1) {
33311eb9c64SZachary Turner       uint32_t depth;
3341d3b7370SShu Anzai       if (args[0].ref().consumeInteger(0, depth)) {
335b9c1b51eSKate Stone         result.AppendError(
336b9c1b51eSKate Stone             "Could not convert enable depth to an unsigned integer.");
33711eb9c64SZachary Turner       } else {
33811eb9c64SZachary Turner         Timer::SetDisplayDepth(depth);
33911eb9c64SZachary Turner         result.SetStatus(eReturnStatusSuccessFinishNoResult);
340932725faSJim Ingham       }
341932725faSJim Ingham     }
342932725faSJim Ingham 
343b9c1b51eSKate Stone     if (!result.Succeeded()) {
34430fdc8d8SChris Lattner       result.AppendError("Missing subcommand");
34530fdc8d8SChris Lattner       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
34630fdc8d8SChris Lattner     }
34730fdc8d8SChris Lattner     return result.Succeeded();
34830fdc8d8SChris Lattner   }
34930fdc8d8SChris Lattner };
35030fdc8d8SChris Lattner 
3511d3b7370SShu Anzai class CommandObjectLogTimerDisable : public CommandObjectParsed {
3521d3b7370SShu Anzai public:
3531d3b7370SShu Anzai   // Constructors and Destructors
3541d3b7370SShu Anzai   CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
3551d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers disable",
3561d3b7370SShu Anzai                             "disable LLDB internal performance timers",
3571d3b7370SShu Anzai                             nullptr) {}
3581d3b7370SShu Anzai 
3591d3b7370SShu Anzai   ~CommandObjectLogTimerDisable() override = default;
3601d3b7370SShu Anzai 
3611d3b7370SShu Anzai protected:
3621d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3631d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3641d3b7370SShu Anzai     Timer::SetDisplayDepth(0);
3651d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3661d3b7370SShu Anzai 
3671d3b7370SShu Anzai     if (!result.Succeeded()) {
3681d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3691d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3701d3b7370SShu Anzai     }
3711d3b7370SShu Anzai     return result.Succeeded();
3721d3b7370SShu Anzai   }
3731d3b7370SShu Anzai };
3741d3b7370SShu Anzai 
3751d3b7370SShu Anzai class CommandObjectLogTimerDump : public CommandObjectParsed {
3761d3b7370SShu Anzai public:
3771d3b7370SShu Anzai   // Constructors and Destructors
3781d3b7370SShu Anzai   CommandObjectLogTimerDump(CommandInterpreter &interpreter)
3791d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers dump",
3801d3b7370SShu Anzai                             "dump LLDB internal performance timers", nullptr) {}
3811d3b7370SShu Anzai 
3821d3b7370SShu Anzai   ~CommandObjectLogTimerDump() override = default;
3831d3b7370SShu Anzai 
3841d3b7370SShu Anzai protected:
3851d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3861d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3871d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3881d3b7370SShu Anzai 
3891d3b7370SShu Anzai     if (!result.Succeeded()) {
3901d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3911d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3921d3b7370SShu Anzai     }
3931d3b7370SShu Anzai     return result.Succeeded();
3941d3b7370SShu Anzai   }
3951d3b7370SShu Anzai };
3961d3b7370SShu Anzai 
3971d3b7370SShu Anzai class CommandObjectLogTimerReset : public CommandObjectParsed {
3981d3b7370SShu Anzai public:
3991d3b7370SShu Anzai   // Constructors and Destructors
4001d3b7370SShu Anzai   CommandObjectLogTimerReset(CommandInterpreter &interpreter)
4011d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers reset",
4021d3b7370SShu Anzai                             "reset LLDB internal performance timers", nullptr) {
4031d3b7370SShu Anzai   }
4041d3b7370SShu Anzai 
4051d3b7370SShu Anzai   ~CommandObjectLogTimerReset() override = default;
4061d3b7370SShu Anzai 
4071d3b7370SShu Anzai protected:
4081d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4091d3b7370SShu Anzai     Timer::ResetCategoryTimes();
4101d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4111d3b7370SShu Anzai 
4121d3b7370SShu Anzai     if (!result.Succeeded()) {
4131d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4141d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4151d3b7370SShu Anzai     }
4161d3b7370SShu Anzai     return result.Succeeded();
4171d3b7370SShu Anzai   }
4181d3b7370SShu Anzai };
4191d3b7370SShu Anzai 
4201d3b7370SShu Anzai class CommandObjectLogTimerIncrement : public CommandObjectParsed {
4211d3b7370SShu Anzai public:
4221d3b7370SShu Anzai   // Constructors and Destructors
4231d3b7370SShu Anzai   CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
4241d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers increment",
4251d3b7370SShu Anzai                             "increment LLDB internal performance timers",
4261d3b7370SShu Anzai                             "log timers increment <bool>") {
4271d3b7370SShu Anzai     CommandArgumentEntry arg;
4281d3b7370SShu Anzai     CommandArgumentData bool_arg;
4291d3b7370SShu Anzai 
4301d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
4311d3b7370SShu Anzai     bool_arg.arg_type = eArgTypeBoolean;
4321d3b7370SShu Anzai     bool_arg.arg_repetition = eArgRepeatPlain;
4331d3b7370SShu Anzai 
4341d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
4351d3b7370SShu Anzai     // argument entry.
4361d3b7370SShu Anzai     arg.push_back(bool_arg);
4371d3b7370SShu Anzai 
4381d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
4391d3b7370SShu Anzai     m_arguments.push_back(arg);
4401d3b7370SShu Anzai   }
4411d3b7370SShu Anzai 
4421d3b7370SShu Anzai   ~CommandObjectLogTimerIncrement() override = default;
4431d3b7370SShu Anzai 
4441d3b7370SShu Anzai   void
4451d3b7370SShu Anzai   HandleArgumentCompletion(CompletionRequest &request,
4461d3b7370SShu Anzai                            OptionElementVector &opt_element_vector) override {
4471d3b7370SShu Anzai     request.TryCompleteCurrentArg("true");
4481d3b7370SShu Anzai     request.TryCompleteCurrentArg("false");
4491d3b7370SShu Anzai   }
4501d3b7370SShu Anzai 
4511d3b7370SShu Anzai protected:
4521d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4531d3b7370SShu Anzai     result.SetStatus(eReturnStatusFailed);
4541d3b7370SShu Anzai 
4551d3b7370SShu Anzai     if (args.GetArgumentCount() == 1) {
4561d3b7370SShu Anzai       bool success;
4571d3b7370SShu Anzai       bool increment =
4581d3b7370SShu Anzai           OptionArgParser::ToBoolean(args[0].ref(), false, &success);
4591d3b7370SShu Anzai 
4601d3b7370SShu Anzai       if (success) {
4611d3b7370SShu Anzai         Timer::SetQuiet(!increment);
4621d3b7370SShu Anzai         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4631d3b7370SShu Anzai       } else
4641d3b7370SShu Anzai         result.AppendError("Could not convert increment value to boolean.");
4651d3b7370SShu Anzai     }
4661d3b7370SShu Anzai 
4671d3b7370SShu Anzai     if (!result.Succeeded()) {
4681d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4691d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4701d3b7370SShu Anzai     }
4711d3b7370SShu Anzai     return result.Succeeded();
4721d3b7370SShu Anzai   }
4731d3b7370SShu Anzai };
4741d3b7370SShu Anzai 
4751d3b7370SShu Anzai class CommandObjectLogTimer : public CommandObjectMultiword {
4761d3b7370SShu Anzai public:
4771d3b7370SShu Anzai   CommandObjectLogTimer(CommandInterpreter &interpreter)
4781d3b7370SShu Anzai       : CommandObjectMultiword(interpreter, "log timers",
4791d3b7370SShu Anzai                                "Enable, disable, dump, and reset LLDB internal "
4801d3b7370SShu Anzai                                "performance timers.",
4811d3b7370SShu Anzai                                "log timers < enable <depth> | disable | dump | "
4821d3b7370SShu Anzai                                "increment <bool> | reset >") {
4831d3b7370SShu Anzai     LoadSubCommand("enable", CommandObjectSP(
4841d3b7370SShu Anzai                                  new CommandObjectLogTimerEnable(interpreter)));
4851d3b7370SShu Anzai     LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
4861d3b7370SShu Anzai                                   interpreter)));
4871d3b7370SShu Anzai     LoadSubCommand("dump",
4881d3b7370SShu Anzai                    CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
4891d3b7370SShu Anzai     LoadSubCommand(
4901d3b7370SShu Anzai         "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
4911d3b7370SShu Anzai     LoadSubCommand(
4921d3b7370SShu Anzai         "increment",
4931d3b7370SShu Anzai         CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
4941d3b7370SShu Anzai   }
4951d3b7370SShu Anzai 
4961d3b7370SShu Anzai   ~CommandObjectLogTimer() override = default;
4971d3b7370SShu Anzai };
4981d3b7370SShu Anzai 
4997428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
500b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "log",
501b9c1b51eSKate Stone                              "Commands controlling LLDB internal logging.",
502b9c1b51eSKate Stone                              "log <subcommand> [<command-options>]") {
503b9c1b51eSKate Stone   LoadSubCommand("enable",
504b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
505b9c1b51eSKate Stone   LoadSubCommand("disable",
506b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
507b9c1b51eSKate Stone   LoadSubCommand("list",
508b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogList(interpreter)));
509b9c1b51eSKate Stone   LoadSubCommand("timers",
510b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
51130fdc8d8SChris Lattner }
51230fdc8d8SChris Lattner 
51326cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
514