2013-11-17 21:01:41 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-03-13 09:09:42 +00:00
| PHP Version 7 |
2013-11-17 21:01:41 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2016-01-01 17:19:27 +00:00
| Copyright ( c ) 1997 - 2016 The PHP Group |
2013-11-17 21:01:41 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 3.01 of the PHP license , |
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Felipe Pena < felipe @ php . net > |
| Authors : Joe Watkins < joe . watkins @ live . co . uk > |
2013-12-18 10:02:50 +00:00
| Authors : Bob Weinand < bwoebi @ php . net > |
2013-11-17 21:01:41 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# include "phpdbg.h"
# include "phpdbg_cmd.h"
# include "phpdbg_utils.h"
2013-11-24 14:54:14 +00:00
# include "phpdbg_set.h"
2014-02-18 20:04:02 +00:00
# include "phpdbg_prompt.h"
2014-10-20 06:46:22 +00:00
# include "phpdbg_io.h"
2013-11-17 21:01:41 +00:00
2016-02-16 22:47:37 +00:00
ZEND_EXTERN_MODULE_GLOBALS ( phpdbg )
2013-11-17 21:01:41 +00:00
2014-02-19 20:18:49 +00:00
static inline const char * phpdbg_command_name ( const phpdbg_command_t * command , char * buffer ) {
size_t pos = 0 ;
if ( command - > parent ) {
memcpy ( & buffer [ pos ] , command - > parent - > name , command - > parent - > name_len ) ;
pos + = command - > parent - > name_len ;
memcpy ( & buffer [ pos ] , " " , sizeof ( " " ) - 1 ) ;
pos + = ( sizeof ( " " ) - 1 ) ;
}
memcpy ( & buffer [ pos ] , command - > name , command - > name_len ) ;
pos + = command - > name_len ;
buffer [ pos ] = 0 ;
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
return buffer ;
}
2014-12-13 22:06:14 +00:00
PHPDBG_API const char * phpdbg_get_param_type ( const phpdbg_param_t * param ) /* { { { */
2013-11-17 21:01:41 +00:00
{
switch ( param - > type ) {
2014-02-16 22:47:20 +00:00
case STACK_PARAM :
return " stack " ;
2013-11-17 21:01:41 +00:00
case EMPTY_PARAM :
return " empty " ;
case ADDR_PARAM :
return " address " ;
case NUMERIC_PARAM :
return " numeric " ;
case METHOD_PARAM :
return " method " ;
2013-12-03 11:31:25 +00:00
case NUMERIC_FUNCTION_PARAM :
return " function opline " ;
2013-11-28 20:36:45 +00:00
case NUMERIC_METHOD_PARAM :
return " method opline " ;
2013-11-17 21:01:41 +00:00
case FILE_PARAM :
2013-12-03 11:31:25 +00:00
return " file or file opline " ;
2013-11-17 21:01:41 +00:00
case STR_PARAM :
return " string " ;
default : /* this is bad */
return " unknown " ;
2013-11-26 10:02:58 +00:00
}
2013-11-17 21:01:41 +00:00
}
2014-12-13 22:06:14 +00:00
PHPDBG_API void phpdbg_clear_param ( phpdbg_param_t * param ) /* { { { */
2013-11-17 21:01:41 +00:00
{
2013-11-18 21:59:42 +00:00
if ( param ) {
switch ( param - > type ) {
case FILE_PARAM :
efree ( param - > file . name ) ;
break ;
case METHOD_PARAM :
efree ( param - > method . class ) ;
efree ( param - > method . name ) ;
break ;
case STR_PARAM :
efree ( param - > str ) ;
break ;
default :
break ;
}
2013-11-17 21:01:41 +00:00
}
2013-11-19 21:02:38 +00:00
2013-11-17 21:01:41 +00:00
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API char * phpdbg_param_tostring ( const phpdbg_param_t * param , char * * pointer ) /* { { { */
2013-12-04 14:20:13 +00:00
{
switch ( param - > type ) {
case STR_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s " , param - > str ) ) ;
2013-12-04 14:20:13 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
case ADDR_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , ZEND_ULONG_FMT , param - > addr ) ) ;
2013-12-04 14:20:13 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
case NUMERIC_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %li " , param - > num ) ) ;
2013-12-04 14:20:13 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
case METHOD_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s::%s " , param - > method . class , param - > method . name ) ) ;
2013-12-04 14:20:13 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
case FILE_PARAM :
2013-12-09 10:15:16 +00:00
if ( param - > num ) {
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s:%lu#%lu " , param - > file . name , param - > file . line , param - > num ) ) ;
2013-12-09 10:15:16 +00:00
} else {
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s:%lu " , param - > file . name , param - > file . line ) ) ;
2013-12-09 10:15:16 +00:00
}
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_FUNCTION_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s#%lu " , param - > str , param - > num ) ) ;
2013-12-09 10:15:16 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_METHOD_PARAM :
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( pointer , " %s::%s#%lu " , param - > method . class , param - > method . name , param - > num ) ) ;
2013-12-04 14:20:13 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
default :
2014-10-24 17:29:50 +00:00
* pointer = strdup ( " unknown " ) ;
2013-12-04 14:20:13 +00:00
}
2013-12-09 11:46:33 +00:00
2013-12-04 14:20:13 +00:00
return * pointer ;
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API void phpdbg_copy_param ( const phpdbg_param_t * src , phpdbg_param_t * dest ) /* { { { */
2013-12-03 00:15:33 +00:00
{
switch ( ( dest - > type = src - > type ) ) {
2014-02-16 22:47:20 +00:00
case STACK_PARAM :
/* nope */
break ;
2014-09-21 02:17:19 +00:00
2013-12-03 00:15:33 +00:00
case STR_PARAM :
dest - > str = estrndup ( src - > str , src - > len ) ;
dest - > len = src - > len ;
break ;
2014-09-21 02:17:19 +00:00
2014-02-21 18:52:06 +00:00
case OP_PARAM :
dest - > str = estrndup ( src - > str , src - > len ) ;
dest - > len = src - > len ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case ADDR_PARAM :
dest - > addr = src - > addr ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case NUMERIC_PARAM :
dest - > num = src - > num ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case METHOD_PARAM :
dest - > method . class = estrdup ( src - > method . class ) ;
dest - > method . name = estrdup ( src - > method . name ) ;
break ;
2013-12-09 11:46:33 +00:00
2014-02-21 18:52:06 +00:00
case NUMERIC_FILE_PARAM :
2013-12-03 00:15:33 +00:00
case FILE_PARAM :
dest - > file . name = estrdup ( src - > file . name ) ;
dest - > file . line = src - > file . line ;
2013-12-09 10:15:16 +00:00
if ( src - > num )
dest - > num = src - > num ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_FUNCTION_PARAM :
dest - > str = estrndup ( src - > str , src - > len ) ;
dest - > num = src - > num ;
dest - > len = src - > len ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_METHOD_PARAM :
dest - > method . class = estrdup ( src - > method . class ) ;
dest - > method . name = estrdup ( src - > method . name ) ;
dest - > num = src - > num ;
2013-12-03 00:15:33 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case EMPTY_PARAM : { /* do nothing */ } break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* not yet */
}
2013-12-03 00:15:33 +00:00
}
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API zend_ulong phpdbg_hash_param ( const phpdbg_param_t * param ) /* { { { */
2013-12-03 00:15:33 +00:00
{
zend_ulong hash = param - > type ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
switch ( param - > type ) {
2014-02-16 22:47:20 +00:00
case STACK_PARAM :
/* nope */
break ;
2014-09-21 02:17:19 +00:00
2013-12-03 00:15:33 +00:00
case STR_PARAM :
hash + = zend_inline_hash_func ( param - > str , param - > len ) ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case METHOD_PARAM :
hash + = zend_inline_hash_func ( param - > method . class , strlen ( param - > method . class ) ) ;
hash + = zend_inline_hash_func ( param - > method . name , strlen ( param - > method . name ) ) ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case FILE_PARAM :
hash + = zend_inline_hash_func ( param - > file . name , strlen ( param - > file . name ) ) ;
hash + = param - > file . line ;
2013-12-09 10:15:16 +00:00
if ( param - > num )
hash + = param - > num ;
2013-12-03 00:15:33 +00:00
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case ADDR_PARAM :
hash + = param - > addr ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case NUMERIC_PARAM :
hash + = param - > num ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_FUNCTION_PARAM :
hash + = zend_inline_hash_func ( param - > str , param - > len ) ;
hash + = param - > num ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_METHOD_PARAM :
hash + = zend_inline_hash_func ( param - > method . class , strlen ( param - > method . class ) ) ;
hash + = zend_inline_hash_func ( param - > method . name , strlen ( param - > method . name ) ) ;
if ( param - > num )
hash + = param - > num ;
break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case EMPTY_PARAM : { /* do nothing */ } break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* not yet */
}
2013-12-03 00:15:33 +00:00
}
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
return hash ;
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API zend_bool phpdbg_match_param ( const phpdbg_param_t * l , const phpdbg_param_t * r ) /* { { { */
2013-12-03 00:15:33 +00:00
{
if ( l & & r ) {
if ( l - > type = = r - > type ) {
switch ( l - > type ) {
2014-02-16 22:47:20 +00:00
case STACK_PARAM :
/* nope, or yep */
return 1 ;
break ;
2014-09-21 02:17:19 +00:00
2013-12-09 10:15:16 +00:00
case NUMERIC_FUNCTION_PARAM :
if ( l - > num ! = r - > num ) {
break ;
}
/* break intentionally omitted */
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case STR_PARAM :
2013-12-09 11:46:33 +00:00
return ( l - > len = = r - > len ) & &
2013-12-03 00:15:33 +00:00
( memcmp ( l - > str , r - > str , l - > len ) = = SUCCESS ) ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case NUMERIC_PARAM :
return ( l - > num = = r - > num ) ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case ADDR_PARAM :
return ( l - > addr = = r - > addr ) ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case FILE_PARAM : {
if ( l - > file . line = = r - > file . line ) {
size_t lengths [ 2 ] = {
strlen ( l - > file . name ) , strlen ( r - > file . name ) } ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
if ( lengths [ 0 ] = = lengths [ 1 ] ) {
2013-12-09 10:15:16 +00:00
if ( ( ! l - > num & & ! r - > num ) | | ( l - > num = = r - > num ) ) {
return ( memcmp (
l - > file . name , r - > file . name , lengths [ 0 ] ) = = SUCCESS ) ;
}
2013-12-03 00:15:33 +00:00
}
}
2013-12-09 11:46:33 +00:00
} break ;
2013-12-09 10:15:16 +00:00
case NUMERIC_METHOD_PARAM :
if ( l - > num ! = r - > num ) {
break ;
}
/* break intentionally omitted */
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case METHOD_PARAM : {
size_t lengths [ 2 ] = {
strlen ( l - > method . class ) , strlen ( r - > method . class ) } ;
if ( lengths [ 0 ] = = lengths [ 1 ] ) {
if ( memcmp ( l - > method . class , r - > method . class , lengths [ 0 ] ) = = SUCCESS ) {
lengths [ 0 ] = strlen ( l - > method . name ) ;
lengths [ 1 ] = strlen ( r - > method . name ) ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
if ( lengths [ 0 ] = = lengths [ 1 ] ) {
return ( memcmp (
l - > method . name , r - > method . name , lengths [ 0 ] ) = = SUCCESS ) ;
}
}
}
} break ;
2013-12-09 11:46:33 +00:00
2013-12-03 00:15:33 +00:00
case EMPTY_PARAM :
return 1 ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* not yet */
}
2013-12-03 00:15:33 +00:00
}
}
}
return 0 ;
} /* }}} */
2014-02-18 20:04:02 +00:00
/* {{{ */
PHPDBG_API void phpdbg_param_debug ( const phpdbg_param_t * param , const char * msg ) {
if ( param & & param - > type ) {
switch ( param - > type ) {
case STR_PARAM :
2015-07-24 19:45:36 +00:00
fprintf ( stderr , " %s STR_PARAM(%s=%zu) \n " , msg , param - > str , param - > len ) ;
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case ADDR_PARAM :
2015-03-09 13:25:43 +00:00
fprintf ( stderr , " %s ADDR_PARAM( " ZEND_ULONG_FMT " ) \n " , msg , param - > addr ) ;
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-21 18:01:50 +00:00
case NUMERIC_FILE_PARAM :
fprintf ( stderr , " %s NUMERIC_FILE_PARAM(%s:#%lu) \n " , msg , param - > file . name , param - > file . line ) ;
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case FILE_PARAM :
2014-02-19 08:33:54 +00:00
fprintf ( stderr , " %s FILE_PARAM(%s:%lu) \n " , msg , param - > file . name , param - > file . line ) ;
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case METHOD_PARAM :
fprintf ( stderr , " %s METHOD_PARAM(%s::%s) \n " , msg , param - > method . class , param - > method . name ) ;
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case NUMERIC_METHOD_PARAM :
fprintf ( stderr , " %s NUMERIC_METHOD_PARAM(%s::%s) \n " , msg , param - > method . class , param - > method . name ) ;
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case NUMERIC_FUNCTION_PARAM :
2014-02-19 08:33:54 +00:00
fprintf ( stderr , " %s NUMERIC_FUNCTION_PARAM(%s::%ld) \n " , msg , param - > str , param - > num ) ;
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case NUMERIC_PARAM :
fprintf ( stderr , " %s NUMERIC_PARAM(%ld) \n " , msg , param - > num ) ;
break ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case COND_PARAM :
2015-07-24 19:45:36 +00:00
fprintf ( stderr , " %s COND_PARAM(%s=%zu) \n " , msg , param - > str , param - > len ) ;
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-21 16:18:46 +00:00
case OP_PARAM :
2015-07-24 19:45:36 +00:00
fprintf ( stderr , " %s OP_PARAM(%s=%zu) \n " , msg , param - > str , param - > len ) ;
2014-02-21 16:18:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* not yet */
}
2014-02-18 20:04:02 +00:00
}
}
} /* }}} */
/* {{{ */
PHPDBG_API void phpdbg_stack_free ( phpdbg_param_t * stack ) {
if ( stack & & stack - > next ) {
phpdbg_param_t * remove = stack - > next ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
while ( remove ) {
phpdbg_param_t * next = NULL ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
if ( remove - > next )
next = remove - > next ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
switch ( remove - > type ) {
2014-02-21 18:01:50 +00:00
case NUMERIC_METHOD_PARAM :
case METHOD_PARAM :
2015-08-03 18:27:46 +00:00
if ( remove - > method . class ) {
efree ( remove - > method . class ) ;
}
if ( remove - > method . name ) {
efree ( remove - > method . name ) ;
}
2014-02-21 18:01:50 +00:00
break ;
case NUMERIC_FUNCTION_PARAM :
case STR_PARAM :
case OP_PARAM :
2015-08-03 23:22:04 +00:00
case EVAL_PARAM :
case SHELL_PARAM :
case COND_PARAM :
case RUN_PARAM :
2015-08-03 18:27:46 +00:00
if ( remove - > str ) {
efree ( remove - > str ) ;
}
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-21 18:01:50 +00:00
case NUMERIC_FILE_PARAM :
2014-02-18 20:04:02 +00:00
case FILE_PARAM :
2015-08-03 18:27:46 +00:00
if ( remove - > file . name ) {
efree ( remove - > file . name ) ;
}
2014-02-18 20:04:02 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* nothing */
}
2014-02-18 20:04:02 +00:00
}
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
free ( remove ) ;
2014-02-21 20:42:15 +00:00
remove = NULL ;
2014-09-21 02:17:19 +00:00
2014-02-21 20:42:15 +00:00
if ( next )
2014-09-21 02:17:19 +00:00
remove = next ;
2014-02-18 20:04:02 +00:00
else break ;
}
}
2014-09-21 02:17:19 +00:00
2014-02-21 20:42:15 +00:00
stack - > next = NULL ;
2014-02-18 20:04:02 +00:00
} /* }}} */
/* {{{ */
PHPDBG_API void phpdbg_stack_push ( phpdbg_param_t * stack , phpdbg_param_t * param ) {
phpdbg_param_t * next = calloc ( 1 , sizeof ( phpdbg_param_t ) ) ;
2014-04-15 15:52:46 +00:00
2015-09-17 20:52:55 +00:00
if ( ! next ) {
2014-02-18 20:04:02 +00:00
return ;
2015-09-17 20:52:55 +00:00
}
2014-04-15 15:52:46 +00:00
2014-02-18 20:04:02 +00:00
* ( next ) = * ( param ) ;
2014-04-15 15:52:46 +00:00
next - > next = NULL ;
2014-02-18 20:04:02 +00:00
if ( stack - > top = = NULL ) {
stack - > top = next ;
2014-04-15 15:52:46 +00:00
next - > top = NULL ;
2014-02-18 20:04:02 +00:00
stack - > next = next ;
} else {
stack - > top - > next = next ;
next - > top = stack - > top ;
stack - > top = next ;
}
2014-04-15 15:52:46 +00:00
2014-02-18 20:04:02 +00:00
stack - > len + + ;
} /* }}} */
2015-09-17 20:52:55 +00:00
/* {{{ */
PHPDBG_API void phpdbg_stack_separate ( phpdbg_param_t * param ) {
phpdbg_param_t * stack = calloc ( 1 , sizeof ( phpdbg_param_t ) ) ;
stack - > type = STACK_PARAM ;
stack - > next = param - > next ;
param - > next = stack ;
stack - > top = param - > top ;
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API int phpdbg_stack_verify ( const phpdbg_command_t * command , phpdbg_param_t * * stack ) {
2014-02-21 19:05:20 +00:00
if ( command ) {
2014-02-19 20:18:49 +00:00
char buffer [ 128 ] = { 0 , } ;
2014-02-19 00:33:49 +00:00
const phpdbg_param_t * top = ( stack ! = NULL ) ? * stack : NULL ;
const char * arg = command - > args ;
2014-02-19 20:18:49 +00:00
size_t least = 0L ,
2014-09-21 02:17:19 +00:00
received = 0L ,
current = 0L ;
2014-02-19 00:33:49 +00:00
zend_bool optional = 0 ;
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
/* check for arg spec */
2014-02-21 19:05:20 +00:00
if ( ! ( arg ) | | ! ( * arg ) ) {
2015-09-17 20:52:55 +00:00
if ( ! top | | top - > type = = STACK_PARAM ) {
2014-02-21 19:05:20 +00:00
return SUCCESS ;
}
2014-09-21 02:17:19 +00:00
2015-01-03 09:22:58 +00:00
phpdbg_error ( " command " , " type= \" toomanyargs \" command= \" %s \" expected= \" 0 \" " , " The command \" %s \" expected no arguments " ,
2014-02-21 19:05:20 +00:00
phpdbg_command_name ( command , buffer ) ) ;
return FAILURE ;
}
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
least = 0L ;
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
/* count least amount of arguments */
while ( arg & & * arg ) {
if ( arg [ 0 ] = = ' | ' ) {
break ;
}
least + + ;
2014-02-19 00:33:49 +00:00
arg + + ;
}
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
arg = command - > args ;
# define verify_arg(e, a, t) if (!(a)) { \
if ( ! optional ) { \
2014-09-21 02:17:19 +00:00
phpdbg_error ( " command " , " type= \" noarg \" command= \" %s \" expected= \" %s \" num= \" %lu \" " , " The command \" %s \" expected %s and got nothing at parameter %lu " , \
2014-02-19 20:18:49 +00:00
phpdbg_command_name ( command , buffer ) , \
( e ) , \
current ) ; \
return FAILURE ; \
} \
} else if ( ( a ) - > type ! = ( t ) ) { \
2014-09-21 02:17:19 +00:00
phpdbg_error ( " command " , " type= \" wrongarg \" command= \" %s \" expected= \" %s \" got= \" %s \" num= \" %lu \" " , " The command \" %s \" expected %s and got %s at parameter %lu " , \
2014-02-19 20:18:49 +00:00
phpdbg_command_name ( command , buffer ) , \
( e ) , \
2014-12-13 22:06:14 +00:00
phpdbg_get_param_type ( ( a ) ) , \
2014-02-19 20:18:49 +00:00
current ) ; \
return FAILURE ; \
}
2014-02-19 00:33:49 +00:00
2014-02-21 19:37:16 +00:00
while ( arg & & * arg ) {
2015-09-17 20:52:55 +00:00
if ( top & & top - > type = = STACK_PARAM ) {
break ;
}
2014-02-19 20:18:49 +00:00
current + + ;
2014-09-21 02:17:19 +00:00
2014-02-19 00:33:49 +00:00
switch ( * arg ) {
2014-02-19 20:18:49 +00:00
case ' | ' : {
current - - ;
2014-02-19 00:33:49 +00:00
optional = 1 ;
arg + + ;
} continue ;
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
case ' i ' : verify_arg ( " raw input " , top , STR_PARAM ) ; break ;
case ' s ' : verify_arg ( " string " , top , STR_PARAM ) ; break ;
case ' n ' : verify_arg ( " number " , top , NUMERIC_PARAM ) ; break ;
case ' m ' : verify_arg ( " method " , top , METHOD_PARAM ) ; break ;
case ' a ' : verify_arg ( " address " , top , ADDR_PARAM ) ; break ;
case ' f ' : verify_arg ( " file:line " , top , FILE_PARAM ) ; break ;
case ' c ' : verify_arg ( " condition " , top , COND_PARAM ) ; break ;
2014-02-21 16:18:46 +00:00
case ' o ' : verify_arg ( " opcode " , top , OP_PARAM ) ; break ;
2014-02-19 20:18:49 +00:00
case ' b ' : verify_arg ( " boolean " , top , NUMERIC_PARAM ) ; break ;
2014-09-21 02:17:19 +00:00
2014-02-19 00:33:49 +00:00
case ' * ' : { /* do nothing */ } break ;
}
2014-09-21 02:17:19 +00:00
2015-09-17 20:52:55 +00:00
if ( top ) {
2014-02-19 20:18:49 +00:00
top = top - > next ;
2015-09-17 20:52:55 +00:00
} else {
break ;
}
2014-09-21 02:17:19 +00:00
2014-02-19 00:33:49 +00:00
received + + ;
arg + + ;
}
2014-02-19 20:18:49 +00:00
# undef verify_arg
if ( ( received < least ) ) {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " command " , " type= \" toofewargs \" command= \" %s \" expected= \" %d \" argtypes= \" %s \" got= \" %d \" " , " The command \" %s \" expected at least %lu arguments (%s) and received %lu " ,
2014-02-19 20:18:49 +00:00
phpdbg_command_name ( command , buffer ) ,
least ,
2014-09-21 02:17:19 +00:00
command - > args ,
2014-02-19 00:33:49 +00:00
received ) ;
return FAILURE ;
}
}
2014-09-21 02:17:19 +00:00
2014-02-19 00:33:49 +00:00
return SUCCESS ;
}
2014-02-18 20:04:02 +00:00
/* {{{ */
2014-12-13 22:06:14 +00:00
PHPDBG_API const phpdbg_command_t * phpdbg_stack_resolve ( const phpdbg_command_t * commands , const phpdbg_command_t * parent , phpdbg_param_t * * top ) {
2014-02-18 20:04:02 +00:00
const phpdbg_command_t * command = commands ;
phpdbg_param_t * name = * top ;
2014-02-19 08:33:54 +00:00
const phpdbg_command_t * matched [ 3 ] = { NULL , NULL , NULL } ;
2014-02-18 20:04:02 +00:00
ulong matches = 0L ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
while ( command & & command - > name & & command - > handler ) {
2014-10-02 23:29:41 +00:00
if ( name - > len = = 1 | | command - > name_len > = name - > len ) {
2014-02-19 08:33:54 +00:00
/* match single letter alias */
if ( command - > alias & & ( name - > len = = 1 ) ) {
if ( command - > alias = = ( * name - > str ) ) {
2014-02-18 20:04:02 +00:00
matched [ matches ] = command ;
matches + + ;
2014-02-19 08:33:54 +00:00
}
} else {
2014-02-21 17:47:02 +00:00
/* match full, case insensitive, command name */
if ( strncasecmp ( command - > name , name - > str , name - > len ) = = SUCCESS ) {
2014-02-19 08:33:54 +00:00
if ( matches < 3 ) {
2014-02-21 21:31:01 +00:00
/* only allow abbreviating commands that can be aliased */
2014-10-07 11:08:30 +00:00
if ( ( name - > len ! = command - > name_len & & command - > alias ) | | name - > len = = command - > name_len ) {
2014-02-21 21:31:01 +00:00
matched [ matches ] = command ;
matches + + ;
}
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
/* exact match */
2014-10-02 23:29:41 +00:00
if ( name - > len = = command - > name_len ) {
2014-02-19 20:18:49 +00:00
break ;
2014-10-02 23:29:41 +00:00
}
2014-09-21 02:17:19 +00:00
} else {
break ;
}
2014-02-19 08:33:54 +00:00
}
2014-02-18 20:04:02 +00:00
}
}
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
command + + ;
}
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
switch ( matches ) {
2014-09-21 02:17:19 +00:00
case 0 :
2014-02-23 07:33:48 +00:00
if ( parent ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " command " , " type= \" notfound \" command= \" %s \" subcommand= \" %s \" " , " The command \" %s %s \" could not be found " , parent - > name , name - > str ) ;
2014-09-21 02:17:19 +00:00
} else {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " command " , " type= \" notfound \" command= \" %s \" " , " The command \" %s \" could not be found " , name - > str ) ;
2014-09-21 02:17:19 +00:00
}
return parent ;
case 1 :
2014-02-18 20:04:02 +00:00
( * top ) = ( * top ) - > next ;
2014-02-19 00:33:49 +00:00
command = matched [ 0 ] ;
2014-09-21 02:17:19 +00:00
break ;
2014-02-18 20:04:02 +00:00
default : {
2014-02-19 20:18:49 +00:00
char * list = NULL ;
2014-08-25 17:28:33 +00:00
uint32_t it = 0 ;
2014-02-19 20:18:49 +00:00
size_t pos = 0 ;
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
while ( it < matches ) {
if ( ! list ) {
2014-10-02 23:29:41 +00:00
list = emalloc ( matched [ it ] - > name_len + 1 + ( it + 1 < matches ? sizeof ( " , " ) - 1 : 0 ) ) ;
2014-02-19 20:18:49 +00:00
} else {
2014-10-02 23:29:41 +00:00
list = erealloc ( list , ( pos + matched [ it ] - > name_len ) + 1 + ( it + 1 < matches ? sizeof ( " , " ) - 1 : 0 ) ) ;
2014-02-19 20:18:49 +00:00
}
memcpy ( & list [ pos ] , matched [ it ] - > name , matched [ it ] - > name_len ) ;
pos + = matched [ it ] - > name_len ;
2014-09-21 02:17:19 +00:00
if ( ( it + 1 ) < matches ) {
memcpy ( & list [ pos ] , " , " , sizeof ( " , " ) - 1 ) ;
2014-02-19 20:18:49 +00:00
pos + = ( sizeof ( " , " ) - 1 ) ;
}
2014-09-21 02:17:19 +00:00
2014-02-19 20:18:49 +00:00
list [ pos ] = 0 ;
it + + ;
}
2014-09-21 02:17:19 +00:00
/* ", " separated matches */
2014-10-07 11:08:30 +00:00
phpdbg_error ( " command " , " type= \" ambiguous \" command= \" %s \" matches= \" %lu \" matched= \" %s \" " , " The command \" %s \" is ambigious, matching %lu commands (%s) " , name - > str , matches , list ) ;
2014-09-21 02:17:19 +00:00
efree ( list ) ;
return NULL ;
}
2014-02-18 20:04:02 +00:00
}
2014-02-19 00:33:49 +00:00
if ( command - > subs & & ( * top ) & & ( ( * top ) - > type = = STR_PARAM ) ) {
2014-12-13 22:06:14 +00:00
return phpdbg_stack_resolve ( command - > subs , command , top ) ;
2014-02-19 00:33:49 +00:00
} else {
return command ;
}
2014-02-18 20:04:02 +00:00
return NULL ;
} /* }}} */
2015-09-17 20:52:55 +00:00
static int phpdbg_internal_stack_execute ( phpdbg_param_t * stack , zend_bool allow_async_unsafe ) {
2014-02-19 08:33:54 +00:00
const phpdbg_command_t * handler = NULL ;
2015-09-17 20:52:55 +00:00
phpdbg_param_t * top = ( phpdbg_param_t * ) stack - > next ;
2014-09-21 02:17:19 +00:00
2014-02-21 18:52:06 +00:00
switch ( top - > type ) {
2014-02-18 20:04:02 +00:00
case EVAL_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
return PHPDBG_COMMAND_HANDLER ( ev ) ( top ) ;
2014-04-16 11:56:26 +00:00
case RUN_PARAM :
2014-10-07 11:08:30 +00:00
if ( ! allow_async_unsafe ) {
phpdbg_error ( " signalsegv " , " command= \" run \" " , " run command is disallowed during hard interrupt " ) ;
2014-10-02 23:29:41 +00:00
}
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
return PHPDBG_COMMAND_HANDLER ( run ) ( top ) ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case SHELL_PARAM :
2014-10-07 11:08:30 +00:00
if ( ! allow_async_unsafe ) {
phpdbg_error ( " signalsegv " , " command= \" sh \" " , " sh command is disallowed during hard interrupt " ) ;
return FAILURE ;
2014-10-02 23:29:41 +00:00
}
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
return PHPDBG_COMMAND_HANDLER ( sh ) ( top ) ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
case STR_PARAM : {
2014-12-13 22:06:14 +00:00
handler = phpdbg_stack_resolve ( phpdbg_prompt_commands , NULL , & top ) ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
if ( handler ) {
2014-10-02 23:29:41 +00:00
if ( ! allow_async_unsafe & & ! ( handler - > flags & PHPDBG_ASYNC_SAFE ) ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " signalsegv " , " command= \" %s \" " , " %s command is disallowed during hard interrupt " , handler - > name ) ;
2014-10-02 23:29:41 +00:00
return FAILURE ;
}
2014-12-13 22:06:14 +00:00
if ( phpdbg_stack_verify ( handler , & top ) = = SUCCESS ) {
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
return handler - > handler ( top ) ;
2014-02-19 00:33:49 +00:00
}
2014-02-18 20:04:02 +00:00
}
2014-02-19 00:33:49 +00:00
} return FAILURE ;
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
default :
2014-09-21 02:17:19 +00:00
phpdbg_error ( " command " , " type= \" invalidcommand \" " , " The first parameter makes no sense ! " ) ;
2014-02-18 20:04:02 +00:00
return FAILURE ;
}
2014-09-21 02:17:19 +00:00
2014-02-18 20:04:02 +00:00
return SUCCESS ;
} /* }}} */
2015-09-17 20:52:55 +00:00
/* {{{ */
PHPDBG_API int phpdbg_stack_execute ( phpdbg_param_t * stack , zend_bool allow_async_unsafe ) {
phpdbg_param_t * top = stack ;
if ( stack - > type ! = STACK_PARAM ) {
phpdbg_error ( " command " , " type= \" nostack \" " , " The passed argument was not a stack ! " ) ;
return FAILURE ;
}
if ( ! stack - > len ) {
phpdbg_error ( " command " , " type= \" emptystack \" " , " The stack contains nothing ! " ) ;
return FAILURE ;
}
do {
if ( top - > type = = STACK_PARAM ) {
2015-09-17 22:50:08 +00:00
int result ;
if ( ( result = phpdbg_internal_stack_execute ( top , allow_async_unsafe ) ) ! = SUCCESS ) {
return result ;
2015-09-17 20:52:55 +00:00
}
}
} while ( ( top = top - > next ) ) ;
return SUCCESS ;
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API char * phpdbg_read_input ( char * buffered ) /* { { { */
2013-11-19 12:39:48 +00:00
{
2014-10-26 02:50:28 +00:00
char buf [ PHPDBG_MAX_CMD ] ;
2013-11-20 10:04:05 +00:00
char * cmd = NULL ;
2014-02-18 19:48:33 +00:00
char * buffer = NULL ;
2013-11-19 12:39:48 +00:00
2014-10-26 19:43:49 +00:00
if ( ( PHPDBG_G ( flags ) & ( PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING ) ) ! = PHPDBG_IS_STOPPING ) {
2014-12-13 22:06:14 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_IS_REMOTE ) & & ( buffered = = NULL ) & & ! phpdbg_active_sigsafe_mem ( ) ) {
2014-09-28 00:57:12 +00:00
fflush ( PHPDBG_G ( io ) [ PHPDBG_STDOUT ] . ptr ) ;
2013-11-28 17:30:27 +00:00
}
2013-12-09 11:46:33 +00:00
if ( buffered = = NULL ) {
2014-10-04 14:31:34 +00:00
# define USE_LIB_STAR (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT))
2014-09-28 00:57:12 +00:00
/* note: EOF makes readline write prompt again in local console mode - and ignored if compiled without readline */
# if USE_LIB_STAR
2015-07-20 20:45:05 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_IS_REMOTE ) | | ! isatty ( PHPDBG_G ( io ) [ PHPDBG_STDIN ] . fd ) )
2014-09-28 00:57:12 +00:00
# endif
{
2014-12-13 22:06:14 +00:00
phpdbg_write ( " prompt " , " " , " %s " , phpdbg_get_prompt ( ) ) ;
phpdbg_consume_stdin_line ( cmd = buf ) ;
2014-01-13 08:14:04 +00:00
}
2014-09-28 00:57:12 +00:00
# if USE_LIB_STAR
else {
2014-12-13 22:06:14 +00:00
cmd = readline ( phpdbg_get_prompt ( ) ) ;
2014-10-26 02:50:28 +00:00
PHPDBG_G ( last_was_newline ) = 1 ;
2014-01-13 08:14:04 +00:00
2015-07-07 20:45:34 +00:00
if ( ! cmd ) {
2015-07-08 14:54:41 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED ;
zend_bailout ( ) ;
2015-07-07 20:45:34 +00:00
}
2013-11-27 17:32:15 +00:00
add_history ( cmd ) ;
}
2013-11-19 12:39:48 +00:00
# endif
2014-09-28 00:57:12 +00:00
} else {
cmd = buffered ;
}
2014-10-26 02:50:28 +00:00
2014-02-18 19:48:33 +00:00
buffer = estrdup ( cmd ) ;
2013-11-19 12:39:48 +00:00
2014-09-28 00:57:12 +00:00
# if USE_LIB_STAR
2015-07-20 20:45:05 +00:00
if ( ! buffered & & cmd & & ! ( PHPDBG_G ( flags ) & PHPDBG_IS_REMOTE ) & & isatty ( PHPDBG_G ( io ) [ PHPDBG_STDIN ] . fd ) ) {
2013-11-19 12:39:48 +00:00
free ( cmd ) ;
}
# endif
}
2013-11-19 21:02:38 +00:00
2014-04-21 20:43:19 +00:00
if ( buffer & & isspace ( * buffer ) ) {
char * trimmed = buffer ;
while ( isspace ( * trimmed ) )
trimmed + + ;
trimmed = estrdup ( trimmed ) ;
efree ( buffer ) ;
buffer = trimmed ;
}
if ( buffer & & strlen ( buffer ) ) {
if ( PHPDBG_G ( buffer ) ) {
2015-08-21 22:36:31 +00:00
free ( PHPDBG_G ( buffer ) ) ;
2014-04-21 20:43:19 +00:00
}
2015-08-21 22:36:31 +00:00
PHPDBG_G ( buffer ) = strdup ( buffer ) ;
} else if ( PHPDBG_G ( buffer ) ) {
if ( buffer ) {
efree ( buffer ) ;
2014-04-21 20:43:19 +00:00
}
2015-08-21 22:36:31 +00:00
buffer = estrdup ( PHPDBG_G ( buffer ) ) ;
2014-04-21 20:43:19 +00:00
}
2014-09-21 02:17:19 +00:00
2014-02-18 19:48:33 +00:00
return buffer ;
2013-11-19 12:39:48 +00:00
} /* }}} */
2014-12-13 22:06:14 +00:00
PHPDBG_API void phpdbg_destroy_input ( char * * input ) /* { { { */
2013-11-19 19:24:21 +00:00
{
2014-02-18 19:48:33 +00:00
efree ( * input ) ;
2013-11-19 20:27:23 +00:00
} /* }}} */
2014-10-26 02:50:28 +00:00
2014-12-13 22:06:14 +00:00
PHPDBG_API int phpdbg_ask_user_permission ( const char * question ) {
2014-10-26 02:50:28 +00:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_WRITE_XML ) ) {
char buf [ PHPDBG_MAX_CMD ] ;
phpdbg_out ( " %s " , question ) ;
phpdbg_out ( " (type y or n): " ) ;
while ( 1 ) {
2014-12-13 22:06:14 +00:00
phpdbg_consume_stdin_line ( buf ) ;
2014-10-26 02:50:28 +00:00
if ( buf [ 1 ] = = ' \n ' & & ( buf [ 0 ] = = ' y ' | | buf [ 0 ] = = ' n ' ) ) {
if ( buf [ 0 ] = = ' y ' ) {
return SUCCESS ;
}
return FAILURE ;
}
phpdbg_out ( " Please enter either y (yes) or n (no): " ) ;
}
}
return SUCCESS ;
}