130fdc8d8SChris Lattner //===-- CommandObjectLog.cpp ------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
1330fdc8d8SChris Lattner // Project includes
1426cac3afSEugene Zelenko #include "CommandObjectLog.h"
1540af72e1SJim Ingham #include "lldb/Interpreter/Args.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Debugger.h"
1753239f00SGreg Clayton #include "lldb/Host/FileSpec.h"
1830fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1930fdc8d8SChris Lattner #include "lldb/Core/Module.h"
2040af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
2130fdc8d8SChris Lattner #include "lldb/Core/RegularExpression.h"
2230fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
2330fdc8d8SChris Lattner #include "lldb/Core/StreamFile.h"
2430fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
256611103cSGreg Clayton #include "lldb/Core/Debugger.h"
265275aaa0SVince Harron #include "lldb/Host/StringConvert.h"
274be3990fSSean Callanan #include "lldb/Interpreter/CommandInterpreter.h"
2830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
2930fdc8d8SChris Lattner #include "lldb/Symbol/LineTable.h"
3030fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
3130fdc8d8SChris Lattner #include "lldb/Symbol/SymbolFile.h"
3230fdc8d8SChris Lattner #include "lldb/Symbol/SymbolVendor.h"
3330fdc8d8SChris Lattner #include "lldb/Target/Process.h"
3430fdc8d8SChris Lattner #include "lldb/Target/Target.h"
3530fdc8d8SChris Lattner 
3630fdc8d8SChris Lattner using namespace lldb;
3730fdc8d8SChris Lattner using namespace lldb_private;
3830fdc8d8SChris Lattner 
395a988416SJim Ingham class CommandObjectLogEnable : public CommandObjectParsed
4030fdc8d8SChris Lattner {
4130fdc8d8SChris Lattner public:
4230fdc8d8SChris Lattner     //------------------------------------------------------------------
4330fdc8d8SChris Lattner     // Constructors and Destructors
4430fdc8d8SChris Lattner     //------------------------------------------------------------------
45a7015092SGreg Clayton     CommandObjectLogEnable(CommandInterpreter &interpreter) :
465a988416SJim Ingham         CommandObjectParsed(interpreter,
47a7015092SGreg Clayton                             "log enable",
4830fdc8d8SChris Lattner                             "Enable logging for a single log channel.",
4926cac3afSEugene Zelenko                             nullptr),
50e1cfbc79STodd Fiala         m_options()
5130fdc8d8SChris Lattner     {
52ceb6b139SCaroline Tice         CommandArgumentEntry arg1;
53ceb6b139SCaroline Tice         CommandArgumentEntry arg2;
54405fe67fSCaroline Tice         CommandArgumentData channel_arg;
55ceb6b139SCaroline Tice         CommandArgumentData category_arg;
56405fe67fSCaroline Tice 
57405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
58405fe67fSCaroline Tice         channel_arg.arg_type = eArgTypeLogChannel;
59405fe67fSCaroline Tice         channel_arg.arg_repetition = eArgRepeatPlain;
60405fe67fSCaroline Tice 
61405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
62ceb6b139SCaroline Tice         arg1.push_back (channel_arg);
63ceb6b139SCaroline Tice 
64ceb6b139SCaroline Tice         category_arg.arg_type = eArgTypeLogCategory;
65ceb6b139SCaroline Tice         category_arg.arg_repetition = eArgRepeatPlus;
66ceb6b139SCaroline Tice 
67ceb6b139SCaroline Tice         arg2.push_back (category_arg);
68405fe67fSCaroline Tice 
69405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
70ceb6b139SCaroline Tice         m_arguments.push_back (arg1);
71ceb6b139SCaroline Tice         m_arguments.push_back (arg2);
7230fdc8d8SChris Lattner     }
7330fdc8d8SChris Lattner 
7426cac3afSEugene Zelenko     ~CommandObjectLogEnable() override = default;
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner     Options *
7713d21e9aSBruce Mitchener     GetOptions () override
7830fdc8d8SChris Lattner     {
7930fdc8d8SChris Lattner         return &m_options;
8030fdc8d8SChris Lattner     }
8130fdc8d8SChris Lattner 
82ab65b34fSGreg Clayton //    int
83ab65b34fSGreg Clayton //    HandleArgumentCompletion (Args &input,
84ab65b34fSGreg Clayton //                              int &cursor_index,
85ab65b34fSGreg Clayton //                              int &cursor_char_position,
86ab65b34fSGreg Clayton //                              OptionElementVector &opt_element_vector,
87ab65b34fSGreg Clayton //                              int match_start_point,
88ab65b34fSGreg Clayton //                              int max_return_elements,
89ab65b34fSGreg Clayton //                              bool &word_complete,
90ab65b34fSGreg Clayton //                              StringList &matches)
91ab65b34fSGreg Clayton //    {
92ab65b34fSGreg Clayton //        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
93ab65b34fSGreg Clayton //        completion_str.erase (cursor_char_position);
94ab65b34fSGreg Clayton //
95ab65b34fSGreg Clayton //        if (cursor_index == 1)
96ab65b34fSGreg Clayton //        {
97ab65b34fSGreg Clayton //            //
98ab65b34fSGreg Clayton //            Log::AutoCompleteChannelName (completion_str.c_str(), matches);
99ab65b34fSGreg Clayton //        }
100ab65b34fSGreg Clayton //        return matches.GetSize();
101ab65b34fSGreg Clayton //    }
102ab65b34fSGreg Clayton //
10330fdc8d8SChris Lattner 
10430fdc8d8SChris Lattner     class CommandOptions : public Options
10530fdc8d8SChris Lattner     {
10630fdc8d8SChris Lattner     public:
107e1cfbc79STodd Fiala         CommandOptions() :
108e1cfbc79STodd Fiala             Options(),
10930fdc8d8SChris Lattner             log_file(),
11030fdc8d8SChris Lattner             log_options(0)
11130fdc8d8SChris Lattner         {
11230fdc8d8SChris Lattner         }
11330fdc8d8SChris Lattner 
11426cac3afSEugene Zelenko         ~CommandOptions () override = default;
11530fdc8d8SChris Lattner 
11613d21e9aSBruce Mitchener         Error
117e1cfbc79STodd Fiala         SetOptionValue (uint32_t option_idx, const char *option_arg,
118e1cfbc79STodd Fiala                         ExecutionContext *execution_context) override
11930fdc8d8SChris Lattner         {
12030fdc8d8SChris Lattner             Error error;
1213bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
12230fdc8d8SChris Lattner 
12330fdc8d8SChris Lattner             switch (short_option)
12430fdc8d8SChris Lattner             {
125889037d7SGreg Clayton             case 'f':  log_file.SetFile(option_arg, true);                    break;
12630fdc8d8SChris Lattner             case 't':  log_options |= LLDB_LOG_OPTION_THREADSAFE;             break;
12730fdc8d8SChris Lattner             case 'v':  log_options |= LLDB_LOG_OPTION_VERBOSE;                break;
12830fdc8d8SChris Lattner             case 'g':  log_options |= LLDB_LOG_OPTION_DEBUG;                  break;
12930fdc8d8SChris Lattner             case 's':  log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;       break;
13030fdc8d8SChris Lattner             case 'T':  log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;      break;
13130fdc8d8SChris Lattner             case 'p':  log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
13230fdc8d8SChris Lattner             case 'n':  log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;    break;
1333a18e319SGreg Clayton             case 'S':  log_options |= LLDB_LOG_OPTION_BACKTRACE;              break;
1348ac06996SPavel Labath             case 'a':  log_options |= LLDB_LOG_OPTION_APPEND;                 break;
13530fdc8d8SChris Lattner             default:
13686edbf41SGreg Clayton                 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
13730fdc8d8SChris Lattner                 break;
13830fdc8d8SChris Lattner             }
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner             return error;
14130fdc8d8SChris Lattner         }
14230fdc8d8SChris Lattner 
14330fdc8d8SChris Lattner         void
144e1cfbc79STodd Fiala         OptionParsingStarting(ExecutionContext *execution_context) override
14530fdc8d8SChris Lattner         {
146889037d7SGreg Clayton             log_file.Clear();
14730fdc8d8SChris Lattner             log_options = 0;
14830fdc8d8SChris Lattner         }
14930fdc8d8SChris Lattner 
150e0d378b3SGreg Clayton         const OptionDefinition*
15113d21e9aSBruce Mitchener         GetDefinitions () override
15230fdc8d8SChris Lattner         {
15330fdc8d8SChris Lattner             return g_option_table;
15430fdc8d8SChris Lattner         }
15530fdc8d8SChris Lattner 
15630fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
15730fdc8d8SChris Lattner 
158e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
15930fdc8d8SChris Lattner 
16030fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
16130fdc8d8SChris Lattner 
162889037d7SGreg Clayton         FileSpec log_file;
16330fdc8d8SChris Lattner         uint32_t log_options;
16430fdc8d8SChris Lattner     };
16530fdc8d8SChris Lattner 
16630fdc8d8SChris Lattner protected:
16713d21e9aSBruce Mitchener     bool
1685a988416SJim Ingham     DoExecute (Args& args,
16913d21e9aSBruce Mitchener              CommandReturnObject &result) override
1705a988416SJim Ingham     {
1715a988416SJim Ingham         if (args.GetArgumentCount() < 2)
1725a988416SJim Ingham         {
1735a988416SJim Ingham             result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
1745a988416SJim Ingham         }
1755a988416SJim Ingham         else
1765a988416SJim Ingham         {
1775a988416SJim Ingham             std::string channel(args.GetArgumentAtIndex(0));
1785a988416SJim Ingham             args.Shift ();  // Shift off the channel
179889037d7SGreg Clayton             char log_file[PATH_MAX];
180889037d7SGreg Clayton             if (m_options.log_file)
181889037d7SGreg Clayton                 m_options.log_file.GetPath(log_file, sizeof(log_file));
182889037d7SGreg Clayton             else
183889037d7SGreg Clayton                 log_file[0] = '\0';
1845a988416SJim Ingham             bool success = m_interpreter.GetDebugger().EnableLog (channel.c_str(),
1855a988416SJim Ingham                                                                   args.GetConstArgumentVector(),
186889037d7SGreg Clayton                                                                   log_file,
1875a988416SJim Ingham                                                                   m_options.log_options,
1885a988416SJim Ingham                                                                   result.GetErrorStream());
1895a988416SJim Ingham             if (success)
1905a988416SJim Ingham                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1915a988416SJim Ingham             else
1925a988416SJim Ingham                 result.SetStatus (eReturnStatusFailed);
1935a988416SJim Ingham         }
1945a988416SJim Ingham         return result.Succeeded();
1955a988416SJim Ingham     }
1965a988416SJim Ingham 
19730fdc8d8SChris Lattner     CommandOptions m_options;
19830fdc8d8SChris Lattner };
19930fdc8d8SChris Lattner 
200e0d378b3SGreg Clayton OptionDefinition
20130fdc8d8SChris Lattner CommandObjectLogEnable::CommandOptions::g_option_table[] =
20230fdc8d8SChris Lattner {
203*ac9c3a62SKate Stone   // clang-format off
20426cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "file",       'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Set the destination file to log to."},
20526cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Enable thread safe logging to avoid interweaved log lines."},
20626cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Enable verbose logging."},
20726cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "debug",      'g', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Enable debug logging."},
20826cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "sequence",   's', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Prepend all log lines with an increasing integer sequence id."},
20926cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "timestamp",  'T', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Prepend all log lines with a timestamp."},
21026cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "pid-tid",    'p', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Prepend all log lines with the process and thread ID that generates the log line."},
21126cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Prepend all log lines with the thread name for the thread that generates the log line."},
21226cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "stack",      'S', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Append a stack backtrace to each log line."},
21326cac3afSEugene Zelenko   {LLDB_OPT_SET_1, false, "append",     'a', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,     "Append to the log file instead of overwriting."},
21426cac3afSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
215*ac9c3a62SKate Stone   // clang-format on
21630fdc8d8SChris Lattner };
21730fdc8d8SChris Lattner 
2185a988416SJim Ingham class CommandObjectLogDisable : public CommandObjectParsed
21930fdc8d8SChris Lattner {
22030fdc8d8SChris Lattner public:
22130fdc8d8SChris Lattner     //------------------------------------------------------------------
22230fdc8d8SChris Lattner     // Constructors and Destructors
22330fdc8d8SChris Lattner     //------------------------------------------------------------------
224a7015092SGreg Clayton     CommandObjectLogDisable(CommandInterpreter &interpreter) :
2255a988416SJim Ingham         CommandObjectParsed(interpreter,
226a7015092SGreg Clayton                             "log disable",
2277149fab4SCaroline Tice                             "Disable one or more log channel categories.",
22826cac3afSEugene Zelenko                             nullptr)
22930fdc8d8SChris Lattner     {
2307149fab4SCaroline Tice         CommandArgumentEntry arg1;
2317149fab4SCaroline Tice         CommandArgumentEntry arg2;
232405fe67fSCaroline Tice         CommandArgumentData channel_arg;
2337149fab4SCaroline Tice         CommandArgumentData category_arg;
234405fe67fSCaroline Tice 
235405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
236405fe67fSCaroline Tice         channel_arg.arg_type = eArgTypeLogChannel;
2377149fab4SCaroline Tice         channel_arg.arg_repetition = eArgRepeatPlain;
238405fe67fSCaroline Tice 
239405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
2407149fab4SCaroline Tice         arg1.push_back (channel_arg);
2417149fab4SCaroline Tice 
2427149fab4SCaroline Tice         category_arg.arg_type = eArgTypeLogCategory;
2437149fab4SCaroline Tice         category_arg.arg_repetition = eArgRepeatPlus;
2447149fab4SCaroline Tice 
2457149fab4SCaroline Tice         arg2.push_back (category_arg);
246405fe67fSCaroline Tice 
247405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
2487149fab4SCaroline Tice         m_arguments.push_back (arg1);
2497149fab4SCaroline Tice         m_arguments.push_back (arg2);
25030fdc8d8SChris Lattner     }
25130fdc8d8SChris Lattner 
25226cac3afSEugene Zelenko     ~CommandObjectLogDisable() override = default;
25330fdc8d8SChris Lattner 
2545a988416SJim Ingham protected:
25513d21e9aSBruce Mitchener     bool
2565a988416SJim Ingham     DoExecute (Args& args,
25713d21e9aSBruce Mitchener              CommandReturnObject &result) override
25830fdc8d8SChris Lattner     {
25930fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
26030fdc8d8SChris Lattner         if (argc == 0)
26130fdc8d8SChris Lattner         {
262dff04404SJim Ingham             result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
26330fdc8d8SChris Lattner         }
26430fdc8d8SChris Lattner         else
26530fdc8d8SChris Lattner         {
26630fdc8d8SChris Lattner             Log::Callbacks log_callbacks;
26730fdc8d8SChris Lattner 
26820ad3c40SCaroline Tice             std::string channel(args.GetArgumentAtIndex(0));
26920ad3c40SCaroline Tice             args.Shift ();  // Shift off the channel
27057abc5d6SGreg Clayton             if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks))
27130fdc8d8SChris Lattner             {
272228063cdSJim Ingham                 log_callbacks.disable (args.GetConstArgumentVector(), &result.GetErrorStream());
27330fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
27430fdc8d8SChris Lattner             }
27530fdc8d8SChris Lattner             else if (channel == "all")
27630fdc8d8SChris Lattner             {
27720ad3c40SCaroline Tice                 Log::DisableAllLogChannels(&result.GetErrorStream());
27830fdc8d8SChris Lattner             }
27930fdc8d8SChris Lattner             else
28030fdc8d8SChris Lattner             {
281ab65b34fSGreg Clayton                 LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
28230fdc8d8SChris Lattner                 if (log_channel_sp)
28330fdc8d8SChris Lattner                 {
284228063cdSJim Ingham                     log_channel_sp->Disable(args.GetConstArgumentVector(), &result.GetErrorStream());
28530fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
28630fdc8d8SChris Lattner                 }
28730fdc8d8SChris Lattner                 else
28830fdc8d8SChris Lattner                     result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
28930fdc8d8SChris Lattner             }
29030fdc8d8SChris Lattner         }
29130fdc8d8SChris Lattner         return result.Succeeded();
29230fdc8d8SChris Lattner     }
29330fdc8d8SChris Lattner };
29430fdc8d8SChris Lattner 
2955a988416SJim Ingham class CommandObjectLogList : public CommandObjectParsed
29630fdc8d8SChris Lattner {
29730fdc8d8SChris Lattner public:
29830fdc8d8SChris Lattner     //------------------------------------------------------------------
29930fdc8d8SChris Lattner     // Constructors and Destructors
30030fdc8d8SChris Lattner     //------------------------------------------------------------------
301a7015092SGreg Clayton     CommandObjectLogList(CommandInterpreter &interpreter) :
3025a988416SJim Ingham         CommandObjectParsed(interpreter,
303a7015092SGreg Clayton                             "log list",
304405fe67fSCaroline Tice                             "List the log categories for one or more log channels.  If none specified, lists them all.",
30526cac3afSEugene Zelenko                             nullptr)
30630fdc8d8SChris Lattner     {
307405fe67fSCaroline Tice         CommandArgumentEntry arg;
308405fe67fSCaroline Tice         CommandArgumentData channel_arg;
309405fe67fSCaroline Tice 
310405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
311405fe67fSCaroline Tice         channel_arg.arg_type = eArgTypeLogChannel;
312405fe67fSCaroline Tice         channel_arg.arg_repetition = eArgRepeatStar;
313405fe67fSCaroline Tice 
314405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
315405fe67fSCaroline Tice         arg.push_back (channel_arg);
316405fe67fSCaroline Tice 
317405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
318405fe67fSCaroline Tice         m_arguments.push_back (arg);
31930fdc8d8SChris Lattner     }
32030fdc8d8SChris Lattner 
32126cac3afSEugene Zelenko     ~CommandObjectLogList() override = default;
32230fdc8d8SChris Lattner 
3235a988416SJim Ingham protected:
32413d21e9aSBruce Mitchener     bool
3255a988416SJim Ingham     DoExecute (Args& args,
32613d21e9aSBruce Mitchener              CommandReturnObject &result) override
32730fdc8d8SChris Lattner     {
32830fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
32930fdc8d8SChris Lattner         if (argc == 0)
33030fdc8d8SChris Lattner         {
33130fdc8d8SChris Lattner             Log::ListAllLogChannels (&result.GetOutputStream());
33230fdc8d8SChris Lattner             result.SetStatus(eReturnStatusSuccessFinishResult);
33330fdc8d8SChris Lattner         }
33430fdc8d8SChris Lattner         else
33530fdc8d8SChris Lattner         {
33630fdc8d8SChris Lattner             for (size_t i=0; i<argc; ++i)
33730fdc8d8SChris Lattner             {
33830fdc8d8SChris Lattner                 Log::Callbacks log_callbacks;
33930fdc8d8SChris Lattner 
34030fdc8d8SChris Lattner                 std::string channel(args.GetArgumentAtIndex(i));
34157abc5d6SGreg Clayton                 if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks))
34230fdc8d8SChris Lattner                 {
34330fdc8d8SChris Lattner                     log_callbacks.list_categories (&result.GetOutputStream());
34430fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishResult);
34530fdc8d8SChris Lattner                 }
34630fdc8d8SChris Lattner                 else if (channel == "all")
34730fdc8d8SChris Lattner                 {
34830fdc8d8SChris Lattner                     Log::ListAllLogChannels (&result.GetOutputStream());
34930fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishResult);
35030fdc8d8SChris Lattner                 }
35130fdc8d8SChris Lattner                 else
35230fdc8d8SChris Lattner                 {
353ab65b34fSGreg Clayton                     LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
35430fdc8d8SChris Lattner                     if (log_channel_sp)
35530fdc8d8SChris Lattner                     {
35630fdc8d8SChris Lattner                         log_channel_sp->ListCategories(&result.GetOutputStream());
35730fdc8d8SChris Lattner                         result.SetStatus(eReturnStatusSuccessFinishNoResult);
35830fdc8d8SChris Lattner                     }
35930fdc8d8SChris Lattner                     else
36030fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
36130fdc8d8SChris Lattner                 }
36230fdc8d8SChris Lattner             }
36330fdc8d8SChris Lattner         }
36430fdc8d8SChris Lattner         return result.Succeeded();
36530fdc8d8SChris Lattner     }
36630fdc8d8SChris Lattner };
36730fdc8d8SChris Lattner 
3685a988416SJim Ingham class CommandObjectLogTimer : public CommandObjectParsed
36930fdc8d8SChris Lattner {
37030fdc8d8SChris Lattner public:
37130fdc8d8SChris Lattner     //------------------------------------------------------------------
37230fdc8d8SChris Lattner     // Constructors and Destructors
37330fdc8d8SChris Lattner     //------------------------------------------------------------------
374a7015092SGreg Clayton     CommandObjectLogTimer(CommandInterpreter &interpreter) :
3755a988416SJim Ingham         CommandObjectParsed (interpreter,
376a7015092SGreg Clayton                            "log timers",
37730fdc8d8SChris Lattner                            "Enable, disable, dump, and reset LLDB internal performance timers.",
378f7f4f501SJim Ingham                            "log timers < enable <depth> | disable | dump | increment <bool> | reset >")
37930fdc8d8SChris Lattner     {
38030fdc8d8SChris Lattner     }
38130fdc8d8SChris Lattner 
38226cac3afSEugene Zelenko     ~CommandObjectLogTimer() override = default;
38330fdc8d8SChris Lattner 
3845a988416SJim Ingham protected:
38513d21e9aSBruce Mitchener     bool
3865a988416SJim Ingham     DoExecute (Args& args,
38713d21e9aSBruce Mitchener              CommandReturnObject &result) override
38830fdc8d8SChris Lattner     {
38930fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
39030fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
39130fdc8d8SChris Lattner 
39230fdc8d8SChris Lattner         if (argc == 1)
39330fdc8d8SChris Lattner         {
39430fdc8d8SChris Lattner             const char *sub_command = args.GetArgumentAtIndex(0);
39530fdc8d8SChris Lattner 
39630fdc8d8SChris Lattner             if (strcasecmp(sub_command, "enable") == 0)
39730fdc8d8SChris Lattner             {
39830fdc8d8SChris Lattner                 Timer::SetDisplayDepth (UINT32_MAX);
39930fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
40030fdc8d8SChris Lattner             }
40130fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "disable") == 0)
40230fdc8d8SChris Lattner             {
40330fdc8d8SChris Lattner                 Timer::DumpCategoryTimes (&result.GetOutputStream());
40430fdc8d8SChris Lattner                 Timer::SetDisplayDepth (0);
40530fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
40630fdc8d8SChris Lattner             }
40730fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "dump") == 0)
40830fdc8d8SChris Lattner             {
40930fdc8d8SChris Lattner                 Timer::DumpCategoryTimes (&result.GetOutputStream());
41030fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
41130fdc8d8SChris Lattner             }
41230fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "reset") == 0)
41330fdc8d8SChris Lattner             {
41430fdc8d8SChris Lattner                 Timer::ResetCategoryTimes ();
41530fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
41630fdc8d8SChris Lattner             }
41730fdc8d8SChris Lattner         }
418932725faSJim Ingham         else if (argc == 2)
419932725faSJim Ingham         {
420932725faSJim Ingham             const char *sub_command = args.GetArgumentAtIndex(0);
421932725faSJim Ingham 
422932725faSJim Ingham             if (strcasecmp(sub_command, "enable") == 0)
423932725faSJim Ingham             {
424932725faSJim Ingham                 bool success;
4255275aaa0SVince Harron                 uint32_t depth = StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success);
426932725faSJim Ingham                 if (success)
427932725faSJim Ingham                 {
428932725faSJim Ingham                     Timer::SetDisplayDepth (depth);
429932725faSJim Ingham                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
430932725faSJim Ingham                 }
431932725faSJim Ingham                 else
432932725faSJim Ingham                     result.AppendError("Could not convert enable depth to an unsigned integer.");
433932725faSJim Ingham             }
434f7f4f501SJim Ingham             if (strcasecmp(sub_command, "increment") == 0)
435f7f4f501SJim Ingham             {
436f7f4f501SJim Ingham                 bool success;
437f7f4f501SJim Ingham                 bool increment = Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success);
438f7f4f501SJim Ingham                 if (success)
439f7f4f501SJim Ingham                 {
440f7f4f501SJim Ingham                     Timer::SetQuiet (!increment);
441f7f4f501SJim Ingham                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
442f7f4f501SJim Ingham                 }
443f7f4f501SJim Ingham                 else
444f7f4f501SJim Ingham                     result.AppendError("Could not convert increment value to boolean.");
445f7f4f501SJim Ingham             }
446932725faSJim Ingham         }
447932725faSJim Ingham 
44830fdc8d8SChris Lattner         if (!result.Succeeded())
44930fdc8d8SChris Lattner         {
45030fdc8d8SChris Lattner             result.AppendError("Missing subcommand");
45130fdc8d8SChris Lattner             result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
45230fdc8d8SChris Lattner         }
45330fdc8d8SChris Lattner         return result.Succeeded();
45430fdc8d8SChris Lattner     }
45530fdc8d8SChris Lattner };
45630fdc8d8SChris Lattner 
4577428a18cSKate Stone CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
4587428a18cSKate Stone     : CommandObjectMultiword(interpreter, "log", "Commands controlling LLDB internal logging.",
4597428a18cSKate Stone                              "log <subcommand> [<command-options>]")
46030fdc8d8SChris Lattner {
461a7015092SGreg Clayton     LoadSubCommand ("enable",  CommandObjectSP (new CommandObjectLogEnable (interpreter)));
462a7015092SGreg Clayton     LoadSubCommand ("disable", CommandObjectSP (new CommandObjectLogDisable (interpreter)));
463a7015092SGreg Clayton     LoadSubCommand ("list",    CommandObjectSP (new CommandObjectLogList (interpreter)));
464a7015092SGreg Clayton     LoadSubCommand ("timers",  CommandObjectSP (new CommandObjectLogTimer (interpreter)));
46530fdc8d8SChris Lattner }
46630fdc8d8SChris Lattner 
46726cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
468