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.",
48*abb0ed44SKazu Hirata                             nullptr) {
49ceb6b139SCaroline Tice     CommandArgumentEntry arg1;
50ceb6b139SCaroline Tice     CommandArgumentEntry arg2;
51405fe67fSCaroline Tice     CommandArgumentData channel_arg;
52ceb6b139SCaroline Tice     CommandArgumentData category_arg;
53405fe67fSCaroline Tice 
54405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
55405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
56405fe67fSCaroline Tice     channel_arg.arg_repetition = eArgRepeatPlain;
57405fe67fSCaroline Tice 
58b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
59b9c1b51eSKate Stone     // argument entry.
60ceb6b139SCaroline Tice     arg1.push_back(channel_arg);
61ceb6b139SCaroline Tice 
62ceb6b139SCaroline Tice     category_arg.arg_type = eArgTypeLogCategory;
63ceb6b139SCaroline Tice     category_arg.arg_repetition = eArgRepeatPlus;
64ceb6b139SCaroline Tice 
65ceb6b139SCaroline Tice     arg2.push_back(category_arg);
66405fe67fSCaroline Tice 
67405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
68ceb6b139SCaroline Tice     m_arguments.push_back(arg1);
69ceb6b139SCaroline Tice     m_arguments.push_back(arg2);
7030fdc8d8SChris Lattner   }
7130fdc8d8SChris Lattner 
7226cac3afSEugene Zelenko   ~CommandObjectLogEnable() override = default;
7330fdc8d8SChris Lattner 
74b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
7530fdc8d8SChris Lattner 
76b9c1b51eSKate Stone   class CommandOptions : public Options {
7730fdc8d8SChris Lattner   public:
78*abb0ed44SKazu Hirata     CommandOptions() {}
7930fdc8d8SChris Lattner 
8026cac3afSEugene Zelenko     ~CommandOptions() override = default;
8130fdc8d8SChris Lattner 
8297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
83b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
8497206d57SZachary Turner       Status error;
853bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
8630fdc8d8SChris Lattner 
87b9c1b51eSKate Stone       switch (short_option) {
88b9c1b51eSKate Stone       case 'f':
898f3be7a3SJonas Devlieghere         log_file.SetFile(option_arg, FileSpec::Style::native);
908f3be7a3SJonas Devlieghere         FileSystem::Instance().Resolve(log_file);
91b9c1b51eSKate Stone         break;
92b9c1b51eSKate Stone       case 't':
93b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_THREADSAFE;
94b9c1b51eSKate Stone         break;
95b9c1b51eSKate Stone       case 'v':
96b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_VERBOSE;
97b9c1b51eSKate Stone         break;
98b9c1b51eSKate Stone       case 's':
99b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
100b9c1b51eSKate Stone         break;
101b9c1b51eSKate Stone       case 'T':
102b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
103b9c1b51eSKate Stone         break;
104b9c1b51eSKate Stone       case 'p':
105b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
106b9c1b51eSKate Stone         break;
107b9c1b51eSKate Stone       case 'n':
108b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
109b9c1b51eSKate Stone         break;
110b9c1b51eSKate Stone       case 'S':
111b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_BACKTRACE;
112b9c1b51eSKate Stone         break;
113b9c1b51eSKate Stone       case 'a':
114b9c1b51eSKate Stone         log_options |= LLDB_LOG_OPTION_APPEND;
115b9c1b51eSKate Stone         break;
116107d9bbdSPavel Labath       case 'F':
117107d9bbdSPavel Labath         log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
11890505a0aSPavel Labath         break;
11930fdc8d8SChris Lattner       default:
12036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12130fdc8d8SChris Lattner       }
12230fdc8d8SChris Lattner 
12330fdc8d8SChris Lattner       return error;
12430fdc8d8SChris Lattner     }
12530fdc8d8SChris Lattner 
126b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
127889037d7SGreg Clayton       log_file.Clear();
12830fdc8d8SChris Lattner       log_options = 0;
12930fdc8d8SChris Lattner     }
13030fdc8d8SChris Lattner 
1311f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
13270602439SZachary Turner       return llvm::makeArrayRef(g_log_options);
1331f0f5b5bSZachary Turner     }
13430fdc8d8SChris Lattner 
13530fdc8d8SChris Lattner     // Instance variables to hold the values for command options.
13630fdc8d8SChris Lattner 
137889037d7SGreg Clayton     FileSpec log_file;
1389494c510SJonas Devlieghere     uint32_t log_options = 0;
13930fdc8d8SChris Lattner   };
14030fdc8d8SChris Lattner 
1416ba63d88SRaphael Isemann   void
1426ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
1436ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
1446ba63d88SRaphael Isemann     CompleteEnableDisable(request);
1456ba63d88SRaphael Isemann   }
1466ba63d88SRaphael Isemann 
14730fdc8d8SChris Lattner protected:
148b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
149b9c1b51eSKate Stone     if (args.GetArgumentCount() < 2) {
150b9c1b51eSKate Stone       result.AppendErrorWithFormat(
151b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
152b9c1b51eSKate Stone           m_cmd_name.c_str());
15311eb9c64SZachary Turner       return false;
15411eb9c64SZachary Turner     }
15511eb9c64SZachary Turner 
15611eb9c64SZachary Turner     // Store into a std::string since we're about to shift the channel off.
157adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
1585a988416SJim Ingham     args.Shift(); // Shift off the channel
159889037d7SGreg Clayton     char log_file[PATH_MAX];
160889037d7SGreg Clayton     if (m_options.log_file)
161889037d7SGreg Clayton       m_options.log_file.GetPath(log_file, sizeof(log_file));
162889037d7SGreg Clayton     else
163889037d7SGreg Clayton       log_file[0] = '\0';
164775588c0SPavel Labath 
165775588c0SPavel Labath     std::string error;
166775588c0SPavel Labath     llvm::raw_string_ostream error_stream(error);
16757179860SJonas Devlieghere     bool success =
16857179860SJonas Devlieghere         GetDebugger().EnableLog(channel, args.GetArgumentArrayRef(), log_file,
16957179860SJonas Devlieghere                                 m_options.log_options, error_stream);
170775588c0SPavel Labath     result.GetErrorStream() << error_stream.str();
171775588c0SPavel Labath 
1725a988416SJim Ingham     if (success)
1735a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1745a988416SJim Ingham     else
1755a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
1765a988416SJim Ingham     return result.Succeeded();
1775a988416SJim Ingham   }
1785a988416SJim Ingham 
17930fdc8d8SChris Lattner   CommandOptions m_options;
18030fdc8d8SChris Lattner };
18130fdc8d8SChris Lattner 
182b9c1b51eSKate Stone class CommandObjectLogDisable : public CommandObjectParsed {
18330fdc8d8SChris Lattner public:
18430fdc8d8SChris Lattner   // Constructors and Destructors
185b9c1b51eSKate Stone   CommandObjectLogDisable(CommandInterpreter &interpreter)
186b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log disable",
1877149fab4SCaroline Tice                             "Disable one or more log channel categories.",
188b9c1b51eSKate Stone                             nullptr) {
1897149fab4SCaroline Tice     CommandArgumentEntry arg1;
1907149fab4SCaroline Tice     CommandArgumentEntry arg2;
191405fe67fSCaroline Tice     CommandArgumentData channel_arg;
1927149fab4SCaroline Tice     CommandArgumentData category_arg;
193405fe67fSCaroline Tice 
194405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
195405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
1967149fab4SCaroline Tice     channel_arg.arg_repetition = eArgRepeatPlain;
197405fe67fSCaroline Tice 
198b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
199b9c1b51eSKate Stone     // argument entry.
2007149fab4SCaroline Tice     arg1.push_back(channel_arg);
2017149fab4SCaroline Tice 
2027149fab4SCaroline Tice     category_arg.arg_type = eArgTypeLogCategory;
2037149fab4SCaroline Tice     category_arg.arg_repetition = eArgRepeatPlus;
2047149fab4SCaroline Tice 
2057149fab4SCaroline Tice     arg2.push_back(category_arg);
206405fe67fSCaroline Tice 
207405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
2087149fab4SCaroline Tice     m_arguments.push_back(arg1);
2097149fab4SCaroline Tice     m_arguments.push_back(arg2);
21030fdc8d8SChris Lattner   }
21130fdc8d8SChris Lattner 
21226cac3afSEugene Zelenko   ~CommandObjectLogDisable() override = default;
21330fdc8d8SChris Lattner 
2146ba63d88SRaphael Isemann   void
2156ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
2166ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
2176ba63d88SRaphael Isemann     CompleteEnableDisable(request);
2186ba63d88SRaphael Isemann   }
2196ba63d88SRaphael Isemann 
2205a988416SJim Ingham protected:
221b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
22211eb9c64SZachary Turner     if (args.empty()) {
223b9c1b51eSKate Stone       result.AppendErrorWithFormat(
224b9c1b51eSKate Stone           "%s takes a log channel and one or more log types.\n",
225b9c1b51eSKate Stone           m_cmd_name.c_str());
22611eb9c64SZachary Turner       return false;
22711eb9c64SZachary Turner     }
22811eb9c64SZachary Turner 
229adcd0268SBenjamin Kramer     const std::string channel = std::string(args[0].ref());
23020ad3c40SCaroline Tice     args.Shift(); // Shift off the channel
231fb0d22d6SPavel Labath     if (channel == "all") {
232775588c0SPavel Labath       Log::DisableAllLogChannels();
2335fb8af40SPavel Labath       result.SetStatus(eReturnStatusSuccessFinishNoResult);
234fb0d22d6SPavel Labath     } else {
235775588c0SPavel Labath       std::string error;
236775588c0SPavel Labath       llvm::raw_string_ostream error_stream(error);
2375e336903SPavel Labath       if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
238775588c0SPavel Labath                                  error_stream))
239fb0d22d6SPavel Labath         result.SetStatus(eReturnStatusSuccessFinishNoResult);
240775588c0SPavel Labath       result.GetErrorStream() << error_stream.str();
24130fdc8d8SChris Lattner     }
24230fdc8d8SChris Lattner     return result.Succeeded();
24330fdc8d8SChris Lattner   }
24430fdc8d8SChris Lattner };
24530fdc8d8SChris Lattner 
246b9c1b51eSKate Stone class CommandObjectLogList : public CommandObjectParsed {
24730fdc8d8SChris Lattner public:
24830fdc8d8SChris Lattner   // Constructors and Destructors
249b9c1b51eSKate Stone   CommandObjectLogList(CommandInterpreter &interpreter)
250b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "log list",
251b9c1b51eSKate Stone                             "List the log categories for one or more log "
252b9c1b51eSKate Stone                             "channels.  If none specified, lists them all.",
253b9c1b51eSKate Stone                             nullptr) {
254405fe67fSCaroline Tice     CommandArgumentEntry arg;
255405fe67fSCaroline Tice     CommandArgumentData channel_arg;
256405fe67fSCaroline Tice 
257405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
258405fe67fSCaroline Tice     channel_arg.arg_type = eArgTypeLogChannel;
259405fe67fSCaroline Tice     channel_arg.arg_repetition = eArgRepeatStar;
260405fe67fSCaroline Tice 
261b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
262b9c1b51eSKate Stone     // argument entry.
263405fe67fSCaroline Tice     arg.push_back(channel_arg);
264405fe67fSCaroline Tice 
265405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
266405fe67fSCaroline Tice     m_arguments.push_back(arg);
26730fdc8d8SChris Lattner   }
26830fdc8d8SChris Lattner 
26926cac3afSEugene Zelenko   ~CommandObjectLogList() override = default;
27030fdc8d8SChris Lattner 
2716ba63d88SRaphael Isemann   void
2726ba63d88SRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
2736ba63d88SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
2746ba63d88SRaphael Isemann     for (llvm::StringRef channel : Log::ListChannels())
2756ba63d88SRaphael Isemann       request.TryCompleteCurrentArg(channel);
2766ba63d88SRaphael Isemann   }
2776ba63d88SRaphael Isemann 
2785a988416SJim Ingham protected:
279b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
280775588c0SPavel Labath     std::string output;
281775588c0SPavel Labath     llvm::raw_string_ostream output_stream(output);
28211eb9c64SZachary Turner     if (args.empty()) {
283775588c0SPavel Labath       Log::ListAllLogChannels(output_stream);
28430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
285b9c1b51eSKate Stone     } else {
286fb0d22d6SPavel Labath       bool success = true;
287fb0d22d6SPavel Labath       for (const auto &entry : args.entries())
288775588c0SPavel Labath         success =
2890d9a201eSRaphael Isemann             success && Log::ListChannelCategories(entry.ref(), output_stream);
290fb0d22d6SPavel Labath       if (success)
29130fdc8d8SChris Lattner         result.SetStatus(eReturnStatusSuccessFinishResult);
29230fdc8d8SChris Lattner     }
293775588c0SPavel Labath     result.GetOutputStream() << output_stream.str();
29430fdc8d8SChris Lattner     return result.Succeeded();
29530fdc8d8SChris Lattner   }
29630fdc8d8SChris Lattner };
29730fdc8d8SChris Lattner 
2981d3b7370SShu Anzai class CommandObjectLogTimerEnable : public CommandObjectParsed {
29930fdc8d8SChris Lattner public:
30030fdc8d8SChris Lattner   // Constructors and Destructors
3011d3b7370SShu Anzai   CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
3021d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers enable",
3031d3b7370SShu Anzai                             "enable LLDB internal performance timers",
3041d3b7370SShu Anzai                             "log timers enable <depth>") {
3051d3b7370SShu Anzai     CommandArgumentEntry arg;
3061d3b7370SShu Anzai     CommandArgumentData depth_arg;
30730fdc8d8SChris Lattner 
3081d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
3091d3b7370SShu Anzai     depth_arg.arg_type = eArgTypeCount;
3101d3b7370SShu Anzai     depth_arg.arg_repetition = eArgRepeatOptional;
3111d3b7370SShu Anzai 
3121d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
3131d3b7370SShu Anzai     // argument entry.
3141d3b7370SShu Anzai     arg.push_back(depth_arg);
3151d3b7370SShu Anzai 
3161d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
3171d3b7370SShu Anzai     m_arguments.push_back(arg);
3181d3b7370SShu Anzai   }
3191d3b7370SShu Anzai 
3201d3b7370SShu Anzai   ~CommandObjectLogTimerEnable() override = default;
32130fdc8d8SChris Lattner 
3225a988416SJim Ingham protected:
323b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
32430fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
32530fdc8d8SChris Lattner 
3261d3b7370SShu Anzai     if (args.GetArgumentCount() == 0) {
32730fdc8d8SChris Lattner       Timer::SetDisplayDepth(UINT32_MAX);
32830fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishNoResult);
3291d3b7370SShu Anzai     } else if (args.GetArgumentCount() == 1) {
33011eb9c64SZachary Turner       uint32_t depth;
3311d3b7370SShu Anzai       if (args[0].ref().consumeInteger(0, depth)) {
332b9c1b51eSKate Stone         result.AppendError(
333b9c1b51eSKate Stone             "Could not convert enable depth to an unsigned integer.");
33411eb9c64SZachary Turner       } else {
33511eb9c64SZachary Turner         Timer::SetDisplayDepth(depth);
33611eb9c64SZachary Turner         result.SetStatus(eReturnStatusSuccessFinishNoResult);
337932725faSJim Ingham       }
338932725faSJim Ingham     }
339932725faSJim Ingham 
340b9c1b51eSKate Stone     if (!result.Succeeded()) {
34130fdc8d8SChris Lattner       result.AppendError("Missing subcommand");
34230fdc8d8SChris Lattner       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
34330fdc8d8SChris Lattner     }
34430fdc8d8SChris Lattner     return result.Succeeded();
34530fdc8d8SChris Lattner   }
34630fdc8d8SChris Lattner };
34730fdc8d8SChris Lattner 
3481d3b7370SShu Anzai class CommandObjectLogTimerDisable : public CommandObjectParsed {
3491d3b7370SShu Anzai public:
3501d3b7370SShu Anzai   // Constructors and Destructors
3511d3b7370SShu Anzai   CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
3521d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers disable",
3531d3b7370SShu Anzai                             "disable LLDB internal performance timers",
3541d3b7370SShu Anzai                             nullptr) {}
3551d3b7370SShu Anzai 
3561d3b7370SShu Anzai   ~CommandObjectLogTimerDisable() override = default;
3571d3b7370SShu Anzai 
3581d3b7370SShu Anzai protected:
3591d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3601d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3611d3b7370SShu Anzai     Timer::SetDisplayDepth(0);
3621d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3631d3b7370SShu Anzai 
3641d3b7370SShu Anzai     if (!result.Succeeded()) {
3651d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3661d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3671d3b7370SShu Anzai     }
3681d3b7370SShu Anzai     return result.Succeeded();
3691d3b7370SShu Anzai   }
3701d3b7370SShu Anzai };
3711d3b7370SShu Anzai 
3721d3b7370SShu Anzai class CommandObjectLogTimerDump : public CommandObjectParsed {
3731d3b7370SShu Anzai public:
3741d3b7370SShu Anzai   // Constructors and Destructors
3751d3b7370SShu Anzai   CommandObjectLogTimerDump(CommandInterpreter &interpreter)
3761d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers dump",
3771d3b7370SShu Anzai                             "dump LLDB internal performance timers", nullptr) {}
3781d3b7370SShu Anzai 
3791d3b7370SShu Anzai   ~CommandObjectLogTimerDump() override = default;
3801d3b7370SShu Anzai 
3811d3b7370SShu Anzai protected:
3821d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
3831d3b7370SShu Anzai     Timer::DumpCategoryTimes(&result.GetOutputStream());
3841d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
3851d3b7370SShu Anzai 
3861d3b7370SShu Anzai     if (!result.Succeeded()) {
3871d3b7370SShu Anzai       result.AppendError("Missing subcommand");
3881d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
3891d3b7370SShu Anzai     }
3901d3b7370SShu Anzai     return result.Succeeded();
3911d3b7370SShu Anzai   }
3921d3b7370SShu Anzai };
3931d3b7370SShu Anzai 
3941d3b7370SShu Anzai class CommandObjectLogTimerReset : public CommandObjectParsed {
3951d3b7370SShu Anzai public:
3961d3b7370SShu Anzai   // Constructors and Destructors
3971d3b7370SShu Anzai   CommandObjectLogTimerReset(CommandInterpreter &interpreter)
3981d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers reset",
3991d3b7370SShu Anzai                             "reset LLDB internal performance timers", nullptr) {
4001d3b7370SShu Anzai   }
4011d3b7370SShu Anzai 
4021d3b7370SShu Anzai   ~CommandObjectLogTimerReset() override = default;
4031d3b7370SShu Anzai 
4041d3b7370SShu Anzai protected:
4051d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4061d3b7370SShu Anzai     Timer::ResetCategoryTimes();
4071d3b7370SShu Anzai     result.SetStatus(eReturnStatusSuccessFinishResult);
4081d3b7370SShu Anzai 
4091d3b7370SShu Anzai     if (!result.Succeeded()) {
4101d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4111d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4121d3b7370SShu Anzai     }
4131d3b7370SShu Anzai     return result.Succeeded();
4141d3b7370SShu Anzai   }
4151d3b7370SShu Anzai };
4161d3b7370SShu Anzai 
4171d3b7370SShu Anzai class CommandObjectLogTimerIncrement : public CommandObjectParsed {
4181d3b7370SShu Anzai public:
4191d3b7370SShu Anzai   // Constructors and Destructors
4201d3b7370SShu Anzai   CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
4211d3b7370SShu Anzai       : CommandObjectParsed(interpreter, "log timers increment",
4221d3b7370SShu Anzai                             "increment LLDB internal performance timers",
4231d3b7370SShu Anzai                             "log timers increment <bool>") {
4241d3b7370SShu Anzai     CommandArgumentEntry arg;
4251d3b7370SShu Anzai     CommandArgumentData bool_arg;
4261d3b7370SShu Anzai 
4271d3b7370SShu Anzai     // Define the first (and only) variant of this arg.
4281d3b7370SShu Anzai     bool_arg.arg_type = eArgTypeBoolean;
4291d3b7370SShu Anzai     bool_arg.arg_repetition = eArgRepeatPlain;
4301d3b7370SShu Anzai 
4311d3b7370SShu Anzai     // There is only one variant this argument could be; put it into the
4321d3b7370SShu Anzai     // argument entry.
4331d3b7370SShu Anzai     arg.push_back(bool_arg);
4341d3b7370SShu Anzai 
4351d3b7370SShu Anzai     // Push the data for the first argument into the m_arguments vector.
4361d3b7370SShu Anzai     m_arguments.push_back(arg);
4371d3b7370SShu Anzai   }
4381d3b7370SShu Anzai 
4391d3b7370SShu Anzai   ~CommandObjectLogTimerIncrement() override = default;
4401d3b7370SShu Anzai 
4411d3b7370SShu Anzai   void
4421d3b7370SShu Anzai   HandleArgumentCompletion(CompletionRequest &request,
4431d3b7370SShu Anzai                            OptionElementVector &opt_element_vector) override {
4441d3b7370SShu Anzai     request.TryCompleteCurrentArg("true");
4451d3b7370SShu Anzai     request.TryCompleteCurrentArg("false");
4461d3b7370SShu Anzai   }
4471d3b7370SShu Anzai 
4481d3b7370SShu Anzai protected:
4491d3b7370SShu Anzai   bool DoExecute(Args &args, CommandReturnObject &result) override {
4501d3b7370SShu Anzai     result.SetStatus(eReturnStatusFailed);
4511d3b7370SShu Anzai 
4521d3b7370SShu Anzai     if (args.GetArgumentCount() == 1) {
4531d3b7370SShu Anzai       bool success;
4541d3b7370SShu Anzai       bool increment =
4551d3b7370SShu Anzai           OptionArgParser::ToBoolean(args[0].ref(), false, &success);
4561d3b7370SShu Anzai 
4571d3b7370SShu Anzai       if (success) {
4581d3b7370SShu Anzai         Timer::SetQuiet(!increment);
4591d3b7370SShu Anzai         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4601d3b7370SShu Anzai       } else
4611d3b7370SShu Anzai         result.AppendError("Could not convert increment value to boolean.");
4621d3b7370SShu Anzai     }
4631d3b7370SShu Anzai 
4641d3b7370SShu Anzai     if (!result.Succeeded()) {
4651d3b7370SShu Anzai       result.AppendError("Missing subcommand");
4661d3b7370SShu Anzai       result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
4671d3b7370SShu Anzai     }
4681d3b7370SShu Anzai     return result.Succeeded();
4691d3b7370SShu Anzai   }
4701d3b7370SShu Anzai };
4711d3b7370SShu Anzai 
4721d3b7370SShu Anzai class CommandObjectLogTimer : public CommandObjectMultiword {
4731d3b7370SShu Anzai public:
4741d3b7370SShu Anzai   CommandObjectLogTimer(CommandInterpreter &interpreter)
4751d3b7370SShu Anzai       : CommandObjectMultiword(interpreter, "log timers",
4761d3b7370SShu Anzai                                "Enable, disable, dump, and reset LLDB internal "
4771d3b7370SShu Anzai                                "performance timers.",
4781d3b7370SShu Anzai                                "log timers < enable <depth> | disable | dump | "
4791d3b7370SShu Anzai                                "increment <bool> | reset >") {
4801d3b7370SShu Anzai     LoadSubCommand("enable", CommandObjectSP(
4811d3b7370SShu Anzai                                  new CommandObjectLogTimerEnable(interpreter)));
4821d3b7370SShu Anzai     LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
4831d3b7370SShu Anzai                                   interpreter)));
4841d3b7370SShu Anzai     LoadSubCommand("dump",
4851d3b7370SShu Anzai                    CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
4861d3b7370SShu Anzai     LoadSubCommand(
4871d3b7370SShu Anzai         "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
4881d3b7370SShu Anzai     LoadSubCommand(
4891d3b7370SShu Anzai         "increment",
4901d3b7370SShu Anzai         CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
4911d3b7370SShu Anzai   }
4921d3b7370SShu Anzai 
4931d3b7370SShu Anzai   ~CommandObjectLogTimer() override = default;
4941d3b7370SShu Anzai };
4951d3b7370SShu Anzai 
4967428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
497b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "log",
498b9c1b51eSKate Stone                              "Commands controlling LLDB internal logging.",
499b9c1b51eSKate Stone                              "log <subcommand> [<command-options>]") {
500b9c1b51eSKate Stone   LoadSubCommand("enable",
501b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogEnable(interpreter)));
502b9c1b51eSKate Stone   LoadSubCommand("disable",
503b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogDisable(interpreter)));
504b9c1b51eSKate Stone   LoadSubCommand("list",
505b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogList(interpreter)));
506b9c1b51eSKate Stone   LoadSubCommand("timers",
507b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectLogTimer(interpreter)));
50830fdc8d8SChris Lattner }
50930fdc8d8SChris Lattner 
51026cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
511