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