2013-11-11 02:06:41 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-01-18 06:09:07 +08:00
| Copyright ( c ) 1997 - 2014 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"
2013-11-11 02:06:41 +08:00
ZEND_EXTERN_MODULE_GLOBALS ( phpdbg ) ;
2013-11-27 21:28:53 +08:00
/* {{{ private api functions */
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_file ( zend_op_array * TSRMLS_DC ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_symbol ( zend_function * TSRMLS_DC ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_method ( zend_op_array * TSRMLS_DC ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opline ( phpdbg_opline_ptr_t TSRMLS_DC ) ;
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opcode ( zend_uchar TSRMLS_DC ) ;
2013-12-03 08:15:33 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_conditional_breakpoint ( zend_execute_data * execute_data TSRMLS_DC ) ; /* }}} */
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
*/
2013-11-28 06:59:02 +08:00
static inline void _phpdbg_break_mapping ( int id , HashTable * table TSRMLS_DC )
{
2014-09-21 10:17:19 +08:00
zend_hash_index_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , ( id ) , ( void * * ) & table , sizeof ( void * ) , NULL ) ;
2013-11-27 06:20:52 +08:00
}
# define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table TSRMLS_CC)
# 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
static void phpdbg_file_breaks_dtor ( void * data ) /* { { { */
2013-11-11 02:06:41 +08:00
{
phpdbg_breakfile_t * bp = ( phpdbg_breakfile_t * ) data ;
efree ( ( char * ) bp - > filename ) ;
} /* }}} */
2013-11-12 08:27:48 +08:00
static void phpdbg_class_breaks_dtor ( void * data ) /* { { { */
{
2013-11-26 18:02:58 +08:00
phpdbg_breakmethod_t * bp = ( phpdbg_breakmethod_t * ) 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 ) ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2013-11-29 04:36:45 +08:00
static void phpdbg_opline_class_breaks_dtor ( void * data ) /* { { { */
{
zend_hash_destroy ( ( HashTable * ) data ) ;
} /* }}} */
static void phpdbg_opline_breaks_dtor ( void * data ) /* { { { */
{
phpdbg_breakopline_t * bp = ( phpdbg_breakopline_t * ) data ;
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 ) ;
}
2013-11-29 04:36:45 +08:00
} /* }}} */
2013-11-27 21:15:52 +08:00
PHPDBG_API void phpdbg_reset_breakpoints ( TSRMLS_D ) /* { { { */
2013-11-26 01:41:09 +08:00
{
2013-11-27 21:15:52 +08:00
if ( zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] ) ) {
HashPosition position [ 2 ] ;
HashTable * * table = NULL ;
2013-11-26 05:39:17 +08:00
2013-11-27 21:15:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , & position [ 0 ] ) ;
2014-09-21 10:17:19 +08:00
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , ( void * * ) & table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , & position [ 0 ] ) ) {
2013-11-27 21:15:52 +08:00
phpdbg_breakbase_t * brake ;
2013-11-26 01:41:09 +08:00
2013-11-27 21:15:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( ( * table ) , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( ( * table ) , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( ( * table ) , & position [ 1 ] ) ) {
2013-11-28 06:59:02 +08:00
brake - > hits = 0 ;
2013-11-26 01:41:09 +08:00
}
}
}
2013-11-27 21:15:52 +08:00
} /* }}} */
2013-11-26 05:39:17 +08:00
2013-11-26 01:41:09 +08:00
PHPDBG_API void phpdbg_export_breakpoints ( FILE * handle TSRMLS_DC ) /* { { { */
{
2013-11-27 06:20:52 +08:00
HashPosition position [ 2 ] ;
HashTable * * table = NULL ;
zend_ulong id = 0L ;
2013-12-03 19:31:25 +08:00
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 ] ) ) ;
2013-11-28 06:59:02 +08:00
/* this only looks like magic, it isn't */
2013-11-27 06:20:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , & position [ 0 ] ) ;
2014-09-21 10:17:19 +08:00
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , ( void * * ) & table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , & position [ 0 ] ) ) {
2013-11-27 06:20:52 +08:00
phpdbg_breakbase_t * brake ;
zend_hash_get_current_key_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , NULL , NULL , & id , 0 , & position [ 0 ] ) ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( ( * table ) , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( ( * table ) , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( ( * table ) , & position [ 1 ] ) ) {
if ( brake - > id = = id ) {
switch ( brake - > type ) {
case PHPDBG_BREAK_FILE : {
2013-11-28 06:59:02 +08:00
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s:%lu \n " ,
2013-11-28 06:59:02 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > filename ,
2013-11-27 06:20:52 +08:00
( ( phpdbg_breakfile_t * ) brake ) - > line ) ;
} break ;
2013-11-28 06:59:02 +08:00
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_SYM : {
2013-11-28 06:59:02 +08:00
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s \n " ,
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 : {
2013-11-28 06:59:02 +08:00
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s::%s \n " ,
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 : {
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s::%s#%ld \n " ,
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 : {
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s#%ld \n " ,
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 : {
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s:#%ld \n " ,
2013-12-07 22:35:35 +08:00
( ( phpdbg_breakopline_t * ) brake ) - > class_name ,
( ( phpdbg_breakopline_t * ) brake ) - > opline_num ) ;
} break ;
2013-11-27 06:20:52 +08:00
case PHPDBG_BREAK_OPCODE : {
2013-11-28 06:59:02 +08:00
fprintf ( handle ,
2014-02-22 02:05:11 +08:00
" break %s \n " ,
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 :
2013-12-07 22:31:10 +08:00
fprintf ( handle ,
2013-12-03 08:35:20 +08:00
" break at %s if %s \n " , conditional - > param . str , conditional - > code ) ;
break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:35:20 +08:00
case METHOD_PARAM :
2013-12-07 22:31:10 +08:00
fprintf ( handle ,
" break at %s::%s if %s \n " ,
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
2013-12-03 08:35:20 +08:00
case FILE_PARAM :
2013-12-07 22:31:10 +08:00
fprintf ( handle ,
" break at %s:%lu if %s \n " ,
2013-12-03 08:35:20 +08:00
conditional - > param . file . name , conditional - > param . file . line ,
conditional - > code ) ;
break ;
2013-12-07 22:31:10 +08:00
2013-12-03 08:35:20 +08:00
default : { /* do nothing */ } break ;
}
} else {
fprintf (
2014-02-22 02:05:11 +08:00
handle , " break if %s \n " , conditional - > code ) ;
2013-12-03 08:35:20 +08:00
}
2013-11-27 06:20:52 +08:00
} break ;
2013-12-03 19:31:25 +08:00
}
}
}
}
}
2013-11-26 01:41:09 +08:00
} /* }}} */
2013-11-24 02:12:51 +08:00
PHPDBG_API void phpdbg_set_breakpoint_file ( const char * path , long line_num TSRMLS_DC ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2014-02-28 15:41:34 +08:00
php_stream_statbuf ssb ;
char realpath [ MAXPATHLEN ] ;
2014-09-21 10:17:19 +08:00
2014-02-28 15:41:34 +08:00
if ( php_stream_stat_path ( path , & ssb ) ! = FAILURE ) {
if ( ssb . sb . st_mode & ( S_IFREG | S_IFLNK ) ) {
2013-11-27 06:20:52 +08:00
HashTable * broken ;
2013-11-26 18:02:58 +08:00
phpdbg_breakfile_t new_break ;
2014-02-28 15:41:34 +08:00
size_t path_len = 0L ;
2014-09-21 10:17:19 +08:00
2014-02-28 15:41:34 +08:00
if ( VCWD_REALPATH ( path , realpath ) ) {
path = realpath ;
}
path_len = strlen ( path ) ;
2014-09-21 10:17:19 +08:00
2013-11-26 18:02:58 +08:00
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] ,
2013-11-27 06:20:52 +08:00
path , path_len , ( void * * ) & broken ) = = FAILURE ) {
HashTable breaks ;
2013-11-11 02:06:41 +08:00
2013-11-27 06:20:52 +08:00
zend_hash_init ( & breaks , 8 , NULL , phpdbg_file_breaks_dtor , 0 ) ;
2013-11-11 03:15:32 +08:00
2013-11-26 18:02:58 +08:00
zend_hash_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] ,
2013-11-27 06:20:52 +08:00
path , path_len , & breaks , sizeof ( HashTable ) ,
( void * * ) & broken ) ;
2013-11-26 18:02:58 +08:00
}
2013-11-12 06:06:36 +08:00
2013-11-27 06:20:52 +08:00
if ( ! zend_hash_index_exists ( broken , line_num ) ) {
PHPDBG_G ( flags ) | = PHPDBG_HAS_FILE_BP ;
2013-11-27 21:01:57 +08:00
2013-12-02 21:19:13 +08:00
PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_FILE ) ;
2013-11-27 21:01:57 +08:00
new_break . filename = estrndup ( path , path_len ) ;
new_break . line = line_num ;
2013-11-28 06:59:02 +08:00
2014-09-21 10:17:19 +08:00
zend_hash_index_update ( broken , line_num , ( void * * ) & new_break , sizeof ( phpdbg_breakfile_t ) , NULL ) ;
2013-11-27 21:01:57 +08:00
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " success= \" success \" id= \" %d \" file= \" %s \" line= \" %ld \" " , " Breakpoint #%d added at %s:%ld " ,
2013-11-27 06:20:52 +08:00
new_break . id , new_break . filename , new_break . line ) ;
2013-11-27 21:01:57 +08:00
2013-11-27 06:20:52 +08:00
PHPDBG_BREAK_MAPPING ( new_break . id , broken ) ;
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" file= \" %s \" line= \" %ld \" " , " Breakpoint at %s:%ld exists " , path , line_num ) ;
2013-11-27 06:20:52 +08:00
}
2013-11-17 06:40:01 +08:00
2013-11-26 18:02:58 +08:00
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" notregular \" file= \" %s \" " , " Cannot set breakpoint in %s, it is not a regular file " , path ) ;
2013-11-26 18:02:58 +08:00
}
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" nofile \" file= \" %s \" " , " Cannot stat %s, it does not exist " , path ) ;
2013-11-26 18:02:58 +08:00
}
2013-11-11 02:06:41 +08:00
} /* }}} */
2013-11-24 20:00:12 +08:00
PHPDBG_API void phpdbg_set_breakpoint_symbol ( const char * name , size_t name_len TSRMLS_DC ) /* { { { */
2013-11-11 02:06:41 +08:00
{
2013-11-12 09:51:50 +08:00
if ( ! zend_hash_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
2013-11-12 09:51:50 +08:00
zend_hash_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , new_break . symbol ,
2013-11-11 05:38:58 +08:00
name_len , & new_break , sizeof ( phpdbg_breaksymbol_t ) , NULL ) ;
2013-11-12 06:06:36 +08:00
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " success= \" success \" id= \" %d \" function= \" %s \" " , " Breakpoint #%d added at %s " ,
2013-11-13 06:39:39 +08:00
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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" function= \" %s \" " , " Breakpoint exists at %s " , name ) ;
2013-11-11 02:06:41 +08:00
}
} /* }}} */
2013-11-28 06:59:02 +08:00
PHPDBG_API void phpdbg_set_breakpoint_method ( const char * class_name , const char * func_name TSRMLS_DC ) /* { { { */
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 ) ;
char * lcname = zend_str_tolower_dup ( func_name , func_len ) ;
2013-11-20 22:55:07 +08:00
2013-11-26 18:02:58 +08:00
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , class_name ,
2013-11-12 21:33:51 +08:00
class_len , ( void * * ) & class_table ) ! = SUCCESS ) {
2013-11-26 18:02:58 +08:00
zend_hash_init ( & class_breaks , 8 , NULL , phpdbg_class_breaks_dtor , 0 ) ;
zend_hash_update (
& PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] ,
class_name , class_len ,
( void * * ) & class_breaks , sizeof ( HashTable ) , ( void * * ) & class_table ) ;
}
2013-11-12 08:27:48 +08:00
2013-11-27 21:01:57 +08:00
if ( ! zend_hash_exists ( class_table , 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
2013-11-27 00:00:28 +08:00
zend_hash_update ( class_table , lcname , func_len ,
2013-11-12 21:33:51 +08:00
& new_break , sizeof ( phpdbg_breakmethod_t ) , NULL ) ;
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " success= \" success \" id= \" %d \" method= \" %s::%s \" " , " Breakpoint #%d added at %s::%s " ,
2013-11-26 18:02:58 +08:00
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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" 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
2014-02-05 08:04:21 +08:00
efree ( lcname ) ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2013-11-24 02:12:51 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opline ( zend_ulong opline TSRMLS_DC ) /* { { { */
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
2013-12-01 22:58:59 +08:00
zend_hash_index_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , opline ,
& new_break , sizeof ( phpdbg_breakline_t ) , NULL ) ;
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " success= \" success \" id= \" %d \" opline= \" %#lx \" " , " Breakpoint #%d added at %#lx " ,
2013-12-02 02:05:30 +08:00
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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" exists \" opline= \" %#lx \" " , " Breakpoint exists at %#lx " , opline ) ;
2013-11-11 19:54:41 +08:00
}
} /* }}} */
2013-12-08 02:18:44 +08:00
PHPDBG_API int phpdbg_resolve_op_array_break ( phpdbg_breakopline_t * brake , zend_op_array * op_array TSRMLS_DC ) /* { { { */
{
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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" 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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" 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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" maxoplines \" 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 ;
zend_hash_index_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , opline_break . opline , & opline_break , sizeof ( phpdbg_breakline_t ) , NULL ) ;
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
2013-12-08 02:18:44 +08:00
PHPDBG_API void phpdbg_resolve_op_array_breaks ( zend_op_array * op_array TSRMLS_DC ) /* { { { */
{
2013-11-29 04:36:45 +08:00
HashTable * func_table = & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ;
HashTable * oplines_table ;
HashPosition position ;
phpdbg_breakopline_t * brake ;
if ( op_array - > scope ! = NULL & &
zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , op_array - > scope - > name , op_array - > scope - > name_length , ( void * * ) & func_table ) = = FAILURE ) {
return ;
}
2013-12-03 19:31:25 +08:00
if ( op_array - > function_name = = NULL ) {
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , op_array - > filename , strlen ( op_array - > filename ) , ( void * * ) & oplines_table ) = = FAILURE ) {
return ;
}
} else if ( zend_hash_find ( func_table , op_array - > function_name ? op_array - > function_name : " " , op_array - > function_name ? strlen ( op_array - > function_name ) : 0 , ( void * * ) & oplines_table ) = = FAILURE ) {
2013-11-29 04:36:45 +08:00
return ;
}
for ( zend_hash_internal_pointer_reset_ex ( oplines_table , & position ) ;
zend_hash_get_current_data_ex ( oplines_table , ( void * * ) & brake , & position ) = = SUCCESS ;
zend_hash_move_forward_ex ( oplines_table , & position ) ) {
2013-11-29 18:38:28 +08:00
if ( phpdbg_resolve_op_array_break ( brake , op_array TSRMLS_CC ) = = SUCCESS ) {
phpdbg_breakline_t * opline_break ;
zend_hash_internal_pointer_end ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ;
zend_hash_get_current_data ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( void * * ) & opline_break ) ;
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " success= \" success \" id= \" %d \" symbol= \" %s \" num= \" %ld \" opline= \" %#lx \" " , " Breakpoint #%d resolved at %s%s%s#%ld (opline %#lx) " ,
2013-12-07 22:35:35 +08:00
brake - > id ,
brake - > class_name ? brake - > class_name : " " ,
brake - > class_name & & brake - > func_name ? " :: " : " " ,
brake - > func_name ? brake - > func_name : " " ,
brake - > opline_num ,
brake - > opline ) ;
2013-11-29 18:38:28 +08:00
}
2013-11-29 04:36:45 +08:00
}
2013-12-08 02:18:44 +08:00
} /* }}} */
2013-11-29 04:36:45 +08:00
2013-12-08 02:18:44 +08:00
PHPDBG_API int phpdbg_resolve_opline_break ( phpdbg_breakopline_t * new_break TSRMLS_DC ) /* { { { */
{
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 ) ) {
if ( phpdbg_resolve_op_array_break ( new_break , PHPDBG_G ( ops ) TSRMLS_CC ) = = SUCCESS ) {
return SUCCESS ;
} else {
return 2 ;
}
}
return FAILURE ;
} else {
zend_execute_data * execute_data = EG ( current_execute_data ) ;
do {
if ( execute_data - > op_array - > function_name = = NULL & & execute_data - > op_array - > scope = = NULL & & ! memcmp ( execute_data - > op_array - > filename , new_break - > class_name , new_break - > class_len ) ) {
if ( phpdbg_resolve_op_array_break ( new_break , execute_data - > op_array TSRMLS_CC ) = = SUCCESS ) {
return SUCCESS ;
} else {
return 2 ;
}
}
} 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 ) {
zend_class_entry * * ce ;
2013-12-07 22:35:35 +08:00
if ( zend_hash_find ( EG ( class_table ) , zend_str_tolower_dup ( new_break - > class_name , new_break - > class_len ) , new_break - > class_len + 1 , ( void * * ) & ce ) = = FAILURE ) {
2013-11-29 04:36:45 +08:00
return FAILURE ;
}
func_table = & ( * ce ) - > function_table ;
}
2013-12-07 22:35:35 +08:00
if ( zend_hash_find ( func_table , zend_str_tolower_dup ( new_break - > func_name , new_break - > func_len ) , new_break - > func_len + 1 , ( void * * ) & func ) = = FAILURE ) {
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 ) {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" internalfunction \" function= \" %s \" " , " %s is not an user defined function, no oplines exist " , new_break - > func_name ) ;
2013-11-29 04:36:45 +08:00
} else {
2014-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" internalfunction \" method= \" %s::%s \" " , " %s::%s is not an 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
}
2013-11-29 05:03:59 +08:00
if ( phpdbg_resolve_op_array_break ( new_break , & func - > op_array TSRMLS_CC ) = = FAILURE ) {
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
2013-12-07 22:35:35 +08:00
PHPDBG_API void phpdbg_set_breakpoint_method_opline ( const char * class , const char * method , zend_ulong opline TSRMLS_DC ) /* { { { */
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
2013-11-29 05:03:59 +08:00
switch ( phpdbg_resolve_opline_break ( & new_break TSRMLS_CC ) ) {
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
}
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , new_break . class_name , new_break . class_len , ( void * * ) & class_table ) = = FAILURE ) {
zend_hash_init ( & class_breaks , 8 , NULL , phpdbg_opline_class_breaks_dtor , 0 ) ;
zend_hash_update (
& PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] ,
new_break . class_name ,
new_break . class_len ,
( void * * ) & class_breaks , sizeof ( HashTable ) , ( void * * ) & class_table ) ;
}
if ( zend_hash_find ( class_table , new_break . func_name , new_break . func_len , ( void * * ) & method_table ) = = FAILURE ) {
zend_hash_init ( & method_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
zend_hash_update (
class_table ,
new_break . func_name ,
new_break . func_len ,
( void * * ) & method_breaks , sizeof ( HashTable ) , ( void * * ) & method_table ) ;
}
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 ) ;
2013-12-07 22:35:35 +08:00
zend_hash_index_update ( method_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) , NULL ) ;
2013-11-29 04:36:45 +08:00
}
2013-12-07 22:35:35 +08:00
PHPDBG_API void phpdbg_set_breakpoint_function_opline ( const char * function , zend_ulong opline TSRMLS_DC ) /* { { { */
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
2013-11-29 05:03:59 +08:00
switch ( phpdbg_resolve_opline_break ( & new_break TSRMLS_CC ) ) {
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
}
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , new_break . func_name , new_break . func_len , ( void * * ) & func_table ) = = FAILURE ) {
zend_hash_init ( & func_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
zend_hash_update (
& PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ,
new_break . func_name ,
new_break . func_len ,
( void * * ) & func_breaks , sizeof ( HashTable ) , ( void * * ) & func_table ) ;
}
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 ;
2013-12-07 22:35:35 +08:00
zend_hash_index_update ( func_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) , NULL ) ;
2013-11-29 04:36:45 +08:00
}
2013-12-07 22:35:35 +08:00
PHPDBG_API void phpdbg_set_breakpoint_file_opline ( const char * file , zend_ulong opline TSRMLS_DC ) /* { { { */
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
switch ( phpdbg_resolve_opline_break ( & new_break TSRMLS_CC ) ) {
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 ;
}
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , new_break . class_name , new_break . class_len , ( void * * ) & file_table ) = = FAILURE ) {
zend_hash_init ( & file_breaks , 8 , NULL , phpdbg_opline_breaks_dtor , 0 ) ;
zend_hash_update (
& PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] ,
new_break . class_name ,
new_break . class_len ,
( void * * ) & file_breaks , sizeof ( HashTable ) , ( void * * ) & file_table ) ;
}
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
2013-12-07 22:35:35 +08:00
zend_hash_index_update ( file_table , opline , & new_break , sizeof ( phpdbg_breakopline_t ) , NULL ) ;
2013-12-03 04:56:25 +08:00
}
2013-11-24 19:43:05 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opcode ( const char * name , size_t name_len TSRMLS_DC ) /* { { { */
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
zend_hash_index_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , hash ,
& new_break , sizeof ( phpdbg_breakop_t ) , NULL ) ;
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
} /* }}} */
2013-11-24 02:12:51 +08:00
PHPDBG_API void phpdbg_set_breakpoint_opline_ex ( phpdbg_opline_ptr_t opline TSRMLS_DC ) /* { { { */
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 ;
2013-11-12 06:06:36 +08:00
2013-11-14 08:29:44 +08:00
zend_hash_index_update ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ,
( zend_ulong ) opline , & new_break , sizeof ( phpdbg_breakline_t ) , NULL ) ;
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
}
} /* }}} */
2013-12-03 08:15:33 +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 TSRMLS_DC ) /* { { { */
2013-11-13 22:22:01 +08:00
{
2013-12-03 08:15:33 +08:00
phpdbg_breakcond_t new_break ;
2014-09-21 10:17:19 +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 (
param , & new_break . param TSRMLS_CC ) ;
} 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
2013-12-03 08:15:33 +08:00
Z_STRLEN ( pv ) = expr_len + sizeof ( " return ; " ) - 1 ;
Z_STRVAL ( pv ) = emalloc ( Z_STRLEN ( pv ) + 1 ) ;
memcpy ( Z_STRVAL ( pv ) , " return " , sizeof ( " return " ) - 1 ) ;
memcpy ( Z_STRVAL ( pv ) + sizeof ( " return " ) - 1 , expr , expr_len ) ;
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) - 1 ] = ' ; ' ;
Z_STRVAL ( pv ) [ Z_STRLEN ( pv ) ] = ' \0 ' ;
Z_TYPE ( pv ) = IS_STRING ;
2013-11-15 19:27:05 +08:00
2014-09-21 10:17:19 +08:00
new_break . ops = zend_compile_string ( & pv , " Conditional Breakpoint Code " TSRMLS_CC ) ;
2013-11-15 19:27:05 +08:00
2013-12-07 22:31:10 +08:00
zval_dtor ( & pv ) ;
2013-12-03 08:15:33 +08:00
if ( new_break . ops ) {
zend_hash_index_update (
& PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , hash , & new_break ,
sizeof ( phpdbg_breakcond_t ) , ( void * * ) & brake ) ;
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 ) - - ;
}
CG ( compiler_options ) = cops ;
} /* }}} */
2013-11-15 19:27:05 +08:00
2013-12-03 08:15:33 +08:00
PHPDBG_API void phpdbg_set_breakpoint_expression ( const char * expr , size_t expr_len TSRMLS_DC ) /* { { { */
{
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 (
& new_break , NULL , expr , expr_len , expr_hash TSRMLS_CC ) ;
} 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-02-19 16:33:54 +08:00
PHPDBG_API void phpdbg_set_breakpoint_at ( const phpdbg_param_t * param TSRMLS_DC ) /* { { { */
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-09-21 10:17:19 +08:00
phpdbg_create_conditional_break ( & new_break , param , condition - > str , condition - > len , hash TSRMLS_CC ) ;
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
} /* }}} */
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_file ( zend_op_array * op_array TSRMLS_DC ) /* { { { */
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 ;
2013-11-11 02:06:41 +08:00
size_t name_len = strlen ( op_array - > filename ) ;
2013-11-14 08:29:44 +08:00
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , op_array - > filename ,
2013-11-27 06:20:52 +08:00
name_len , ( void * * ) & breaks ) = = FAILURE ) {
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
2013-11-27 06:20:52 +08:00
if ( zend_hash_index_find ( breaks , ( * EG ( opline_ptr ) ) - > lineno , ( void * * ) & brake ) = = SUCCESS ) {
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
} /* }}} */
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_symbol ( zend_function * fbc TSRMLS_DC ) /* { { { */
2013-11-11 02:06:41 +08:00
{
const char * fname ;
2013-11-12 08:40:40 +08:00
zend_op_array * ops ;
2013-11-27 21:01:57 +08:00
phpdbg_breakbase_t * brake ;
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
2013-11-12 08:40:40 +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 */
return phpdbg_find_breakpoint_method ( ops TSRMLS_CC ) ;
2013-11-12 08:40:40 +08:00
}
2013-11-11 02:06:41 +08:00
2013-11-12 08:47:27 +08:00
fname = ops - > function_name ;
2013-11-11 02:06:41 +08:00
if ( ! fname ) {
fname = " main " ;
}
2013-11-11 05:38:58 +08:00
2013-11-27 21:01:57 +08:00
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , fname , strlen ( fname ) , ( void * * ) & brake ) = = SUCCESS ) {
return brake ;
2013-11-11 02:06:41 +08:00
}
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-11 05:57:43 +08:00
} /* }}} */
2013-11-11 19:54:41 +08:00
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_method ( zend_op_array * ops TSRMLS_DC ) /* { { { */
2013-11-12 08:27:48 +08:00
{
HashTable * class_table ;
2013-11-27 21:01:57 +08:00
phpdbg_breakbase_t * brake ;
2013-11-12 08:27:48 +08:00
2013-11-14 08:29:44 +08:00
if ( zend_hash_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , ops - > scope - > name ,
ops - > scope - > name_length , ( void * * ) & class_table ) = = SUCCESS ) {
2013-11-26 23:58:27 +08:00
char * lcname = zend_str_tolower_dup ( ops - > function_name , strlen ( ops - > function_name ) ) ;
size_t lcname_len = strlen ( lcname ) ;
2013-11-28 06:59:02 +08:00
2013-11-12 08:27:48 +08:00
if ( zend_hash_find (
class_table ,
2013-11-26 23:58:27 +08:00
lcname ,
2013-11-27 21:01:57 +08:00
lcname_len , ( void * * ) & brake ) = = SUCCESS ) {
2013-11-26 23:58:27 +08:00
efree ( lcname ) ;
2013-11-27 21:01:57 +08:00
return brake ;
2013-11-12 08:27:48 +08:00
}
2013-11-28 06:59:02 +08:00
2013-11-26 23:58:27 +08:00
efree ( lcname ) ;
2013-11-12 08:27:48 +08:00
}
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-12 08:27:48 +08:00
} /* }}} */
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opline ( phpdbg_opline_ptr_t opline TSRMLS_DC ) /* { { { */
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
2013-11-14 08:29:44 +08:00
if ( zend_hash_index_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ,
2013-11-27 21:01:57 +08:00
( zend_ulong ) opline , ( void * * ) & brake ) = = SUCCESS ) {
2013-12-07 22:35:35 +08:00
return ( brake - > base ? ( phpdbg_breakbase_t * ) brake - > base : ( phpdbg_breakbase_t * ) brake ) ;
2013-11-11 19:54:41 +08:00
}
2013-11-12 06:06:36 +08:00
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-11 19:54:41 +08:00
} /* }}} */
2013-11-11 22:33:53 +08:00
2013-11-28 06:59:02 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_breakpoint_opcode ( zend_uchar opcode TSRMLS_DC ) /* { { { */
2013-11-24 07:14:16 +08:00
{
2013-11-27 21:01:57 +08:00
phpdbg_breakbase_t * brake ;
2013-11-24 07:14:16 +08:00
const char * opname = phpdbg_decode_opcode ( opcode ) ;
if ( memcmp ( opname , PHPDBG_STRL ( " UNKNOWN " ) ) = = 0 ) {
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-24 07:14:16 +08:00
}
if ( zend_hash_index_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] ,
2013-11-27 21:01:57 +08:00
zend_hash_func ( opname , strlen ( opname ) ) , ( void * * ) & brake ) = = SUCCESS ) {
return brake ;
2013-11-24 07:14:16 +08:00
}
2013-11-27 21:01:57 +08:00
return NULL ;
2013-11-24 07:14:16 +08:00
} /* }}} */
2013-12-03 08:15:33 +08:00
static inline zend_bool phpdbg_find_breakpoint_param ( phpdbg_param_t * param , zend_execute_data * execute_data TSRMLS_DC ) /* { { { */
{
zend_function * function = ( zend_function * ) execute_data - > function_state . function ;
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 ;
2013-12-03 08:15:33 +08:00
str = ops - > function_name ? ops - > function_name : " main " ;
len = 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 : {
2013-12-07 22:35:35 +08:00
if ( param - > file . line = = zend_get_executed_lineno ( TSRMLS_C ) ) {
2013-12-03 08:15:33 +08:00
const char * str = zend_get_executed_filename ( TSRMLS_C ) ;
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 ) {
2013-12-09 20:25:00 +08:00
size_t lengths [ 2 ] = { strlen ( param - > method . class ) , ops - > scope - > name_length } ;
if ( lengths [ 0 ] = = lengths [ 1 ] & & memcmp ( param - > method . class , ops - > scope - > name , lengths [ 0 ] ) = = SUCCESS ) {
lengths [ 0 ] = strlen ( param - > method . name ) ;
lengths [ 1 ] = strlen ( ops - > function_name ) ;
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
} /* }}} */
2013-12-03 08:15:33 +08:00
static inline phpdbg_breakbase_t * phpdbg_find_conditional_breakpoint ( zend_execute_data * execute_data TSRMLS_DC ) /* { { { */
2013-11-13 22:22:01 +08:00
{
phpdbg_breakcond_t * bp ;
2013-11-26 18:02:58 +08:00
HashPosition position ;
int breakpoint = FAILURE ;
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , & position ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , ( void * ) & bp , & position ) = = SUCCESS ;
2014-02-17 00:41:50 +08:00
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , & position ) ) {
2013-11-26 18:02:58 +08:00
zval * retval = NULL ;
zval * * orig_retval = EG ( return_value_ptr_ptr ) ;
zend_op_array * orig_ops = EG ( active_op_array ) ;
zend_op * * orig_opline = EG ( opline_ptr ) ;
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 ) {
if ( ! phpdbg_find_breakpoint_param ( & bp - > param , execute_data TSRMLS_CC ) ) {
continue ;
}
}
2013-11-26 18:02:58 +08:00
ALLOC_INIT_ZVAL ( retval ) ;
EG ( return_value_ptr_ptr ) = & retval ;
EG ( active_op_array ) = bp - > ops ;
EG ( no_extensions ) = 1 ;
if ( ! EG ( active_symbol_table ) ) {
zend_rebuild_symbol_table ( TSRMLS_C ) ;
}
zend_try {
PHPDBG_G ( flags ) | = PHPDBG_IN_COND_BP ;
zend_execute ( EG ( active_op_array ) TSRMLS_CC ) ;
2014-04-13 18:32:35 +08:00
# if PHP_VERSION_ID >= 50700
2013-12-18 18:17:43 +08:00
if ( zend_is_true ( retval TSRMLS_CC ) ) {
# else
2013-12-18 18:12:17 +08:00
if ( zend_is_true ( retval ) ) {
2013-12-18 18:17:43 +08:00
# endif
2013-11-26 18:02:58 +08:00
breakpoint = SUCCESS ;
}
} zend_catch {
EG ( no_extensions ) = 1 ;
EG ( return_value_ptr_ptr ) = orig_retval ;
EG ( active_op_array ) = orig_ops ;
EG ( opline_ptr ) = orig_opline ;
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_COND_BP ;
} zend_end_try ( ) ;
EG ( no_extensions ) = 1 ;
EG ( return_value_ptr_ptr ) = orig_retval ;
EG ( active_op_array ) = orig_ops ;
EG ( opline_ptr ) = orig_opline ;
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_COND_BP ;
if ( breakpoint = = SUCCESS ) {
break ;
}
}
2013-11-14 07:36:02 +08:00
2013-11-27 21:01:57 +08:00
return ( breakpoint = = SUCCESS ) ? ( ( phpdbg_breakbase_t * ) bp ) : NULL ;
2013-11-13 22:22:01 +08:00
} /* }}} */
2013-11-28 06:59:02 +08:00
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakpoint ( zend_execute_data * execute_data TSRMLS_DC ) /* { { { */
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 ) & &
2013-12-03 08:15:33 +08:00
( base = phpdbg_find_conditional_breakpoint ( execute_data TSRMLS_CC ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 19:45:05 +08:00
}
2013-11-28 06:59:02 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FILE_BP ) & &
2013-11-27 21:32:38 +08:00
( base = phpdbg_find_breakpoint_file ( execute_data - > op_array TSRMLS_CC ) ) ) {
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 ) ) {
/* check we are at the beginning of the stack */
if ( execute_data - > opline = = EG ( active_op_array ) - > opcodes ) {
2013-11-27 21:01:57 +08:00
if ( ( base = phpdbg_find_breakpoint_symbol (
execute_data - > function_state . function TSRMLS_CC ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
}
}
2013-11-28 06:59:02 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPLINE_BP ) & &
2013-11-27 21:32:38 +08:00
( base = phpdbg_find_breakpoint_opline ( execute_data - > opline TSRMLS_CC ) ) ) {
2013-12-02 21:19:13 +08:00
goto result ;
2013-11-24 07:46:24 +08:00
}
2013-11-28 06:59:02 +08:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPCODE_BP ) & &
2013-11-27 21:32:38 +08:00
( base = phpdbg_find_breakpoint_opcode ( execute_data - > opline - > opcode TSRMLS_CC ) ) ) {
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
PHPDBG_API void phpdbg_delete_breakpoint ( zend_ulong num TSRMLS_DC ) /* { { { */
{
2013-11-27 06:20:52 +08:00
HashTable * * table ;
2013-12-02 21:43:21 +08:00
HashPosition position ;
phpdbg_breakbase_t * brake ;
2013-12-08 02:18:44 +08:00
2013-12-07 22:35:35 +08:00
if ( ( brake = phpdbg_find_breakbase_ex ( num , & table , & position TSRMLS_CC ) ) ) {
2013-12-02 21:43:21 +08:00
char * key ;
2014-09-21 10:17:19 +08:00
uint32_t klen ;
2013-12-02 21:43:21 +08:00
zend_ulong idx ;
int type = brake - > type ;
char * name = NULL ;
size_t name_len = 0L ;
switch ( type ) {
case PHPDBG_BREAK_FILE :
case PHPDBG_BREAK_METHOD :
if ( zend_hash_num_elements ( ( * table ) ) = = 1 ) {
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 : {
if ( zend_hash_num_elements ( ( * table ) ) = = 1 ) {
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
}
2013-12-07 22:35:35 +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
}
2013-12-02 21:43:21 +08:00
switch ( zend_hash_get_current_key_ex (
( * table ) , & key , & klen , & idx , 0 , & position ) ) {
2013-12-03 04:56:25 +08:00
2013-12-02 21:43:21 +08:00
case HASH_KEY_IS_STRING :
zend_hash_del ( ( * table ) , key , klen ) ;
break ;
2013-11-24 19:58:08 +08:00
2013-12-02 21:43:21 +08:00
default :
zend_hash_index_del ( ( * table ) , idx ) ;
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 ) {
zend_hash_del ( & PHPDBG_G ( bp ) [ type ] , name , name_len ) ;
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-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " deleted= \" deleted \" 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-09-21 10:17:19 +08:00
phpdbg_error ( " breakpoint " , " type= \" nobreakpoint \" id= \" %ld \" " , " Failed to find breakpoint #%ld " , num ) ;
2013-11-24 20:14:53 +08:00
}
2013-11-24 19:58:08 +08:00
} /* }}} */
2013-11-24 02:12:51 +08:00
PHPDBG_API void phpdbg_clear_breakpoints ( TSRMLS_D ) /* { { { */
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 ] ) ;
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
} /* }}} */
2013-11-28 06:59:02 +08:00
PHPDBG_API void phpdbg_hit_breakpoint ( phpdbg_breakbase_t * brake , zend_bool output TSRMLS_DC ) /* { { { */
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 ) {
phpdbg_print_breakpoint ( brake TSRMLS_CC ) ;
}
} /* }}} */
2013-11-28 06:59:02 +08:00
PHPDBG_API void phpdbg_print_breakpoint ( phpdbg_breakbase_t * brake TSRMLS_DC ) /* { { { */
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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( 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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( phpdbg_breakline_t * ) brake ) - > hits ) ;
} break ;
2013-12-07 22:35:35 +08:00
case PHPDBG_BREAK_METHOD_OPLINE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" method= \" %s::%s \" opline= \" %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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( phpdbg_breakopline_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_FUNCTION_OPLINE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opline= \" %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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( phpdbg_breakopline_t * ) brake ) - > hits ) ;
} break ;
case PHPDBG_BREAK_FILE_OPLINE : {
2014-09-21 10:17:19 +08:00
phpdbg_notice ( " breakpoint " , " id= \" %d \" opline= \" %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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( 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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
2013-11-28 06:59:02 +08:00
zend_get_executed_lineno ( TSRMLS_C ) ,
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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( 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 ,
phpdbg_param_tostring ( & ( ( phpdbg_breakcond_t * ) brake ) - > param , & param TSRMLS_CC ) ,
( ( phpdbg_breakcond_t * ) brake ) - > code ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( 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 ,
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ,
( ( 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 " ,
2013-11-27 21:01:57 +08:00
zend_get_executed_filename ( TSRMLS_C ) ,
zend_get_executed_lineno ( TSRMLS_C ) ) ;
}
}
} /* }}} */
2013-12-02 21:19:13 +08:00
PHPDBG_API void phpdbg_enable_breakpoint ( zend_ulong id TSRMLS_DC ) /* { { { */
{
phpdbg_breakbase_t * brake = phpdbg_find_breakbase ( id TSRMLS_CC ) ;
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
if ( brake ) {
brake - > disabled = 0 ;
}
} /* }}} */
PHPDBG_API void phpdbg_disable_breakpoint ( zend_ulong id TSRMLS_DC ) /* { { { */
{
phpdbg_breakbase_t * brake = phpdbg_find_breakbase ( id TSRMLS_CC ) ;
2013-12-07 22:31:10 +08:00
2013-12-02 21:19:13 +08:00
if ( brake ) {
brake - > disabled = 1 ;
}
} /* }}} */
PHPDBG_API void phpdbg_enable_breakpoints ( TSRMLS_D ) /* { { { */
{
PHPDBG_G ( flags ) | = PHPDBG_IS_BP_ENABLED ;
} /* }}} */
PHPDBG_API void phpdbg_disable_breakpoints ( TSRMLS_D ) { /* {{{ */
2013-12-07 22:31:10 +08:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_BP_ENABLED ;
2013-12-02 21:19:13 +08:00
} /* }}} */
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase ( zend_ulong id TSRMLS_DC ) /* { { { */
{
HashTable * * table ;
HashPosition position ;
return phpdbg_find_breakbase_ex ( id , & table , & position TSRMLS_CC ) ;
} /* }}} */
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase_ex ( zend_ulong id , HashTable * * * table , HashPosition * position TSRMLS_DC ) /* { { { */
{
if ( zend_hash_index_find ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_MAP ] , id , ( void * * ) table ) = = SUCCESS ) {
phpdbg_breakbase_t * brake ;
for ( zend_hash_internal_pointer_reset_ex ( ( * * table ) , position ) ;
zend_hash_get_current_data_ex ( ( * * table ) , ( void * * ) & brake , position ) = = SUCCESS ;
zend_hash_move_forward_ex ( ( * * table ) , position ) ) {
2013-12-07 22:35:35 +08:00
2013-12-02 21:19:13 +08:00
if ( brake - > id = = id ) {
return brake ;
}
}
}
return NULL ;
} /* }}} */
2013-11-24 02:12:51 +08:00
PHPDBG_API void phpdbg_print_breakpoints ( zend_ulong type TSRMLS_DC ) /* { { { */
2013-11-13 00:04:41 +08:00
{
2014-09-21 10:17:19 +08:00
phpdbg_xml ( " <breakpoints> " ) ;
2013-11-26 18:02:58 +08:00
switch ( type ) {
case PHPDBG_BREAK_SYM : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_SYM_BP ) ) {
HashPosition position ;
phpdbg_breaksymbol_t * brake ;
2014-09-21 10:17:19 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Function Breakpoints: \n " ) ;
2013-11-26 18:02:58 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , & position ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , ( void * * ) & brake , & position ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] , & position ) ) {
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 ,
2013-12-02 21:19:13 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-11-26 18:02:58 +08:00
}
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 ) ) {
HashPosition position [ 2 ] ;
HashTable * class_table ;
char * class_name = NULL ;
2014-09-21 10:17:19 +08:00
uint32_t class_len = 0 ;
2013-11-26 18:02:58 +08:00
zend_ulong class_idx = 0L ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Method Breakpoints: \n " ) ;
2013-11-26 18:02:58 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , & position [ 0 ] ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , ( void * * ) & class_table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] , & position [ 0 ] ) ) {
if ( zend_hash_get_current_key_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] ,
& class_name , & class_len , & class_idx , 0 , & position [ 0 ] ) = = HASH_KEY_IS_STRING ) {
phpdbg_breakmethod_t * brake ;
for ( zend_hash_internal_pointer_reset_ex ( class_table , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( class_table , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( class_table , & position [ 1 ] ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " method " , " id= \" %d \" name= \" %s::%s \" disabled= \" %s \" " , " #%d \t \t %s::%s%s " ,
2013-12-07 22:31:10 +08:00
brake - > id , brake - > class_name , brake - > func_name ,
2013-12-02 21:19:13 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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
HashPosition position [ 2 ] ;
HashTable * points ;
2013-11-26 18:02:58 +08:00
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " File Breakpoints: \n " ) ;
2013-11-27 06:20:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , & position [ 0 ] ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , ( void * * ) & points , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] , & position [ 0 ] ) ) {
2013-11-26 18:02:58 +08:00
phpdbg_breakfile_t * brake ;
2013-11-27 06:20:52 +08:00
for ( zend_hash_internal_pointer_reset_ex ( points , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( points , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( points , & position [ 1 ] ) ) {
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 ,
2013-12-02 21:19:13 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-11-26 18:02:58 +08:00
}
}
2013-11-28 06:59:02 +08:00
2013-11-26 18:02:58 +08:00
} break ;
case PHPDBG_BREAK_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_OPLINE_BP ) ) {
2013-11-28 06:59:02 +08:00
HashPosition position ;
2013-11-26 18:02:58 +08:00
phpdbg_breakline_t * brake ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Opline Breakpoints: \n " ) ;
2013-11-26 18:02:58 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , & position ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , ( void * * ) & brake , & position ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] , & position ) ) {
2013-12-03 04:56:25 +08:00
switch ( brake - > type ) {
case PHPDBG_BREAK_METHOD_OPLINE :
case PHPDBG_BREAK_FUNCTION_OPLINE :
case PHPDBG_BREAK_FILE_OPLINE :
2014-09-21 10:17:19 +08:00
phpdbg_out ( " opline " , " id= \" %d \" num= \" %#lx \" type= \" %s \" disabled= \" %s \" " , " #%d \t \t %#lx \t \t (%s breakpoint)%s " , brake - > id , brake - > opline ,
2013-12-03 04:56:25 +08:00
brake - > type = = PHPDBG_BREAK_METHOD_OPLINE ? " method " :
brake - > type = = PHPDBG_BREAK_FUNCTION_OPLINE ? " function " :
brake - > type = = PHPDBG_BREAK_FILE_OPLINE ? " file " :
2013-12-07 22:35:35 +08:00
" --- error --- " ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 04:56:25 +08:00
break ;
default :
2014-09-21 10:17:19 +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 ;
}
}
} break ;
case PHPDBG_BREAK_METHOD_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_METHOD_OPLINE_BP ) ) {
HashPosition position [ 3 ] ;
HashTable * class_table , * method_table ;
char * class_name = NULL , * method_name = NULL ;
2014-09-21 10:17:19 +08:00
uint32_t class_len = 0 , method_len = 0 ;
2013-12-03 04:56:25 +08:00
zend_ulong class_idx = 0L , method_idx = 0L ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Method opline Breakpoints: \n " ) ;
2013-12-03 04:56:25 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , & position [ 0 ] ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , ( void * * ) & class_table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] , & position [ 0 ] ) ) {
if ( zend_hash_get_current_key_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] ,
& class_name , & class_len , & class_idx , 0 , & position [ 0 ] ) = = HASH_KEY_IS_STRING ) {
for ( zend_hash_internal_pointer_reset_ex ( class_table , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( class_table , ( void * * ) & method_table , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( class_table , & position [ 1 ] ) ) {
if ( zend_hash_get_current_key_ex ( class_table ,
& method_name , & method_len , & method_idx , 0 , & position [ 0 ] ) = = HASH_KEY_IS_STRING ) {
phpdbg_breakopline_t * brake ;
for ( zend_hash_internal_pointer_reset_ex ( method_table , & position [ 2 ] ) ;
zend_hash_get_current_data_ex ( method_table , ( void * * ) & brake , & position [ 2 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( method_table , & position [ 2 ] ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " methodopline " , " id= \" %d \" name= \" %s::%s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s::%s opline %ld%s " ,
2013-12-07 22:35:35 +08:00
brake - > id , brake - > class_name , brake - > func_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 04:56:25 +08:00
}
}
}
}
}
} break ;
case PHPDBG_BREAK_FUNCTION_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FUNCTION_OPLINE_BP ) ) {
HashPosition position [ 2 ] ;
HashTable * function_table ;
char * function_name = NULL ;
2014-09-21 10:17:19 +08:00
uint32_t function_len = 0 ;
2013-12-03 04:56:25 +08:00
zend_ulong function_idx = 0L ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Function opline Breakpoints: \n " ) ;
2013-12-03 04:56:25 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , & position [ 0 ] ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , ( void * * ) & function_table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] , & position [ 0 ] ) ) {
if ( zend_hash_get_current_key_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ,
& function_name , & function_len , & function_idx , 0 , & position [ 0 ] ) = = HASH_KEY_IS_STRING ) {
phpdbg_breakopline_t * brake ;
for ( zend_hash_internal_pointer_reset_ex ( function_table , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( function_table , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( function_table , & position [ 1 ] ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " functionopline " , " id= \" %d \" name= \" %s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s opline %ld%s " ,
2013-12-07 22:35:35 +08:00
brake - > id , brake - > func_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 04:56:25 +08:00
}
}
}
} break ;
case PHPDBG_BREAK_FILE_OPLINE : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_FILE_OPLINE_BP ) ) {
HashPosition position [ 2 ] ;
HashTable * file_table ;
char * file_name = NULL ;
2014-09-21 10:17:19 +08:00
uint32_t file_len = 0 ;
2013-12-03 04:56:25 +08:00
zend_ulong file_idx = 0L ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " File opline Breakpoints: \n " ) ;
2013-12-03 04:56:25 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , & position [ 0 ] ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , ( void * * ) & file_table , & position [ 0 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] , & position [ 0 ] ) ) {
if ( zend_hash_get_current_key_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] ,
& file_name , & file_len , & file_idx , 0 , & position [ 0 ] ) = = HASH_KEY_IS_STRING ) {
phpdbg_breakopline_t * brake ;
for ( zend_hash_internal_pointer_reset_ex ( file_table , & position [ 1 ] ) ;
zend_hash_get_current_data_ex ( file_table , ( void * * ) & brake , & position [ 1 ] ) = = SUCCESS ;
zend_hash_move_forward_ex ( file_table , & position [ 1 ] ) ) {
2014-09-21 10:17:19 +08:00
phpdbg_writeln ( " fileopline " , " id= \" %d \" name= \" %s \" num= \" %ld \" disabled= \" %s \" " , " #%d \t \t %s opline %ld%s " ,
2013-12-07 22:35:35 +08:00
brake - > id , brake - > class_name , brake - > opline_num ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
2013-12-03 04:56:25 +08:00
}
}
2013-11-26 18:02:58 +08:00
}
} break ;
case PHPDBG_BREAK_COND : if ( ( PHPDBG_G ( flags ) & PHPDBG_HAS_COND_BP ) ) {
HashPosition position ;
phpdbg_breakcond_t * brake ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Conditional Breakpoints: \n " ) ;
2013-11-26 18:02:58 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , & position ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , ( void * * ) & brake , & position ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] , & position ) ) {
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 " ,
2013-12-07 22:31:10 +08:00
brake - > id ,
2013-12-03 08:43:05 +08:00
brake - > param . str ,
2013-12-07 22:31:10 +08:00
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_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 " ,
2013-12-09 20:25:00 +08:00
brake - > id ,
brake - > param . str ,
brake - > param . num ,
brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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 " ,
2013-12-07 22:31:10 +08:00
brake - > id ,
2013-12-03 08:43:05 +08:00
brake - > param . method . class ,
brake - > param . method . name ,
2013-12-07 22:31:10 +08:00
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 " ,
2013-12-09 20:25:00 +08:00
brake - > id ,
brake - > param . method . class ,
brake - > param . method . name ,
brake - > param . num ,
brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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 " ,
2013-12-07 22:31:10 +08:00
brake - > id ,
2013-12-03 08:43:05 +08:00
brake - > param . file . name ,
brake - > param . file . line ,
brake - > code ,
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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 " ,
2013-12-07 22:31:10 +08:00
brake - > id ,
2013-12-03 08:43:05 +08:00
brake - > param . addr ,
2013-12-07 22:31:10 +08:00
brake - > code ,
2013-12-03 08:43:05 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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 ,
2013-12-03 08:43:05 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
}
2013-11-26 18:02:58 +08:00
}
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 ) {
HashPosition position ;
phpdbg_breakop_t * brake ;
2014-09-23 05:28:07 +08:00
phpdbg_out ( SEPARATE " \n " ) ;
phpdbg_out ( " Opcode Breakpoints: \n " ) ;
2013-11-26 18:02:58 +08:00
for ( zend_hash_internal_pointer_reset_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , & position ) ;
zend_hash_get_current_data_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , ( void * * ) & brake , & position ) = = SUCCESS ;
zend_hash_move_forward_ex ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPCODE ] , & position ) ) {
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 ,
2013-12-02 21:19:13 +08:00
( ( phpdbg_breakbase_t * ) brake ) - > disabled ? " [disabled] " : " " ) ;
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
} /* }}} */