2013-08-23 17:46:38 +00:00
//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
2016-07-23 20:50:09 +00:00
# include "CommandObjectProcess.h"
2013-08-23 17:46:38 +00:00
# include "lldb/Breakpoint/Breakpoint.h"
# include "lldb/Breakpoint/BreakpointLocation.h"
# include "lldb/Breakpoint/BreakpointSite.h"
# include "lldb/Core/State.h"
# include "lldb/Core/Module.h"
2014-11-25 21:00:58 +00:00
# include "lldb/Core/PluginManager.h"
2013-08-23 17:46:38 +00:00
# include "lldb/Host/Host.h"
2015-02-09 01:44:09 +00:00
# include "lldb/Host/StringConvert.h"
2013-08-23 17:46:38 +00:00
# include "lldb/Interpreter/Args.h"
# include "lldb/Interpreter/Options.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Target/Platform.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/StopInfo.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
2015-07-03 16:57:06 +00:00
# include "lldb/Target/UnixSignals.h"
2013-08-23 17:46:38 +00:00
using namespace lldb ;
using namespace lldb_private ;
class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed
{
public :
CommandObjectProcessLaunchOrAttach ( CommandInterpreter & interpreter ,
const char * name ,
const char * help ,
const char * syntax ,
uint32_t flags ,
const char * new_process_action ) :
CommandObjectParsed ( interpreter , name , help , syntax , flags ) ,
m_new_process_action ( new_process_action ) { }
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessLaunchOrAttach ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
bool
2014-02-18 16:23:10 +00:00
StopProcessIfNecessary ( Process * process , StateType & state , CommandReturnObject & result )
2013-08-23 17:46:38 +00:00
{
state = eStateInvalid ;
if ( process )
{
state = process - > GetState ( ) ;
if ( process - > IsAlive ( ) & & state ! = eStateConnected )
{
char message [ 1024 ] ;
if ( process - > GetState ( ) = = eStateAttaching )
: : snprintf ( message , sizeof ( message ) , " There is a pending attach, abort it and %s? " , m_new_process_action . c_str ( ) ) ;
else if ( process - > GetShouldDetach ( ) )
: : snprintf ( message , sizeof ( message ) , " There is a running process, detach from it and %s? " , m_new_process_action . c_str ( ) ) ;
else
: : snprintf ( message , sizeof ( message ) , " There is a running process, kill it and %s? " , m_new_process_action . c_str ( ) ) ;
if ( ! m_interpreter . Confirm ( message , true ) )
{
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
else
{
if ( process - > GetShouldDetach ( ) )
{
bool keep_stopped = false ;
Error detach_error ( process - > Detach ( keep_stopped ) ) ;
if ( detach_error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2016-07-23 20:50:09 +00:00
process = nullptr ;
2013-08-23 17:46:38 +00:00
}
else
{
result . AppendErrorWithFormat ( " Failed to detach from process: %s \n " , detach_error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
2015-07-03 16:57:06 +00:00
Error destroy_error ( process - > Destroy ( false ) ) ;
2013-08-23 17:46:38 +00:00
if ( destroy_error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
2016-07-23 20:50:09 +00:00
process = nullptr ;
2013-08-23 17:46:38 +00:00
}
else
{
result . AppendErrorWithFormat ( " Failed to kill process: %s \n " , destroy_error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
}
}
}
return result . Succeeded ( ) ;
}
2016-07-23 20:50:09 +00:00
2013-08-23 17:46:38 +00:00
std : : string m_new_process_action ;
} ;
2016-07-23 20:50:09 +00:00
2013-08-23 17:46:38 +00:00
//-------------------------------------------------------------------------
// CommandObjectProcessLaunch
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessLaunch
class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
{
public :
CommandObjectProcessLaunch ( CommandInterpreter & interpreter ) :
2016-07-23 20:50:09 +00:00
CommandObjectProcessLaunchOrAttach ( interpreter ,
" process launch " ,
" Launch the executable in the debugger. " ,
nullptr ,
eCommandRequiresTarget ,
" restart " ) ,
2013-08-23 17:46:38 +00:00
m_options ( interpreter )
{
CommandArgumentEntry arg ;
CommandArgumentData run_args_arg ;
// Define the first (and only) variant of this arg.
run_args_arg . arg_type = eArgTypeRunArgs ;
run_args_arg . arg_repetition = eArgRepeatOptional ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( run_args_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessLaunch ( ) override = default ;
2013-08-23 17:46:38 +00:00
2015-12-30 11:55:28 +00:00
int
2013-08-23 17:46:38 +00:00
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 ,
2015-12-30 11:55:28 +00:00
StringList & matches ) override
2013-08-23 17:46:38 +00:00
{
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
2016-07-23 20:50:09 +00:00
CommandCompletions : : InvokeCommonCompletionCallbacks ( m_interpreter ,
CommandCompletions : : eDiskFileCompletion ,
completion_str . c_str ( ) ,
match_start_point ,
max_return_elements ,
nullptr ,
word_complete ,
matches ) ;
2013-08-23 17:46:38 +00:00
return matches . GetSize ( ) ;
}
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
2015-12-30 11:55:28 +00:00
const char *
GetRepeatCommand ( Args & current_command_args , uint32_t index ) override
2013-08-23 17:46:38 +00:00
{
// No repeat for "process launch"...
return " " ;
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & launch_args , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Debugger & debugger = m_interpreter . GetDebugger ( ) ;
Target * target = debugger . GetSelectedTarget ( ) . get ( ) ;
2016-07-23 20:50:09 +00:00
// If our listener is nullptr, users aren't allows to launch
2014-02-18 16:23:10 +00:00
ModuleSP exe_module_sp = target - > GetExecutableModule ( ) ;
2013-08-23 17:46:38 +00:00
2016-07-23 20:50:09 +00:00
if ( exe_module_sp = = nullptr )
2013-08-23 17:46:38 +00:00
{
result . AppendError ( " no file in target, create a debug target using the 'target create' command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
StateType state = eStateInvalid ;
2014-02-18 16:23:10 +00:00
if ( ! StopProcessIfNecessary ( m_exe_ctx . GetProcessPtr ( ) , state , result ) )
2013-08-23 17:46:38 +00:00
return false ;
const char * target_settings_argv0 = target - > GetArg0 ( ) ;
2014-11-25 21:00:58 +00:00
// Determine whether we will disable ASLR or leave it in the default state (i.e. enabled if the platform supports it).
// First check if the process launch options explicitly turn on/off disabling ASLR. If so, use that setting;
// otherwise, use the 'settings target.disable-aslr' setting.
bool disable_aslr = false ;
if ( m_options . disable_aslr ! = eLazyBoolCalculate )
{
// The user specified an explicit setting on the process launch line. Use it.
disable_aslr = ( m_options . disable_aslr = = eLazyBoolYes ) ;
}
else
{
// The user did not explicitly specify whether to disable ASLR. Fall back to the target.disable-aslr setting.
disable_aslr = target - > GetDisableASLR ( ) ;
}
if ( disable_aslr )
2014-02-18 16:23:10 +00:00
m_options . launch_info . GetFlags ( ) . Set ( eLaunchFlagDisableASLR ) ;
2014-11-25 21:00:58 +00:00
else
m_options . launch_info . GetFlags ( ) . Clear ( eLaunchFlagDisableASLR ) ;
if ( target - > GetDetachOnError ( ) )
m_options . launch_info . GetFlags ( ) . Set ( eLaunchFlagDetachOnError ) ;
2014-02-18 16:23:10 +00:00
if ( target - > GetDisableSTDIO ( ) )
m_options . launch_info . GetFlags ( ) . Set ( eLaunchFlagDisableSTDIO ) ;
2013-08-23 17:46:38 +00:00
2014-02-18 16:23:10 +00:00
Args environment ;
target - > GetEnvironmentAsArgs ( environment ) ;
if ( environment . GetArgumentCount ( ) > 0 )
m_options . launch_info . GetEnvironmentEntries ( ) . AppendArguments ( environment ) ;
2013-08-23 17:46:38 +00:00
if ( target_settings_argv0 )
{
m_options . launch_info . GetArguments ( ) . AppendArgument ( target_settings_argv0 ) ;
2014-02-18 16:23:10 +00:00
m_options . launch_info . SetExecutableFile ( exe_module_sp - > GetPlatformFileSpec ( ) , false ) ;
2013-08-23 17:46:38 +00:00
}
else
{
2014-02-18 16:23:10 +00:00
m_options . launch_info . SetExecutableFile ( exe_module_sp - > GetPlatformFileSpec ( ) , true ) ;
2013-08-23 17:46:38 +00:00
}
if ( launch_args . GetArgumentCount ( ) = = 0 )
{
2015-07-03 16:57:06 +00:00
m_options . launch_info . GetArguments ( ) . AppendArguments ( target - > GetProcessLaunchInfo ( ) . GetArguments ( ) ) ;
2013-08-23 17:46:38 +00:00
}
else
{
m_options . launch_info . GetArguments ( ) . AppendArguments ( launch_args ) ;
// Save the arguments for subsequent runs in the current target.
target - > SetRunArguments ( launch_args ) ;
}
2015-02-06 21:38:51 +00:00
StreamString stream ;
Error error = target - > Launch ( m_options . launch_info , & stream ) ;
2013-08-23 17:46:38 +00:00
if ( error . Success ( ) )
{
2014-02-18 16:23:10 +00:00
ProcessSP process_sp ( target - > GetProcessSP ( ) ) ;
if ( process_sp )
2013-08-23 17:46:38 +00:00
{
2015-07-03 16:57:06 +00:00
// There is a race condition where this thread will return up the call stack to the main command
// handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
// a chance to call PushProcessIOHandler().
process_sp - > SyncIOHandler ( 0 , 2000 ) ;
2015-02-06 21:38:51 +00:00
const char * data = stream . GetData ( ) ;
if ( data & & strlen ( data ) > 0 )
result . AppendMessage ( stream . GetData ( ) ) ;
2015-07-03 16:57:06 +00:00
const char * archname = exe_module_sp - > GetArchitecture ( ) . GetArchitectureName ( ) ;
2014-02-18 16:23:10 +00:00
result . AppendMessageWithFormat ( " Process % " PRIu64 " launched: '%s' (%s) \n " , process_sp - > GetID ( ) , exe_module_sp - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) , archname ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
result . SetDidChangeProcessState ( true ) ;
}
else
{
result . AppendError ( " no error returned from Target::Launch, and target has no process " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 17:46:38 +00:00
}
}
else
{
2014-02-18 16:23:10 +00:00
result . AppendError ( error . AsCString ( ) ) ;
2013-08-23 17:46:38 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
protected :
ProcessLaunchCommandOptions m_options ;
} ;
//#define SET1 LLDB_OPT_SET_1
//#define SET2 LLDB_OPT_SET_2
//#define SET3 LLDB_OPT_SET_3
//
//OptionDefinition
//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
//{
2016-07-23 20:50:09 +00:00
//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
//{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."},
//{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."},
//{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."},
//{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
//{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
//{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
//{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."},
//{ 0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr }
2013-08-23 17:46:38 +00:00
//};
//
//#undef SET1
//#undef SET2
//#undef SET3
//-------------------------------------------------------------------------
// CommandObjectProcessAttach
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessAttach
class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2013-08-23 17:46:38 +00:00
Error
2015-12-30 11:55:28 +00:00
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
2013-08-23 17:46:38 +00:00
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success = false ;
switch ( short_option )
{
case ' c ' :
attach_info . SetContinueOnceAttached ( true ) ;
break ;
case ' p ' :
{
2015-02-09 01:44:09 +00:00
lldb : : pid_t pid = StringConvert : : ToUInt32 ( option_arg , LLDB_INVALID_PROCESS_ID , 0 , & success ) ;
2013-08-23 17:46:38 +00:00
if ( ! success | | pid = = LLDB_INVALID_PROCESS_ID )
{
error . SetErrorStringWithFormat ( " invalid process ID '%s' " , option_arg ) ;
}
else
{
attach_info . SetProcessID ( pid ) ;
}
}
break ;
case ' P ' :
attach_info . SetProcessPluginName ( option_arg ) ;
break ;
case ' n ' :
attach_info . GetExecutableFile ( ) . SetFile ( option_arg , false ) ;
break ;
case ' w ' :
attach_info . SetWaitForLaunch ( true ) ;
break ;
case ' i ' :
attach_info . SetIgnoreExisting ( false ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
2015-12-30 11:55:28 +00:00
OptionParsingStarting ( ) override
2013-08-23 17:46:38 +00:00
{
attach_info . Clear ( ) ;
}
const OptionDefinition *
2015-12-30 11:55:28 +00:00
GetDefinitions ( ) override
2013-08-23 17:46:38 +00:00
{
return g_option_table ;
}
2015-12-30 11:55:28 +00:00
bool
2013-08-23 17:46:38 +00:00
HandleOptionArgumentCompletion ( Args & input ,
int cursor_index ,
int char_pos ,
OptionElementVector & opt_element_vector ,
int opt_element_index ,
int match_start_point ,
int max_return_elements ,
bool & word_complete ,
2015-12-30 11:55:28 +00:00
StringList & matches ) override
2013-08-23 17:46:38 +00:00
{
int opt_arg_pos = opt_element_vector [ opt_element_index ] . opt_arg_pos ;
int opt_defs_index = opt_element_vector [ opt_element_index ] . opt_defs_index ;
// We are only completing the name option for now...
const OptionDefinition * opt_defs = GetDefinitions ( ) ;
if ( opt_defs [ opt_defs_index ] . short_option = = ' n ' )
{
// Are we in the name?
// Look to see if there is a -P argument provided, and if so use that plugin, otherwise
// use the default plugin.
2016-07-23 20:50:09 +00:00
const char * partial_name = nullptr ;
2013-08-23 17:46:38 +00:00
partial_name = input . GetArgumentAtIndex ( opt_arg_pos ) ;
PlatformSP platform_sp ( m_interpreter . GetPlatform ( true ) ) ;
if ( platform_sp )
{
ProcessInstanceInfoList process_infos ;
ProcessInstanceInfoMatch match_info ;
if ( partial_name )
{
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( partial_name , false ) ;
match_info . SetNameMatchType ( eNameMatchStartsWith ) ;
}
platform_sp - > FindProcesses ( match_info , process_infos ) ;
const size_t num_matches = process_infos . GetSize ( ) ;
if ( num_matches > 0 )
{
2016-07-23 20:50:09 +00:00
for ( size_t i = 0 ; i < num_matches ; + + i )
2013-08-23 17:46:38 +00:00
{
matches . AppendString ( process_infos . GetProcessNameAtIndex ( i ) ,
process_infos . GetProcessNameLengthAtIndex ( i ) ) ;
}
}
}
}
return false ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
ProcessAttachInfo attach_info ;
} ;
CommandObjectProcessAttach ( CommandInterpreter & interpreter ) :
CommandObjectProcessLaunchOrAttach ( interpreter ,
" process attach " ,
" Attach to a process. " ,
" process attach <cmd-options> " ,
0 ,
" attach " ) ,
m_options ( interpreter )
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessAttach ( ) override = default ;
2013-08-23 17:46:38 +00:00
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
2015-02-09 01:44:09 +00:00
PlatformSP platform_sp ( m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
2013-08-23 17:46:38 +00:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
// N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach
// and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
// ourselves here.
StateType state = eStateInvalid ;
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( ! StopProcessIfNecessary ( process , state , result ) )
return false ;
2016-07-23 20:50:09 +00:00
if ( target = = nullptr )
2013-08-23 17:46:38 +00:00
{
// If there isn't a current target create one.
TargetSP new_target_sp ;
Error error ;
2016-07-23 20:50:09 +00:00
error = m_interpreter . GetDebugger ( ) . GetTargetList ( ) . CreateTarget ( m_interpreter . GetDebugger ( ) ,
nullptr ,
nullptr ,
false ,
nullptr , // No platform options
new_target_sp ) ;
2013-08-23 17:46:38 +00:00
target = new_target_sp . get ( ) ;
2016-07-23 20:50:09 +00:00
if ( target = = nullptr | | error . Fail ( ) )
2013-08-23 17:46:38 +00:00
{
result . AppendError ( error . AsCString ( " Error creating target " ) ) ;
return false ;
}
m_interpreter . GetDebugger ( ) . GetTargetList ( ) . SetSelectedTarget ( target ) ;
}
// Record the old executable module, we want to issue a warning if the process of attaching changed the
// current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
ModuleSP old_exec_module_sp = target - > GetExecutableModule ( ) ;
ArchSpec old_arch_spec = target - > GetArchitecture ( ) ;
if ( command . GetArgumentCount ( ) )
{
result . AppendErrorWithFormat ( " Invalid arguments for '%s'. \n Usage: %s \n " , m_cmd_name . c_str ( ) , m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2015-02-09 01:44:09 +00:00
return false ;
2013-08-23 17:46:38 +00:00
}
2015-02-09 01:44:09 +00:00
m_interpreter . UpdateExecutionContext ( nullptr ) ;
2015-07-03 16:57:06 +00:00
StreamString stream ;
const auto error = target - > Attach ( m_options . attach_info , & stream ) ;
2015-02-09 01:44:09 +00:00
if ( error . Success ( ) )
{
2015-07-03 16:57:06 +00:00
ProcessSP process_sp ( target - > GetProcessSP ( ) ) ;
if ( process_sp )
2013-08-23 17:46:38 +00:00
{
2015-07-03 16:57:06 +00:00
if ( stream . GetData ( ) )
result . AppendMessage ( stream . GetData ( ) ) ;
2015-02-09 01:44:09 +00:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2015-07-03 16:57:06 +00:00
result . SetDidChangeProcessState ( true ) ;
2016-01-13 20:06:56 +00:00
result . SetAbnormalStopWasExpected ( true ) ;
2013-08-23 17:46:38 +00:00
}
2015-02-09 01:44:09 +00:00
else
2013-08-23 17:46:38 +00:00
{
2015-07-03 16:57:06 +00:00
result . AppendError ( " no error returned from Target::Attach, and target has no process " ) ;
2015-02-09 01:44:09 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 17:46:38 +00:00
}
2015-02-09 01:44:09 +00:00
}
else
{
result . AppendErrorWithFormat ( " attach failed: %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
if ( ! result . Succeeded ( ) )
return false ;
// Okay, we're done. Last step is to warn if the executable module has changed:
char new_path [ PATH_MAX ] ;
ModuleSP new_exec_module_sp ( target - > GetExecutableModule ( ) ) ;
if ( ! old_exec_module_sp )
{
// We might not have a module if we attached to a raw pid...
if ( new_exec_module_sp )
2013-08-23 17:46:38 +00:00
{
2015-02-09 01:44:09 +00:00
new_exec_module_sp - > GetFileSpec ( ) . GetPath ( new_path , PATH_MAX ) ;
result . AppendMessageWithFormat ( " Executable module set to \" %s \" . \n " , new_path ) ;
2013-08-23 17:46:38 +00:00
}
2015-02-09 01:44:09 +00:00
}
else if ( old_exec_module_sp - > GetFileSpec ( ) ! = new_exec_module_sp - > GetFileSpec ( ) )
{
char old_path [ PATH_MAX ] ;
2013-08-23 17:46:38 +00:00
2015-02-09 01:44:09 +00:00
old_exec_module_sp - > GetFileSpec ( ) . GetPath ( old_path , PATH_MAX ) ;
new_exec_module_sp - > GetFileSpec ( ) . GetPath ( new_path , PATH_MAX ) ;
result . AppendWarningWithFormat ( " Executable module changed from \" %s \" to \" %s \" . \n " ,
old_path , new_path ) ;
}
if ( ! old_arch_spec . IsValid ( ) )
{
result . AppendMessageWithFormat ( " Architecture set to: %s. \n " , target - > GetArchitecture ( ) . GetTriple ( ) . getTriple ( ) . c_str ( ) ) ;
2013-08-23 17:46:38 +00:00
}
2015-02-09 01:44:09 +00:00
else if ( ! old_arch_spec . IsExactMatch ( target - > GetArchitecture ( ) ) )
{
result . AppendWarningWithFormat ( " Architecture changed from %s to %s. \n " ,
old_arch_spec . GetTriple ( ) . getTriple ( ) . c_str ( ) ,
target - > GetArchitecture ( ) . GetTriple ( ) . getTriple ( ) . c_str ( ) ) ;
}
// This supports the use-case scenario of immediately continuing the process once attached.
if ( m_options . attach_info . GetContinueOnceAttached ( ) )
m_interpreter . HandleCommand ( " process continue " , eLazyBoolNo , result ) ;
2013-08-23 17:46:38 +00:00
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectProcessAttach : : CommandOptions : : g_option_table [ ] =
{
2016-07-23 20:50:09 +00:00
{ LLDB_OPT_SET_ALL , false , " continue " , ' c ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Immediately continue the process once attached. " } ,
{ LLDB_OPT_SET_ALL , false , " plugin " , ' P ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePlugin , " Name of the process plugin you want to use. " } ,
{ LLDB_OPT_SET_1 , false , " pid " , ' p ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePid , " The process ID of an existing process to attach to. " } ,
{ LLDB_OPT_SET_2 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeProcessName , " The name of the process to attach to. " } ,
{ LLDB_OPT_SET_2 , false , " include-existing " , ' i ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Include existing processes when doing attach -w. " } ,
{ LLDB_OPT_SET_2 , false , " waitfor " , ' w ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Wait for the process with <process-name> to launch. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2013-08-23 17:46:38 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessContinue
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessContinue
class CommandObjectProcessContinue : public CommandObjectParsed
{
public :
CommandObjectProcessContinue ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" process continue " ,
" Continue execution of all threads in the current process. " ,
" process continue " ,
2015-07-03 16:57:06 +00:00
eCommandRequiresProcess |
eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused ) ,
2013-08-23 17:46:38 +00:00
m_options ( interpreter )
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessContinue ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2013-08-23 17:46:38 +00:00
Error
2015-12-30 11:55:28 +00:00
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
2013-08-23 17:46:38 +00:00
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success = false ;
switch ( short_option )
{
case ' i ' :
2015-02-09 01:44:09 +00:00
m_ignore = StringConvert : : ToUInt32 ( option_arg , 0 , 0 , & success ) ;
2013-08-23 17:46:38 +00:00
if ( ! success )
error . SetErrorStringWithFormat ( " invalid value for ignore option: \" %s \" , should be a number. " , option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
2015-12-30 11:55:28 +00:00
OptionParsingStarting ( ) override
2013-08-23 17:46:38 +00:00
{
m_ignore = 0 ;
}
const OptionDefinition *
2015-12-30 11:55:28 +00:00
GetDefinitions ( ) override
2013-08-23 17:46:38 +00:00
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
uint32_t m_ignore ;
} ;
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
bool synchronous_execution = m_interpreter . GetSynchronous ( ) ;
StateType state = process - > GetState ( ) ;
if ( state = = eStateStopped )
{
if ( command . GetArgumentCount ( ) ! = 0 )
{
result . AppendErrorWithFormat ( " The '%s' command does not take any arguments. \n " , m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( m_options . m_ignore > 0 )
{
2016-07-23 20:50:09 +00:00
ThreadSP sel_thread_sp ( GetDefaultThread ( ) - > shared_from_this ( ) ) ;
2013-08-23 17:46:38 +00:00
if ( sel_thread_sp )
{
StopInfoSP stop_info_sp = sel_thread_sp - > GetStopInfo ( ) ;
if ( stop_info_sp & & stop_info_sp - > GetStopReason ( ) = = eStopReasonBreakpoint )
{
lldb : : break_id_t bp_site_id = ( lldb : : break_id_t ) stop_info_sp - > GetValue ( ) ;
BreakpointSiteSP bp_site_sp ( process - > GetBreakpointSiteList ( ) . FindByID ( bp_site_id ) ) ;
if ( bp_site_sp )
{
const size_t num_owners = bp_site_sp - > GetNumberOfOwners ( ) ;
for ( size_t i = 0 ; i < num_owners ; i + + )
{
Breakpoint & bp_ref = bp_site_sp - > GetOwnerAtIndex ( i ) - > GetBreakpoint ( ) ;
if ( ! bp_ref . IsInternal ( ) )
{
bp_ref . SetIgnoreCount ( m_options . m_ignore ) ;
}
}
}
}
}
}
{ // Scope for thread list mutex:
2016-07-23 20:50:09 +00:00
std : : lock_guard < std : : recursive_mutex > guard ( process - > GetThreadList ( ) . GetMutex ( ) ) ;
2013-08-23 17:46:38 +00:00
const uint32_t num_threads = process - > GetThreadList ( ) . GetSize ( ) ;
// Set the actions that the threads should each take when resuming
for ( uint32_t idx = 0 ; idx < num_threads ; + + idx )
{
2014-11-25 21:00:58 +00:00
const bool override_suspend = false ;
process - > GetThreadList ( ) . GetThreadAtIndex ( idx ) - > SetResumeState ( eStateRunning , override_suspend ) ;
2013-08-23 17:46:38 +00:00
}
}
2014-11-25 21:00:58 +00:00
2015-07-03 16:57:06 +00:00
const uint32_t iohandler_id = process - > GetIOHandlerID ( ) ;
2015-02-06 21:38:51 +00:00
StreamString stream ;
Error error ;
if ( synchronous_execution )
error = process - > ResumeSynchronous ( & stream ) ;
else
error = process - > Resume ( ) ;
2014-11-25 21:00:58 +00:00
2013-08-23 17:46:38 +00:00
if ( error . Success ( ) )
{
2014-11-25 21:00:58 +00:00
// There is a race condition where this thread will return up the call stack to the main command
2015-07-03 16:57:06 +00:00
// handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
// a chance to call PushProcessIOHandler().
process - > SyncIOHandler ( iohandler_id , 2000 ) ;
2014-11-25 21:00:58 +00:00
2013-08-23 17:46:38 +00:00
result . AppendMessageWithFormat ( " Process % " PRIu64 " resuming \n " , process - > GetID ( ) ) ;
if ( synchronous_execution )
{
2015-02-06 21:38:51 +00:00
// If any state changed events had anything to say, add that to the result
if ( stream . GetData ( ) )
result . AppendMessage ( stream . GetData ( ) ) ;
2013-08-23 17:46:38 +00:00
result . SetDidChangeProcessState ( true ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . SetStatus ( eReturnStatusSuccessContinuingNoResult ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Failed to resume process: %s. \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " Process cannot be continued from its current state (%s). \n " ,
StateAsCString ( state ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectProcessContinue : : CommandOptions : : g_option_table [ ] =
{
2016-07-23 20:50:09 +00:00
{ LLDB_OPT_SET_ALL , false , " ignore-count " , ' i ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger ,
2013-08-23 17:46:38 +00:00
" Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread. " } ,
2016-07-23 20:50:09 +00:00
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2013-08-23 17:46:38 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessDetach
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessDetach
class CommandObjectProcessDetach : public CommandObjectParsed
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2013-08-23 17:46:38 +00:00
Error
2015-12-30 11:55:28 +00:00
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
2013-08-23 17:46:38 +00:00
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' s ' :
bool tmp_result ;
bool success ;
tmp_result = Args : : StringToBoolean ( option_arg , false , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid boolean option: \" %s \" " , option_arg ) ;
else
{
if ( tmp_result )
m_keep_stopped = eLazyBoolYes ;
else
m_keep_stopped = eLazyBoolNo ;
}
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
2015-12-30 11:55:28 +00:00
OptionParsingStarting ( ) override
2013-08-23 17:46:38 +00:00
{
m_keep_stopped = eLazyBoolCalculate ;
}
const OptionDefinition *
2015-12-30 11:55:28 +00:00
GetDefinitions ( ) override
2013-08-23 17:46:38 +00:00
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
LazyBool m_keep_stopped ;
} ;
2016-07-23 20:50:09 +00:00
CommandObjectProcessDetach ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " process detach " , " Detach from the current target process. " ,
" process detach " ,
eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched ) ,
m_options ( interpreter )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessDetach ( ) override = default ;
2013-08-23 17:46:38 +00:00
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
// FIXME: This will be a Command Option:
bool keep_stopped ;
if ( m_options . m_keep_stopped = = eLazyBoolCalculate )
{
// Check the process default:
2016-07-23 20:50:09 +00:00
keep_stopped = process - > GetDetachKeepsStopped ( ) ;
2013-08-23 17:46:38 +00:00
}
else if ( m_options . m_keep_stopped = = eLazyBoolYes )
keep_stopped = true ;
else
keep_stopped = false ;
Error error ( process - > Detach ( keep_stopped ) ) ;
if ( error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Detach failed: %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectProcessDetach : : CommandOptions : : g_option_table [ ] =
{
2016-07-23 20:50:09 +00:00
{ LLDB_OPT_SET_1 , false , " keep-stopped " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Whether or not the process should be kept stopped on detach (if possible). " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2013-08-23 17:46:38 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessConnect
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessConnect
class CommandObjectProcessConnect : public CommandObjectParsed
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2013-08-23 17:46:38 +00:00
Error
2015-12-30 11:55:28 +00:00
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
2013-08-23 17:46:38 +00:00
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' p ' :
plugin_name . assign ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
2015-12-30 11:55:28 +00:00
OptionParsingStarting ( ) override
2013-08-23 17:46:38 +00:00
{
plugin_name . clear ( ) ;
}
const OptionDefinition *
2015-12-30 11:55:28 +00:00
GetDefinitions ( ) override
2013-08-23 17:46:38 +00:00
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
std : : string plugin_name ;
} ;
CommandObjectProcessConnect ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" process connect " ,
" Connect to a remote debug service. " ,
" process connect <remote-url> " ,
0 ) ,
m_options ( interpreter )
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessConnect ( ) override = default ;
2013-08-23 17:46:38 +00:00
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
2015-12-30 11:55:28 +00:00
if ( command . GetArgumentCount ( ) ! = 1 )
2013-08-23 17:46:38 +00:00
{
2015-12-30 11:55:28 +00:00
result . AppendErrorWithFormat ( " '%s' takes exactly one argument: \n Usage: %s \n " ,
m_cmd_name . c_str ( ) ,
m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 17:46:38 +00:00
}
2015-12-30 11:55:28 +00:00
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( process & & process - > IsAlive ( ) )
2013-08-23 17:46:38 +00:00
{
2015-12-30 11:55:28 +00:00
result . AppendErrorWithFormat ( " Process % " PRIu64 " is currently being debugged, kill the process before connecting. \n " ,
process - > GetID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 17:46:38 +00:00
}
2015-12-30 11:55:28 +00:00
const char * plugin_name = nullptr ;
if ( ! m_options . plugin_name . empty ( ) )
plugin_name = m_options . plugin_name . c_str ( ) ;
2013-08-23 17:46:38 +00:00
2015-12-30 11:55:28 +00:00
Error error ;
Debugger & debugger = m_interpreter . GetDebugger ( ) ;
PlatformSP platform_sp = m_interpreter . GetPlatform ( true ) ;
ProcessSP process_sp = platform_sp - > ConnectProcess ( command . GetArgumentAtIndex ( 0 ) ,
plugin_name ,
debugger ,
debugger . GetSelectedTarget ( ) . get ( ) ,
error ) ;
if ( error . Fail ( ) | | process_sp = = nullptr )
2013-08-23 17:46:38 +00:00
{
2015-12-30 11:55:28 +00:00
result . AppendError ( error . AsCString ( " Error connecting to the process " ) ) ;
2013-08-23 17:46:38 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
2015-12-30 11:55:28 +00:00
return false ;
2013-08-23 17:46:38 +00:00
}
2015-12-30 11:55:28 +00:00
return true ;
2013-08-23 17:46:38 +00:00
}
2015-12-30 11:55:28 +00:00
2013-08-23 17:46:38 +00:00
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectProcessConnect : : CommandOptions : : g_option_table [ ] =
{
2016-07-23 20:50:09 +00:00
{ LLDB_OPT_SET_ALL , false , " plugin " , ' p ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePlugin , " Name of the process plugin you want to use. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2013-08-23 17:46:38 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessPlugin
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessPlugin
class CommandObjectProcessPlugin : public CommandObjectProxy
{
public :
2016-07-23 20:50:09 +00:00
CommandObjectProcessPlugin ( CommandInterpreter & interpreter )
: CommandObjectProxy ( interpreter , " process plugin " ,
" Send a custom command to the current target process plug-in. " , " process plugin <args> " , 0 )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessPlugin ( ) override = default ;
2015-12-30 11:55:28 +00:00
CommandObject *
GetProxyCommandObject ( ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_interpreter . GetExecutionContext ( ) . GetProcessPtr ( ) ;
if ( process )
return process - > GetPluginCommandObject ( ) ;
2016-07-23 20:50:09 +00:00
return nullptr ;
2013-08-23 17:46:38 +00:00
}
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessLoad
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessLoad
class CommandObjectProcessLoad : public CommandObjectParsed
{
public :
2015-12-30 11:55:28 +00:00
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2015-12-30 11:55:28 +00:00
Error
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' i ' :
do_install = true ;
if ( option_arg & & option_arg [ 0 ] )
install_path . SetFile ( option_arg , false ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
OptionParsingStarting ( ) override
{
do_install = false ;
install_path . Clear ( ) ;
}
const OptionDefinition *
GetDefinitions ( ) override
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
bool do_install ;
FileSpec install_path ;
} ;
2013-08-23 17:46:38 +00:00
CommandObjectProcessLoad ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" process load " ,
" Load a shared library into the current process. " ,
" process load <filename> [<filename> ...] " ,
2015-07-03 16:57:06 +00:00
eCommandRequiresProcess |
eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
2015-12-30 11:55:28 +00:00
eCommandProcessMustBePaused ) ,
m_options ( interpreter )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessLoad ( ) override = default ;
2015-12-30 11:55:28 +00:00
Options *
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
2015-12-30 11:55:28 +00:00
return & m_options ;
2013-08-23 17:46:38 +00:00
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
const size_t argc = command . GetArgumentCount ( ) ;
2016-07-23 20:50:09 +00:00
for ( uint32_t i = 0 ; i < argc ; + + i )
2013-08-23 17:46:38 +00:00
{
Error error ;
2015-12-30 11:55:28 +00:00
PlatformSP platform = process - > GetTarget ( ) . GetPlatform ( ) ;
2013-08-23 17:46:38 +00:00
const char * image_path = command . GetArgumentAtIndex ( i ) ;
2015-12-30 11:55:28 +00:00
uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN ;
if ( ! m_options . do_install )
{
FileSpec image_spec ( image_path , false ) ;
platform - > ResolveRemotePath ( image_spec , image_spec ) ;
image_token = platform - > LoadImage ( process , FileSpec ( ) , image_spec , error ) ;
}
else if ( m_options . install_path )
{
FileSpec image_spec ( image_path , true ) ;
platform - > ResolveRemotePath ( m_options . install_path , m_options . install_path ) ;
image_token = platform - > LoadImage ( process , image_spec , m_options . install_path , error ) ;
}
else
{
FileSpec image_spec ( image_path , true ) ;
image_token = platform - > LoadImage ( process , image_spec , FileSpec ( ) , error ) ;
}
2013-08-23 17:46:38 +00:00
if ( image_token ! = LLDB_INVALID_IMAGE_TOKEN )
{
2015-12-30 11:55:28 +00:00
result . AppendMessageWithFormat ( " Loading \" %s \" ...ok \n Image %u loaded. \n " , image_path , image_token ) ;
2013-08-23 17:46:38 +00:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " failed to load '%s': %s " , image_path , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
return result . Succeeded ( ) ;
}
2015-12-30 11:55:28 +00:00
CommandOptions m_options ;
2013-08-23 17:46:38 +00:00
} ;
2015-12-30 11:55:28 +00:00
OptionDefinition
CommandObjectProcessLoad : : CommandOptions : : g_option_table [ ] =
{
{ LLDB_OPT_SET_ALL , false , " install " , ' i ' , OptionParser : : eOptionalArgument , nullptr , nullptr , 0 , eArgTypePath , " Install the shared library to the target. If specified without an argument then the library will installed in the current working directory. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
} ;
2013-08-23 17:46:38 +00:00
//-------------------------------------------------------------------------
// CommandObjectProcessUnload
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessUnload
class CommandObjectProcessUnload : public CommandObjectParsed
{
public :
CommandObjectProcessUnload ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" process unload " ,
" Unload a shared library from the current process using the index returned by a previous call to \" process load \" . " ,
" process unload <index> " ,
2015-07-03 16:57:06 +00:00
eCommandRequiresProcess |
eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessUnload ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
const size_t argc = command . GetArgumentCount ( ) ;
2016-07-23 20:50:09 +00:00
for ( uint32_t i = 0 ; i < argc ; + + i )
2013-08-23 17:46:38 +00:00
{
const char * image_token_cstr = command . GetArgumentAtIndex ( i ) ;
2015-02-09 01:44:09 +00:00
uint32_t image_token = StringConvert : : ToUInt32 ( image_token_cstr , LLDB_INVALID_IMAGE_TOKEN , 0 ) ;
2013-08-23 17:46:38 +00:00
if ( image_token = = LLDB_INVALID_IMAGE_TOKEN )
{
result . AppendErrorWithFormat ( " invalid image index argument '%s' " , image_token_cstr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
else
{
2015-12-30 11:55:28 +00:00
Error error ( process - > GetTarget ( ) . GetPlatform ( ) - > UnloadImage ( process , image_token ) ) ;
2013-08-23 17:46:38 +00:00
if ( error . Success ( ) )
{
result . AppendMessageWithFormat ( " Unloading shared library with index %u...ok \n " , image_token ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " failed to unload image: %s " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
}
}
return result . Succeeded ( ) ;
}
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessSignal
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessSignal
class CommandObjectProcessSignal : public CommandObjectParsed
{
public :
2016-07-23 20:50:09 +00:00
CommandObjectProcessSignal ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " process signal " , " Send a UNIX signal to the current target process. " ,
nullptr , eCommandRequiresProcess | eCommandTryTargetAPILock )
2013-08-23 17:46:38 +00:00
{
CommandArgumentEntry arg ;
CommandArgumentData signal_arg ;
// Define the first (and only) variant of this arg.
signal_arg . arg_type = eArgTypeUnixSignal ;
signal_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( signal_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessSignal ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
if ( command . GetArgumentCount ( ) = = 1 )
{
int signo = LLDB_INVALID_SIGNAL_NUMBER ;
const char * signal_name = command . GetArgumentAtIndex ( 0 ) ;
if ( : : isxdigit ( signal_name [ 0 ] ) )
2015-02-09 01:44:09 +00:00
signo = StringConvert : : ToSInt32 ( signal_name , LLDB_INVALID_SIGNAL_NUMBER , 0 ) ;
2013-08-23 17:46:38 +00:00
else
2015-09-06 14:32:30 +00:00
signo = process - > GetUnixSignals ( ) - > GetSignalNumberFromName ( signal_name ) ;
2013-08-23 17:46:38 +00:00
if ( signo = = LLDB_INVALID_SIGNAL_NUMBER )
{
result . AppendErrorWithFormat ( " Invalid signal argument '%s'. \n " , command . GetArgumentAtIndex ( 0 ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
else
{
Error error ( process - > Signal ( signo ) ) ;
if ( error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Failed to send signal %i: %s \n " , signo , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
}
else
{
result . AppendErrorWithFormat ( " '%s' takes exactly one signal number argument: \n Usage: %s \n " , m_cmd_name . c_str ( ) ,
m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessInterrupt
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessInterrupt
class CommandObjectProcessInterrupt : public CommandObjectParsed
{
public :
2016-07-23 20:50:09 +00:00
CommandObjectProcessInterrupt ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " process interrupt " , " Interrupt the current target process. " ,
" process interrupt " ,
eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessInterrupt ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
2016-07-23 20:50:09 +00:00
if ( process = = nullptr )
2013-08-23 17:46:38 +00:00
{
result . AppendError ( " no process to halt " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( command . GetArgumentCount ( ) = = 0 )
{
bool clear_thread_plans = true ;
Error error ( process - > Halt ( clear_thread_plans ) ) ;
if ( error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Failed to halt process: %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " '%s' takes no arguments: \n Usage: %s \n " ,
m_cmd_name . c_str ( ) ,
m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessKill
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessKill
class CommandObjectProcessKill : public CommandObjectParsed
{
public :
2016-07-23 20:50:09 +00:00
CommandObjectProcessKill ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " process kill " , " Terminate the current target process. " , " process kill " ,
eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessKill ( ) override = default ;
2013-08-23 17:46:38 +00:00
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
2016-07-23 20:50:09 +00:00
if ( process = = nullptr )
2013-08-23 17:46:38 +00:00
{
result . AppendError ( " no process to kill " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( command . GetArgumentCount ( ) = = 0 )
{
2015-07-03 16:57:06 +00:00
Error error ( process - > Destroy ( true ) ) ;
2013-08-23 17:46:38 +00:00
if ( error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Failed to kill process: %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " '%s' takes no arguments: \n Usage: %s \n " ,
m_cmd_name . c_str ( ) ,
m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
} ;
2014-11-25 21:00:58 +00:00
//-------------------------------------------------------------------------
// CommandObjectProcessSaveCore
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessSaveCore
class CommandObjectProcessSaveCore : public CommandObjectParsed
{
public :
CommandObjectProcessSaveCore ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" process save-core " ,
" Save the current process as a core file using an appropriate file type. " ,
" process save-core FILE " ,
2015-07-03 16:57:06 +00:00
eCommandRequiresProcess |
eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched )
2014-11-25 21:00:58 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessSaveCore ( ) override = default ;
2014-11-25 21:00:58 +00:00
protected :
bool
DoExecute ( Args & command ,
2015-12-30 11:55:28 +00:00
CommandReturnObject & result ) override
2014-11-25 21:00:58 +00:00
{
ProcessSP process_sp = m_exe_ctx . GetProcessSP ( ) ;
if ( process_sp )
{
if ( command . GetArgumentCount ( ) = = 1 )
{
FileSpec output_file ( command . GetArgumentAtIndex ( 0 ) , false ) ;
Error error = PluginManager : : SaveCore ( process_sp , output_file ) ;
if ( error . Success ( ) )
{
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
result . AppendErrorWithFormat ( " Failed to save core file for process: %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendErrorWithFormat ( " '%s' takes one arguments: \n Usage: %s \n " ,
m_cmd_name . c_str ( ) ,
m_cmd_syntax . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendError ( " invalid process " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
return result . Succeeded ( ) ;
}
} ;
2013-08-23 17:46:38 +00:00
//-------------------------------------------------------------------------
// CommandObjectProcessStatus
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessStatus
class CommandObjectProcessStatus : public CommandObjectParsed
{
public :
2016-07-23 20:50:09 +00:00
CommandObjectProcessStatus ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " process status " ,
" Show status and stop location for the current target process. " , " process status " ,
eCommandRequiresProcess | eCommandTryTargetAPILock )
2013-08-23 17:46:38 +00:00
{
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessStatus ( ) override = default ;
2013-08-23 17:46:38 +00:00
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & command , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
Stream & strm = result . GetOutputStream ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2015-07-03 16:57:06 +00:00
// No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
2013-08-23 17:46:38 +00:00
Process * process = m_exe_ctx . GetProcessPtr ( ) ;
const bool only_threads_with_stop_reason = true ;
const uint32_t start_frame = 0 ;
const uint32_t num_frames = 1 ;
const uint32_t num_frames_with_source = 1 ;
process - > GetStatus ( strm ) ;
process - > GetThreadStatus ( strm ,
only_threads_with_stop_reason ,
start_frame ,
num_frames ,
num_frames_with_source ) ;
return result . Succeeded ( ) ;
}
} ;
//-------------------------------------------------------------------------
// CommandObjectProcessHandle
//-------------------------------------------------------------------------
# pragma mark CommandObjectProcessHandle
class CommandObjectProcessHandle : public CommandObjectParsed
{
public :
class CommandOptions : public Options
{
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter )
{
OptionParsingStarting ( ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandOptions ( ) override = default ;
2013-08-23 17:46:38 +00:00
Error
2015-12-30 11:55:28 +00:00
SetOptionValue ( uint32_t option_idx , const char * option_arg ) override
2013-08-23 17:46:38 +00:00
{
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
case ' s ' :
stop = option_arg ;
break ;
case ' n ' :
notify = option_arg ;
break ;
case ' p ' :
pass = option_arg ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " , short_option ) ;
break ;
}
return error ;
}
void
2015-12-30 11:55:28 +00:00
OptionParsingStarting ( ) override
2013-08-23 17:46:38 +00:00
{
stop . clear ( ) ;
notify . clear ( ) ;
pass . clear ( ) ;
}
const OptionDefinition *
2015-12-30 11:55:28 +00:00
GetDefinitions ( ) override
2013-08-23 17:46:38 +00:00
{
return g_option_table ;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
std : : string stop ;
std : : string notify ;
std : : string pass ;
} ;
2016-07-23 20:50:09 +00:00
CommandObjectProcessHandle ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " process handle " ,
" Manage LLDB handling of OS signals for the current target process. Defaults to showing current policy. " ,
nullptr ) ,
m_options ( interpreter )
2013-08-23 17:46:38 +00:00
{
2015-09-06 14:32:30 +00:00
SetHelpLong ( " \n If no signals are specified, update them all. If no update "
" option is specified, list the current values. " ) ;
2013-08-23 17:46:38 +00:00
CommandArgumentEntry arg ;
CommandArgumentData signal_arg ;
signal_arg . arg_type = eArgTypeUnixSignal ;
signal_arg . arg_repetition = eArgRepeatStar ;
arg . push_back ( signal_arg ) ;
m_arguments . push_back ( arg ) ;
}
2016-07-23 20:50:09 +00:00
~ CommandObjectProcessHandle ( ) override = default ;
2013-08-23 17:46:38 +00:00
Options *
2015-12-30 11:55:28 +00:00
GetOptions ( ) override
2013-08-23 17:46:38 +00:00
{
return & m_options ;
}
bool
VerifyCommandOptionValue ( const std : : string & option , int & real_value )
{
bool okay = true ;
bool success = false ;
bool tmp_value = Args : : StringToBoolean ( option . c_str ( ) , false , & success ) ;
if ( success & & tmp_value )
real_value = 1 ;
else if ( success & & ! tmp_value )
real_value = 0 ;
else
{
// If the value isn't 'true' or 'false', it had better be 0 or 1.
2015-02-09 01:44:09 +00:00
real_value = StringConvert : : ToUInt32 ( option . c_str ( ) , 3 ) ;
2013-08-23 17:46:38 +00:00
if ( real_value ! = 0 & & real_value ! = 1 )
okay = false ;
}
return okay ;
}
void
PrintSignalHeader ( Stream & str )
{
2015-07-03 16:57:06 +00:00
str . Printf ( " NAME PASS STOP NOTIFY \n " ) ;
str . Printf ( " =========== ===== ===== ====== \n " ) ;
2013-08-23 17:46:38 +00:00
}
void
2015-09-06 14:32:30 +00:00
PrintSignal ( Stream & str , int32_t signo , const char * sig_name , const UnixSignalsSP & signals_sp )
2013-08-23 17:46:38 +00:00
{
bool stop ;
bool suppress ;
bool notify ;
2015-07-03 16:57:06 +00:00
str . Printf ( " %-11s " , sig_name ) ;
2015-09-06 14:32:30 +00:00
if ( signals_sp - > GetSignalInfo ( signo , suppress , stop , notify ) )
2013-08-23 17:46:38 +00:00
{
bool pass = ! suppress ;
str . Printf ( " %s %s %s " ,
( pass ? " true " : " false " ) ,
( stop ? " true " : " false " ) ,
( notify ? " true " : " false " ) ) ;
}
str . Printf ( " \n " ) ;
}
void
2015-09-06 14:32:30 +00:00
PrintSignalInformation ( Stream & str , Args & signal_args , int num_valid_signals , const UnixSignalsSP & signals_sp )
2013-08-23 17:46:38 +00:00
{
PrintSignalHeader ( str ) ;
if ( num_valid_signals > 0 )
{
size_t num_args = signal_args . GetArgumentCount ( ) ;
for ( size_t i = 0 ; i < num_args ; + + i )
{
2015-09-06 14:32:30 +00:00
int32_t signo = signals_sp - > GetSignalNumberFromName ( signal_args . GetArgumentAtIndex ( i ) ) ;
2013-08-23 17:46:38 +00:00
if ( signo ! = LLDB_INVALID_SIGNAL_NUMBER )
2015-09-06 14:32:30 +00:00
PrintSignal ( str , signo , signal_args . GetArgumentAtIndex ( i ) , signals_sp ) ;
2013-08-23 17:46:38 +00:00
}
}
else // Print info for ALL signals
{
2015-09-06 14:32:30 +00:00
int32_t signo = signals_sp - > GetFirstSignalNumber ( ) ;
2013-08-23 17:46:38 +00:00
while ( signo ! = LLDB_INVALID_SIGNAL_NUMBER )
{
2015-09-06 14:32:30 +00:00
PrintSignal ( str , signo , signals_sp - > GetSignalAsCString ( signo ) , signals_sp ) ;
signo = signals_sp - > GetNextSignalNumber ( signo ) ;
2013-08-23 17:46:38 +00:00
}
}
}
protected :
bool
2015-12-30 11:55:28 +00:00
DoExecute ( Args & signal_args , CommandReturnObject & result ) override
2013-08-23 17:46:38 +00:00
{
TargetSP target_sp = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) ;
if ( ! target_sp )
{
result . AppendError ( " No current target; "
" cannot handle signals until you have a valid target and process. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ProcessSP process_sp = target_sp - > GetProcessSP ( ) ;
if ( ! process_sp )
{
result . AppendError ( " No current process; cannot handle signals until you have a valid process. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int stop_action = - 1 ; // -1 means leave the current setting alone
int pass_action = - 1 ; // -1 means leave the current setting alone
int notify_action = - 1 ; // -1 means leave the current setting alone
if ( ! m_options . stop . empty ( )
& & ! VerifyCommandOptionValue ( m_options . stop , stop_action ) )
{
result . AppendError ( " Invalid argument for command option --stop; must be true or false. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( ! m_options . notify . empty ( )
& & ! VerifyCommandOptionValue ( m_options . notify , notify_action ) )
{
result . AppendError ( " Invalid argument for command option --notify; must be true or false. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( ! m_options . pass . empty ( )
& & ! VerifyCommandOptionValue ( m_options . pass , pass_action ) )
{
result . AppendError ( " Invalid argument for command option --pass; must be true or false. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
size_t num_args = signal_args . GetArgumentCount ( ) ;
2015-09-06 14:32:30 +00:00
UnixSignalsSP signals_sp = process_sp - > GetUnixSignals ( ) ;
2013-08-23 17:46:38 +00:00
int num_signals_set = 0 ;
if ( num_args > 0 )
{
for ( size_t i = 0 ; i < num_args ; + + i )
{
2015-09-06 14:32:30 +00:00
int32_t signo = signals_sp - > GetSignalNumberFromName ( signal_args . GetArgumentAtIndex ( i ) ) ;
2013-08-23 17:46:38 +00:00
if ( signo ! = LLDB_INVALID_SIGNAL_NUMBER )
{
// Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
// the value is either 0 or 1.
if ( stop_action ! = - 1 )
2015-09-06 14:32:30 +00:00
signals_sp - > SetShouldStop ( signo , stop_action ) ;
2013-08-23 17:46:38 +00:00
if ( pass_action ! = - 1 )
{
2015-09-06 14:32:30 +00:00
bool suppress = ! pass_action ;
signals_sp - > SetShouldSuppress ( signo , suppress ) ;
2013-08-23 17:46:38 +00:00
}
if ( notify_action ! = - 1 )
2015-09-06 14:32:30 +00:00
signals_sp - > SetShouldNotify ( signo , notify_action ) ;
2013-08-23 17:46:38 +00:00
+ + num_signals_set ;
}
else
{
result . AppendErrorWithFormat ( " Invalid signal name '%s' \n " , signal_args . GetArgumentAtIndex ( i ) ) ;
}
}
}
else
{
// No signal specified, if any command options were specified, update ALL signals.
if ( ( notify_action ! = - 1 ) | | ( stop_action ! = - 1 ) | | ( pass_action ! = - 1 ) )
{
if ( m_interpreter . Confirm ( " Do you really want to update all the signals? " , false ) )
{
2015-09-06 14:32:30 +00:00
int32_t signo = signals_sp - > GetFirstSignalNumber ( ) ;
2013-08-23 17:46:38 +00:00
while ( signo ! = LLDB_INVALID_SIGNAL_NUMBER )
{
if ( notify_action ! = - 1 )
2015-09-06 14:32:30 +00:00
signals_sp - > SetShouldNotify ( signo , notify_action ) ;
2013-08-23 17:46:38 +00:00
if ( stop_action ! = - 1 )
2015-09-06 14:32:30 +00:00
signals_sp - > SetShouldStop ( signo , stop_action ) ;
2013-08-23 17:46:38 +00:00
if ( pass_action ! = - 1 )
{
2015-09-06 14:32:30 +00:00
bool suppress = ! pass_action ;
signals_sp - > SetShouldSuppress ( signo , suppress ) ;
2013-08-23 17:46:38 +00:00
}
2015-09-06 14:32:30 +00:00
signo = signals_sp - > GetNextSignalNumber ( signo ) ;
2013-08-23 17:46:38 +00:00
}
}
}
}
2015-09-06 14:32:30 +00:00
PrintSignalInformation ( result . GetOutputStream ( ) , signal_args , num_signals_set , signals_sp ) ;
2013-08-23 17:46:38 +00:00
if ( num_signals_set > 0 )
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
else
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
CommandOptions m_options ;
} ;
OptionDefinition
CommandObjectProcessHandle : : CommandOptions : : g_option_table [ ] =
{
2016-07-23 20:50:09 +00:00
{ LLDB_OPT_SET_1 , false , " stop " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Whether or not the process should be stopped if the signal is received. " } ,
{ LLDB_OPT_SET_1 , false , " notify " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Whether or not the debugger should notify the user if the signal is received. " } ,
{ LLDB_OPT_SET_1 , false , " pass " , ' p ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Whether or not the signal should be passed to the process. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2013-08-23 17:46:38 +00:00
} ;
//-------------------------------------------------------------------------
// CommandObjectMultiwordProcess
//-------------------------------------------------------------------------
2016-07-23 20:50:09 +00:00
CommandObjectMultiwordProcess : : CommandObjectMultiwordProcess ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " process " , " Commands for interacting with processes on the current platform. " ,
" process <subcommand> [<subcommand-options>] " )
2013-08-23 17:46:38 +00:00
{
LoadSubCommand ( " attach " , CommandObjectSP ( new CommandObjectProcessAttach ( interpreter ) ) ) ;
LoadSubCommand ( " launch " , CommandObjectSP ( new CommandObjectProcessLaunch ( interpreter ) ) ) ;
LoadSubCommand ( " continue " , CommandObjectSP ( new CommandObjectProcessContinue ( interpreter ) ) ) ;
LoadSubCommand ( " connect " , CommandObjectSP ( new CommandObjectProcessConnect ( interpreter ) ) ) ;
LoadSubCommand ( " detach " , CommandObjectSP ( new CommandObjectProcessDetach ( interpreter ) ) ) ;
LoadSubCommand ( " load " , CommandObjectSP ( new CommandObjectProcessLoad ( interpreter ) ) ) ;
LoadSubCommand ( " unload " , CommandObjectSP ( new CommandObjectProcessUnload ( interpreter ) ) ) ;
LoadSubCommand ( " signal " , CommandObjectSP ( new CommandObjectProcessSignal ( interpreter ) ) ) ;
LoadSubCommand ( " handle " , CommandObjectSP ( new CommandObjectProcessHandle ( interpreter ) ) ) ;
LoadSubCommand ( " status " , CommandObjectSP ( new CommandObjectProcessStatus ( interpreter ) ) ) ;
LoadSubCommand ( " interrupt " , CommandObjectSP ( new CommandObjectProcessInterrupt ( interpreter ) ) ) ;
LoadSubCommand ( " kill " , CommandObjectSP ( new CommandObjectProcessKill ( interpreter ) ) ) ;
LoadSubCommand ( " plugin " , CommandObjectSP ( new CommandObjectProcessPlugin ( interpreter ) ) ) ;
2014-11-25 21:00:58 +00:00
LoadSubCommand ( " save-core " , CommandObjectSP ( new CommandObjectProcessSaveCore ( interpreter ) ) ) ;
2013-08-23 17:46:38 +00:00
}
2016-07-23 20:50:09 +00:00
CommandObjectMultiwordProcess : : ~ CommandObjectMultiwordProcess ( ) = default ;