2013-11-11 02:06:41 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-03-13 17:09:42 +08:00
| PHP Version 7 |
2013-11-11 02:06:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2018-01-02 12:57:58 +08:00
| Copyright ( c ) 1997 - 2018 The PHP Group |
2013-11-11 02:06:41 +08: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 18:02:50 +08:00
| Authors : Bob Weinand < bwoebi @ php . net > |
2013-11-11 02:06:41 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# include "zend.h"
# include "zend_hash.h"
# include "phpdbg.h"
# include "phpdbg_bp.h"
2013-11-13 06:39:39 +08:00
# include "phpdbg_utils.h"
2013-11-24 07:46:24 +08:00
# include "phpdbg_opcode.h"
2013-11-13 22:22:01 +08:00
# include "zend_globals.h"
2016-11-13 19:55:35 +08:00
# include "ext/standard/php_string.h"
2013-11-11 02:06:41 +08:00
2016-02-17 06:47:37 +08:00
ZEND_EXTERN_MODULE_GLOBALS ( phpdbg )
2013-11-11 02:06:41 +08:00
2013-11-27 21:28:53 +08:00
/* {{{ private api functions */
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_file ( zend_op_array * ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_symbol ( zend_function * ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_method ( zend_op_array * ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opline ( phpdbg_opline_ptr_t ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opcode ( zend_uchar ) ;
static inline phpdbg_breakbase_t * phpdbg_find_conditional_breakpoint ( zend_execute_data * execute_data ) ; /* }}} */
2013-11-27 21:28:53 +08:00
2013-11-27 06:20:52 +08:00
/*
* Note :
2013-11-28 06:59:02 +08:00
* A break point must always set the correct id and type
2013-11-27 06:20:52 +08:00
* A set breakpoint function must always map new points
*/
2015-04-21 21:53:12 +08:00
static inline void _phpdbg_break_mapping ( int id , HashTable * table ) /* { { { */
2013-11-28 06:59:02 +08:00
{
2014-10-25 01:29:50 +08:00
zend_hash_index_update_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , id , table ) ;
2013-11-27 06:20:52 +08:00
}
2015-04-21 21:53:12 +08:00
/* }}} */
2013-11-27 06:20:52 +08:00
2014-12-14 06:06:14 +08:00
# define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table)
2013-11-27 06:20:52 +08:00
# define PHPDBG_BREAK_UNMAPPING(id) \
zend_hash_index_del ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , ( id ) )
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
# define PHPDBG_BREAK_INIT(b, t) do {\
b . id = PHPDBG_G ( bp_count ) + + ; \
b . type = t ; \
b . disabled = 0 ; \
b . hits = 0 ; \
} while ( 0 )
2013-11-27 06:20:52 +08:00
2014-10-25 01:29:50 +08:00
static void phpdbg_file_breaks_dtor ( zval * data ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2014-10-25 01:29:50 +08:00
phpdbg_breakfile_t * bp = ( phpdbg_breakfile_t * ) Z_PTR_P ( data ) ;
2013-11-11 02:06:41 +08:00
efree ( ( char * ) bp - > filename ) ;
2015-07-24 23:17:09 +08:00
efree ( bp ) ;
2013-11-11 02:06:41 +08:00
} /* }}} */
2014-10-25 01:29:50 +08:00
static void phpdbg_class_breaks_dtor ( zval * data ) /* { { { */
2013-11-12 08:27:48 +08:00
{
2014-10-25 01:29:50 +08:00
phpdbg_breakmethod_t * bp = ( phpdbg_breakmethod_t * ) Z_PTR_P ( data ) ;
2013-11-12 09:41:14 +08:00
2013-11-26 18:02:58 +08:00
efree ( ( char * ) bp - > class_name ) ;
efree ( ( char * ) bp - > func_name ) ;
2015-07-24 23:17:09 +08:00
efree ( bp ) ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2014-10-25 01:29:50 +08:00
static void phpdbg_opline_class_breaks_dtor ( zval * data ) /* { { { */
2013-11-29 04:36:45 +08:00
{
2015-07-24 23:17:09 +08:00
zend_hash_destroy ( Z_ARRVAL_P ( data ) ) ;
efree ( Z_ARRVAL_P ( data ) ) ;
2013-11-29 04:36:45 +08:00
} /* }}} */
2014-10-25 01:29:50 +08:00
static void phpdbg_opline_breaks_dtor ( zval * data ) /* { { { */
2013-11-29 04:36:45 +08:00
{
2014-10-25 01:29:50 +08:00
phpdbg_breakopline_t * bp = ( phpdbg_breakopline_t * ) Z_PTR_P ( data ) ;
2013-11-29 04:36:45 +08:00
2013-12-01 22:58:59 +08:00
if ( bp - > class_name ) {
efree ( ( char * ) bp - > class_name ) ;
}
if ( bp - > func_name ) {
efree ( ( char * ) bp - > func_name ) ;
}
2015-07-24 23:17:09 +08:00
efree ( bp ) ;
2013-11-29 04:36:45 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_reset_breakpoints ( void ) /* { { { */
2013-11-26 01:41:09 +08:00
{
2014-10-25 01:29:50 +08:00
HashTable * table ;
2013-11-26 05:39:17 +08:00
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , table ) {
phpdbg_breakbase_t * brake ;
2013-11-26 01:41:09 +08:00
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( table , brake ) {
brake - > hits = 0 ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-27 21:15:52 +08:00
} /* }}} */
2013-11-26 05:39:17 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_export_breakpoints ( FILE * handle ) /* { { { */
2014-10-29 00:20:21 +08:00
{
char * string ;
2014-12-14 06:06:14 +08:00
phpdbg_export_breakpoints_to_string ( & string ) ;
2014-10-29 00:20:21 +08:00
fputs ( string , handle ) ;
}
2015-04-21 21:53:12 +08:00
/* }}} */
2014-10-29 00:20:21 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_export_breakpoints_to_string ( char * * str ) /* { { { */
2013-11-26 01:41:09 +08:00
{
2014-10-25 01:29:50 +08:00
HashTable * table ;
2013-11-27 06:20:52 +08:00
zend_ulong id = 0L ;
2013-12-03 19:31:25 +08:00
2014-10-29 00:20:21 +08:00
* str = " " ;
2013-11-27 06:20:52 +08:00
if ( zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " exportbreakpoint " , " count= \" %d \" " , " Exporting %d breakpoints " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] ) ) ;
2014-10-25 01:29:50 +08:00
2013-11-28 06:59:02 +08:00
/* this only looks like magic, it isn't */
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_NUM_KEY_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , id , table ) {
2013-11-27 06:20:52 +08:00
phpdbg_breakbase_t * brake ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( table , brake ) {
2013-11-27 06:20:52 +08:00
if ( brake - > id = = id ) {
2014-10-29 00:20:21 +08:00
char * new_str = NULL ;
2013-11-27 06:20:52 +08:00
switch ( brake - > type ) {
case PHPDBG_BREAK_FILE : {
2018-06-29 05:19:16 +08:00
zend_string * filename = php_addcslashes_str ( ( ( phpdbg_breakfile_t * ) brake ) - > filename , strlen ( ( ( phpdbg_breakfile_t * ) brake ) - > filename ) , " \\ \" \n " , 3 ) ;
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
2016-11-13 18:59:13 +08:00
" %sbreak \" %s \" :%lu \n " , * str ,
2016-11-13 19:55:35 +08:00
ZSTR_VAL ( filename ) ,
2013-11-27 06:20:52 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > line ) ;
2016-11-13 19:55:35 +08:00
zend_string_release ( filename ) ;
2013-11-27 06:20:52 +08:00
} break ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_SYM : {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
" %sbreak %s \n " , * str ,
2013-11-27 06:20:52 +08:00
( ( phpdbg_breaksymbol_t * ) brake ) - > symbol ) ;
} break ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_METHOD : {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
" %sbreak %s::%s \n " , * str ,
2013-11-28 06:59:02 +08:00
( ( phpdbg_breakmethod_t * ) brake ) - > class_name ,
2013-11-27 06:20:52 +08:00
( ( phpdbg_breakmethod_t * ) brake ) - > func_name ) ;
} break ;
2013-11-28 06:59:02 +08:00
2013-12-07 22:35:35 +08:00
case PHPDBG_BREAK_METHOD_OPLINE : {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
2014-10-29 00:40:27 +08:00
" %sbreak %s::%s#%llu \n " , * str ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > class_name ,
( ( phpdbg_breakopline_t * ) brake ) - > func_name ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ) ;
} break ;
case PHPDBG_BREAK_FUNCTION_OPLINE : {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
2014-10-29 00:40:27 +08:00
" %sbreak %s#%llu \n " , * str ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > func_name ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ) ;
} break ;
case PHPDBG_BREAK_FILE_OPLINE : {
2018-06-29 05:19:16 +08:00
zend_string * filename = php_addcslashes_str ( ( ( phpdbg_breakopline_t * ) brake ) - > class_name , strlen ( ( ( phpdbg_breakopline_t * ) brake ) - > class_name ) , " \\ \" \n " , 3 ) ;
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
2016-11-13 19:55:35 +08:00
" %sbreak \" %s \" :#%llu \n " , * str ,
2016-11-14 01:30:23 +08:00
ZSTR_VAL ( filename ) ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ) ;
2016-11-13 19:55:35 +08:00
zend_string_release ( filename ) ;
2013-12-07 22:35:35 +08:00
} break ;
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_OPCODE : {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
" %sbreak %s \n " , * str ,
2013-11-27 06:20:52 +08:00
( ( phpdbg_breakop_t * ) brake ) - > name ) ;
} break ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_COND : {
2013-12-03 08:35:20 +08:00
phpdbg_breakcond_t * conditional = ( phpdbg_breakcond_t * ) brake ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:35:20 +08:00
if ( conditional - > paramed ) {
switch ( conditional - > param . type ) {
case STR_PARAM :
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
" %sbreak at %s if %s \n " , * str , conditional - > param . str , conditional - > code ) ;
2013-12-03 08:35:20 +08:00
break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:35:20 +08:00
case METHOD_PARAM :
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
" %sbreak at %s::%s if %s \n " , * str ,
2013-12-03 08:35:20 +08:00
conditional - > param . method . class , conditional - > param . method . name ,
conditional - > code ) ;
break ;
2013-12-07 22:31:10 +08:00
2016-11-13 19:55:35 +08:00
case FILE_PARAM : {
2018-06-29 05:19:16 +08:00
zend_string * filename = php_addcslashes_str ( conditional - > param . file . name , strlen ( conditional - > param . file . name ) , " \\ \" \n " , 3 ) ;
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str ,
2016-11-13 19:55:35 +08:00
" %sbreak at \" %s \" :%lu if %s \n " , * str ,
2016-11-14 01:30:23 +08:00
ZSTR_VAL ( filename ) , conditional - > param . file . line ,
2013-12-03 08:35:20 +08:00
conditional - > code ) ;
2016-11-13 19:55:35 +08:00
zend_string_release ( filename ) ;
} break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:35:20 +08:00
default : { /* do nothing */ } break ;
}
} else {
2014-10-29 00:20:21 +08:00
phpdbg_asprintf ( & new_str , " %sbreak if %s \n " , str , conditional - > code ) ;
2013-12-03 08:35:20 +08:00
}
2013-11-27 06:20:52 +08:00
} break ;
2015-08-23 18:58:32 +08:00
default : continue ;
2013-12-03 19:31:25 +08:00
}
2014-10-29 00:20:21 +08:00
if ( ( * str ) [ 0 ] ) {
efree ( * str ) ;
}
* str = new_str ;
2013-12-03 19:31:25 +08:00
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-03 19:31:25 +08:00
}
2014-10-29 00:20:21 +08:00
if ( ! ( * str ) [ 0 ] ) {
* str = NULL ;
}
2013-11-26 01:41:09 +08:00
} /* }}} */
2016-10-13 02:11:51 +08:00
PHPDBG_API void phpdbg_set_breakpoint_file ( const char * path , size_t path_len , long line_num ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2014-02-28 15:41:34 +08:00
php_stream_statbuf ssb ;
char realpath [ MAXPATHLEN ] ;
2014-10-27 03:43:49 +08:00
const char * original_path = path ;
2014-10-30 19:15:27 +08:00
zend_bool pending = 0 ;
2015-07-24 23:17:09 +08:00
zend_string * path_str ;
2014-09-21 10:17:19 +08:00
2015-07-24 23:17:09 +08:00
HashTable * broken , * file_breaks = & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] ;
2014-10-27 03:43:49 +08:00
phpdbg_breakfile_t new_break ;
2014-09-21 10:17:19 +08:00
2016-10-13 02:11:51 +08:00
if ( ! path_len ) {
if ( VCWD_REALPATH ( path , realpath ) ) {
path = realpath ;
}
2014-10-27 03:43:49 +08:00
}
path_len = strlen ( path ) ;
2015-05-31 13:35:01 +08:00
phpdbg_debug ( " file path: %s, resolved path: %s, was compiled: %d \n " , original_path , path , zend_hash_str_exists ( & PHPDBG_G ( file_sources ) , path , path_len ) ) ;
2014-10-28 19:38:07 +08:00
2014-10-27 07:34:56 +08:00
if ( ! zend_hash_str_exists ( & PHPDBG_G ( file_sources ) , path , path_len ) ) {
2014-10-27 03:43:49 +08:00
if ( php_stream_stat_path ( path , & ssb ) = = FAILURE ) {
if ( original_path [ 0 ] = = ' / ' ) {
phpdbg_error ( " breakpoint " , " type= \" nofile \" add= \" fail \" file= \" %s \" " , " Cannot stat %s, it does not exist " , original_path ) ;
return ;
2014-02-28 15:41:34 +08:00
}
2014-10-27 03:43:49 +08:00
file_breaks = & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] ;
path = original_path ;
2014-02-28 15:41:34 +08:00
path_len = strlen ( path ) ;
2014-10-27 03:43:49 +08:00
pending = 1 ;
} else if ( ! ( ssb . sb . st_mode & ( S_IFREG | S_IFLNK ) ) ) {
phpdbg_error ( " breakpoint " , " type= \" notregular \" add= \" fail \" file= \" %s \" " , " Cannot set breakpoint in %s, it is not a regular file " , path ) ;
return ;
2014-10-28 19:38:07 +08:00
} else {
phpdbg_debug ( " File exists, but not compiled \n " ) ;
2014-10-27 03:43:49 +08:00
}
}
2014-09-21 10:17:19 +08:00
2015-07-24 23:17:09 +08:00
path_str = zend_string_init ( path , path_len , 0 ) ;
if ( ! ( broken = zend_hash_find_ptr ( file_breaks , path_str ) ) ) {
2014-10-27 03:43:49 +08:00
HashTable breaks ;
zend_hash_init ( & breaks , 8 , NULL , phpdbg_file_breaks_dtor , 0 ) ;
2013-11-11 02:06:41 +08:00
2015-07-24 23:17:09 +08:00
broken = zend_hash_add_mem ( file_breaks , path_str , & breaks , sizeof ( HashTable ) ) ;
2014-10-27 03:43:49 +08:00
}
2013-11-11 03:15:32 +08:00
2014-10-27 03:43:49 +08:00
if ( ! zend_hash_index_exists ( broken , line_num ) ) {
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_FILE ) ;
new_break . filename = estrndup ( path , path_len ) ;
new_break . line = line_num ;
2013-11-12 06:06:36 +08:00
2014-10-27 07:34:56 +08:00
zend_hash_index_update_mem ( broken , line_num , & new_break , sizeof ( phpdbg_breakfile_t ) ) ;
2013-11-12 06:06:36 +08:00
2014-10-27 20:55:20 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , broken ) ;
if ( pending ) {
2015-07-24 23:17:09 +08:00
zend_string * file ;
2014-10-27 21:32:58 +08:00
ZEND_HASH_FOREACH_STR_KEY ( & PHPDBG_G ( file_sources ) , file ) {
2014-10-28 19:38:07 +08:00
HashTable * fileht ;
phpdbg_debug ( " Compare against loaded %s \n " , file ) ;
2015-06-30 18:59:27 +08:00
if ( ! ( pending = ( ( fileht = phpdbg_resolve_pending_file_break_ex ( ZSTR_VAL ( file ) , ZSTR_LEN ( file ) , path_str , broken ) ) = = NULL ) ) ) {
2015-07-19 05:35:59 +08:00
new_break = * ( phpdbg_breakfile_t * ) zend_hash_index_find_ptr ( fileht , line_num ) ;
2014-10-27 20:55:20 +08:00
break ;
}
2014-10-27 21:32:58 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2014-10-27 20:55:20 +08:00
}
2014-10-27 03:43:49 +08:00
if ( pending ) {
PHPDBG_G ( flags ) | = PHPDBG_HAS_PENDING_FILE_BP ;
2013-11-27 21:01:57 +08:00
2014-10-27 03:43:49 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" file= \" %s \" line= \" %ld \" pending= \" pending \" " , " Pending breakpoint #%d added at %s:%ld " , new_break . id , new_break . filename , new_break . line ) ;
} else {
PHPDBG_G ( flags ) | = PHPDBG_HAS_FILE_BP ;
2013-11-28 06:59:02 +08:00
2014-10-27 03:43:49 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" file= \" %s \" line= \" %ld \" " , " Breakpoint #%d added at %s:%ld " , new_break . id , new_break . filename , new_break . line ) ;
}
} else {
phpdbg_error ( " breakpoint " , " type= \" exists \" add= \" fail \" file= \" %s \" line= \" %ld \" " , " Breakpoint at %s:%ld exists " , path , line_num ) ;
}
2015-07-24 23:17:09 +08:00
zend_string_release ( path_str ) ;
2014-10-27 03:43:49 +08:00
} /* }}} */
2013-11-27 21:01:57 +08:00
2016-12-22 21:32:02 +08:00
PHPDBG_API HashTable * phpdbg_resolve_pending_file_break_ex ( const char * file , uint32_t filelen , zend_string * cur , HashTable * fileht ) /* { { { */
2014-10-27 03:43:49 +08:00
{
2015-06-30 18:59:27 +08:00
phpdbg_debug ( " file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d \n " , file , filelen , ZSTR_VAL ( cur ) , ZSTR_LEN ( cur ) , filelen > ZSTR_LEN ( cur ) ? file [ filelen - ZSTR_LEN ( cur ) - 1 ] : ' ? ' , filelen > ZSTR_LEN ( cur ) ? memcmp ( file + filelen - ZSTR_LEN ( cur ) , ZSTR_VAL ( cur ) , ZSTR_LEN ( cur ) ) : 0 ) ;
2014-10-28 19:38:07 +08:00
2015-07-21 05:25:50 +08:00
# ifdef _WIN32
# define WIN32_PATH_CHECK file[filelen - ZSTR_LEN(cur) - 1] == '\\'
# else
# define WIN32_PATH_CHECK 0
# endif
if ( ( ( ZSTR_LEN ( cur ) < filelen & & ( file [ filelen - ZSTR_LEN ( cur ) - 1 ] = = ' / ' | | WIN32_PATH_CHECK ) ) | | filelen = = ZSTR_LEN ( cur ) ) & & ! memcmp ( file + filelen - ZSTR_LEN ( cur ) , ZSTR_VAL ( cur ) , ZSTR_LEN ( cur ) ) ) {
2014-10-27 20:55:20 +08:00
phpdbg_breakfile_t * brake , new_brake ;
2014-10-29 00:40:27 +08:00
HashTable * master ;
2014-10-27 03:43:49 +08:00
2014-10-27 20:55:20 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_FILE_BP ;
2014-10-27 03:43:49 +08:00
2014-10-27 21:32:58 +08:00
if ( ! ( master = zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , file , filelen ) ) ) {
2014-10-28 19:38:07 +08:00
HashTable new_ht ;
zend_hash_init ( & new_ht , 8 , NULL , phpdbg_file_breaks_dtor , 0 ) ;
2014-10-29 00:40:27 +08:00
master = zend_hash_str_add_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , file , filelen , & new_ht , sizeof ( HashTable ) ) ;
2014-10-27 20:55:20 +08:00
}
2014-10-27 03:43:49 +08:00
2014-10-27 21:32:58 +08:00
ZEND_HASH_FOREACH_PTR ( fileht , brake ) {
2014-10-27 20:55:20 +08:00
new_brake = * brake ;
new_brake . filename = estrndup ( file , filelen ) ;
PHPDBG_BREAK_UNMAPPING ( brake - > id ) ;
2015-07-19 05:35:59 +08:00
if ( zend_hash_index_add_mem ( master , brake - > line , & new_brake , sizeof ( phpdbg_breakfile_t ) ) ) {
2014-10-27 20:55:20 +08:00
PHPDBG_BREAK_MAPPING ( brake - > id , master ) ;
2013-11-27 06:20:52 +08:00
}
2014-10-27 21:32:58 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-17 06:40:01 +08:00
2014-10-27 21:32:58 +08:00
zend_hash_del ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] , cur ) ;
2014-10-27 03:43:49 +08:00
2014-10-27 20:55:20 +08:00
if ( ! zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] ) ) {
PHPDBG_G ( flags ) & = ~ PHPDBG_HAS_PENDING_FILE_BP ;
2013-11-26 18:02:58 +08:00
}
2014-10-27 03:43:49 +08:00
2014-10-28 19:38:07 +08:00
phpdbg_debug ( " compiled file: %s, cur bp file: %s \n " , file , cur ) ;
return master ;
2014-10-27 20:55:20 +08:00
}
2013-11-17 06:40:01 +08:00
2014-10-27 20:55:20 +08:00
return NULL ;
} /* }}} */
2014-10-27 03:43:49 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_resolve_pending_file_break ( const char * file ) /* { { { */
2014-10-27 20:55:20 +08:00
{
HashTable * fileht ;
2016-12-22 21:32:02 +08:00
uint32_t filelen = strlen ( file ) ;
2014-10-27 21:32:58 +08:00
zend_string * cur ;
2014-10-27 03:43:49 +08:00
2014-10-28 19:38:07 +08:00
phpdbg_debug ( " was compiled: %s \n " , file ) ;
2014-10-27 21:32:58 +08:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] , cur , fileht ) {
2014-10-28 19:38:07 +08:00
phpdbg_debug ( " check bp: %s \n " , cur ) ;
2014-12-14 06:06:14 +08:00
phpdbg_resolve_pending_file_break_ex ( file , filelen , cur , fileht ) ;
2014-10-27 07:34:56 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-11 02:06:41 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_symbol ( const char * name , size_t name_len ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2015-07-20 07:17:27 +08:00
char * lcname ;
if ( * name = = ' \\ ' ) {
name + + ;
name_len - - ;
}
lcname = zend_str_tolower_dup ( name , name_len ) ;
2014-10-25 01:29:50 +08:00
if ( ! zend_hash_str_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , name , name_len ) ) {
2013-11-11 05:38:58 +08:00
phpdbg_breaksymbol_t new_break ;
2013-11-11 02:06:41 +08:00
2013-11-12 09:24:53 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_SYM_BP ;
2013-11-11 02:06:41 +08:00
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_SYM ) ;
2013-11-20 22:55:07 +08:00
new_break . symbol = estrndup ( name , name_len ) ;
2013-11-11 02:06:41 +08:00
2015-07-20 07:17:27 +08:00
zend_hash_str_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , lcname , name_len , & new_break , sizeof ( phpdbg_breaksymbol_t ) ) ;
2013-11-12 06:06:36 +08:00
2014-10-25 01:29:50 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" function= \" %s \" " , " Breakpoint #%d added at %s " , new_break . id , new_break . symbol ) ;
2013-11-27 21:01:57 +08:00
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] ) ;
2013-11-11 17:14:30 +08:00
} else {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" add= \" fail \" function= \" %s \" " , " Breakpoint exists at %s " , name ) ;
2013-11-11 02:06:41 +08:00
}
2015-07-20 07:17:27 +08:00
efree ( lcname ) ;
2013-11-11 02:06:41 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_method ( const char * class_name , const char * func_name ) /* { { { */
2013-11-12 08:27:48 +08:00
{
2013-11-26 18:02:58 +08:00
HashTable class_breaks , * class_table ;
2013-12-07 22:35:35 +08:00
size_t class_len = strlen ( class_name ) ;
size_t func_len = strlen ( func_name ) ;
2015-07-20 07:17:27 +08:00
char * func_lcname , * class_lcname ;
if ( * class_name = = ' \\ ' ) {
class_name + + ;
class_len - - ;
}
2013-11-20 22:55:07 +08:00
2015-07-20 07:17:27 +08:00
func_lcname = zend_str_tolower_dup ( func_name , func_len ) ;
class_lcname = zend_str_tolower_dup ( class_name , class_len ) ;
if ( ! ( class_table = zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , class_lcname , class_len ) ) ) {
2013-11-26 18:02:58 +08:00
zend_hash_init ( & class_breaks , 8 , NULL , phpdbg_class_breaks_dtor , 0 ) ;
2015-07-20 07:17:27 +08:00
class_table = zend_hash_str_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , class_lcname , class_len , & class_breaks , sizeof ( HashTable ) ) ;
2013-11-26 18:02:58 +08:00
}
2013-11-12 08:27:48 +08:00
2015-07-20 07:17:27 +08:00
if ( ! zend_hash_str_exists ( class_table , func_lcname , func_len ) ) {
2013-11-26 18:02:58 +08:00
phpdbg_breakmethod_t new_break ;
2013-11-12 09:41:14 +08:00
2013-11-26 18:02:58 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_METHOD_BP ;
2013-11-12 09:41:14 +08:00
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_METHOD ) ;
2013-11-26 18:02:58 +08:00
new_break . class_name = estrndup ( class_name , class_len ) ;
new_break . class_len = class_len ;
new_break . func_name = estrndup ( func_name , func_len ) ;
new_break . func_len = func_len ;
2013-11-12 09:41:14 +08:00
2015-07-20 07:17:27 +08:00
zend_hash_str_update_mem ( class_table , func_lcname , func_len , & new_break , sizeof ( phpdbg_breakmethod_t ) ) ;
2013-11-12 21:33:51 +08:00
2014-10-25 01:29:50 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" method= \" %s::%s \" " , " Breakpoint #%d added at %s::%s " , new_break . id , class_name , func_name ) ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , class_table ) ;
2013-11-26 18:02:58 +08:00
} else {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" add= \" fail \" method= \" %s::%s \" " , " Breakpoint exists at %s::%s " , class_name , func_name ) ;
2014-02-05 08:04:21 +08:00
}
2013-11-28 06:59:02 +08:00
2015-07-20 07:17:27 +08:00
efree ( func_lcname ) ;
efree ( class_lcname ) ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opline ( zend_ulong opline ) /* { { { */
2013-11-11 19:54:41 +08:00
{
2013-11-12 09:51:50 +08:00
if ( ! zend_hash_index_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , opline ) ) {
2013-11-11 19:54:41 +08:00
phpdbg_breakline_t new_break ;
2013-11-12 09:24:53 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_OPLINE_BP ;
2013-11-12 06:06:36 +08:00
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_OPLINE ) ;
2013-12-01 22:58:59 +08:00
new_break . name = NULL ;
new_break . opline = opline ;
2013-12-07 22:35:35 +08:00
new_break . base = NULL ;
2013-12-02 02:05:30 +08:00
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , opline , & new_break , sizeof ( phpdbg_breakline_t ) ) ;
2013-12-01 22:58:59 +08:00
2014-10-25 01:29:50 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" opline= \" %#lx \" " , " Breakpoint #%d added at %#lx " , new_break . id , new_break . opline ) ;
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
2013-11-11 19:54:41 +08:00
} else {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" add= \" fail \" opline= \" %#lx \" " , " Breakpoint exists at %#lx " , opline ) ;
2013-11-11 19:54:41 +08:00
}
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API int phpdbg_resolve_op_array_break ( phpdbg_breakopline_t * brake , zend_op_array * op_array ) /* { { { */
2013-12-08 02:18:44 +08:00
{
2013-11-29 04:36:45 +08:00
phpdbg_breakline_t opline_break ;
2014-02-19 08:13:03 +08:00
if ( op_array - > last < = brake - > opline_num ) {
2013-11-29 04:36:45 +08:00
if ( brake - > class_name = = NULL ) {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" add= \" fail \" maxoplinenum= \" %d \" function= \" %s \" usedoplinenum= \" %ld \" " , " There are only %d oplines in function %s (breaking at opline %ld impossible) " , op_array - > last , brake - > func_name , brake - > opline_num ) ;
2013-12-03 04:56:25 +08:00
} else if ( brake - > func_name = = NULL ) {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" add= \" fail \" maxoplinenum= \" %d \" file= \" %s \" usedoplinenum= \" %ld \" " , " There are only %d oplines in file %s (breaking at opline %ld impossible) " , op_array - > last , brake - > class_name , brake - > opline_num ) ;
2013-11-29 04:36:45 +08:00
} else {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" add= \" fail \" maxoplinenum= \" %d \" method= \" %s::%s \" usedoplinenum= \" %ld \" " , " There are only %d oplines in method %s::%s (breaking at opline %ld impossible) " , op_array - > last , brake - > class_name , brake - > func_name , brake - > opline_num ) ;
2013-11-29 04:36:45 +08:00
}
2013-11-29 05:03:59 +08:00
return FAILURE ;
2013-11-29 04:36:45 +08:00
}
2013-12-07 22:35:35 +08:00
opline_break . disabled = 0 ;
opline_break . hits = 0 ;
2013-11-29 04:36:45 +08:00
opline_break . id = brake - > id ;
2013-12-07 22:35:35 +08:00
opline_break . opline = brake - > opline = ( zend_ulong ) ( op_array - > opcodes + brake - > opline_num ) ;
2013-11-29 04:36:45 +08:00
opline_break . name = NULL ;
2013-12-07 22:35:35 +08:00
opline_break . base = brake ;
2013-12-03 04:56:25 +08:00
if ( op_array - > scope ) {
opline_break . type = PHPDBG_BREAK_METHOD_OPLINE ;
} else if ( op_array - > function_name ) {
opline_break . type = PHPDBG_BREAK_FUNCTION_OPLINE ;
} else {
opline_break . type = PHPDBG_BREAK_FILE_OPLINE ;
}
2013-11-29 04:36:45 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_OPLINE_BP ;
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , opline_break . opline , & opline_break , sizeof ( phpdbg_breakline_t ) ) ;
2013-11-29 05:03:59 +08:00
return SUCCESS ;
2013-12-08 02:18:44 +08:00
} /* }}} */
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_resolve_op_array_breaks ( zend_op_array * op_array ) /* { { { */
2013-12-08 02:18:44 +08:00
{
2013-11-29 04:36:45 +08:00
HashTable * func_table = & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ;
HashTable * oplines_table ;
phpdbg_breakopline_t * brake ;
2014-10-25 01:29:50 +08:00
if ( op_array - > scope ! = NULL & & ! ( func_table = zend_hash_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , op_array - > scope - > name ) ) ) {
2013-11-29 04:36:45 +08:00
return ;
}
2013-12-03 19:31:25 +08:00
if ( op_array - > function_name = = NULL ) {
2014-10-25 01:29:50 +08:00
if ( ! ( oplines_table = zend_hash_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , op_array - > filename ) ) ) {
2013-12-03 19:31:25 +08:00
return ;
}
2014-10-25 01:29:50 +08:00
} else if ( ! op_array - > function_name | | ! ( oplines_table = zend_hash_find_ptr ( func_table , op_array - > function_name ) ) ) {
2013-11-29 04:36:45 +08:00
return ;
}
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( oplines_table , brake ) {
2014-12-14 06:06:14 +08:00
if ( phpdbg_resolve_op_array_break ( brake , op_array ) = = SUCCESS ) {
2013-11-29 18:38:28 +08:00
phpdbg_breakline_t * opline_break ;
zend_hash_internal_pointer_end ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
2014-10-25 01:29:50 +08:00
opline_break = zend_hash_get_current_data_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
2013-11-29 18:38:28 +08:00
2014-10-05 18:33:24 +08:00
phpdbg_notice ( " breakpoint " , " add= \" success \" id= \" %d \" symbol= \" %s \" num= \" %ld \" opline= \" %#lx \" " , " Breakpoint #%d resolved at %s%s%s#%ld (opline %#lx) " ,
2015-07-27 21:02:01 +08:00
opline_break - > id ,
2014-10-25 01:29:50 +08:00
brake - > class_name ? brake - > class_name : " " ,
brake - > class_name & & brake - > func_name ? " :: " : " " ,
brake - > func_name ? brake - > func_name : " " ,
2013-12-07 22:35:35 +08:00
brake - > opline_num ,
2015-07-27 21:02:01 +08:00
opline_break - > opline ) ;
2013-11-29 18:38:28 +08:00
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-08 02:18:44 +08:00
} /* }}} */
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API int phpdbg_resolve_opline_break ( phpdbg_breakopline_t * new_break ) /* { { { */
2013-12-08 02:18:44 +08:00
{
2013-11-29 04:36:45 +08:00
HashTable * func_table = EG ( function_table ) ;
zend_function * func ;
2013-12-03 04:56:25 +08:00
if ( new_break - > func_name = = NULL ) {
2013-12-03 23:10:57 +08:00
if ( EG ( current_execute_data ) = = NULL ) {
if ( PHPDBG_G ( ops ) ! = NULL & & ! memcmp ( PHPDBG_G ( ops ) - > filename , new_break - > class_name , new_break - > class_len ) ) {
2014-12-14 06:06:14 +08:00
if ( phpdbg_resolve_op_array_break ( new_break , PHPDBG_G ( ops ) ) = = SUCCESS ) {
2013-12-03 23:10:57 +08:00
return SUCCESS ;
} else {
return 2 ;
}
}
return FAILURE ;
} else {
zend_execute_data * execute_data = EG ( current_execute_data ) ;
do {
2016-02-18 03:26:47 +08:00
if ( ZEND_USER_CODE ( execute_data - > func - > common . type ) ) {
zend_op_array * op_array = & execute_data - > func - > op_array ;
if ( op_array - > function_name = = NULL & & op_array - > scope = = NULL & & new_break - > class_len = = ZSTR_LEN ( op_array - > filename ) & & ! memcmp ( ZSTR_VAL ( op_array - > filename ) , new_break - > class_name , new_break - > class_len ) ) {
if ( phpdbg_resolve_op_array_break ( new_break , op_array ) = = SUCCESS ) {
return SUCCESS ;
} else {
return 2 ;
}
2013-12-03 23:10:57 +08:00
}
}
} while ( ( execute_data = execute_data - > prev_execute_data ) ! = NULL ) ;
return FAILURE ;
}
2013-12-03 04:56:25 +08:00
}
2013-11-29 04:36:45 +08:00
if ( new_break - > class_name ! = NULL ) {
2014-10-25 01:29:50 +08:00
zend_class_entry * ce ;
if ( ! ( ce = zend_hash_str_find_ptr ( EG ( class_table ) , zend_str_tolower_dup ( new_break - > class_name , new_break - > class_len ) , new_break - > class_len ) ) ) {
2013-11-29 04:36:45 +08:00
return FAILURE ;
}
2014-10-25 01:29:50 +08:00
func_table = & ce - > function_table ;
2013-11-29 04:36:45 +08:00
}
2014-10-25 01:29:50 +08:00
if ( ! ( func = zend_hash_str_find_ptr ( func_table , zend_str_tolower_dup ( new_break - > func_name , new_break - > func_len ) , new_break - > func_len ) ) ) {
2013-12-03 04:56:25 +08:00
if ( new_break - > class_name ! = NULL & & new_break - > func_name ! = NULL ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" nomethod \" method= \" %s::%s \" " , " Method %s doesn't exist in class %s " , new_break - > func_name , new_break - > class_name ) ;
2013-12-07 22:35:35 +08:00
return 2 ;
2013-11-29 04:36:45 +08:00
}
return FAILURE ;
}
if ( func - > type ! = ZEND_USER_FUNCTION ) {
if ( new_break - > class_name = = NULL ) {
2015-05-14 02:05:59 +08:00
phpdbg_error ( " breakpoint " , " type= \" internalfunction \" function= \" %s \" " , " %s is not a user defined function, no oplines exist " , new_break - > func_name ) ;
2013-11-29 04:36:45 +08:00
} else {
2015-05-14 02:05:59 +08:00
phpdbg_error ( " breakpoint " , " type= \" internalfunction \" method= \" %s::%s \" " , " %s::%s is not a user defined method, no oplines exist " , new_break - > class_name , new_break - > func_name ) ;
2013-11-29 04:36:45 +08:00
}
2013-11-29 05:03:59 +08:00
return 2 ;
2013-11-29 04:36:45 +08:00
}
2014-12-14 06:06:14 +08:00
if ( phpdbg_resolve_op_array_break ( new_break , & func - > op_array ) = = FAILURE ) {
2013-11-29 05:03:59 +08:00
return 2 ;
}
2013-11-29 04:36:45 +08:00
return SUCCESS ;
2013-12-08 02:18:44 +08:00
} /* }}} */
2013-11-29 04:36:45 +08:00
2015-07-20 07:17:27 +08:00
/* TODO ... method/function oplines need to be normalized (leading backslash, lowercase) and file oplines need to be resolved properly */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_method_opline ( const char * class , const char * method , zend_ulong opline ) /* { { { */
2013-11-29 04:36:45 +08:00
{
phpdbg_breakopline_t new_break ;
HashTable class_breaks , * class_table ;
HashTable method_breaks , * method_table ;
2013-12-07 22:35:35 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_METHOD_OPLINE ) ;
2013-11-29 04:36:45 +08:00
new_break . func_len = strlen ( method ) ;
new_break . func_name = estrndup ( method , new_break . func_len ) ;
new_break . class_len = strlen ( class ) ;
new_break . class_name = estrndup ( class , new_break . class_len ) ;
2013-12-07 22:35:35 +08:00
new_break . opline_num = opline ;
new_break . opline = 0 ;
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
switch ( phpdbg_resolve_opline_break ( & new_break ) ) {
2013-11-29 05:03:59 +08:00
case FAILURE :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " pending= \" pending \" id= \" %d \" method= \" %::%s \" num= \" %ld \" " , " Pending breakpoint #%d at %s::%s#%ld " , new_break . id , new_break . class_name , new_break . func_name , opline ) ;
2013-11-29 05:03:59 +08:00
break ;
case SUCCESS :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" method= \" %::%s \" num= \" %ld \" " , " Breakpoint #%d added at %s::%s#%ld " , new_break . id , new_break . class_name , new_break . func_name , opline ) ;
2013-11-29 05:03:59 +08:00
break ;
case 2 :
return ;
2013-11-29 04:36:45 +08:00
}
2014-10-25 01:29:50 +08:00
if ( ! ( class_table = zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , new_break . class_name , new_break . class_len ) ) ) {
2013-11-29 04:36:45 +08:00
zend_hash_init ( & class_breaks , 8 , NULL , phpdbg_opline_class_breaks_dtor , 0 ) ;
2014-10-25 01:29:50 +08:00
class_table = zend_hash_str_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , new_break . class_name , new_break . class_len , & class_breaks , sizeof ( HashTable ) ) ;
2013-11-29 04:36:45 +08:00
}
2014-10-25 01:29:50 +08:00
if ( ! ( method_table = zend_hash_str_find_ptr ( class_table , new_break . func_name , new_break . func_len ) ) ) {
2013-11-29 04:36:45 +08:00
zend_hash_init ( & method_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
2014-10-25 01:29:50 +08:00
method_table = zend_hash_str_update_mem ( class_table , new_break . func_name , new_break . func_len , & method_breaks , sizeof ( HashTable ) ) ;
2013-11-29 04:36:45 +08:00
}
if ( zend_hash_index_exists ( method_table , opline ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" method= \" %s \" num= \" %ld \" " , " Breakpoint already exists for %s::%s#%ld " , new_break . class_name , new_break . func_name , opline ) ;
2013-12-09 18:15:16 +08:00
efree ( ( char * ) new_break . func_name ) ;
efree ( ( char * ) new_break . class_name ) ;
2013-11-29 04:36:45 +08:00
PHPDBG_G ( bp_count ) - - ;
return ;
}
2013-12-01 22:58:59 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_METHOD_OPLINE_BP ;
2013-12-08 03:28:23 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , method_table ) ;
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( method_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) ) ;
2013-11-29 04:36:45 +08:00
}
2015-04-21 21:53:12 +08:00
/* }}} */
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_function_opline ( const char * function , zend_ulong opline ) /* { { { */
2013-11-29 04:36:45 +08:00
{
phpdbg_breakopline_t new_break ;
HashTable func_breaks , * func_table ;
2013-12-07 22:35:35 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_FUNCTION_OPLINE ) ;
2013-11-29 04:36:45 +08:00
new_break . func_len = strlen ( function ) ;
new_break . func_name = estrndup ( function , new_break . func_len ) ;
2013-12-01 22:58:59 +08:00
new_break . class_len = 0 ;
new_break . class_name = NULL ;
2013-12-07 22:35:35 +08:00
new_break . opline_num = opline ;
new_break . opline = 0 ;
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
switch ( phpdbg_resolve_opline_break ( & new_break ) ) {
2013-11-29 05:03:59 +08:00
case FAILURE :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " pending= \" pending \" id= \" %d \" function= \" %s \" num= \" %ld \" " , " Pending breakpoint #%d at %s#%ld " , new_break . id , new_break . func_name , opline ) ;
2013-11-29 05:03:59 +08:00
break ;
case SUCCESS :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" function= \" %s \" num= \" %ld \" " , " Breakpoint #%d added at %s#%ld " , new_break . id , new_break . func_name , opline ) ;
2013-11-29 05:03:59 +08:00
break ;
case 2 :
return ;
2013-11-29 04:36:45 +08:00
}
2014-10-25 01:29:50 +08:00
if ( ! ( func_table = zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , new_break . func_name , new_break . func_len ) ) ) {
2013-11-29 04:36:45 +08:00
zend_hash_init ( & func_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
2014-10-25 01:29:50 +08:00
func_table = zend_hash_str_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , new_break . func_name , new_break . func_len , & func_breaks , sizeof ( HashTable ) ) ;
2013-11-29 04:36:45 +08:00
}
if ( zend_hash_index_exists ( func_table , opline ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" function= \" %s \" num= \" %ld \" " , " Breakpoint already exists for %s#%ld " , new_break . func_name , opline ) ;
2013-12-09 18:15:16 +08:00
efree ( ( char * ) new_break . func_name ) ;
2013-11-29 04:36:45 +08:00
PHPDBG_G ( bp_count ) - - ;
return ;
}
2013-12-08 03:28:23 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , func_table ) ;
2013-12-01 22:58:59 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_FUNCTION_OPLINE_BP ;
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( func_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) ) ;
2013-11-29 04:36:45 +08:00
}
2015-04-21 21:53:12 +08:00
/* }}} */
2013-11-29 04:36:45 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_file_opline ( const char * file , zend_ulong opline ) /* { { { */
2013-12-03 04:56:25 +08:00
{
phpdbg_breakopline_t new_break ;
HashTable file_breaks , * file_table ;
2013-12-07 22:35:35 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_FILE_OPLINE ) ;
2013-12-03 04:56:25 +08:00
new_break . func_len = 0 ;
new_break . func_name = NULL ;
new_break . class_len = strlen ( file ) ;
new_break . class_name = estrndup ( file , new_break . class_len ) ;
2013-12-07 22:35:35 +08:00
new_break . opline_num = opline ;
new_break . opline = 0 ;
2013-12-03 04:56:25 +08:00
2014-12-14 06:06:14 +08:00
switch ( phpdbg_resolve_opline_break ( & new_break ) ) {
2013-12-03 04:56:25 +08:00
case FAILURE :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " pending= \" pending \" id= \" %d \" file= \" %s \" num= \" %ld \" " , " Pending breakpoint #%d at %s:%ld " , new_break . id , new_break . class_name , opline ) ;
2013-12-03 04:56:25 +08:00
break ;
case SUCCESS :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" file= \" %s \" num= \" %ld \" " , " Breakpoint #%d added at %s:%ld " , new_break . id , new_break . class_name , opline ) ;
2013-12-03 04:56:25 +08:00
break ;
case 2 :
return ;
}
2014-10-25 01:29:50 +08:00
if ( ! ( file_table = zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , new_break . class_name , new_break . class_len ) ) ) {
2013-12-03 04:56:25 +08:00
zend_hash_init ( & file_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
2014-10-25 01:29:50 +08:00
file_table = zend_hash_str_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , new_break . class_name , new_break . class_len , & file_breaks , sizeof ( HashTable ) ) ;
2013-12-03 04:56:25 +08:00
}
if ( zend_hash_index_exists ( file_table , opline ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" file= \" %s \" num= \" %d \" " , " Breakpoint already exists for %s:%ld " , new_break . class_name , opline ) ;
2013-12-09 18:15:16 +08:00
efree ( ( char * ) new_break . class_name ) ;
2013-12-03 04:56:25 +08:00
PHPDBG_G ( bp_count ) - - ;
return ;
}
2013-12-08 03:28:23 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , file_table ) ;
2013-12-03 23:10:57 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_FILE_OPLINE_BP ;
2013-12-03 04:56:25 +08:00
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( file_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) ) ;
2013-12-03 04:56:25 +08:00
}
2015-04-21 21:53:12 +08:00
/* }}} */
2013-12-03 04:56:25 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opcode ( const char * name , size_t name_len ) /* { { { */
2013-11-24 07:14:16 +08:00
{
phpdbg_breakop_t new_break ;
2013-11-24 19:43:05 +08:00
zend_ulong hash = zend_hash_func ( name , name_len ) ;
2013-11-24 07:14:16 +08:00
if ( zend_hash_index_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , hash ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" opcode= \" %s \" " , " Breakpoint exists for %s " , name ) ;
2013-11-24 07:14:16 +08:00
return ;
}
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_OPCODE ) ;
2013-11-24 20:14:53 +08:00
new_break . hash = hash ;
2013-11-24 19:43:05 +08:00
new_break . name = estrndup ( name , name_len ) ;
2013-11-24 07:14:16 +08:00
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , hash , & new_break , sizeof ( phpdbg_breakop_t ) ) ;
2013-11-24 07:14:16 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_OPCODE_BP ;
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opcode= \" %s \" " , " Breakpoint #%d added at %s " , new_break . id , name ) ;
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] ) ;
2013-11-24 07:14:16 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opline_ex ( phpdbg_opline_ptr_t opline ) /* { { { */
2013-11-11 22:33:53 +08:00
{
2013-11-12 09:51:50 +08:00
if ( ! zend_hash_index_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( zend_ulong ) opline ) ) {
2013-11-11 22:33:53 +08:00
phpdbg_breakline_t new_break ;
2013-11-12 09:24:53 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_OPLINE_BP ;
2013-11-12 06:06:36 +08:00
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_OPLINE ) ;
2013-11-11 22:59:51 +08:00
new_break . opline = ( zend_ulong ) opline ;
2015-08-23 18:58:32 +08:00
new_break . base = NULL ;
2013-11-12 06:06:36 +08:00
2014-10-25 01:29:50 +08:00
zend_hash_index_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( zend_ulong ) opline , & new_break , sizeof ( phpdbg_breakline_t ) ) ;
2013-11-12 06:06:36 +08:00
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opline= \" %#lx \" " , " Breakpoint #%d added at %#lx " , new_break . id , new_break . opline ) ;
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
2014-09-21 10:17:19 +08:00
} else {
phpdbg_error ( " breakpoint " , " type= \" exists \" opline= \" %#lx \" " , " Breakpoint exists for opline %#lx " , ( zend_ulong ) opline ) ;
2013-11-11 22:33:53 +08:00
}
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline void phpdbg_create_conditional_break ( phpdbg_breakcond_t * brake , const phpdbg_param_t * param , const char * expr , size_t expr_len , zend_ulong hash ) /* { { { */
2013-11-13 22:22:01 +08:00
{
2013-12-03 08:15:33 +08:00
phpdbg_breakcond_t new_break ;
2014-08-26 01:28:33 +08:00
uint32_t cops = CG ( compiler_options ) ;
2013-12-03 08:15:33 +08:00
zval pv ;
2013-11-14 07:36:02 +08:00
2013-12-03 08:15:33 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_COND ) ;
new_break . hash = hash ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( param ) {
new_break . paramed = 1 ;
phpdbg_copy_param (
2014-12-14 06:06:14 +08:00
param , & new_break . param ) ;
2013-12-03 08:15:33 +08:00
} else {
new_break . paramed = 0 ;
}
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
cops = CG ( compiler_options ) ;
2013-11-14 07:36:02 +08:00
2013-12-03 08:15:33 +08:00
CG ( compiler_options ) = ZEND_COMPILE_DEFAULT_FOR_EVAL ;
2013-11-14 07:36:02 +08:00
2013-12-03 08:15:33 +08:00
new_break . code = estrndup ( expr , expr_len ) ;
new_break . code_len = expr_len ;
2013-12-07 22:31:10 +08:00
2014-10-25 01:29:50 +08:00
Z_STR ( pv ) = zend_string_alloc ( expr_len + sizeof ( " return ; " ) - 1 , 0 ) ;
2013-12-03 08:15:33 +08:00
memcpy ( Z_STRVAL ( pv ) , " return " , sizeof ( " return " ) - 1 ) ;
memcpy ( Z_STRVAL ( pv ) + sizeof ( " return " ) - 1 , expr , expr_len ) ;
2014-08-26 01:24:55 +08:00
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) - 1 ] = ' ; ' ;
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) ] = ' \0 ' ;
2014-10-25 01:29:50 +08:00
Z_TYPE_INFO ( pv ) = IS_STRING ;
2013-11-15 19:27:05 +08:00
2014-12-14 06:06:14 +08:00
new_break . ops = zend_compile_string ( & pv , " Conditional Breakpoint Code " ) ;
2013-11-15 19:27:05 +08:00
2018-07-05 00:22:24 +08:00
zval_ptr_dtor_str ( & pv ) ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( new_break . ops ) {
2014-10-25 01:29:50 +08:00
brake = zend_hash_index_update_mem ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , hash , & new_break , sizeof ( phpdbg_breakcond_t ) ) ;
2013-11-15 19:27:05 +08:00
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" expression= \" %s \" ptr= \" %p \" " , " Conditional breakpoint #%d added %s/%p " , brake - > id , brake - > code , brake - > ops ) ;
2013-11-15 19:27:05 +08:00
2013-12-03 08:15:33 +08:00
PHPDBG_G ( flags ) | = PHPDBG_HAS_COND_BP ;
PHPDBG_BREAK_MAPPING ( new_break . id , & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] ) ;
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " compile " , " expression= \" %s \" " , " Failed to compile code for expression %s " , expr ) ;
2013-12-03 08:15:33 +08:00
efree ( ( char * ) new_break . code ) ;
PHPDBG_G ( bp_count ) - - ;
}
2014-10-25 01:29:50 +08:00
2013-12-03 08:15:33 +08:00
CG ( compiler_options ) = cops ;
} /* }}} */
2013-11-15 19:27:05 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_expression ( const char * expr , size_t expr_len ) /* { { { */
2013-12-03 08:15:33 +08:00
{
zend_ulong expr_hash = zend_inline_hash_func ( expr , expr_len ) ;
phpdbg_breakcond_t new_break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( ! zend_hash_index_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , expr_hash ) ) {
phpdbg_create_conditional_break (
2014-12-14 06:06:14 +08:00
& new_break , NULL , expr , expr_len , expr_hash ) ;
2013-12-03 08:15:33 +08:00
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" expression= \" %s \" " , " Conditional break %s exists " , expr ) ;
2013-12-03 08:15:33 +08:00
}
} /* }}} */
2013-11-15 19:27:05 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_set_breakpoint_at ( const phpdbg_param_t * param ) /* { { { */
2013-12-03 08:15:33 +08:00
{
2014-02-21 23:00:55 +08:00
phpdbg_breakcond_t new_break ;
phpdbg_param_t * condition ;
zend_ulong hash = 0L ;
2014-09-21 10:17:19 +08:00
2014-02-21 23:00:55 +08:00
if ( param - > next ) {
condition = param - > next ;
hash = zend_inline_hash_func ( condition - > str , condition - > len ) ;
2014-09-21 10:17:19 +08:00
2014-02-21 23:00:55 +08:00
if ( ! zend_hash_index_exists ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , hash ) ) {
2014-12-14 06:06:14 +08:00
phpdbg_create_conditional_break ( & new_break , param , condition - > str , condition - > len , hash ) ;
2013-11-15 19:27:05 +08:00
} else {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " type= \" exists \" arg= \" %s \" " , " Conditional break %s exists at the specified location " , condition - > str ) ;
}
2013-11-26 18:02:58 +08:00
}
2014-09-21 10:17:19 +08:00
2013-11-13 22:22:01 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_file ( zend_op_array * op_array ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2013-11-27 06:20:52 +08:00
HashTable * breaks ;
2013-11-27 21:01:57 +08:00
phpdbg_breakbase_t * brake ;
2014-10-28 19:38:07 +08:00
#if 0
2016-10-13 02:11:51 +08:00
phpdbg_debug ( " Op at: %.*s %d \n " , ZSTR_LEN ( op_array - > filename ) , ZSTR_VAL ( op_array - > filename ) , ( * EG ( opline_ptr ) ) - > lineno ) ;
2014-10-28 19:38:07 +08:00
# endif
2013-11-11 02:06:41 +08:00
2016-10-13 02:11:51 +08:00
/* NOTE: realpath resolution should have happened at compile time - no reason to do it here again */
if ( ! ( breaks = zend_hash_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , op_array - > filename ) ) ) {
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-11 03:15:32 +08:00
}
2013-11-11 02:06:41 +08:00
2014-10-25 01:29:50 +08:00
if ( EG ( current_execute_data ) & & ( brake = zend_hash_index_find_ptr ( breaks , EG ( current_execute_data ) - > opline - > lineno ) ) ) {
2013-11-27 21:01:57 +08:00
return brake ;
2013-11-11 02:06:41 +08:00
}
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-11 02:06:41 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_symbol ( zend_function * fbc ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2013-11-12 08:40:40 +08:00
zend_op_array * ops ;
2013-11-11 02:06:41 +08:00
if ( fbc - > type ! = ZEND_USER_FUNCTION ) {
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-11 02:06:41 +08:00
}
2013-11-12 09:41:14 +08:00
2014-10-25 01:29:50 +08:00
ops = ( zend_op_array * ) fbc ;
2013-11-12 09:41:14 +08:00
2013-11-12 08:40:40 +08:00
if ( ops - > scope ) {
2013-11-26 18:02:58 +08:00
/* find method breaks here */
2014-12-14 06:06:14 +08:00
return phpdbg_find_breakpoint_method ( ops ) ;
2013-11-12 08:40:40 +08:00
}
2013-11-11 02:06:41 +08:00
2014-10-25 01:29:50 +08:00
if ( ops - > function_name ) {
2015-07-20 07:17:27 +08:00
phpdbg_breakbase_t * brake ;
zend_string * fname = zend_string_tolower ( ops - > function_name ) ;
brake = zend_hash_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , fname ) ;
zend_string_release ( fname ) ;
return brake ;
2014-10-25 01:29:50 +08:00
} else {
2015-07-20 07:17:27 +08:00
return zend_hash_str_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , ZEND_STRL ( " main " ) ) ;
2013-11-11 02:06:41 +08:00
}
2013-11-11 05:57:43 +08:00
} /* }}} */
2013-11-11 19:54:41 +08:00
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_method ( zend_op_array * ops ) /* { { { */
2013-11-12 08:27:48 +08:00
{
HashTable * class_table ;
2014-10-25 01:29:50 +08:00
phpdbg_breakbase_t * brake = NULL ;
2015-07-20 07:17:27 +08:00
zend_string * class_lcname = zend_string_tolower ( ops - > scope - > name ) ;
2013-11-12 08:27:48 +08:00
2015-07-20 07:17:27 +08:00
if ( ( class_table = zend_hash_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , class_lcname ) ) ) {
zend_string * lcname = zend_string_tolower ( ops - > function_name ) ;
2014-10-25 01:29:50 +08:00
2015-07-20 07:17:27 +08:00
brake = zend_hash_find_ptr ( class_table , lcname ) ;
2013-11-28 06:59:02 +08:00
2015-07-20 07:17:27 +08:00
zend_string_release ( lcname ) ;
2013-11-12 08:27:48 +08:00
}
2015-07-20 07:17:27 +08:00
zend_string_release ( class_lcname ) ;
2014-10-25 01:29:50 +08:00
return brake ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opline ( phpdbg_opline_ptr_t opline ) /* { { { */
2013-11-11 19:54:41 +08:00
{
2013-12-07 22:35:35 +08:00
phpdbg_breakline_t * brake ;
2013-11-11 19:54:41 +08:00
2014-10-25 01:29:50 +08:00
if ( ( brake = zend_hash_index_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( zend_ulong ) opline ) ) & & brake - > base ) {
return ( phpdbg_breakbase_t * ) brake - > base ;
2013-11-11 19:54:41 +08:00
}
2013-11-12 06:06:36 +08:00
2014-10-25 01:29:50 +08:00
return ( phpdbg_breakbase_t * ) brake ;
2013-11-11 19:54:41 +08:00
} /* }}} */
2013-11-11 22:33:53 +08:00
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opcode ( zend_uchar opcode ) /* { { { */
2013-11-24 07:14:16 +08:00
{
2015-07-19 05:55:59 +08:00
const char * opname = zend_get_opcode_name ( opcode ) ;
2013-11-24 07:14:16 +08:00
2015-07-19 05:55:59 +08:00
if ( ! opname ) {
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-24 07:14:16 +08:00
}
2014-10-25 01:29:50 +08:00
return zend_hash_index_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , zend_hash_func ( opname , strlen ( opname ) ) ) ;
2013-11-24 07:14:16 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline zend_bool phpdbg_find_breakpoint_param ( phpdbg_param_t * param , zend_execute_data * execute_data ) /* { { { */
2013-12-03 08:15:33 +08:00
{
2014-10-25 01:29:50 +08:00
zend_function * function = execute_data - > func ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
switch ( param - > type ) {
2013-12-09 20:25:00 +08:00
case NUMERIC_FUNCTION_PARAM :
2013-12-03 08:15:33 +08:00
case STR_PARAM : {
/* function breakpoint */
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( function - > type ! = ZEND_USER_FUNCTION ) {
return 0 ;
}
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
{
const char * str = NULL ;
size_t len = 0L ;
2013-12-09 20:25:00 +08:00
zend_op_array * ops = ( zend_op_array * ) function ;
2015-06-30 18:59:27 +08:00
str = ops - > function_name ? ZSTR_VAL ( ops - > function_name ) : " main " ;
len = ops - > function_name ? ZSTR_LEN ( ops - > function_name ) : strlen ( str ) ;
2013-12-07 22:31:10 +08:00
2013-12-09 20:25:00 +08:00
if ( len = = param - > len & & memcmp ( param - > str , str , len ) = = SUCCESS ) {
return param - > type = = STR_PARAM | | execute_data - > opline - ops - > opcodes = = param - > num ;
2013-12-03 08:15:33 +08:00
}
}
} break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
case FILE_PARAM : {
2014-12-14 06:06:14 +08:00
if ( param - > file . line = = zend_get_executed_lineno ( ) ) {
const char * str = zend_get_executed_filename ( ) ;
2013-12-03 08:15:33 +08:00
size_t lengths [ 2 ] = { strlen ( param - > file . name ) , strlen ( str ) } ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( lengths [ 0 ] = = lengths [ 1 ] ) {
return ( memcmp (
param - > file . name , str , lengths [ 0 ] ) = = SUCCESS ) ;
}
}
} break ;
2013-12-07 22:31:10 +08:00
2013-12-09 20:25:00 +08:00
case NUMERIC_METHOD_PARAM :
2013-12-03 08:15:33 +08:00
case METHOD_PARAM : {
if ( function - > type ! = ZEND_USER_FUNCTION ) {
return 0 ;
}
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
{
zend_op_array * ops = ( zend_op_array * ) function ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( ops - > scope ) {
2015-06-30 18:59:27 +08:00
size_t lengths [ 2 ] = { strlen ( param - > method . class ) , ZSTR_LEN ( ops - > scope - > name ) } ;
2013-12-09 20:25:00 +08:00
if ( lengths [ 0 ] = = lengths [ 1 ] & & memcmp ( param - > method . class , ops - > scope - > name , lengths [ 0 ] ) = = SUCCESS ) {
lengths [ 0 ] = strlen ( param - > method . name ) ;
2015-06-30 18:59:27 +08:00
lengths [ 1 ] = ZSTR_LEN ( ops - > function_name ) ;
2013-12-09 20:25:00 +08:00
if ( lengths [ 0 ] = = lengths [ 1 ] & & memcmp ( param - > method . name , ops - > function_name , lengths [ 0 ] ) = = SUCCESS ) {
return param - > type = = METHOD_PARAM | | ( execute_data - > opline - ops - > opcodes ) = = param - > num ;
2013-12-03 08:15:33 +08:00
}
}
}
}
} break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
case ADDR_PARAM : {
2013-12-07 22:35:35 +08:00
return ( ( zend_ulong ) ( phpdbg_opline_ptr_t ) execute_data - > opline = = param - > addr ) ;
2013-12-03 08:15:33 +08:00
} break ;
2013-12-08 02:18:44 +08:00
2013-12-07 22:35:35 +08:00
default : {
/* do nothing */
} break ;
2013-11-24 07:14:16 +08:00
}
2013-12-03 08:15:33 +08:00
return 0 ;
2013-11-24 07:14:16 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_conditional_breakpoint ( zend_execute_data * execute_data ) /* { { { */
2013-11-13 22:22:01 +08:00
{
phpdbg_breakcond_t * bp ;
2013-11-26 18:02:58 +08:00
int breakpoint = FAILURE ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , bp ) {
zval retval ;
const zend_op * orig_opline = EG ( current_execute_data ) - > opline ;
zend_function * orig_func = EG ( current_execute_data ) - > func ;
zval * orig_retval = EG ( current_execute_data ) - > return_value ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( ( ( phpdbg_breakbase_t * ) bp ) - > disabled ) {
continue ;
}
2013-12-07 22:31:10 +08:00
2013-12-03 08:15:33 +08:00
if ( bp - > paramed ) {
2014-12-14 06:06:14 +08:00
if ( ! phpdbg_find_breakpoint_param ( & bp - > param , execute_data ) ) {
2013-12-03 08:15:33 +08:00
continue ;
}
}
2013-11-26 18:02:58 +08:00
EG ( no_extensions ) = 1 ;
2014-12-14 06:06:14 +08:00
zend_rebuild_symbol_table ( ) ;
2013-11-26 18:02:58 +08:00
zend_try {
PHPDBG_G ( flags ) | = PHPDBG_IN_COND_BP ;
2014-12-14 06:06:14 +08:00
zend_execute ( bp - > ops , & retval ) ;
if ( zend_is_true ( & retval ) ) {
2013-11-26 18:02:58 +08:00
breakpoint = SUCCESS ;
}
} zend_end_try ( ) ;
2014-10-25 01:29:50 +08:00
EG ( no_extensions ) = 1 ;
EG ( current_execute_data ) - > opline = orig_opline ;
EG ( current_execute_data ) - > func = orig_func ;
EG ( current_execute_data ) - > return_value = orig_retval ;
2013-11-26 18:02:58 +08:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_COND_BP ;
if ( breakpoint = = SUCCESS ) {
break ;
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-14 07:36:02 +08:00
2014-10-25 01:29:50 +08:00
return ( breakpoint = = SUCCESS ) ? ( ( phpdbg_breakbase_t * ) bp ) : NULL ;
2013-11-13 22:22:01 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakpoint ( zend_execute_data * execute_data ) /* { { { */
2013-11-24 07:46:24 +08:00
{
2013-11-27 21:01:57 +08:00
phpdbg_breakbase_t * base = NULL ;
2013-11-28 06:59:02 +08:00
2013-11-26 05:39:17 +08:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IS_BP_ENABLED ) ) {
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-26 05:39:17 +08:00
}
2013-11-24 19:45:05 +08:00
/* conditions cannot be executed by eval()'d code */
2013-11-28 06:59:02 +08:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IN_EVAL ) & &
( PHPDBG_G ( flags ) & PHPDBG_HAS_COND_BP ) & &
2014-12-14 06:06:14 +08:00
( base = phpdbg_find_conditional_breakpoint ( execute_data ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 19:45:05 +08:00
}
2014-12-14 06:06:14 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FILE_BP ) & & ( base = phpdbg_find_breakpoint_file ( & execute_data - > func - > op_array ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
if ( PHPDBG_G ( flags ) & ( PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_SYM_BP ) ) {
2015-07-20 02:32:46 +08:00
zend_op_array * op_array = & execute_data - > func - > op_array ;
/* check we are at the beginning of the stack, but after argument RECV */
if ( execute_data - > opline = = op_array - > opcodes + op_array - > num_args + ! ! ( op_array - > fn_flags & ZEND_ACC_VARIADIC ) ) {
2014-12-14 06:06:14 +08:00
if ( ( base = phpdbg_find_breakpoint_symbol ( execute_data - > func ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
}
}
2014-12-14 06:06:14 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPLINE_BP ) & & ( base = phpdbg_find_breakpoint_opline ( ( phpdbg_opline_ptr_t ) execute_data - > opline ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
2014-12-14 06:06:14 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPCODE_BP ) & & ( base = phpdbg_find_breakpoint_opcode ( execute_data - > opline - > opcode ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
2013-11-27 21:01:57 +08:00
return NULL ;
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
result :
/* we return nothing for disable breakpoints */
if ( base - > disabled ) {
return NULL ;
}
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
return base ;
2013-11-24 20:06:45 +08:00
} /* }}} */
2013-11-24 19:58:08 +08:00
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_delete_breakpoint ( zend_ulong num ) /* { { { */
2013-11-24 19:58:08 +08:00
{
2014-10-25 01:29:50 +08:00
HashTable * table ;
2013-12-02 21:43:21 +08:00
phpdbg_breakbase_t * brake ;
2014-10-25 01:29:50 +08:00
zend_string * strkey ;
zend_ulong numkey ;
2013-12-08 02:18:44 +08:00
2014-12-14 06:06:14 +08:00
if ( ( brake = phpdbg_find_breakbase_ex ( num , & table , & numkey , & strkey ) ) ) {
2013-12-02 21:43:21 +08:00
int type = brake - > type ;
char * name = NULL ;
size_t name_len = 0L ;
switch ( type ) {
case PHPDBG_BREAK_FILE :
case PHPDBG_BREAK_METHOD :
2014-10-25 01:29:50 +08:00
if ( zend_hash_num_elements ( table ) = = 1 ) {
2013-12-02 21:43:21 +08:00
name = estrdup ( brake - > name ) ;
name_len = strlen ( name ) ;
if ( zend_hash_num_elements ( & PHPDBG_G ( bp ) [ type ] ) = = 1 ) {
PHPDBG_G ( flags ) & = ~ ( 1 < < ( brake - > type + 1 ) ) ;
2013-12-03 04:56:25 +08:00
}
}
2013-12-02 21:43:21 +08:00
break ;
2013-12-03 04:56:25 +08:00
2013-12-02 21:43:21 +08:00
default : {
2014-10-25 01:29:50 +08:00
if ( zend_hash_num_elements ( table ) = = 1 ) {
2013-12-02 21:43:21 +08:00
PHPDBG_G ( flags ) & = ~ ( 1 < < ( brake - > type + 1 ) ) ;
2013-12-03 04:56:25 +08:00
}
}
}
2013-12-07 22:35:35 +08:00
switch ( type ) {
case PHPDBG_BREAK_FILE_OPLINE :
case PHPDBG_BREAK_FUNCTION_OPLINE :
case PHPDBG_BREAK_METHOD_OPLINE :
if ( zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) = = 1 ) {
PHPDBG_G ( flags ) & = PHPDBG_HAS_OPLINE_BP ;
2013-12-03 04:56:25 +08:00
}
2014-10-25 01:29:50 +08:00
zend_hash_index_del ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( ( phpdbg_breakopline_t * ) brake ) - > opline ) ;
2013-12-03 04:56:25 +08:00
}
2014-10-25 01:29:50 +08:00
if ( strkey ) {
zend_hash_del ( table , strkey ) ;
} else {
zend_hash_index_del ( table , numkey ) ;
2013-11-24 19:58:08 +08:00
}
2013-12-02 21:43:21 +08:00
switch ( type ) {
case PHPDBG_BREAK_FILE :
case PHPDBG_BREAK_METHOD :
if ( name ) {
2014-10-25 01:29:50 +08:00
zend_hash_str_del ( & PHPDBG_G ( bp ) [ type ] , name , name_len ) ;
2013-12-02 21:43:21 +08:00
efree ( name ) ;
2013-11-24 19:58:08 +08:00
}
2013-12-02 21:43:21 +08:00
break ;
2013-11-24 19:58:08 +08:00
}
2013-11-24 20:14:53 +08:00
2014-10-05 18:33:24 +08:00
phpdbg_notice ( " breakpoint " , " deleted= \" success \" id= \" %ld \" " , " Deleted breakpoint #%ld " , num ) ;
2013-12-07 22:31:10 +08:00
PHPDBG_BREAK_UNMAPPING ( num ) ;
2013-11-27 06:20:52 +08:00
} else {
2014-10-05 18:33:24 +08:00
phpdbg_error ( " breakpoint " , " type= \" nobreakpoint \" deleted= \" fail \" id= \" %ld \" " , " Failed to find breakpoint #%ld " , num ) ;
2013-11-24 20:14:53 +08:00
}
2013-11-24 19:58:08 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_clear_breakpoints ( void ) /* { { { */
2013-11-12 01:19:05 +08:00
{
2013-11-26 18:02:58 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] ) ;
2014-10-27 03:43:49 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] ) ;
2013-11-26 18:02:58 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] ) ;
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
2013-12-07 22:35:35 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] ) ;
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ) ;
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] ) ;
2013-11-26 18:02:58 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] ) ;
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] ) ;
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] ) ;
2013-11-27 06:20:52 +08:00
zend_hash_clean ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] ) ;
2013-11-14 07:36:02 +08:00
2013-11-26 18:02:58 +08:00
PHPDBG_G ( flags ) & = ~ PHPDBG_BP_MASK ;
2013-11-12 09:58:39 +08:00
2013-11-26 18:02:58 +08:00
PHPDBG_G ( bp_count ) = 0 ;
2013-11-12 01:19:05 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_hit_breakpoint ( phpdbg_breakbase_t * brake , zend_bool output ) /* { { { */
2013-11-27 21:01:57 +08:00
{
brake - > hits + + ;
2013-11-28 06:59:02 +08:00
2013-11-27 21:01:57 +08:00
if ( output ) {
2014-12-14 06:06:14 +08:00
phpdbg_print_breakpoint ( brake ) ;
2013-11-27 21:01:57 +08:00
}
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_print_breakpoint ( phpdbg_breakbase_t * brake ) /* { { { */
2013-11-27 21:01:57 +08:00
{
2013-11-28 06:59:02 +08:00
if ( ! brake )
2013-11-27 21:01:57 +08:00
goto unknown ;
switch ( brake - > type ) {
case PHPDBG_BREAK_FILE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d at %s:%ld, hits: %lu " ,
2013-11-28 06:59:02 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > id ,
( ( phpdbg_breakfile_t * ) brake ) - > filename ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > line ,
( ( phpdbg_breakfile_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_SYM : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" function= \" %s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %s() at %s:%u, hits: %lu " ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breaksymbol_t * ) brake ) - > id ,
( ( phpdbg_breaksymbol_t * ) brake ) - > symbol ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > hits ) ;
2013-11-27 21:01:57 +08:00
} break ;
case PHPDBG_BREAK_OPLINE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opline= \" %#lx \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %#lx at %s:%u, hits: %lu " ,
2013-11-28 06:59:02 +08:00
( ( phpdbg_breakline_t * ) brake ) - > id ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakline_t * ) brake ) - > opline ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakline_t * ) brake ) - > hits ) ;
} break ;
2013-12-07 22:35:35 +08:00
case PHPDBG_BREAK_METHOD_OPLINE : {
2014-09-23 23:04:39 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" method= \" %s::%s \" num= \" %lu \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %s::%s()#%lu at %s:%u, hits: %lu " ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > id ,
( ( phpdbg_breakopline_t * ) brake ) - > class_name ,
( ( phpdbg_breakopline_t * ) brake ) - > func_name ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_FUNCTION_OPLINE : {
2014-09-23 23:04:39 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" num= \" %lu \" function= \" %s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %s()#%lu at %s:%u, hits: %lu " ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > id ,
( ( phpdbg_breakopline_t * ) brake ) - > func_name ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_FILE_OPLINE : {
2014-09-23 23:04:39 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" num= \" %lu \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in #%lu at %s:%u, hits: %lu " ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > id ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > hits ) ;
} break ;
2013-11-27 21:01:57 +08:00
case PHPDBG_BREAK_OPCODE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opcode= \" %s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %s at %s:%u, hits: %lu " ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakop_t * ) brake ) - > id ,
( ( phpdbg_breakop_t * ) brake ) - > name ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakop_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_METHOD : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" method= \" %s::%s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Breakpoint #%d in %s::%s() at %s:%u, hits: %lu " ,
2013-11-28 06:59:02 +08:00
( ( phpdbg_breakmethod_t * ) brake ) - > id ,
( ( phpdbg_breakmethod_t * ) brake ) - > class_name ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakmethod_t * ) brake ) - > func_name ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-11-27 21:01:57 +08:00
( ( phpdbg_breakmethod_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_COND : {
2013-12-04 22:20:13 +08:00
if ( ( ( phpdbg_breakcond_t * ) brake ) - > paramed ) {
char * param ;
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" location= \" %s \" eval= \" %s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Conditional breakpoint #%d: at %s if %s at %s:%u, hits: %lu " ,
2013-12-04 22:20:13 +08:00
( ( phpdbg_breakcond_t * ) brake ) - > id ,
2014-12-14 06:06:14 +08:00
phpdbg_param_tostring ( & ( ( phpdbg_breakcond_t * ) brake ) - > param , & param ) ,
2013-12-04 22:20:13 +08:00
( ( phpdbg_breakcond_t * ) brake ) - > code ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-04 22:20:13 +08:00
( ( phpdbg_breakcond_t * ) brake ) - > hits ) ;
2013-12-07 22:31:10 +08:00
if ( param )
2013-12-04 22:20:13 +08:00
free ( param ) ;
} else {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" eval= \" %s \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Conditional breakpoint #%d: on %s == true at %s:%u, hits: %lu " ,
2013-12-04 22:20:13 +08:00
( ( phpdbg_breakcond_t * ) brake ) - > id ,
( ( phpdbg_breakcond_t * ) brake ) - > code ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ,
2013-12-04 22:20:13 +08:00
( ( phpdbg_breakcond_t * ) brake ) - > hits ) ;
}
2013-12-07 22:31:10 +08:00
2013-11-27 21:01:57 +08:00
} break ;
default : {
unknown :
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" \" file= \" %s \" line= \" %ld \" hits= \" %lu \" " , " Unknown breakpoint at %s:%u " ,
2014-12-14 06:06:14 +08:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ) ;
2013-11-27 21:01:57 +08:00
}
}
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_enable_breakpoint ( zend_ulong id ) /* { { { */
2013-12-02 21:19:13 +08:00
{
2014-12-14 06:06:14 +08:00
phpdbg_breakbase_t * brake = phpdbg_find_breakbase ( id ) ;
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
if ( brake ) {
brake - > disabled = 0 ;
}
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_disable_breakpoint ( zend_ulong id ) /* { { { */
2013-12-02 21:19:13 +08:00
{
2014-12-14 06:06:14 +08:00
phpdbg_breakbase_t * brake = phpdbg_find_breakbase ( id ) ;
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
if ( brake ) {
brake - > disabled = 1 ;
}
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_enable_breakpoints ( void ) /* { { { */
2013-12-02 21:19:13 +08:00
{
PHPDBG_G ( flags ) | = PHPDBG_IS_BP_ENABLED ;
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_disable_breakpoints ( void ) { /* {{{ */
2013-12-07 22:31:10 +08:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_BP_ENABLED ;
2013-12-02 21:19:13 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase ( zend_ulong id ) /* { { { */
2013-12-02 21:19:13 +08:00
{
2014-10-25 01:29:50 +08:00
HashTable * table ;
zend_string * strkey ;
zend_ulong numkey ;
2013-12-02 21:19:13 +08:00
2014-12-14 06:06:14 +08:00
return phpdbg_find_breakbase_ex ( id , & table , & numkey , & strkey ) ;
2013-12-02 21:19:13 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase_ex ( zend_ulong id , HashTable * * table , zend_ulong * numkey , zend_string * * strkey ) /* { { { */
2013-12-02 21:19:13 +08:00
{
2014-10-25 01:29:50 +08:00
if ( ( * table = zend_hash_index_find_ptr ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , id ) ) ) {
2013-12-02 21:19:13 +08:00
phpdbg_breakbase_t * brake ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_KEY_PTR ( * table , * numkey , * strkey , brake ) {
2013-12-02 21:19:13 +08:00
if ( brake - > id = = id ) {
return brake ;
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-02 21:19:13 +08:00
}
2014-10-25 01:29:50 +08:00
2013-12-02 21:19:13 +08:00
return NULL ;
} /* }}} */
2014-12-14 06:06:14 +08:00
PHPDBG_API void phpdbg_print_breakpoints ( zend_ulong type ) /* { { { */
2013-11-13 00:04:41 +08:00
{
2014-10-09 18:24:52 +08:00
phpdbg_xml ( " <breakpoints %r> " ) ;
2014-09-21 10:17:19 +08:00
2013-11-26 18:02:58 +08:00
switch ( type ) {
case PHPDBG_BREAK_SYM : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_SYM_BP ) ) {
phpdbg_breaksymbol_t * brake ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Function Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , brake ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " function " , " id= \" %d \" name= \" %s \" disabled= \" %s \" " , " #%d \t \t %s%s " ,
2013-12-07 22:31:10 +08:00
brake - > id , brake - > symbol ,
2014-10-25 01:29:50 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-24 19:43:05 +08:00
} break ;
2013-11-26 18:02:58 +08:00
case PHPDBG_BREAK_METHOD : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_METHOD_BP ) ) {
HashTable * class_table ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Method Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , class_table ) {
phpdbg_breakmethod_t * brake ;
ZEND_HASH_FOREACH_PTR ( class_table , brake ) {
phpdbg_writeln ( " method " , " id= \" %d \" name= \" %s::%s \" disabled= \" %s \" " , " #%d \t \t %s::%s%s " ,
brake - > id , brake - > class_name , brake - > func_name ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-26 18:02:58 +08:00
} break ;
case PHPDBG_BREAK_FILE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FILE_BP ) ) {
2013-11-27 06:20:52 +08:00
HashTable * points ;
2013-11-26 18:02:58 +08:00
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " File Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , points ) {
2013-11-26 18:02:58 +08:00
phpdbg_breakfile_t * brake ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( points , brake ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " file " , " id= \" %d \" name= \" %s \" line= \" %lu \" disabled= \" %s \" " , " #%d \t \t %s:%lu%s " ,
2013-12-07 22:31:10 +08:00
brake - > id , brake - > filename , brake - > line ,
2014-10-25 01:29:50 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2014-10-27 03:43:49 +08:00
} if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_PENDING_FILE_BP ) ) {
HashTable * points ;
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Pending File Breakpoints: \n " ) ;
2014-10-27 07:34:56 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_PENDING ] , points ) {
2014-10-27 03:43:49 +08:00
phpdbg_breakfile_t * brake ;
2013-11-28 06:59:02 +08:00
2014-10-27 07:34:56 +08:00
ZEND_HASH_FOREACH_PTR ( points , brake ) {
2014-10-27 03:43:49 +08:00
phpdbg_writeln ( " file " , " id= \" %d \" name= \" %s \" line= \" %lu \" disabled= \" %s \" pending= \" pending \" " , " #%d \t \t %s:%lu%s " ,
brake - > id , brake - > filename , brake - > line ,
2014-10-27 07:34:56 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-26 18:02:58 +08:00
} break ;
case PHPDBG_BREAK_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPLINE_BP ) ) {
phpdbg_breakline_t * brake ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Opline Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , brake ) {
const char * type ;
2013-12-03 04:56:25 +08:00
switch ( brake - > type ) {
case PHPDBG_BREAK_METHOD_OPLINE :
2014-10-25 01:29:50 +08:00
type = " method " ;
goto print_opline ;
2013-12-03 04:56:25 +08:00
case PHPDBG_BREAK_FUNCTION_OPLINE :
2014-10-25 01:29:50 +08:00
type = " function " ;
goto print_opline ;
2013-12-03 04:56:25 +08:00
case PHPDBG_BREAK_FILE_OPLINE :
2014-10-25 01:29:50 +08:00
type = " method " ;
print_opline : {
if ( brake - > type = = PHPDBG_BREAK_METHOD_OPLINE ) {
type = " method " ;
} else if ( brake - > type = = PHPDBG_BREAK_FUNCTION_OPLINE ) {
type = " function " ;
} else if ( brake - > type = = PHPDBG_BREAK_FILE_OPLINE ) {
type = " file " ;
}
phpdbg_writeln ( " opline " , " id= \" %d \" num= \" %#lx \" type= \" %s \" disabled= \" %s \" " , " #%d \t \t %#lx \t \t (%s breakpoint)%s " ,
brake - > id , brake - > opline , type ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} break ;
2013-12-03 04:56:25 +08:00
default :
2014-10-25 01:29:50 +08:00
phpdbg_writeln ( " opline " , " id= \" %d \" num= \" %#lx \" disabled= \" %s \" " , " #%d \t \t %#lx%s " ,
brake - > id , brake - > opline ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 04:56:25 +08:00
break ;
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-03 04:56:25 +08:00
} break ;
case PHPDBG_BREAK_METHOD_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_METHOD_OPLINE_BP ) ) {
HashTable * class_table , * method_table ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Method opline Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , class_table ) {
ZEND_HASH_FOREACH_PTR ( class_table , method_table ) {
phpdbg_breakopline_t * brake ;
2013-12-03 04:56:25 +08:00
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( method_table , brake ) {
phpdbg_writeln ( " methodopline " , " id= \" %d \" name= \" %s::%s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s::%s opline %ld%s " ,
brake - > id , brake - > class_name , brake - > func_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-03 04:56:25 +08:00
} break ;
case PHPDBG_BREAK_FUNCTION_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FUNCTION_OPLINE_BP ) ) {
HashTable * function_table ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Function opline Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , function_table ) {
phpdbg_breakopline_t * brake ;
ZEND_HASH_FOREACH_PTR ( function_table , brake ) {
phpdbg_writeln ( " functionopline " , " id= \" %d \" name= \" %s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s opline %ld%s " ,
brake - > id , brake - > func_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-12-03 04:56:25 +08:00
} break ;
case PHPDBG_BREAK_FILE_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FILE_OPLINE_BP ) ) {
HashTable * file_table ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " File opline Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , file_table ) {
phpdbg_breakopline_t * brake ;
ZEND_HASH_FOREACH_PTR ( file_table , brake ) {
phpdbg_writeln ( " fileopline " , " id= \" %d \" name= \" %s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s opline %ld%s " ,
brake - > id , brake - > class_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-26 18:02:58 +08:00
} break ;
case PHPDBG_BREAK_COND : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_COND_BP ) ) {
phpdbg_breakcond_t * brake ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Conditional Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , brake ) {
2013-12-03 08:43:05 +08:00
if ( brake - > paramed ) {
switch ( brake - > param . type ) {
case STR_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalfunction " , " id= \" %d \" name= \" %s \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at %s if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . str , brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 08:43:05 +08:00
break ;
2013-12-07 22:31:10 +08:00
2013-12-09 20:25:00 +08:00
case NUMERIC_FUNCTION_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalfunctionopline " , " id= \" %d \" name= \" %s \" num= \" %ld \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at %s#%ld if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . str , brake - > param . num , brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-09 20:25:00 +08:00
break ;
2013-12-03 08:43:05 +08:00
case METHOD_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalmethod " , " id= \" %d \" name= \" %s::%s \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at %s::%s if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . method . class , brake - > param . method . name , brake - > code ,
2013-12-03 08:43:05 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
break ;
2013-12-07 22:31:10 +08:00
2013-12-09 20:25:00 +08:00
case NUMERIC_METHOD_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalmethodopline " , " id= \" %d \" name= \" %s::%s \" num= \" %d \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at %s::%s#%ld if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . method . class , brake - > param . method . name , brake - > param . num , brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-09 20:25:00 +08:00
break ;
2013-12-03 08:43:05 +08:00
case FILE_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalfile " , " id= \" %d \" name= \" %s \" line= \" %d \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at %s:%lu if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . file . name , brake - > param . file . line , brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 08:43:05 +08:00
break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:43:05 +08:00
case ADDR_PARAM :
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " evalopline " , " id= \" %d \" opline= \" %#lx \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t at #%lx if %s%s " ,
2014-10-25 01:29:50 +08:00
brake - > id , brake - > param . addr , brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 08:43:05 +08:00
break ;
2013-12-07 22:35:35 +08:00
default :
2014-09-21 10:17:19 +08:00
phpdbg_error ( " eval " , " type= \" invalidparameter \" " , " Invalid parameter type for conditional breakpoint " ) ;
2013-12-07 22:35:35 +08:00
return ;
2013-12-03 08:43:05 +08:00
}
} else {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " eval " , " id= \" %d \" eval= \" %s \" disabled= \" %s \" " , " #%d \t \t if %s%s " ,
2013-12-07 22:31:10 +08:00
brake - > id , brake - > code ,
2014-10-25 01:29:50 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 08:43:05 +08:00
}
2014-10-25 01:29:50 +08:00
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-24 19:43:05 +08:00
} break ;
2013-11-26 18:02:58 +08:00
case PHPDBG_BREAK_OPCODE : if ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPCODE_BP ) {
phpdbg_breakop_t * brake ;
2014-10-20 02:09:39 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Opcode Breakpoints: \n " ) ;
2014-10-25 01:29:50 +08:00
ZEND_HASH_FOREACH_PTR ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , brake ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " opcode " , " id= \" %d \" name= \" %s \" disabled= \" %s \" " , " #%d \t \t %s%s " ,
2013-12-07 22:31:10 +08:00
brake - > id , brake - > name ,
2014-10-25 01:29:50 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2013-11-26 18:02:58 +08:00
} break ;
}
2014-09-21 10:17:19 +08:00
phpdbg_xml ( " </breakpoints> " ) ;
2013-11-13 00:04:41 +08:00
} /* }}} */