2013-08-23 13:46:38 -04:00
//===-- CommandObjectPlatform.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
2016-07-23 16:50:09 -04:00
# include <mutex>
2013-08-23 13:46:38 -04:00
// Other libraries and framework includes
// Project includes
2016-07-23 16:50:09 -04:00
# include "CommandObjectPlatform.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/DataExtractor.h"
# include "lldb/Core/Debugger.h"
# include "lldb/Core/Module.h"
# include "lldb/Core/PluginManager.h"
2015-02-08 20:44:09 -05:00
# include "lldb/Host/StringConvert.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/Args.h"
# include "lldb/Interpreter/CommandInterpreter.h"
2014-11-25 16:00:58 -05:00
# include "lldb/Interpreter/CommandOptionValidators.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/CommandReturnObject.h"
2013-12-03 13:51:59 -05:00
# include "lldb/Interpreter/OptionGroupFile.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/OptionGroupPlatform.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Platform.h"
# include "lldb/Target/Process.h"
2013-11-06 11:48:53 -05:00
# include "lldb/Utility/Utils.h"
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
# include "llvm/ADT/SmallString.h"
2013-08-23 13:46:38 -04:00
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
static mode_t ParsePermissionString ( const char * ) = delete ;
static mode_t ParsePermissionString ( llvm : : StringRef permissions ) {
if ( permissions . size ( ) ! = 9 )
return ( mode_t ) ( - 1 ) ;
bool user_r , user_w , user_x , group_r , group_w , group_x , world_r , world_w ,
world_x ;
user_r = ( permissions [ 0 ] = = ' r ' ) ;
user_w = ( permissions [ 1 ] = = ' w ' ) ;
user_x = ( permissions [ 2 ] = = ' x ' ) ;
group_r = ( permissions [ 3 ] = = ' r ' ) ;
group_w = ( permissions [ 4 ] = = ' w ' ) ;
group_x = ( permissions [ 5 ] = = ' x ' ) ;
world_r = ( permissions [ 6 ] = = ' r ' ) ;
world_w = ( permissions [ 7 ] = = ' w ' ) ;
world_x = ( permissions [ 8 ] = = ' x ' ) ;
mode_t user , group , world ;
user = ( user_r ? 4 : 0 ) | ( user_w ? 2 : 0 ) | ( user_x ? 1 : 0 ) ;
group = ( group_r ? 4 : 0 ) | ( group_w ? 2 : 0 ) | ( group_x ? 1 : 0 ) ;
world = ( world_r ? 4 : 0 ) | ( world_w ? 2 : 0 ) | ( world_x ? 1 : 0 ) ;
return user | group | world ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
static OptionDefinition g_permissions_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " permissions-value " , ' v ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePermissionsNumber , " Give out the numeric value for permissions (e.g. 757) " } ,
{ LLDB_OPT_SET_ALL , false , " permissions-string " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePermissionsString , " Give out the string value for permissions (e.g. rwxr-xr--). " } ,
{ LLDB_OPT_SET_ALL , false , " user-read " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow user to read. " } ,
{ LLDB_OPT_SET_ALL , false , " user-write " , ' w ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow user to write. " } ,
{ LLDB_OPT_SET_ALL , false , " user-exec " , ' x ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow user to execute. " } ,
{ LLDB_OPT_SET_ALL , false , " group-read " , ' R ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow group to read. " } ,
{ LLDB_OPT_SET_ALL , false , " group-write " , ' W ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow group to write. " } ,
{ LLDB_OPT_SET_ALL , false , " group-exec " , ' X ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow group to execute. " } ,
{ LLDB_OPT_SET_ALL , false , " world-read " , ' d ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow world to read. " } ,
{ LLDB_OPT_SET_ALL , false , " world-write " , ' t ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow world to write. " } ,
{ LLDB_OPT_SET_ALL , false , " world-exec " , ' e ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Allow world to execute. " } ,
// clang-format on
2013-11-06 11:48:53 -05:00
} ;
2017-01-02 14:26:05 -05:00
class OptionPermissions : public OptionGroup {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
OptionPermissions ( ) { }
~ OptionPermissions ( ) override = default ;
lldb_private : : Error
SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
char short_option = ( char ) GetDefinitions ( ) [ option_idx ] . short_option ;
switch ( short_option ) {
case ' v ' : {
if ( option_arg . getAsInteger ( 8 , m_permissions ) ) {
m_permissions = 0777 ;
error . SetErrorStringWithFormat ( " invalid value for permissions: %s " ,
option_arg . str ( ) . c_str ( ) ) ;
}
} break ;
case ' s ' : {
mode_t perms = ParsePermissionString ( option_arg ) ;
if ( perms = = ( mode_t ) - 1 )
error . SetErrorStringWithFormat ( " invalid value for permissions: %s " ,
option_arg . str ( ) . c_str ( ) ) ;
else
m_permissions = perms ;
} break ;
case ' r ' :
m_permissions | = lldb : : eFilePermissionsUserRead ;
break ;
case ' w ' :
m_permissions | = lldb : : eFilePermissionsUserWrite ;
break ;
case ' x ' :
m_permissions | = lldb : : eFilePermissionsUserExecute ;
break ;
case ' R ' :
m_permissions | = lldb : : eFilePermissionsGroupRead ;
break ;
case ' W ' :
m_permissions | = lldb : : eFilePermissionsGroupWrite ;
break ;
case ' X ' :
m_permissions | = lldb : : eFilePermissionsGroupExecute ;
break ;
case ' d ' :
m_permissions | = lldb : : eFilePermissionsWorldRead ;
break ;
case ' t ' :
m_permissions | = lldb : : eFilePermissionsWorldWrite ;
break ;
case ' e ' :
m_permissions | = lldb : : eFilePermissionsWorldExecute ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
break ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
return error ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_permissions = 0 ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_permissions_options ) ;
}
// Instance variables to hold the values for command options.
uint32_t m_permissions ;
2016-07-23 16:50:09 -04:00
2013-11-06 11:48:53 -05:00
private :
2017-01-02 14:26:05 -05:00
DISALLOW_COPY_AND_ASSIGN ( OptionPermissions ) ;
2013-11-06 11:48:53 -05:00
} ;
2013-08-23 13:46:38 -04:00
//----------------------------------------------------------------------
// "platform select <platform-name>"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformSelect : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformSelect ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform select " ,
" Create a platform if needed and select it as the "
" current platform. " ,
" platform select <platform-name> " , 0 ) ,
m_option_group ( ) ,
m_platform_options (
false ) // Don't include the "--platform" option by passing false
{
m_option_group . Append ( & m_platform_options , LLDB_OPT_SET_ALL , 1 ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectPlatformSelect ( ) override = default ;
int HandleCompletion ( Args & input , int & cursor_index ,
int & cursor_char_position , int match_start_point ,
int max_return_elements , bool & word_complete ,
StringList & matches ) override {
std : : string completion_str ( input . GetArgumentAtIndex ( cursor_index ) ) ;
completion_str . erase ( cursor_char_position ) ;
CommandCompletions : : PlatformPluginNames (
GetCommandInterpreter ( ) , completion_str . c_str ( ) , match_start_point ,
max_return_elements , nullptr , word_complete , matches ) ;
return matches . GetSize ( ) ;
}
Options * GetOptions ( ) override { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
if ( args . GetArgumentCount ( ) = = 1 ) {
const char * platform_name = args . GetArgumentAtIndex ( 0 ) ;
if ( platform_name & & platform_name [ 0 ] ) {
const bool select = true ;
m_platform_options . SetPlatformName ( platform_name ) ;
Error error ;
ArchSpec platform_arch ;
PlatformSP platform_sp ( m_platform_options . CreatePlatformWithOptions (
m_interpreter , ArchSpec ( ) , select , error , platform_arch ) ) ;
if ( platform_sp ) {
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . SetSelectedPlatform (
platform_sp ) ;
platform_sp - > GetStatus ( result . GetOutputStream ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " invalid platform name " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError (
" platform create takes a platform name as an argument \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupPlatform m_platform_options ;
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// "platform list"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform list " ,
" List all platforms that are available. " , nullptr ,
0 ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformList ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Stream & ostrm = result . GetOutputStream ( ) ;
ostrm . Printf ( " Available platforms: \n " ) ;
PlatformSP host_platform_sp ( Platform : : GetHostPlatform ( ) ) ;
ostrm . Printf ( " %s: %s \n " , host_platform_sp - > GetPluginName ( ) . GetCString ( ) ,
host_platform_sp - > GetDescription ( ) ) ;
uint32_t idx ;
for ( idx = 0 ; 1 ; + + idx ) {
const char * plugin_name =
PluginManager : : GetPlatformPluginNameAtIndex ( idx ) ;
if ( plugin_name = = nullptr )
break ;
const char * plugin_desc =
PluginManager : : GetPlatformPluginDescriptionAtIndex ( idx ) ;
if ( plugin_desc = = nullptr )
break ;
ostrm . Printf ( " %s: %s \n " , plugin_name , plugin_desc ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( idx = = 0 ) {
result . AppendError ( " no platforms are available \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// "platform status"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformStatus : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformStatus ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform status " ,
" Display status for the current platform. " , nullptr ,
0 ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformStatus ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Stream & ostrm = result . GetOutputStream ( ) ;
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
PlatformSP platform_sp ;
if ( target ) {
platform_sp = target - > GetPlatform ( ) ;
}
if ( ! platform_sp ) {
platform_sp =
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ;
}
if ( platform_sp ) {
platform_sp - > GetStatus ( ostrm ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " no platform us currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// "platform connect <connect-url>"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformConnect : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformConnect ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " platform connect " ,
" Select the current platform by providing a connection URL. " ,
" platform connect <connect-url> " , 0 ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformConnect ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Stream & ostrm = result . GetOutputStream ( ) ;
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
Error error ( platform_sp - > ConnectRemote ( args ) ) ;
if ( error . Success ( ) ) {
platform_sp - > GetStatus ( ostrm ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
platform_sp - > ConnectToWaitingProcesses ( m_interpreter . GetDebugger ( ) ,
error ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendErrorWithFormat ( " %s \n " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform is currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
Options * GetOptions ( ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
OptionGroupOptions * m_platform_options = nullptr ;
if ( platform_sp ) {
m_platform_options = platform_sp - > GetConnectionOptions ( m_interpreter ) ;
if ( m_platform_options ! = nullptr & & ! m_platform_options - > m_did_finalize )
m_platform_options - > Finalize ( ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return m_platform_options ;
}
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// "platform disconnect"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformDisconnect : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformDisconnect ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform disconnect " ,
" Disconnect from the current platform. " ,
" platform disconnect " , 0 ) { }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformDisconnect ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
if ( args . GetArgumentCount ( ) = = 0 ) {
Error error ;
if ( platform_sp - > IsConnected ( ) ) {
// Cache the instance name if there is one since we are
// about to disconnect and the name might go with it.
const char * hostname_cstr = platform_sp - > GetHostname ( ) ;
std : : string hostname ;
if ( hostname_cstr )
hostname . assign ( hostname_cstr ) ;
error = platform_sp - > DisconnectRemote ( ) ;
if ( error . Success ( ) ) {
Stream & ostrm = result . GetOutputStream ( ) ;
if ( hostname . empty ( ) )
ostrm . Printf ( " Disconnected from \" %s \" \n " ,
platform_sp - > GetPluginName ( ) . GetCString ( ) ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
ostrm . Printf ( " Disconnected from \" %s \" \n " , hostname . c_str ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendErrorWithFormat ( " %s " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
// Not connected...
result . AppendErrorWithFormat (
" not connected to '%s' " ,
platform_sp - > GetPluginName ( ) . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
// Bad args
result . AppendError (
" \" platform disconnect \" doesn't take any arguments " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform is currently selected " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2013-11-06 11:48:53 -05:00
2013-12-03 13:51:59 -05:00
//----------------------------------------------------------------------
// "platform settings"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformSettings : public CommandObjectParsed {
2013-12-03 13:51:59 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformSettings ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform settings " ,
" Set settings for the current target's platform, "
" or for a platform by name. " ,
" platform settings " , 0 ) ,
m_options ( ) ,
m_option_working_dir ( LLDB_OPT_SET_1 , false , " working-dir " , ' w ' , 0 ,
eArgTypePath ,
" The working directory for the platform. " ) {
m_options . Append ( & m_option_working_dir , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
}
~ CommandObjectPlatformSettings ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-12-03 13:51:59 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
if ( m_option_working_dir . GetOptionValue ( ) . OptionWasSet ( ) )
platform_sp - > SetWorkingDirectory (
m_option_working_dir . GetOptionValue ( ) . GetCurrentValue ( ) ) ;
} else {
result . AppendError ( " no platform is currently selected " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-12-03 13:51:59 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
Options * GetOptions ( ) override {
if ( ! m_options . DidFinalize ( ) )
m_options . Finalize ( ) ;
return & m_options ;
}
2016-07-23 16:50:09 -04:00
2013-12-03 13:51:59 -05:00
protected :
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_options ;
OptionGroupFile m_option_working_dir ;
2013-12-03 13:51:59 -05:00
} ;
2013-08-23 13:46:38 -04:00
//----------------------------------------------------------------------
2013-11-06 11:48:53 -05:00
// "platform mkdir"
2013-08-23 13:46:38 -04:00
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformMkDir : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformMkDir ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform mkdir " ,
" Make a new directory on the remote end. " , nullptr ,
2016-07-23 16:50:09 -04:00
0 ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) { }
~ CommandObjectPlatformMkDir ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
std : : string cmd_line ;
args . GetCommandString ( cmd_line ) ;
uint32_t mode ;
const OptionPermissions * options_permissions =
( const OptionPermissions * ) m_options . GetGroupWithOption ( ' r ' ) ;
if ( options_permissions )
mode = options_permissions - > m_permissions ;
else
mode = lldb : : eFilePermissionsUserRWX | lldb : : eFilePermissionsGroupRWX |
lldb : : eFilePermissionsWorldRX ;
Error error = platform_sp - > MakeDirectory ( FileSpec { cmd_line , false } , mode ) ;
if ( error . Success ( ) ) {
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override {
if ( ! m_options . DidFinalize ( ) ) {
m_options . Append ( new OptionPermissions ( ) ) ;
m_options . Finalize ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return & m_options ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform fopen"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformFOpen : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformFOpen ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform file open " ,
" Open a file on the remote end. " , nullptr , 0 ) ,
m_options ( ) { }
~ CommandObjectPlatformFOpen ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
Error error ;
std : : string cmd_line ;
args . GetCommandString ( cmd_line ) ;
mode_t perms ;
const OptionPermissions * options_permissions =
( const OptionPermissions * ) m_options . GetGroupWithOption ( ' r ' ) ;
if ( options_permissions )
perms = options_permissions - > m_permissions ;
else
perms = lldb : : eFilePermissionsUserRW | lldb : : eFilePermissionsGroupRW |
lldb : : eFilePermissionsWorldRead ;
lldb : : user_id_t fd = platform_sp - > OpenFile (
FileSpec ( cmd_line , false ) ,
File : : eOpenOptionRead | File : : eOpenOptionWrite |
File : : eOpenOptionAppend | File : : eOpenOptionCanCreate ,
perms , error ) ;
if ( error . Success ( ) ) {
result . AppendMessageWithFormat ( " File Descriptor = % " PRIu64 " \n " , fd ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override {
if ( ! m_options . DidFinalize ( ) ) {
m_options . Append ( new OptionPermissions ( ) ) ;
m_options . Finalize ( ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return & m_options ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
2013-08-23 13:46:38 -04:00
2013-11-06 11:48:53 -05:00
//----------------------------------------------------------------------
// "platform fclose"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformFClose : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformFClose ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform file close " ,
" Close a file on the remote end. " , nullptr , 0 ) { }
~ CommandObjectPlatformFClose ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
std : : string cmd_line ;
args . GetCommandString ( cmd_line ) ;
const lldb : : user_id_t fd =
StringConvert : : ToUInt64 ( cmd_line . c_str ( ) , UINT64_MAX ) ;
Error error ;
bool success = platform_sp - > CloseFile ( fd , error ) ;
if ( success ) {
result . AppendMessageWithFormat ( " file % " PRIu64 " closed. \n " , fd ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
2013-11-06 11:48:53 -05:00
// "platform fread"
2013-08-23 13:46:38 -04:00
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_platform_fread_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeIndex , " Offset into the file at which to start reading. " } ,
{ LLDB_OPT_SET_1 , false , " count " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeCount , " Number of bytes to read from the file. " } ,
// clang-format on
} ;
class CommandObjectPlatformFRead : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformFRead ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform file read " ,
" Read data from a file on the remote end. " , nullptr ,
2016-07-23 16:50:09 -04:00
0 ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) { }
~ CommandObjectPlatformFRead ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
std : : string cmd_line ;
args . GetCommandString ( cmd_line ) ;
const lldb : : user_id_t fd =
StringConvert : : ToUInt64 ( cmd_line . c_str ( ) , UINT64_MAX ) ;
std : : string buffer ( m_options . m_count , 0 ) ;
Error error ;
uint32_t retcode = platform_sp - > ReadFile (
fd , m_options . m_offset , & buffer [ 0 ] , m_options . m_count , error ) ;
result . AppendMessageWithFormat ( " Return = %d \n " , retcode ) ;
result . AppendMessageWithFormat ( " Data = \" %s \" \n " , buffer . c_str ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_options ; }
protected :
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' o ' :
if ( option_arg . getAsInteger ( 0 , m_offset ) )
error . SetErrorStringWithFormat ( " invalid offset: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' c ' :
if ( option_arg . getAsInteger ( 0 , m_count ) )
error . SetErrorStringWithFormat ( " invalid offset: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_offset = 0 ;
m_count = 1 ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_platform_fread_options ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
uint32_t m_offset ;
uint32_t m_count ;
} ;
CommandOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform fwrite"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_platform_fwrite_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " offset " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeIndex , " Offset into the file at which to start reading. " } ,
{ LLDB_OPT_SET_1 , false , " data " , ' d ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeValue , " Text to write to the file. " } ,
// clang-format on
} ;
class CommandObjectPlatformFWrite : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformFWrite ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform file write " ,
" Write data to a file on the remote end. " , nullptr ,
2016-07-23 16:50:09 -04:00
0 ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) { }
~ CommandObjectPlatformFWrite ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
std : : string cmd_line ;
args . GetCommandString ( cmd_line ) ;
Error error ;
const lldb : : user_id_t fd =
StringConvert : : ToUInt64 ( cmd_line . c_str ( ) , UINT64_MAX ) ;
uint32_t retcode =
platform_sp - > WriteFile ( fd , m_options . m_offset , & m_options . m_data [ 0 ] ,
m_options . m_data . size ( ) , error ) ;
result . AppendMessageWithFormat ( " Return = %d \n " , retcode ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_options ; }
protected :
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' o ' :
if ( option_arg . getAsInteger ( 0 , m_offset ) )
error . SetErrorStringWithFormat ( " invalid offset: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' d ' :
m_data . assign ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_offset = 0 ;
m_data . clear ( ) ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_platform_fwrite_options ) ;
}
// Instance variables to hold the values for command options.
uint32_t m_offset ;
std : : string m_data ;
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformFile : public CommandObjectMultiword {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectPlatformFile ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " platform file " ,
" Commands to access files on the current platform. " ,
" platform file [open|close|read|write] ... " ) {
LoadSubCommand (
" open " , CommandObjectSP ( new CommandObjectPlatformFOpen ( interpreter ) ) ) ;
LoadSubCommand (
" close " , CommandObjectSP ( new CommandObjectPlatformFClose ( interpreter ) ) ) ;
LoadSubCommand (
" read " , CommandObjectSP ( new CommandObjectPlatformFRead ( interpreter ) ) ) ;
LoadSubCommand (
" write " , CommandObjectSP ( new CommandObjectPlatformFWrite ( interpreter ) ) ) ;
}
~ CommandObjectPlatformFile ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-11-06 11:48:53 -05:00
private :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// For CommandObjectPlatform only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectPlatformFile ) ;
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform get-file remote-file-path host-file-path"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformGetFile : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformGetFile ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " platform get-file " ,
" Transfer a file from the remote end to the local host. " ,
" platform get-file <remote-file-spec> <local-file-spec> " , 0 ) {
SetHelpLong (
R " (Examples:
2015-09-06 10:32:30 -04:00
( lldb ) platform get - file / the / remote / file / path / the / local / file / path
2017-01-02 14:26:05 -05:00
Transfer a file from the remote end with file path / the / remote / file / path to the local host . ) " );
CommandArgumentEntry arg1 , arg2 ;
CommandArgumentData file_arg_remote , file_arg_host ;
// Define the first (and only) variant of this arg.
file_arg_remote . arg_type = eArgTypeFilename ;
file_arg_remote . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg1 . push_back ( file_arg_remote ) ;
// Define the second (and only) variant of this arg.
file_arg_host . arg_type = eArgTypeFilename ;
file_arg_host . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg2 . push_back ( file_arg_host ) ;
// Push the data for the first and the second arguments into the m_arguments
// vector.
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
}
~ CommandObjectPlatformGetFile ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
// If the number of arguments is incorrect, issue an error message.
if ( args . GetArgumentCount ( ) ! = 2 ) {
result . GetErrorStream ( ) . Printf ( " error: required arguments missing; "
" specify both the source and destination "
" file paths \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
const char * remote_file_path = args . GetArgumentAtIndex ( 0 ) ;
const char * local_file_path = args . GetArgumentAtIndex ( 1 ) ;
Error error = platform_sp - > GetFile ( FileSpec ( remote_file_path , false ) ,
FileSpec ( local_file_path , false ) ) ;
if ( error . Success ( ) ) {
result . AppendMessageWithFormat (
" successfully get-file from %s (remote) to %s (host) \n " ,
remote_file_path , local_file_path ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendMessageWithFormat ( " get-file failed: %s \n " ,
error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform get-size remote-file-path"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformGetSize : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformGetSize ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform get-size " ,
" Get the file size from the remote end. " ,
" platform get-size <remote-file-spec> " , 0 ) {
SetHelpLong (
R " (Examples:
2015-09-06 10:32:30 -04:00
( lldb ) platform get - size / the / remote / file / path
2017-01-02 14:26:05 -05:00
Get the file size from the remote end with path / the / remote / file / path . ) " );
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
CommandArgumentEntry arg1 ;
CommandArgumentData file_arg_remote ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
// Define the first (and only) variant of this arg.
file_arg_remote . arg_type = eArgTypeFilename ;
file_arg_remote . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg1 . push_back ( file_arg_remote ) ;
2013-11-06 11:48:53 -05:00
2017-01-02 14:26:05 -05:00
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg1 ) ;
}
~ CommandObjectPlatformGetSize ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
// If the number of arguments is incorrect, issue an error message.
if ( args . GetArgumentCount ( ) ! = 1 ) {
result . GetErrorStream ( ) . Printf ( " error: required argument missing; "
" specify the source file path as the only "
" argument \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
std : : string remote_file_path ( args . GetArgumentAtIndex ( 0 ) ) ;
user_id_t size =
platform_sp - > GetFileSize ( FileSpec ( remote_file_path , false ) ) ;
if ( size ! = UINT64_MAX ) {
result . AppendMessageWithFormat ( " File size of %s (remote): % " PRIu64
" \n " ,
remote_file_path . c_str ( ) , size ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendMessageWithFormat (
" Error getting file size of %s (remote) \n " ,
remote_file_path . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform put-file"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformPutFile : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformPutFile ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " platform put-file " ,
" Transfer a file from this system to the remote end. " , nullptr , 0 ) {
}
~ CommandObjectPlatformPutFile ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
const char * src = args . GetArgumentAtIndex ( 0 ) ;
const char * dst = args . GetArgumentAtIndex ( 1 ) ;
FileSpec src_fs ( src , true ) ;
FileSpec dst_fs ( dst ? dst : src_fs . GetFilename ( ) . GetCString ( ) , false ) ;
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
Error error ( platform_sp - > PutFile ( src_fs , dst_fs ) ) ;
if ( error . Success ( ) ) {
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform currently selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform process launch"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformProcessLaunch ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform process launch " ,
" Launch a new process on a remote platform. " ,
" platform process launch program " ,
eCommandRequiresTarget | eCommandTryTargetAPILock ) ,
m_options ( ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformProcessLaunch ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
2016-07-23 16:50:09 -04:00
2013-11-06 11:48:53 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
PlatformSP platform_sp ;
if ( target ) {
platform_sp = target - > GetPlatform ( ) ;
}
if ( ! platform_sp ) {
platform_sp =
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ;
}
2013-11-06 11:48:53 -05:00
2017-01-02 14:26:05 -05:00
if ( platform_sp ) {
Error error ;
const size_t argc = args . GetArgumentCount ( ) ;
Target * target = m_exe_ctx . GetTargetPtr ( ) ;
Module * exe_module = target - > GetExecutableModulePointer ( ) ;
if ( exe_module ) {
m_options . launch_info . GetExecutableFile ( ) = exe_module - > GetFileSpec ( ) ;
llvm : : SmallString < PATH_MAX > exe_path ;
m_options . launch_info . GetExecutableFile ( ) . GetPath ( exe_path ) ;
if ( ! exe_path . empty ( ) )
m_options . launch_info . GetArguments ( ) . AppendArgument ( exe_path ) ;
m_options . launch_info . GetArchitecture ( ) = exe_module - > GetArchitecture ( ) ;
}
if ( argc > 0 ) {
if ( m_options . launch_info . GetExecutableFile ( ) ) {
// We already have an executable file, so we will use this
// and all arguments to this function are extra arguments
m_options . launch_info . GetArguments ( ) . AppendArguments ( args ) ;
} else {
// We don't have any file yet, so the first argument is our
// executable, and the rest are program arguments
const bool first_arg_is_executable = true ;
m_options . launch_info . SetArguments ( args , first_arg_is_executable ) ;
}
}
if ( m_options . launch_info . GetExecutableFile ( ) ) {
Debugger & debugger = m_interpreter . GetDebugger ( ) ;
if ( argc = = 0 )
target - > GetRunArguments ( m_options . launch_info . GetArguments ( ) ) ;
ProcessSP process_sp ( platform_sp - > DebugProcess (
m_options . launch_info , debugger , target , error ) ) ;
if ( process_sp & & process_sp - > IsAlive ( ) ) {
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
if ( error . Success ( ) )
result . AppendError ( " process launch failed " ) ;
2013-11-06 11:48:53 -05:00
else
2017-01-02 14:26:05 -05:00
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
result . AppendError ( " 'platform process launch' uses the current target "
" file and arguments, or the executable and its "
" arguments can be specified in this command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
result . AppendError ( " no platform is selected \n " ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-11-06 11:48:53 -05:00
protected :
2017-01-02 14:26:05 -05:00
ProcessLaunchCommandOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform process list"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
OptionDefinition g_platform_process_list_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " pid " , ' p ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePid , " List the process info for a specific process ID. " } ,
{ LLDB_OPT_SET_2 , true , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeProcessName , " Find processes with executable basenames that match a string. " } ,
{ LLDB_OPT_SET_3 , true , " ends-with " , ' e ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeProcessName , " Find processes with executable basenames that end with a string. " } ,
{ LLDB_OPT_SET_4 , true , " starts-with " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeProcessName , " Find processes with executable basenames that start with a string. " } ,
{ LLDB_OPT_SET_5 , true , " contains " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeProcessName , " Find processes with executable basenames that contain a string. " } ,
{ LLDB_OPT_SET_6 , true , " regex " , ' r ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeRegularExpression , " Find processes with executable basenames that match a regular expression. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " parent " , ' P ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePid , " Find processes that have a matching parent process ID. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " uid " , ' u ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger , " Find processes that have a matching user ID. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " euid " , ' U ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger , " Find processes that have a matching effective user ID. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " gid " , ' g ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger , " Find processes that have a matching group ID. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " egid " , ' G ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger , " Find processes that have a matching effective group ID. " } ,
{ LLDB_OPT_SET_FROM_TO ( 2 , 6 ) , false , " arch " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeArchitecture , " Find processes that have a matching architecture. " } ,
{ LLDB_OPT_SET_FROM_TO ( 1 , 6 ) , false , " show-args " , ' A ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Show process arguments instead of the process executable basename. " } ,
{ LLDB_OPT_SET_FROM_TO ( 1 , 6 ) , false , " verbose " , ' v ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Enable verbose output. " } ,
// clang-format on
} ;
class CommandObjectPlatformProcessList : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformProcessList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform process list " ,
" List processes on a remote platform by name, pid, "
" or many other matching attributes. " ,
" platform process list " , 0 ) ,
m_options ( ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectPlatformProcessList ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
2016-07-23 16:50:09 -04:00
2013-11-06 11:48:53 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
PlatformSP platform_sp ;
if ( target ) {
platform_sp = target - > GetPlatform ( ) ;
}
if ( ! platform_sp ) {
platform_sp =
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ;
}
if ( platform_sp ) {
Error error ;
if ( args . GetArgumentCount ( ) = = 0 ) {
if ( platform_sp ) {
Stream & ostrm = result . GetOutputStream ( ) ;
lldb : : pid_t pid =
m_options . match_info . GetProcessInfo ( ) . GetProcessID ( ) ;
if ( pid ! = LLDB_INVALID_PROCESS_ID ) {
ProcessInstanceInfo proc_info ;
if ( platform_sp - > GetProcessInfo ( pid , proc_info ) ) {
ProcessInstanceInfo : : DumpTableHeader ( ostrm , platform_sp . get ( ) ,
m_options . show_args ,
m_options . verbose ) ;
proc_info . DumpAsTableRow ( ostrm , platform_sp . get ( ) ,
m_options . show_args , m_options . verbose ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendErrorWithFormat (
" no process found with pid = % " PRIu64 " \n " , pid ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
} else {
ProcessInstanceInfoList proc_infos ;
const uint32_t matches =
platform_sp - > FindProcesses ( m_options . match_info , proc_infos ) ;
const char * match_desc = nullptr ;
const char * match_name =
m_options . match_info . GetProcessInfo ( ) . GetName ( ) ;
if ( match_name & & match_name [ 0 ] ) {
switch ( m_options . match_info . GetNameMatchType ( ) ) {
case eNameMatchIgnore :
break ;
case eNameMatchEquals :
match_desc = " matched " ;
break ;
case eNameMatchContains :
match_desc = " contained " ;
break ;
case eNameMatchStartsWith :
match_desc = " started with " ;
break ;
case eNameMatchEndsWith :
match_desc = " ended with " ;
break ;
case eNameMatchRegularExpression :
match_desc = " matched the regular expression " ;
break ;
}
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
if ( matches = = 0 ) {
if ( match_desc )
result . AppendErrorWithFormat (
" no processes were found that %s \" %s \" on the \" %s \" "
" platform \n " ,
match_desc , match_name ,
platform_sp - > GetPluginName ( ) . GetCString ( ) ) ;
else
result . AppendErrorWithFormat (
" no processes were found on the \" %s \" platform \n " ,
platform_sp - > GetPluginName ( ) . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
result . AppendMessageWithFormat (
" %u matching process%s found on \" %s \" " , matches ,
matches > 1 ? " es were " : " was " ,
platform_sp - > GetName ( ) . GetCString ( ) ) ;
if ( match_desc )
result . AppendMessageWithFormat ( " whose name %s \" %s \" " ,
match_desc , match_name ) ;
result . AppendMessageWithFormat ( " \n " ) ;
ProcessInstanceInfo : : DumpTableHeader ( ostrm , platform_sp . get ( ) ,
m_options . show_args ,
m_options . verbose ) ;
for ( uint32_t i = 0 ; i < matches ; + + i ) {
proc_infos . GetProcessInfoAtIndex ( i ) . DumpAsTableRow (
ostrm , platform_sp . get ( ) , m_options . show_args ,
m_options . verbose ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
} else {
result . AppendError ( " invalid args: process list takes only options \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform is selected \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , match_info ( ) , show_args ( false ) , verbose ( false ) {
static std : : once_flag g_once_flag ;
std : : call_once ( g_once_flag , [ ] ( ) {
PosixPlatformCommandOptionValidator * posix_validator =
new PosixPlatformCommandOptionValidator ( ) ;
for ( auto & Option : g_platform_process_list_options ) {
switch ( Option . short_option ) {
case ' u ' :
case ' U ' :
case ' g ' :
case ' G ' :
Option . validator = posix_validator ;
break ;
default :
break ;
}
}
} ) ;
}
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success = false ;
uint32_t id = LLDB_INVALID_PROCESS_ID ;
success = ! option_arg . getAsInteger ( 0 , id ) ;
switch ( short_option ) {
case ' p ' : {
match_info . GetProcessInfo ( ) . SetProcessID ( id ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid process ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
case ' P ' :
match_info . GetProcessInfo ( ) . SetParentProcessID ( id ) ;
if ( ! success )
error . SetErrorStringWithFormat (
" invalid parent process ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' u ' :
match_info . GetProcessInfo ( ) . SetUserID ( success ? id : UINT32_MAX ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid user ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' U ' :
match_info . GetProcessInfo ( ) . SetEffectiveUserID ( success ? id
: UINT32_MAX ) ;
if ( ! success )
error . SetErrorStringWithFormat (
" invalid effective user ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' g ' :
match_info . GetProcessInfo ( ) . SetGroupID ( success ? id : UINT32_MAX ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid group ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' G ' :
match_info . GetProcessInfo ( ) . SetEffectiveGroupID ( success ? id
: UINT32_MAX ) ;
if ( ! success )
error . SetErrorStringWithFormat (
" invalid effective group ID string: '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' a ' : {
TargetSP target_sp =
execution_context ? execution_context - > GetTargetSP ( ) : TargetSP ( ) ;
DebuggerSP debugger_sp =
target_sp ? target_sp - > GetDebugger ( ) . shared_from_this ( )
: DebuggerSP ( ) ;
PlatformSP platform_sp =
debugger_sp ? debugger_sp - > GetPlatformList ( ) . GetSelectedPlatform ( )
: PlatformSP ( ) ;
match_info . GetProcessInfo ( ) . GetArchitecture ( ) . SetTriple (
option_arg , platform_sp . get ( ) ) ;
} break ;
case ' n ' :
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( option_arg ,
false ) ;
match_info . SetNameMatchType ( eNameMatchEquals ) ;
break ;
case ' e ' :
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( option_arg ,
false ) ;
match_info . SetNameMatchType ( eNameMatchEndsWith ) ;
break ;
case ' s ' :
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( option_arg ,
false ) ;
match_info . SetNameMatchType ( eNameMatchStartsWith ) ;
break ;
case ' c ' :
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( option_arg ,
false ) ;
match_info . SetNameMatchType ( eNameMatchContains ) ;
break ;
case ' r ' :
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . SetFile ( option_arg ,
false ) ;
match_info . SetNameMatchType ( eNameMatchRegularExpression ) ;
break ;
case ' A ' :
show_args = true ;
break ;
case ' v ' :
verbose = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
match_info . Clear ( ) ;
show_args = false ;
verbose = false ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_platform_process_list_options ) ;
}
// Instance variables to hold the values for command options.
ProcessInstanceInfoMatch match_info ;
bool show_args ;
bool verbose ;
} ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
//----------------------------------------------------------------------
// "platform process info"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformProcessInfo ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " platform process info " ,
" Get detailed information for one or more process by process ID. " ,
" platform process info <pid> [<pid> <pid> ...] " , 0 ) {
CommandArgumentEntry arg ;
CommandArgumentData pid_args ;
// Define the first (and only) variant of this arg.
pid_args . arg_type = eArgTypePid ;
pid_args . arg_repetition = eArgRepeatStar ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( pid_args ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectPlatformProcessInfo ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-11-06 11:48:53 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
PlatformSP platform_sp ;
if ( target ) {
platform_sp = target - > GetPlatform ( ) ;
}
if ( ! platform_sp ) {
platform_sp =
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ;
}
if ( platform_sp ) {
const size_t argc = args . GetArgumentCount ( ) ;
if ( argc > 0 ) {
Error error ;
if ( platform_sp - > IsConnected ( ) ) {
Stream & ostrm = result . GetOutputStream ( ) ;
for ( auto & entry : args . entries ( ) ) {
lldb : : pid_t pid ;
if ( entry . ref . getAsInteger ( 0 , pid ) ) {
result . AppendErrorWithFormat ( " invalid process ID argument '%s' " ,
entry . ref . str ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
} else {
ProcessInstanceInfo proc_info ;
if ( platform_sp - > GetProcessInfo ( pid , proc_info ) ) {
ostrm . Printf ( " Process information for process % " PRIu64 " : \n " ,
pid ) ;
proc_info . Dump ( ostrm , platform_sp . get ( ) ) ;
} else {
ostrm . Printf ( " error: no process information is available for "
" process % " PRIu64 " \n " ,
pid ) ;
}
ostrm . EOL ( ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
}
} else {
// Not connected...
result . AppendErrorWithFormat (
" not connected to '%s' " ,
platform_sp - > GetPluginName ( ) . GetCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
// No args
result . AppendError ( " one or more process id(s) must be specified " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
result . AppendError ( " no platform is currently selected " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
} ;
static OptionDefinition g_platform_process_attach_options [ ] = {
// clang-format off
{ 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 , " waitfor " , ' w ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Wait for the process with <process-name> to launch. " } ,
// clang-format on
2013-11-06 11:48:53 -05:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) {
// Keep default values of all options in one place: OptionParsingStarting
// ()
OptionParsingStarting ( nullptr ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' p ' : {
lldb : : pid_t pid = LLDB_INVALID_PROCESS_ID ;
if ( option_arg . getAsInteger ( 0 , pid ) ) {
error . SetErrorStringWithFormat ( " invalid process ID '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
} 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 ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
attach_info . Clear ( ) ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_platform_process_attach_options ) ;
}
bool 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 ,
CommandInterpreter & interpreter , bool & word_complete ,
StringList & matches ) override {
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...
if ( GetDefinitions ( ) [ 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.
const char * partial_name = nullptr ;
partial_name = input . GetArgumentAtIndex ( opt_arg_pos ) ;
PlatformSP platform_sp ( 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 uint32_t num_matches = process_infos . GetSize ( ) ;
if ( num_matches > 0 ) {
for ( uint32_t i = 0 ; i < num_matches ; + + i ) {
matches . AppendString (
process_infos . GetProcessNameAtIndex ( i ) ,
process_infos . GetProcessNameLengthAtIndex ( i ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
ProcessAttachInfo attach_info ;
} ;
CommandObjectPlatformProcessAttach ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " platform process attach " ,
" Attach to a process. " ,
" platform process attach <cmd-options> " ) ,
m_options ( ) { }
~ CommandObjectPlatformProcessAttach ( ) override = default ;
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( platform_sp ) {
Error err ;
ProcessSP remote_process_sp = platform_sp - > Attach (
m_options . attach_info , m_interpreter . GetDebugger ( ) , nullptr , err ) ;
if ( err . Fail ( ) ) {
result . AppendError ( err . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else if ( ! remote_process_sp ) {
result . AppendError ( " could not attach: unknown reason " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendError ( " no platform is currently selected " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
Options * GetOptions ( ) override { return & m_options ; }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
protected :
CommandOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformProcess : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectPlatformProcess ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " platform process " ,
" Commands to query, launch and attach to "
" processes on the current platform. " ,
" platform process [attach|launch|list] ... " ) {
LoadSubCommand (
" attach " ,
CommandObjectSP ( new CommandObjectPlatformProcessAttach ( interpreter ) ) ) ;
LoadSubCommand (
" launch " ,
CommandObjectSP ( new CommandObjectPlatformProcessLaunch ( interpreter ) ) ) ;
LoadSubCommand ( " info " , CommandObjectSP ( new CommandObjectPlatformProcessInfo (
interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP ( new CommandObjectPlatformProcessList (
interpreter ) ) ) ;
}
~ CommandObjectPlatformProcess ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
//------------------------------------------------------------------
// For CommandObjectPlatform only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN ( CommandObjectPlatformProcess ) ;
2013-08-23 13:46:38 -04:00
} ;
2013-11-06 11:48:53 -05:00
//----------------------------------------------------------------------
// "platform shell"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_platform_shell_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " timeout " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeValue , " Seconds to wait for the remote host to finish running the command. " } ,
// clang-format on
} ;
class CommandObjectPlatformShell : public CommandObjectRaw {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , timeout ( 10 ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandOptions ( ) override = default ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_platform_shell_options ) ;
}
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const char short_option = ( char ) GetDefinitions ( ) [ option_idx ] . short_option ;
switch ( short_option ) {
case ' t ' :
timeout = 10 ;
if ( option_arg . getAsInteger ( 10 , timeout ) )
error . SetErrorStringWithFormat (
" could not convert \" %s \" to a numeric value. " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override { }
uint32_t timeout ;
} ;
CommandObjectPlatformShell ( CommandInterpreter & interpreter )
: CommandObjectRaw ( interpreter , " platform shell " ,
" Run a shell command on the current platform. " ,
" platform shell <shell-command> " , 0 ) ,
m_options ( ) { }
~ CommandObjectPlatformShell ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
bool DoExecute ( const char * raw_command_line ,
CommandReturnObject & result ) override {
ExecutionContext exe_ctx = GetCommandInterpreter ( ) . GetExecutionContext ( ) ;
m_options . NotifyOptionParsingStarting ( & exe_ctx ) ;
const char * expr = nullptr ;
// Print out an usage syntax on an empty command line.
if ( raw_command_line [ 0 ] = = ' \0 ' ) {
result . GetOutputStream ( ) . Printf ( " %s \n " , this - > GetSyntax ( ) . str ( ) . c_str ( ) ) ;
return true ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
if ( raw_command_line [ 0 ] = = ' - ' ) {
// We have some options and these options MUST end with --.
const char * end_options = nullptr ;
const char * s = raw_command_line ;
while ( s & & s [ 0 ] ) {
end_options = : : strstr ( s , " -- " ) ;
if ( end_options ) {
end_options + = 2 ; // Get past the "--"
if ( : : isspace ( end_options [ 0 ] ) ) {
expr = end_options ;
while ( : : isspace ( * expr ) )
+ + expr ;
break ;
}
}
s = end_options ;
}
if ( end_options ) {
Args args (
llvm : : StringRef ( raw_command_line , end_options - raw_command_line ) ) ;
if ( ! ParseOptions ( args , result ) )
return false ;
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( expr = = nullptr )
expr = raw_command_line ;
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
Error error ;
if ( platform_sp ) {
FileSpec working_dir { } ;
std : : string output ;
int status = - 1 ;
int signo = - 1 ;
error = ( platform_sp - > RunShellCommand ( expr , working_dir , & status , & signo ,
& output , m_options . timeout ) ) ;
if ( ! output . empty ( ) )
result . GetOutputStream ( ) . PutCString ( output ) ;
if ( status > 0 ) {
if ( signo > 0 ) {
const char * signo_cstr = Host : : GetSignalAsCString ( signo ) ;
if ( signo_cstr )
result . GetOutputStream ( ) . Printf (
" error: command returned with status %i and signal %s \n " ,
status , signo_cstr ) ;
else
result . GetOutputStream ( ) . Printf (
" error: command returned with status %i and signal %i \n " ,
status , signo ) ;
} else
result . GetOutputStream ( ) . Printf (
" error: command returned with status %i \n " , status ) ;
}
} else {
result . GetOutputStream ( ) . Printf (
" error: cannot run remote shell commands without a platform \n " ) ;
error . SetErrorString (
" error: cannot run remote shell commands without a platform " ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
return true ;
}
2013-11-06 11:48:53 -05:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
2013-11-06 11:48:53 -05:00
} ;
//----------------------------------------------------------------------
// "platform install" - install a target to a remote end
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectPlatformInstall : public CommandObjectParsed {
2013-11-06 11:48:53 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectPlatformInstall ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " platform target-install " ,
" Install a target (bundle or executable file) to the remote end. " ,
" platform target-install <local-thing> <remote-sandbox> " , 0 ) { }
~ CommandObjectPlatformInstall ( ) override = default ;
bool DoExecute ( Args & args , CommandReturnObject & result ) override {
if ( args . GetArgumentCount ( ) ! = 2 ) {
result . AppendError ( " platform target-install takes two arguments " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
// TODO: move the bulk of this code over to the platform itself
FileSpec src ( args . GetArgumentAtIndex ( 0 ) , true ) ;
FileSpec dst ( args . GetArgumentAtIndex ( 1 ) , false ) ;
if ( ! src . Exists ( ) ) {
result . AppendError ( " source location does not exist or is not accessible " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
PlatformSP platform_sp (
m_interpreter . GetDebugger ( ) . GetPlatformList ( ) . GetSelectedPlatform ( ) ) ;
if ( ! platform_sp ) {
result . AppendError ( " no platform currently selected " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-11-06 11:48:53 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Error error = platform_sp - > Install ( src , dst ) ;
if ( error . Success ( ) ) {
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendErrorWithFormat ( " install failed: %s " , error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2016-07-23 16:50:09 -04:00
CommandObjectPlatform : : CommandObjectPlatform ( CommandInterpreter & interpreter )
2017-01-02 14:26:05 -05:00
: CommandObjectMultiword (
interpreter , " platform " , " Commands to manage and create platforms. " ,
" platform [connect|disconnect|info|list|status|select] ... " ) {
LoadSubCommand ( " select " ,
CommandObjectSP ( new CommandObjectPlatformSelect ( interpreter ) ) ) ;
LoadSubCommand ( " list " ,
CommandObjectSP ( new CommandObjectPlatformList ( interpreter ) ) ) ;
LoadSubCommand ( " status " ,
CommandObjectSP ( new CommandObjectPlatformStatus ( interpreter ) ) ) ;
LoadSubCommand ( " connect " , CommandObjectSP (
new CommandObjectPlatformConnect ( interpreter ) ) ) ;
LoadSubCommand (
" disconnect " ,
CommandObjectSP ( new CommandObjectPlatformDisconnect ( interpreter ) ) ) ;
LoadSubCommand ( " settings " , CommandObjectSP ( new CommandObjectPlatformSettings (
interpreter ) ) ) ;
LoadSubCommand ( " mkdir " ,
CommandObjectSP ( new CommandObjectPlatformMkDir ( interpreter ) ) ) ;
LoadSubCommand ( " file " ,
CommandObjectSP ( new CommandObjectPlatformFile ( interpreter ) ) ) ;
LoadSubCommand ( " get-file " , CommandObjectSP ( new CommandObjectPlatformGetFile (
interpreter ) ) ) ;
LoadSubCommand ( " get-size " , CommandObjectSP ( new CommandObjectPlatformGetSize (
interpreter ) ) ) ;
LoadSubCommand ( " put-file " , CommandObjectSP ( new CommandObjectPlatformPutFile (
interpreter ) ) ) ;
LoadSubCommand ( " process " , CommandObjectSP (
new CommandObjectPlatformProcess ( interpreter ) ) ) ;
LoadSubCommand ( " shell " ,
CommandObjectSP ( new CommandObjectPlatformShell ( interpreter ) ) ) ;
LoadSubCommand (
" target-install " ,
CommandObjectSP ( new CommandObjectPlatformInstall ( interpreter ) ) ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectPlatform : : ~ CommandObjectPlatform ( ) = default ;