2010-06-09 00:52:24 +08:00
//===-- CommandObjectLog.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectLog.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/lldb-private-log.h"
2010-06-16 03:49:27 +08:00
# include "lldb/Interpreter/Args.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Debugger.h"
2011-02-08 13:05:52 +08:00
# include "lldb/Host/FileSpec.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Log.h"
# include "lldb/Core/Module.h"
2010-06-16 03:49:27 +08:00
# include "lldb/Interpreter/Options.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/RegularExpression.h"
# include "lldb/Core/Stream.h"
# include "lldb/Core/StreamFile.h"
# include "lldb/Core/Timer.h"
2010-06-23 09:19:29 +08:00
# include "lldb/Core/Debugger.h"
2010-06-24 05:28:25 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Symbol/LineTable.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/SymbolFile.h"
# include "lldb/Symbol/SymbolVendor.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/Target.h"
using namespace lldb ;
using namespace lldb_private ;
2012-06-09 05:56:10 +08:00
class CommandObjectLogEnable : public CommandObjectParsed
2010-06-09 00:52:24 +08:00
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
2010-09-18 09:14:36 +08:00
CommandObjectLogEnable ( CommandInterpreter & interpreter ) :
2012-06-09 05:56:10 +08:00
CommandObjectParsed ( interpreter ,
" log enable " ,
" Enable logging for a single log channel. " ,
NULL ) ,
2011-04-08 06:46:35 +08:00
m_options ( interpreter )
2010-06-09 00:52:24 +08:00
{
2010-10-26 11:11:13 +08:00
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
2010-10-05 06:28:36 +08:00
CommandArgumentData channel_arg ;
2010-10-26 11:11:13 +08:00
CommandArgumentData category_arg ;
2010-10-05 06:28:36 +08:00
// Define the first (and only) variant of this arg.
channel_arg . arg_type = eArgTypeLogChannel ;
channel_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
2010-10-26 11:11:13 +08:00
arg1 . push_back ( channel_arg ) ;
2010-10-05 06:28:36 +08:00
2010-10-26 11:11:13 +08:00
category_arg . arg_type = eArgTypeLogCategory ;
category_arg . arg_repetition = eArgRepeatPlus ;
arg2 . push_back ( category_arg ) ;
2010-10-05 06:28:36 +08:00
// Push the data for the first argument into the m_arguments vector.
2010-10-26 11:11:13 +08:00
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
2010-06-09 00:52:24 +08:00
}
virtual
~ CommandObjectLogEnable ( )
{
}
Options *
GetOptions ( )
{
return & m_options ;
}
2011-04-14 06:47:15 +08:00
// int
// HandleArgumentCompletion (Args &input,
// int &cursor_index,
// int &cursor_char_position,
// OptionElementVector &opt_element_vector,
// int match_start_point,
// int max_return_elements,
// bool &word_complete,
// StringList &matches)
// {
// std::string completion_str (input.GetArgumentAtIndex(cursor_index));
// completion_str.erase (cursor_char_position);
//
// if (cursor_index == 1)
// {
// //
// Log::AutoCompleteChannelName (completion_str.c_str(), matches);
// }
// return matches.GetSize();
// }
//
2010-06-09 00:52:24 +08:00
class CommandOptions : public Options
{
public :
2011-04-08 06:46:35 +08:00
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
2010-06-09 00:52:24 +08:00
log_file ( ) ,
log_options ( 0 )
{
}
virtual
~ CommandOptions ( )
{
}
virtual Error
2011-04-13 08:18:08 +08:00
SetOptionValue ( uint32_t option_idx , const char * option_arg )
2010-06-09 00:52:24 +08:00
{
Error error ;
2012-12-04 08:32:51 +08:00
const int short_option = m_getopt_table [ option_idx ] . val ;
2010-06-09 00:52:24 +08:00
switch ( short_option )
{
case ' f ' : log_file = option_arg ; break ;
case ' t ' : log_options | = LLDB_LOG_OPTION_THREADSAFE ; break ;
case ' v ' : log_options | = LLDB_LOG_OPTION_VERBOSE ; break ;
case ' g ' : log_options | = LLDB_LOG_OPTION_DEBUG ; break ;
case ' s ' : log_options | = LLDB_LOG_OPTION_PREPEND_SEQUENCE ; break ;
case ' T ' : log_options | = LLDB_LOG_OPTION_PREPEND_TIMESTAMP ; break ;
case ' p ' : log_options | = LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD ; break ;
case ' n ' : log_options | = LLDB_LOG_OPTION_PREPEND_THREAD_NAME ; break ;
2012-10-09 06:41:53 +08:00
case ' S ' : log_options | = LLDB_LOG_OPTION_BACKTRACE ; break ;
2010-06-09 00:52:24 +08:00
default :
2011-10-26 08:56:27 +08:00
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
2010-06-09 00:52:24 +08:00
break ;
}
return error ;
}
void
2011-04-13 08:18:08 +08:00
OptionParsingStarting ( )
2010-06-09 00:52:24 +08:00
{
log_file . clear ( ) ;
log_options = 0 ;
}
2011-03-25 05:19:54 +08:00
const OptionDefinition *
2010-06-09 00:52:24 +08:00
GetDefinitions ( )
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
2011-03-25 05:19:54 +08:00
static OptionDefinition g_option_table [ ] ;
2010-06-09 00:52:24 +08:00
// Instance variables to hold the values for command options.
std : : string log_file ;
uint32_t log_options ;
} ;
protected :
2012-06-09 05:56:10 +08:00
virtual bool
DoExecute ( Args & args ,
CommandReturnObject & result )
{
if ( args . GetArgumentCount ( ) < 2 )
{
result . AppendErrorWithFormat ( " %s takes a log channel and one or more log types. \n " , m_cmd_name . c_str ( ) ) ;
}
else
{
std : : string channel ( args . GetArgumentAtIndex ( 0 ) ) ;
args . Shift ( ) ; // Shift off the channel
bool success = m_interpreter . GetDebugger ( ) . EnableLog ( channel . c_str ( ) ,
args . GetConstArgumentVector ( ) ,
m_options . log_file . c_str ( ) ,
m_options . log_options ,
result . GetErrorStream ( ) ) ;
if ( success )
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
else
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
2010-06-09 00:52:24 +08:00
CommandOptions m_options ;
} ;
2011-03-25 05:19:54 +08:00
OptionDefinition
2010-06-09 00:52:24 +08:00
CommandObjectLogEnable : : CommandOptions : : g_option_table [ ] =
{
2010-10-02 03:59:14 +08:00
{ LLDB_OPT_SET_1 , false , " file " , ' f ' , required_argument , NULL , 0 , eArgTypeFilename , " Set the destination file to log to. " } ,
{ LLDB_OPT_SET_1 , false , " threadsafe " , ' t ' , no_argument , NULL , 0 , eArgTypeNone , " Enable thread safe logging to avoid interweaved log lines. " } ,
{ LLDB_OPT_SET_1 , false , " verbose " , ' v ' , no_argument , NULL , 0 , eArgTypeNone , " Enable verbose logging. " } ,
{ LLDB_OPT_SET_1 , false , " debug " , ' g ' , no_argument , NULL , 0 , eArgTypeNone , " Enable debug logging. " } ,
{ LLDB_OPT_SET_1 , false , " sequence " , ' s ' , no_argument , NULL , 0 , eArgTypeNone , " Prepend all log lines with an increasing integer sequence id. " } ,
{ LLDB_OPT_SET_1 , false , " timestamp " , ' T ' , no_argument , NULL , 0 , eArgTypeNone , " Prepend all log lines with a timestamp. " } ,
{ LLDB_OPT_SET_1 , false , " pid-tid " , ' p ' , no_argument , NULL , 0 , eArgTypeNone , " Prepend all log lines with the process and thread ID that generates the log line. " } ,
{ LLDB_OPT_SET_1 , false , " thread-name " , ' n ' , no_argument , NULL , 0 , eArgTypeNone , " Prepend all log lines with the thread name for the thread that generates the log line. " } ,
2012-10-09 06:41:53 +08:00
{ LLDB_OPT_SET_1 , false , " stack " , ' S ' , no_argument , NULL , 0 , eArgTypeNone , " Append a stack backtrace to each log line. " } ,
2010-10-02 03:59:14 +08:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
2010-06-09 00:52:24 +08:00
} ;
2012-06-09 05:56:10 +08:00
class CommandObjectLogDisable : public CommandObjectParsed
2010-06-09 00:52:24 +08:00
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
2010-09-18 09:14:36 +08:00
CommandObjectLogDisable ( CommandInterpreter & interpreter ) :
2012-06-09 05:56:10 +08:00
CommandObjectParsed ( interpreter ,
" log disable " ,
" Disable one or more log channel categories. " ,
NULL )
2010-06-09 00:52:24 +08:00
{
2010-10-30 05:56:41 +08:00
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
2010-10-05 06:28:36 +08:00
CommandArgumentData channel_arg ;
2010-10-30 05:56:41 +08:00
CommandArgumentData category_arg ;
2010-10-05 06:28:36 +08:00
// Define the first (and only) variant of this arg.
channel_arg . arg_type = eArgTypeLogChannel ;
2010-10-30 05:56:41 +08:00
channel_arg . arg_repetition = eArgRepeatPlain ;
2010-10-05 06:28:36 +08:00
// There is only one variant this argument could be; put it into the argument entry.
2010-10-30 05:56:41 +08:00
arg1 . push_back ( channel_arg ) ;
2010-10-05 06:28:36 +08:00
2010-10-30 05:56:41 +08:00
category_arg . arg_type = eArgTypeLogCategory ;
category_arg . arg_repetition = eArgRepeatPlus ;
arg2 . push_back ( category_arg ) ;
2010-10-05 06:28:36 +08:00
// Push the data for the first argument into the m_arguments vector.
2010-10-30 05:56:41 +08:00
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
2010-06-09 00:52:24 +08:00
}
virtual
~ CommandObjectLogDisable ( )
{
}
2012-06-09 05:56:10 +08:00
protected :
2010-06-09 00:52:24 +08:00
virtual bool
2012-06-09 05:56:10 +08:00
DoExecute ( Args & args ,
2010-06-09 00:52:24 +08:00
CommandReturnObject & result )
{
const size_t argc = args . GetArgumentCount ( ) ;
if ( argc = = 0 )
{
2012-05-12 08:38:30 +08:00
result . AppendErrorWithFormat ( " %s takes a log channel and one or more log types. \n " , m_cmd_name . c_str ( ) ) ;
2010-06-09 00:52:24 +08:00
}
else
{
2010-10-30 05:48:37 +08:00
Log : : Callbacks log_callbacks ;
2010-06-09 00:52:24 +08:00
2010-10-30 05:48:37 +08:00
std : : string channel ( args . GetArgumentAtIndex ( 0 ) ) ;
args . Shift ( ) ; // Shift off the channel
if ( Log : : GetLogChannelCallbacks ( channel . c_str ( ) , log_callbacks ) )
{
2012-02-21 10:23:08 +08:00
log_callbacks . disable ( args . GetConstArgumentVector ( ) , & result . GetErrorStream ( ) ) ;
2010-10-30 05:48:37 +08:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else if ( channel = = " all " )
{
Log : : DisableAllLogChannels ( & result . GetErrorStream ( ) ) ;
}
else
{
2011-04-14 06:47:15 +08:00
LogChannelSP log_channel_sp ( LogChannel : : FindPlugin ( channel . c_str ( ) ) ) ;
2010-10-30 05:48:37 +08:00
if ( log_channel_sp )
2010-06-09 00:52:24 +08:00
{
2012-02-21 10:23:08 +08:00
log_channel_sp - > Disable ( args . GetConstArgumentVector ( ) , & result . GetErrorStream ( ) ) ;
2010-06-09 00:52:24 +08:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
2010-10-30 05:48:37 +08:00
result . AppendErrorWithFormat ( " Invalid log channel '%s'. \n " , args . GetArgumentAtIndex ( 0 ) ) ;
2010-06-09 00:52:24 +08:00
}
}
return result . Succeeded ( ) ;
}
} ;
2012-06-09 05:56:10 +08:00
class CommandObjectLogList : public CommandObjectParsed
2010-06-09 00:52:24 +08:00
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
2010-09-18 09:14:36 +08:00
CommandObjectLogList ( CommandInterpreter & interpreter ) :
2012-06-09 05:56:10 +08:00
CommandObjectParsed ( interpreter ,
" log list " ,
" List the log categories for one or more log channels. If none specified, lists them all. " ,
NULL )
2010-06-09 00:52:24 +08:00
{
2010-10-05 06:28:36 +08:00
CommandArgumentEntry arg ;
CommandArgumentData channel_arg ;
// Define the first (and only) variant of this arg.
channel_arg . arg_type = eArgTypeLogChannel ;
channel_arg . arg_repetition = eArgRepeatStar ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( channel_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
2010-06-09 00:52:24 +08:00
}
virtual
~ CommandObjectLogList ( )
{
}
2012-06-09 05:56:10 +08:00
protected :
2010-06-09 00:52:24 +08:00
virtual bool
2012-06-09 05:56:10 +08:00
DoExecute ( Args & args ,
2010-06-09 00:52:24 +08:00
CommandReturnObject & result )
{
const size_t argc = args . GetArgumentCount ( ) ;
if ( argc = = 0 )
{
Log : : ListAllLogChannels ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
for ( size_t i = 0 ; i < argc ; + + i )
{
Log : : Callbacks log_callbacks ;
std : : string channel ( args . GetArgumentAtIndex ( i ) ) ;
if ( Log : : GetLogChannelCallbacks ( channel . c_str ( ) , log_callbacks ) )
{
log_callbacks . list_categories ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else if ( channel = = " all " )
{
Log : : ListAllLogChannels ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
2011-04-14 06:47:15 +08:00
LogChannelSP log_channel_sp ( LogChannel : : FindPlugin ( channel . c_str ( ) ) ) ;
2010-06-09 00:52:24 +08:00
if ( log_channel_sp )
{
log_channel_sp - > ListCategories ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
result . AppendErrorWithFormat ( " Invalid log channel '%s'. \n " , args . GetArgumentAtIndex ( 0 ) ) ;
}
}
}
return result . Succeeded ( ) ;
}
} ;
2012-06-09 05:56:10 +08:00
class CommandObjectLogTimer : public CommandObjectParsed
2010-06-09 00:52:24 +08:00
{
public :
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
2010-09-18 09:14:36 +08:00
CommandObjectLogTimer ( CommandInterpreter & interpreter ) :
2012-06-09 05:56:10 +08:00
CommandObjectParsed ( interpreter ,
" log timers " ,
" Enable, disable, dump, and reset LLDB internal performance timers. " ,
" log timers < enable <depth> | disable | dump | increment <bool> | reset > " )
2010-06-09 00:52:24 +08:00
{
}
virtual
~ CommandObjectLogTimer ( )
{
}
2012-06-09 05:56:10 +08:00
protected :
2010-06-09 00:52:24 +08:00
virtual bool
2012-06-09 05:56:10 +08:00
DoExecute ( Args & args ,
2010-06-09 00:52:24 +08:00
CommandReturnObject & result )
{
const size_t argc = args . GetArgumentCount ( ) ;
result . SetStatus ( eReturnStatusFailed ) ;
if ( argc = = 1 )
{
const char * sub_command = args . GetArgumentAtIndex ( 0 ) ;
if ( strcasecmp ( sub_command , " enable " ) = = 0 )
{
Timer : : SetDisplayDepth ( UINT32_MAX ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else if ( strcasecmp ( sub_command , " disable " ) = = 0 )
{
Timer : : DumpCategoryTimes ( & result . GetOutputStream ( ) ) ;
Timer : : SetDisplayDepth ( 0 ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else if ( strcasecmp ( sub_command , " dump " ) = = 0 )
{
Timer : : DumpCategoryTimes ( & result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else if ( strcasecmp ( sub_command , " reset " ) = = 0 )
{
Timer : : ResetCategoryTimes ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
}
2010-11-05 07:08:26 +08:00
else if ( argc = = 2 )
{
const char * sub_command = args . GetArgumentAtIndex ( 0 ) ;
if ( strcasecmp ( sub_command , " enable " ) = = 0 )
{
bool success ;
uint32_t depth = Args : : StringToUInt32 ( args . GetArgumentAtIndex ( 1 ) , 0 , 0 , & success ) ;
if ( success )
{
Timer : : SetDisplayDepth ( depth ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
result . AppendError ( " Could not convert enable depth to an unsigned integer. " ) ;
}
2010-11-05 07:19:21 +08:00
if ( strcasecmp ( sub_command , " increment " ) = = 0 )
{
bool success ;
bool increment = Args : : StringToBoolean ( args . GetArgumentAtIndex ( 1 ) , false , & success ) ;
if ( success )
{
Timer : : SetQuiet ( ! increment ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
result . AppendError ( " Could not convert increment value to boolean. " ) ;
}
2010-11-05 07:08:26 +08:00
}
2010-06-09 00:52:24 +08:00
if ( ! result . Succeeded ( ) )
{
result . AppendError ( " Missing subcommand " ) ;
result . AppendErrorWithFormat ( " Usage: %s \n " , m_cmd_syntax . c_str ( ) ) ;
}
return result . Succeeded ( ) ;
}
} ;
//----------------------------------------------------------------------
// CommandObjectLog constructor
//----------------------------------------------------------------------
2010-06-23 09:19:29 +08:00
CommandObjectLog : : CommandObjectLog ( CommandInterpreter & interpreter ) :
2010-09-18 09:14:36 +08:00
CommandObjectMultiword ( interpreter ,
" log " ,
2010-06-09 00:52:24 +08:00
" A set of commands for operating on logs. " ,
" log <command> [<command-options>] " )
{
2010-09-18 09:14:36 +08:00
LoadSubCommand ( " enable " , CommandObjectSP ( new CommandObjectLogEnable ( interpreter ) ) ) ;
LoadSubCommand ( " disable " , CommandObjectSP ( new CommandObjectLogDisable ( interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectLogList ( interpreter ) ) ) ;
LoadSubCommand ( " timers " , CommandObjectSP ( new CommandObjectLogTimer ( interpreter ) ) ) ;
2010-06-09 00:52:24 +08:00
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
CommandObjectLog : : ~ CommandObjectLog ( )
{
}