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
14*26cac3afSEugene 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.",
49*26cac3afSEugene Zelenko                             nullptr),
50eb0103f2SGreg Clayton         m_options (interpreter)
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 
74*26cac3afSEugene 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:
107eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
108eb0103f2SGreg Clayton             Options (interpreter),
10930fdc8d8SChris Lattner             log_file (),
11030fdc8d8SChris Lattner             log_options (0)
11130fdc8d8SChris Lattner         {
11230fdc8d8SChris Lattner         }
11330fdc8d8SChris Lattner 
114*26cac3afSEugene Zelenko         ~CommandOptions () override = default;
11530fdc8d8SChris Lattner 
11613d21e9aSBruce Mitchener         Error
11713d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
11830fdc8d8SChris Lattner         {
11930fdc8d8SChris Lattner             Error error;
1203bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
12130fdc8d8SChris Lattner 
12230fdc8d8SChris Lattner             switch (short_option)
12330fdc8d8SChris Lattner             {
124889037d7SGreg Clayton             case 'f':  log_file.SetFile(option_arg, true);                    break;
12530fdc8d8SChris Lattner             case 't':  log_options |= LLDB_LOG_OPTION_THREADSAFE;             break;
12630fdc8d8SChris Lattner             case 'v':  log_options |= LLDB_LOG_OPTION_VERBOSE;                break;
12730fdc8d8SChris Lattner             case 'g':  log_options |= LLDB_LOG_OPTION_DEBUG;                  break;
12830fdc8d8SChris Lattner             case 's':  log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;       break;
12930fdc8d8SChris Lattner             case 'T':  log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;      break;
13030fdc8d8SChris Lattner             case 'p':  log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
13130fdc8d8SChris Lattner             case 'n':  log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;    break;
1323a18e319SGreg Clayton             case 'S':  log_options |= LLDB_LOG_OPTION_BACKTRACE;              break;
1338ac06996SPavel Labath             case 'a':  log_options |= LLDB_LOG_OPTION_APPEND;                 break;
13430fdc8d8SChris Lattner             default:
13586edbf41SGreg Clayton                 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
13630fdc8d8SChris Lattner                 break;
13730fdc8d8SChris Lattner             }
13830fdc8d8SChris Lattner 
13930fdc8d8SChris Lattner             return error;
14030fdc8d8SChris Lattner         }
14130fdc8d8SChris Lattner 
14230fdc8d8SChris Lattner         void
14313d21e9aSBruce Mitchener         OptionParsingStarting () override
14430fdc8d8SChris Lattner         {
145889037d7SGreg Clayton             log_file.Clear();
14630fdc8d8SChris Lattner             log_options = 0;
14730fdc8d8SChris Lattner         }
14830fdc8d8SChris Lattner 
149e0d378b3SGreg Clayton         const OptionDefinition*
15013d21e9aSBruce Mitchener         GetDefinitions () override
15130fdc8d8SChris Lattner         {
15230fdc8d8SChris Lattner             return g_option_table;
15330fdc8d8SChris Lattner         }
15430fdc8d8SChris Lattner 
15530fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
15630fdc8d8SChris Lattner 
157e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
15830fdc8d8SChris Lattner 
15930fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
16030fdc8d8SChris Lattner 
161889037d7SGreg Clayton         FileSpec log_file;
16230fdc8d8SChris Lattner         uint32_t log_options;
16330fdc8d8SChris Lattner     };
16430fdc8d8SChris Lattner 
16530fdc8d8SChris Lattner protected:
16613d21e9aSBruce Mitchener     bool
1675a988416SJim Ingham     DoExecute (Args& args,
16813d21e9aSBruce Mitchener              CommandReturnObject &result) override
1695a988416SJim Ingham     {
1705a988416SJim Ingham         if (args.GetArgumentCount() < 2)
1715a988416SJim Ingham         {
1725a988416SJim Ingham             result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
1735a988416SJim Ingham         }
1745a988416SJim Ingham         else
1755a988416SJim Ingham         {
1765a988416SJim Ingham             std::string channel(args.GetArgumentAtIndex(0));
1775a988416SJim Ingham             args.Shift ();  // Shift off the channel
178889037d7SGreg Clayton             char log_file[PATH_MAX];
179889037d7SGreg Clayton             if (m_options.log_file)
180889037d7SGreg Clayton                 m_options.log_file.GetPath(log_file, sizeof(log_file));
181889037d7SGreg Clayton             else
182889037d7SGreg Clayton                 log_file[0] = '\0';
1835a988416SJim Ingham             bool success = m_interpreter.GetDebugger().EnableLog (channel.c_str(),
1845a988416SJim Ingham                                                                   args.GetConstArgumentVector(),
185889037d7SGreg Clayton                                                                   log_file,
1865a988416SJim Ingham                                                                   m_options.log_options,
1875a988416SJim Ingham                                                                   result.GetErrorStream());
1885a988416SJim Ingham             if (success)
1895a988416SJim Ingham                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1905a988416SJim Ingham             else
1915a988416SJim Ingham                 result.SetStatus (eReturnStatusFailed);
1925a988416SJim Ingham         }
1935a988416SJim Ingham         return result.Succeeded();
1945a988416SJim Ingham     }
1955a988416SJim Ingham 
19630fdc8d8SChris Lattner     CommandOptions m_options;
19730fdc8d8SChris Lattner };
19830fdc8d8SChris Lattner 
199e0d378b3SGreg Clayton OptionDefinition
20030fdc8d8SChris Lattner CommandObjectLogEnable::CommandOptions::g_option_table[] =
20130fdc8d8SChris Lattner {
202*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "file",       'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename,   "Set the destination file to log to."},
203*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Enable thread safe logging to avoid interweaved log lines." },
204*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Enable verbose logging." },
205*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "debug",      'g', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Enable debug logging." },
206*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "sequence",   's', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Prepend all log lines with an increasing integer sequence id." },
207*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "timestamp",  'T', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Prepend all log lines with a timestamp." },
208*26cac3afSEugene 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." },
209*26cac3afSEugene 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." },
210*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "stack",      'S', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Append a stack backtrace to each log line." },
211*26cac3afSEugene Zelenko { LLDB_OPT_SET_1, false, "append",     'a', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,       "Append to the log file instead of overwriting." },
212*26cac3afSEugene Zelenko { 0, false, nullptr,                       0,  0,                 nullptr, nullptr, 0, eArgTypeNone,       nullptr }
21330fdc8d8SChris Lattner };
21430fdc8d8SChris Lattner 
2155a988416SJim Ingham class CommandObjectLogDisable : public CommandObjectParsed
21630fdc8d8SChris Lattner {
21730fdc8d8SChris Lattner public:
21830fdc8d8SChris Lattner     //------------------------------------------------------------------
21930fdc8d8SChris Lattner     // Constructors and Destructors
22030fdc8d8SChris Lattner     //------------------------------------------------------------------
221a7015092SGreg Clayton     CommandObjectLogDisable(CommandInterpreter &interpreter) :
2225a988416SJim Ingham         CommandObjectParsed(interpreter,
223a7015092SGreg Clayton                             "log disable",
2247149fab4SCaroline Tice                             "Disable one or more log channel categories.",
225*26cac3afSEugene Zelenko                             nullptr)
22630fdc8d8SChris Lattner     {
2277149fab4SCaroline Tice         CommandArgumentEntry arg1;
2287149fab4SCaroline Tice         CommandArgumentEntry arg2;
229405fe67fSCaroline Tice         CommandArgumentData channel_arg;
2307149fab4SCaroline Tice         CommandArgumentData category_arg;
231405fe67fSCaroline Tice 
232405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
233405fe67fSCaroline Tice         channel_arg.arg_type = eArgTypeLogChannel;
2347149fab4SCaroline Tice         channel_arg.arg_repetition = eArgRepeatPlain;
235405fe67fSCaroline Tice 
236405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
2377149fab4SCaroline Tice         arg1.push_back (channel_arg);
2387149fab4SCaroline Tice 
2397149fab4SCaroline Tice         category_arg.arg_type = eArgTypeLogCategory;
2407149fab4SCaroline Tice         category_arg.arg_repetition = eArgRepeatPlus;
2417149fab4SCaroline Tice 
2427149fab4SCaroline Tice         arg2.push_back (category_arg);
243405fe67fSCaroline Tice 
244405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
2457149fab4SCaroline Tice         m_arguments.push_back (arg1);
2467149fab4SCaroline Tice         m_arguments.push_back (arg2);
24730fdc8d8SChris Lattner     }
24830fdc8d8SChris Lattner 
249*26cac3afSEugene Zelenko     ~CommandObjectLogDisable() override = default;
25030fdc8d8SChris Lattner 
2515a988416SJim Ingham protected:
25213d21e9aSBruce Mitchener     bool
2535a988416SJim Ingham     DoExecute (Args& args,
25413d21e9aSBruce Mitchener              CommandReturnObject &result) override
25530fdc8d8SChris Lattner     {
25630fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
25730fdc8d8SChris Lattner         if (argc == 0)
25830fdc8d8SChris Lattner         {
259dff04404SJim Ingham             result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
26030fdc8d8SChris Lattner         }
26130fdc8d8SChris Lattner         else
26230fdc8d8SChris Lattner         {
26330fdc8d8SChris Lattner             Log::Callbacks log_callbacks;
26430fdc8d8SChris Lattner 
26520ad3c40SCaroline Tice             std::string channel(args.GetArgumentAtIndex(0));
26620ad3c40SCaroline Tice             args.Shift ();  // Shift off the channel
26757abc5d6SGreg Clayton             if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks))
26830fdc8d8SChris Lattner             {
269228063cdSJim Ingham                 log_callbacks.disable (args.GetConstArgumentVector(), &result.GetErrorStream());
27030fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
27130fdc8d8SChris Lattner             }
27230fdc8d8SChris Lattner             else if (channel == "all")
27330fdc8d8SChris Lattner             {
27420ad3c40SCaroline Tice                 Log::DisableAllLogChannels(&result.GetErrorStream());
27530fdc8d8SChris Lattner             }
27630fdc8d8SChris Lattner             else
27730fdc8d8SChris Lattner             {
278ab65b34fSGreg Clayton                 LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
27930fdc8d8SChris Lattner                 if (log_channel_sp)
28030fdc8d8SChris Lattner                 {
281228063cdSJim Ingham                     log_channel_sp->Disable(args.GetConstArgumentVector(), &result.GetErrorStream());
28230fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
28330fdc8d8SChris Lattner                 }
28430fdc8d8SChris Lattner                 else
28530fdc8d8SChris Lattner                     result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
28630fdc8d8SChris Lattner             }
28730fdc8d8SChris Lattner         }
28830fdc8d8SChris Lattner         return result.Succeeded();
28930fdc8d8SChris Lattner     }
29030fdc8d8SChris Lattner };
29130fdc8d8SChris Lattner 
2925a988416SJim Ingham class CommandObjectLogList : public CommandObjectParsed
29330fdc8d8SChris Lattner {
29430fdc8d8SChris Lattner public:
29530fdc8d8SChris Lattner     //------------------------------------------------------------------
29630fdc8d8SChris Lattner     // Constructors and Destructors
29730fdc8d8SChris Lattner     //------------------------------------------------------------------
298a7015092SGreg Clayton     CommandObjectLogList(CommandInterpreter &interpreter) :
2995a988416SJim Ingham         CommandObjectParsed(interpreter,
300a7015092SGreg Clayton                             "log list",
301405fe67fSCaroline Tice                             "List the log categories for one or more log channels.  If none specified, lists them all.",
302*26cac3afSEugene Zelenko                             nullptr)
30330fdc8d8SChris Lattner     {
304405fe67fSCaroline Tice         CommandArgumentEntry arg;
305405fe67fSCaroline Tice         CommandArgumentData channel_arg;
306405fe67fSCaroline Tice 
307405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
308405fe67fSCaroline Tice         channel_arg.arg_type = eArgTypeLogChannel;
309405fe67fSCaroline Tice         channel_arg.arg_repetition = eArgRepeatStar;
310405fe67fSCaroline Tice 
311405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
312405fe67fSCaroline Tice         arg.push_back (channel_arg);
313405fe67fSCaroline Tice 
314405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
315405fe67fSCaroline Tice         m_arguments.push_back (arg);
31630fdc8d8SChris Lattner     }
31730fdc8d8SChris Lattner 
318*26cac3afSEugene Zelenko     ~CommandObjectLogList() override = default;
31930fdc8d8SChris Lattner 
3205a988416SJim Ingham protected:
32113d21e9aSBruce Mitchener     bool
3225a988416SJim Ingham     DoExecute (Args& args,
32313d21e9aSBruce Mitchener              CommandReturnObject &result) override
32430fdc8d8SChris Lattner     {
32530fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
32630fdc8d8SChris Lattner         if (argc == 0)
32730fdc8d8SChris Lattner         {
32830fdc8d8SChris Lattner             Log::ListAllLogChannels (&result.GetOutputStream());
32930fdc8d8SChris Lattner             result.SetStatus(eReturnStatusSuccessFinishResult);
33030fdc8d8SChris Lattner         }
33130fdc8d8SChris Lattner         else
33230fdc8d8SChris Lattner         {
33330fdc8d8SChris Lattner             for (size_t i=0; i<argc; ++i)
33430fdc8d8SChris Lattner             {
33530fdc8d8SChris Lattner                 Log::Callbacks log_callbacks;
33630fdc8d8SChris Lattner 
33730fdc8d8SChris Lattner                 std::string channel(args.GetArgumentAtIndex(i));
33857abc5d6SGreg Clayton                 if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks))
33930fdc8d8SChris Lattner                 {
34030fdc8d8SChris Lattner                     log_callbacks.list_categories (&result.GetOutputStream());
34130fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishResult);
34230fdc8d8SChris Lattner                 }
34330fdc8d8SChris Lattner                 else if (channel == "all")
34430fdc8d8SChris Lattner                 {
34530fdc8d8SChris Lattner                     Log::ListAllLogChannels (&result.GetOutputStream());
34630fdc8d8SChris Lattner                     result.SetStatus(eReturnStatusSuccessFinishResult);
34730fdc8d8SChris Lattner                 }
34830fdc8d8SChris Lattner                 else
34930fdc8d8SChris Lattner                 {
350ab65b34fSGreg Clayton                     LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
35130fdc8d8SChris Lattner                     if (log_channel_sp)
35230fdc8d8SChris Lattner                     {
35330fdc8d8SChris Lattner                         log_channel_sp->ListCategories(&result.GetOutputStream());
35430fdc8d8SChris Lattner                         result.SetStatus(eReturnStatusSuccessFinishNoResult);
35530fdc8d8SChris Lattner                     }
35630fdc8d8SChris Lattner                     else
35730fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
35830fdc8d8SChris Lattner                 }
35930fdc8d8SChris Lattner             }
36030fdc8d8SChris Lattner         }
36130fdc8d8SChris Lattner         return result.Succeeded();
36230fdc8d8SChris Lattner     }
36330fdc8d8SChris Lattner };
36430fdc8d8SChris Lattner 
3655a988416SJim Ingham class CommandObjectLogTimer : public CommandObjectParsed
36630fdc8d8SChris Lattner {
36730fdc8d8SChris Lattner public:
36830fdc8d8SChris Lattner     //------------------------------------------------------------------
36930fdc8d8SChris Lattner     // Constructors and Destructors
37030fdc8d8SChris Lattner     //------------------------------------------------------------------
371a7015092SGreg Clayton     CommandObjectLogTimer(CommandInterpreter &interpreter) :
3725a988416SJim Ingham         CommandObjectParsed (interpreter,
373a7015092SGreg Clayton                            "log timers",
37430fdc8d8SChris Lattner                            "Enable, disable, dump, and reset LLDB internal performance timers.",
375f7f4f501SJim Ingham                            "log timers < enable <depth> | disable | dump | increment <bool> | reset >")
37630fdc8d8SChris Lattner     {
37730fdc8d8SChris Lattner     }
37830fdc8d8SChris Lattner 
379*26cac3afSEugene Zelenko     ~CommandObjectLogTimer() override = default;
38030fdc8d8SChris Lattner 
3815a988416SJim Ingham protected:
38213d21e9aSBruce Mitchener     bool
3835a988416SJim Ingham     DoExecute (Args& args,
38413d21e9aSBruce Mitchener              CommandReturnObject &result) override
38530fdc8d8SChris Lattner     {
38630fdc8d8SChris Lattner         const size_t argc = args.GetArgumentCount();
38730fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
38830fdc8d8SChris Lattner 
38930fdc8d8SChris Lattner         if (argc == 1)
39030fdc8d8SChris Lattner         {
39130fdc8d8SChris Lattner             const char *sub_command = args.GetArgumentAtIndex(0);
39230fdc8d8SChris Lattner 
39330fdc8d8SChris Lattner             if (strcasecmp(sub_command, "enable") == 0)
39430fdc8d8SChris Lattner             {
39530fdc8d8SChris Lattner                 Timer::SetDisplayDepth (UINT32_MAX);
39630fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
39730fdc8d8SChris Lattner             }
39830fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "disable") == 0)
39930fdc8d8SChris Lattner             {
40030fdc8d8SChris Lattner                 Timer::DumpCategoryTimes (&result.GetOutputStream());
40130fdc8d8SChris Lattner                 Timer::SetDisplayDepth (0);
40230fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
40330fdc8d8SChris Lattner             }
40430fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "dump") == 0)
40530fdc8d8SChris Lattner             {
40630fdc8d8SChris Lattner                 Timer::DumpCategoryTimes (&result.GetOutputStream());
40730fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
40830fdc8d8SChris Lattner             }
40930fdc8d8SChris Lattner             else if (strcasecmp(sub_command, "reset") == 0)
41030fdc8d8SChris Lattner             {
41130fdc8d8SChris Lattner                 Timer::ResetCategoryTimes ();
41230fdc8d8SChris Lattner                 result.SetStatus(eReturnStatusSuccessFinishResult);
41330fdc8d8SChris Lattner             }
41430fdc8d8SChris Lattner         }
415932725faSJim Ingham         else if (argc == 2)
416932725faSJim Ingham         {
417932725faSJim Ingham             const char *sub_command = args.GetArgumentAtIndex(0);
418932725faSJim Ingham 
419932725faSJim Ingham             if (strcasecmp(sub_command, "enable") == 0)
420932725faSJim Ingham             {
421932725faSJim Ingham                 bool success;
4225275aaa0SVince Harron                 uint32_t depth = StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success);
423932725faSJim Ingham                 if (success)
424932725faSJim Ingham                 {
425932725faSJim Ingham                     Timer::SetDisplayDepth (depth);
426932725faSJim Ingham                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
427932725faSJim Ingham                 }
428932725faSJim Ingham                 else
429932725faSJim Ingham                     result.AppendError("Could not convert enable depth to an unsigned integer.");
430932725faSJim Ingham             }
431f7f4f501SJim Ingham             if (strcasecmp(sub_command, "increment") == 0)
432f7f4f501SJim Ingham             {
433f7f4f501SJim Ingham                 bool success;
434f7f4f501SJim Ingham                 bool increment = Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success);
435f7f4f501SJim Ingham                 if (success)
436f7f4f501SJim Ingham                 {
437f7f4f501SJim Ingham                     Timer::SetQuiet (!increment);
438f7f4f501SJim Ingham                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
439f7f4f501SJim Ingham                 }
440f7f4f501SJim Ingham                 else
441f7f4f501SJim Ingham                     result.AppendError("Could not convert increment value to boolean.");
442f7f4f501SJim Ingham             }
443932725faSJim Ingham         }
444932725faSJim Ingham 
44530fdc8d8SChris Lattner         if (!result.Succeeded())
44630fdc8d8SChris Lattner         {
44730fdc8d8SChris Lattner             result.AppendError("Missing subcommand");
44830fdc8d8SChris Lattner             result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
44930fdc8d8SChris Lattner         }
45030fdc8d8SChris Lattner         return result.Succeeded();
45130fdc8d8SChris Lattner     }
45230fdc8d8SChris Lattner };
45330fdc8d8SChris Lattner 
4546611103cSGreg Clayton CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter) :
455a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
456a7015092SGreg Clayton                             "log",
45730fdc8d8SChris Lattner                             "A set of commands for operating on logs.",
45830fdc8d8SChris Lattner                             "log <command> [<command-options>]")
45930fdc8d8SChris Lattner {
460a7015092SGreg Clayton     LoadSubCommand ("enable",  CommandObjectSP (new CommandObjectLogEnable (interpreter)));
461a7015092SGreg Clayton     LoadSubCommand ("disable", CommandObjectSP (new CommandObjectLogDisable (interpreter)));
462a7015092SGreg Clayton     LoadSubCommand ("list",    CommandObjectSP (new CommandObjectLogList (interpreter)));
463a7015092SGreg Clayton     LoadSubCommand ("timers",  CommandObjectSP (new CommandObjectLogTimer (interpreter)));
46430fdc8d8SChris Lattner }
46530fdc8d8SChris Lattner 
466*26cac3afSEugene Zelenko CommandObjectLog::~CommandObjectLog() = default;
467