2013-11-10 01:30:32 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-03-13 09:09:42 +00:00
| PHP Version 7 |
2013-11-10 01:30:32 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2016-01-01 17:19:27 +00:00
| Copyright ( c ) 1997 - 2016 The PHP Group |
2013-11-10 01:30:32 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 3.01 of the PHP license , |
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Felipe Pena < felipe @ php . net > |
2013-11-10 10:44:42 +00:00
| Authors : Joe Watkins < joe . watkins @ live . co . uk > |
2013-11-22 19:06:31 +00:00
| Authors : Bob Weinand < bwoebi @ php . net > |
2013-11-10 01:30:32 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# include <stdio.h>
# include <string.h>
# include "zend.h"
2013-11-10 13:01:46 +00:00
# include "zend_compile.h"
2014-10-24 17:29:50 +00:00
# include "zend_exceptions.h"
2015-03-13 08:29:43 +00:00
# include "zend_vm.h"
2015-04-21 21:09:09 +00:00
# include "zend_generators.h"
2015-07-16 08:28:59 +00:00
# include "zend_interfaces.h"
2013-11-10 10:44:42 +00:00
# include "phpdbg.h"
2014-09-09 00:15:33 +00:00
2013-11-10 10:44:42 +00:00
# include "phpdbg_help.h"
2013-11-12 08:26:11 +00:00
# include "phpdbg_print.h"
2013-11-17 15:42:34 +00:00
# include "phpdbg_info.h"
2013-11-13 14:22:01 +00:00
# include "phpdbg_break.h"
2013-11-10 20:01:09 +00:00
# include "phpdbg_opcode.h"
2013-11-12 00:24:24 +00:00
# include "phpdbg_list.h"
2013-11-12 02:19:43 +00:00
# include "phpdbg_utils.h"
2013-11-17 21:01:41 +00:00
# include "phpdbg_prompt.h"
# include "phpdbg_cmd.h"
2013-11-24 14:54:14 +00:00
# include "phpdbg_set.h"
2013-12-08 18:29:15 +00:00
# include "phpdbg_frame.h"
2014-02-18 19:48:33 +00:00
# include "phpdbg_lexer.h"
# include "phpdbg_parser.h"
2014-09-10 13:53:40 +00:00
# include "phpdbg_wait.h"
2014-10-21 09:46:32 +00:00
# include "phpdbg_eol.h"
2014-09-10 13:53:40 +00:00
2015-03-16 09:10:26 +00:00
# if ZEND_VM_KIND != ZEND_VM_KIND_CALL
# error "phpdbg can only be built with CALL zend vm kind"
# endif
2016-02-16 22:47:37 +00:00
ZEND_EXTERN_MODULE_GLOBALS ( phpdbg )
2014-10-26 02:50:28 +00:00
extern int phpdbg_startup_run ;
2014-09-09 00:15:33 +00:00
# ifdef HAVE_LIBDL
# ifdef PHP_WIN32
# include "win32/param.h"
# include "win32/winutil.h"
# define GET_DL_ERROR() php_win_err()
# elif defined(NETWARE)
# include <sys/param.h>
# define GET_DL_ERROR() dlerror()
# else
# include <sys/param.h>
# define GET_DL_ERROR() DL_ERROR()
# endif
# endif
2014-02-18 19:48:33 +00:00
2013-11-13 21:15:45 +00:00
/* {{{ command declarations */
2013-11-21 19:47:31 +00:00
const phpdbg_command_t phpdbg_prompt_commands [ ] = {
2014-10-02 23:29:41 +00:00
PHPDBG_COMMAND_D ( exec , " set execution context " , ' e ' , NULL , " s " , 0 ) ,
PHPDBG_COMMAND_D ( step , " step through execution " , ' s ' , NULL , 0 , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( continue , " continue execution " , ' c ' , NULL , 0 , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( run , " attempt execution " , ' r ' , NULL , " |s " , 0 ) ,
2014-10-03 10:43:32 +00:00
PHPDBG_COMMAND_D ( ev , " evaluate some code " , 0 , NULL , " i " , PHPDBG_ASYNC_SAFE ) , /* restricted ASYNC_SAFE */
2014-10-02 23:29:41 +00:00
PHPDBG_COMMAND_D ( until , " continue past the current line " , ' u ' , NULL , 0 , 0 ) ,
PHPDBG_COMMAND_D ( finish , " continue past the end of the stack " , ' F ' , NULL , 0 , 0 ) ,
PHPDBG_COMMAND_D ( leave , " continue until the end of the stack " , ' L ' , NULL , 0 , 0 ) ,
2015-03-21 22:03:22 +00:00
PHPDBG_COMMAND_D ( print , " print something " , ' p ' , phpdbg_print_commands , " |*c " , 0 ) ,
2014-10-02 23:29:41 +00:00
PHPDBG_COMMAND_D ( break , " set breakpoint " , ' b ' , phpdbg_break_commands , " |*c " , 0 ) ,
PHPDBG_COMMAND_D ( back , " show trace " , ' t ' , NULL , " |n " , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( frame , " switch to a frame " , ' f ' , NULL , " |n " , PHPDBG_ASYNC_SAFE ) ,
2015-03-21 22:03:22 +00:00
PHPDBG_COMMAND_D ( list , " lists some code " , ' l ' , phpdbg_list_commands , " * " , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( info , " displays some informations " , ' i ' , phpdbg_info_commands , " |s " , PHPDBG_ASYNC_SAFE ) ,
2014-10-02 23:29:41 +00:00
PHPDBG_COMMAND_D ( clean , " clean the execution environment " , ' X ' , NULL , 0 , 0 ) ,
PHPDBG_COMMAND_D ( clear , " clear breakpoints " , ' C ' , NULL , 0 , 0 ) ,
PHPDBG_COMMAND_D ( help , " show help menu " , ' h ' , phpdbg_help_commands , " |s " , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( set , " set phpdbg configuration " , ' S ' , phpdbg_set_commands , " s " , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( register , " register a function " , ' R ' , NULL , " s " , 0 ) ,
PHPDBG_COMMAND_D ( source , " execute a phpdbginit " , ' < ' , NULL , " s " , 0 ) ,
PHPDBG_COMMAND_D ( export , " export breaks to a .phpdbginit script " , ' > ' , NULL , " s " , PHPDBG_ASYNC_SAFE ) ,
PHPDBG_COMMAND_D ( sh , " shell a command " , 0 , NULL , " i " , 0 ) ,
PHPDBG_COMMAND_D ( quit , " exit phpdbg " , ' q ' , NULL , 0 , PHPDBG_ASYNC_SAFE ) ,
2014-10-04 21:21:34 +00:00
PHPDBG_COMMAND_D ( wait , " wait for other process " , ' W ' , NULL , 0 , 0 ) ,
2014-10-02 23:29:41 +00:00
PHPDBG_COMMAND_D ( watch , " set watchpoint " , ' w ' , phpdbg_watch_commands , " |ss " , 0 ) ,
2015-04-21 10:31:43 +00:00
PHPDBG_COMMAND_D ( next , " step over next line " , ' n ' , NULL , 0 , PHPDBG_ASYNC_SAFE ) ,
2014-10-21 09:29:18 +00:00
PHPDBG_COMMAND_D ( eol , " set EOL " , ' E ' , NULL , " |s " , 0 ) ,
2013-11-17 21:01:41 +00:00
PHPDBG_END_COMMAND
2013-11-13 21:15:45 +00:00
} ; /* }}} */
2013-11-10 10:44:42 +00:00
2014-12-13 22:06:14 +00:00
static inline int phpdbg_call_register ( phpdbg_param_t * stack ) /* { { { */
2013-12-06 20:18:44 +00:00
{
2014-02-21 20:42:15 +00:00
phpdbg_param_t * name = NULL ;
2013-12-06 20:18:44 +00:00
2014-02-21 20:42:15 +00:00
if ( stack - > type = = STACK_PARAM ) {
2014-10-07 10:30:26 +00:00
char * lc_name ;
2014-10-07 22:27:12 +00:00
2014-02-21 20:42:15 +00:00
name = stack - > next ;
2014-09-21 02:17:19 +00:00
2014-02-21 21:31:01 +00:00
if ( ! name | | name - > type ! = STR_PARAM ) {
return FAILURE ;
}
2014-02-19 08:33:54 +00:00
2014-10-07 10:30:26 +00:00
lc_name = zend_str_tolower_dup ( name - > str , name - > len ) ;
2014-02-19 08:33:54 +00:00
2014-10-24 17:29:50 +00:00
if ( zend_hash_str_exists ( & PHPDBG_G ( registered ) , lc_name , name - > len ) ) {
zval fretval ;
2014-02-19 08:33:54 +00:00
zend_fcall_info fci ;
memset ( & fci , 0 , sizeof ( zend_fcall_info ) ) ;
2014-10-24 17:29:50 +00:00
ZVAL_STRINGL ( & fci . function_name , lc_name , name - > len ) ;
2014-02-19 08:33:54 +00:00
fci . size = sizeof ( zend_fcall_info ) ;
fci . function_table = & PHPDBG_G ( registered ) ;
2016-03-02 13:56:39 +00:00
//???fci.symbol_table = zend_rebuild_symbol_table();
fci . symbol_table = NULL ;
2014-10-24 17:29:50 +00:00
fci . object = NULL ;
fci . retval = & fretval ;
2014-02-19 08:33:54 +00:00
fci . no_separation = 1 ;
2014-02-21 20:42:15 +00:00
if ( name - > next ) {
2014-02-19 08:33:54 +00:00
zval params ;
2014-02-21 20:42:15 +00:00
phpdbg_param_t * next = name - > next ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
array_init ( & params ) ;
2014-02-24 22:30:46 +00:00
while ( next ) {
char * buffered = NULL ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
switch ( next - > type ) {
2014-02-24 22:30:46 +00:00
case OP_PARAM :
case COND_PARAM :
2014-02-19 08:33:54 +00:00
case STR_PARAM :
2014-10-24 17:29:50 +00:00
add_next_index_stringl ( & params , next - > str , next - > len ) ;
2014-02-19 08:33:54 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
case NUMERIC_PARAM :
2014-08-25 17:24:55 +00:00
add_next_index_long ( & params , next - > num ) ;
2014-02-19 08:33:54 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-24 22:30:46 +00:00
case METHOD_PARAM :
2014-10-24 17:29:50 +00:00
spprintf ( & buffered , 0 , " %s::%s " , next - > method . class , next - > method . name ) ;
add_next_index_string ( & params , buffered ) ;
2014-02-24 22:30:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-24 22:30:46 +00:00
case NUMERIC_METHOD_PARAM :
2014-10-24 17:29:50 +00:00
spprintf ( & buffered , 0 , " %s::%s#%ld " , next - > method . class , next - > method . name , next - > num ) ;
add_next_index_string ( & params , buffered ) ;
2014-02-24 22:30:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-24 22:30:46 +00:00
case NUMERIC_FUNCTION_PARAM :
2014-10-24 17:29:50 +00:00
spprintf ( & buffered , 0 , " %s#%ld " , next - > str , next - > num ) ;
add_next_index_string ( & params , buffered ) ;
2014-02-24 22:30:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-24 22:30:46 +00:00
case FILE_PARAM :
2014-10-24 17:29:50 +00:00
spprintf ( & buffered , 0 , " %s:%ld " , next - > file . name , next - > file . line ) ;
add_next_index_string ( & params , buffered ) ;
2014-02-24 22:30:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-24 22:30:46 +00:00
case NUMERIC_FILE_PARAM :
2014-10-24 17:29:50 +00:00
spprintf ( & buffered , 0 , " %s:#%ld " , next - > file . name , next - > file . line ) ;
add_next_index_string ( & params , buffered ) ;
2014-02-24 22:30:46 +00:00
break ;
2014-09-21 02:17:19 +00:00
2014-02-19 08:33:54 +00:00
default : {
/* not yet */
}
}
2014-09-21 02:17:19 +00:00
next = next - > next ;
2014-02-19 08:33:54 +00:00
}
2013-12-06 20:18:44 +00:00
2014-12-13 22:06:14 +00:00
zend_fcall_info_args ( & fci , & params ) ;
2014-02-19 08:33:54 +00:00
} else {
fci . params = NULL ;
fci . param_count = 0 ;
2013-12-06 20:18:44 +00:00
}
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
2013-12-06 20:18:44 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_debug ( " created %d params from arguments " , fci . param_count ) ;
2013-12-06 20:18:44 +00:00
2014-12-13 22:06:14 +00:00
if ( zend_call_function ( & fci , NULL ) = = SUCCESS ) {
zend_print_zval_r ( & fretval , 0 ) ;
2014-10-19 18:09:39 +00:00
phpdbg_out ( " \n " ) ;
2014-10-24 17:29:50 +00:00
zval_ptr_dtor ( & fretval ) ;
2014-02-19 08:33:54 +00:00
}
2013-12-06 20:18:44 +00:00
2014-10-24 17:29:50 +00:00
zval_dtor ( & fci . function_name ) ;
2014-10-07 10:30:26 +00:00
efree ( lc_name ) ;
2013-12-06 20:18:44 +00:00
2014-02-19 08:33:54 +00:00
return SUCCESS ;
2014-09-21 02:17:19 +00:00
}
2014-10-07 10:30:26 +00:00
efree ( lc_name ) ;
2013-12-06 20:18:44 +00:00
}
return FAILURE ;
} /* }}} */
2014-10-28 16:20:21 +00:00
struct phpdbg_init_state {
int line ;
zend_bool in_code ;
char * code ;
size_t code_len ;
const char * init_file ;
} ;
2014-09-21 02:17:19 +00:00
2014-12-13 22:06:14 +00:00
static void phpdbg_line_init ( char * cmd , struct phpdbg_init_state * state ) {
2014-10-28 16:20:21 +00:00
size_t cmd_len = strlen ( cmd ) ;
2013-11-17 12:07:01 +00:00
2014-10-28 16:20:21 +00:00
state - > line + + ;
2013-11-17 12:07:01 +00:00
2014-10-28 16:20:21 +00:00
while ( cmd_len > 0L & & isspace ( cmd [ cmd_len - 1 ] ) ) {
cmd_len - - ;
}
2013-11-16 10:59:50 +00:00
2014-10-28 16:20:21 +00:00
cmd [ cmd_len ] = ' \0 ' ;
2013-11-17 12:07:01 +00:00
2014-10-28 16:20:21 +00:00
if ( * cmd & & cmd_len > 0L & & cmd [ 0 ] ! = ' # ' ) {
if ( cmd_len = = 2 ) {
if ( memcmp ( cmd , " <: " , sizeof ( " <: " ) - 1 ) = = SUCCESS ) {
state - > in_code = 1 ;
return ;
} else {
if ( memcmp ( cmd , " :> " , sizeof ( " :> " ) - 1 ) = = SUCCESS ) {
state - > in_code = 0 ;
state - > code [ state - > code_len ] = ' \0 ' ;
2014-12-13 22:06:14 +00:00
zend_eval_stringl ( state - > code , state - > code_len , NULL , " phpdbginit code " ) ;
2014-10-28 16:20:21 +00:00
free ( state - > code ) ;
state - > code = NULL ;
return ;
}
}
}
2013-11-20 12:10:27 +00:00
2014-10-28 16:20:21 +00:00
if ( state - > in_code ) {
if ( state - > code = = NULL ) {
state - > code = malloc ( cmd_len + 1 ) ;
} else {
state - > code = realloc ( state - > code , state - > code_len + cmd_len + 1 ) ;
}
2014-02-21 20:42:15 +00:00
2014-10-28 16:20:21 +00:00
if ( state - > code ) {
memcpy ( & state - > code [ state - > code_len ] , cmd , cmd_len ) ;
state - > code_len + = cmd_len ;
}
2013-11-20 12:10:27 +00:00
2014-10-28 16:20:21 +00:00
return ;
}
2014-09-21 02:17:19 +00:00
2014-10-28 16:20:21 +00:00
zend_try {
2014-12-13 22:06:14 +00:00
char * input = phpdbg_read_input ( cmd ) ;
2014-10-28 16:20:21 +00:00
phpdbg_param_t stack ;
2014-06-08 20:34:30 +00:00
2014-10-28 16:20:21 +00:00
phpdbg_init_param ( & stack , STACK_PARAM ) ;
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 1 ) ;
2014-06-08 20:34:30 +00:00
2014-12-13 22:06:14 +00:00
if ( phpdbg_do_parse ( & stack , input ) < = 0 ) {
switch ( phpdbg_stack_execute ( & stack , 1 /* allow_async_unsafe == 1 */ ) ) {
2014-10-28 16:20:21 +00:00
case FAILURE :
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
if ( phpdbg_call_register ( & stack ) = = FAILURE ) {
2014-10-28 16:20:21 +00:00
if ( state - > init_file ) {
2014-12-13 22:06:14 +00:00
phpdbg_output_err_buf ( " initfailure " , " %b file= \" %s \" line= \" %d \" input= \" %s \" " , " Unrecognized command in %s:%d: %s, %b! " , state - > init_file , state - > line , input ) ;
2014-10-28 16:20:21 +00:00
} else {
2014-12-13 22:06:14 +00:00
phpdbg_output_err_buf ( " initfailure " , " %b line= \" %d \" input= \" %s \" " , " Unrecognized command on line %d: %s, %b! " , state - > line , input ) ;
2014-10-28 16:20:21 +00:00
}
2014-10-26 21:21:18 +00:00
}
2014-10-28 16:20:21 +00:00
break ;
2013-11-17 12:07:01 +00:00
}
}
2013-11-16 10:59:50 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
2014-10-28 16:20:21 +00:00
phpdbg_stack_free ( & stack ) ;
2014-12-13 22:06:14 +00:00
phpdbg_destroy_input ( & input ) ;
2014-10-28 16:20:21 +00:00
} zend_catch {
PHPDBG_G ( flags ) & = ~ ( PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING ) ;
if ( PHPDBG_G ( flags ) & PHPDBG_IS_QUITTING ) {
zend_bailout ( ) ;
}
} zend_end_try ( ) ;
}
}
2014-12-13 22:06:14 +00:00
void phpdbg_string_init ( char * buffer ) {
2014-10-28 16:20:21 +00:00
struct phpdbg_init_state state = { 0 } ;
char * str = strtok ( buffer , " \n " ) ;
while ( str ) {
2014-12-13 22:06:14 +00:00
phpdbg_line_init ( str , & state ) ;
2014-10-28 16:20:21 +00:00
str = strtok ( NULL , " \n " ) ;
}
if ( state . code ) {
free ( state . code ) ;
}
}
2014-12-13 22:06:14 +00:00
void phpdbg_try_file_init ( char * init_file , size_t init_file_len , zend_bool free_init ) /* { { { */
2014-10-28 16:20:21 +00:00
{
2014-12-16 10:46:06 +00:00
zend_stat_t sb ;
2014-10-28 16:20:21 +00:00
if ( init_file & & VCWD_STAT ( init_file , & sb ) ! = - 1 ) {
FILE * fp = fopen ( init_file , " r " ) ;
if ( fp ) {
char cmd [ PHPDBG_MAX_CMD ] ;
struct phpdbg_init_state state = { 0 } ;
state . init_file = init_file ;
while ( fgets ( cmd , PHPDBG_MAX_CMD , fp ) ! = NULL ) {
2014-12-13 22:06:14 +00:00
phpdbg_line_init ( cmd , & state ) ;
2014-10-28 16:20:21 +00:00
}
if ( state . code ) {
free ( state . code ) ;
2013-11-17 12:07:01 +00:00
}
2013-11-16 10:59:50 +00:00
2013-11-17 12:07:01 +00:00
fclose ( fp ) ;
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " initfailure " , " type= \" openfile \" file= \" %s \" " , " Failed to open %s for initialization " , init_file ) ;
2013-11-17 12:07:01 +00:00
}
2013-11-16 10:59:50 +00:00
2013-11-25 12:19:01 +00:00
if ( free_init ) {
2013-12-04 23:26:14 +00:00
free ( init_file ) ;
2013-11-17 12:07:01 +00:00
}
}
2013-11-14 14:14:13 +00:00
} /* }}} */
2013-11-10 11:03:29 +00:00
2014-12-13 22:06:14 +00:00
void phpdbg_init ( char * init_file , size_t init_file_len , zend_bool use_default ) /* { { { */
2013-11-25 12:19:01 +00:00
{
if ( ! init_file & & use_default ) {
char * scan_dir = getenv ( " PHP_INI_SCAN_DIR " ) ;
2015-06-24 22:35:52 +00:00
char * sys_ini ;
2013-11-25 16:15:51 +00:00
int i ;
2013-11-25 12:19:01 +00:00
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( & sys_ini , " %s/ " PHPDBG_INIT_FILENAME , PHP_CONFIG_FILE_PATH ) ) ;
2015-06-24 22:35:52 +00:00
phpdbg_try_file_init ( sys_ini , strlen ( sys_ini ) , 0 ) ;
free ( sys_ini ) ;
2013-11-25 12:19:01 +00:00
if ( ! scan_dir ) {
scan_dir = PHP_CONFIG_FILE_SCAN_DIR ;
}
2013-11-25 16:15:51 +00:00
while ( * scan_dir ! = 0 ) {
i = 0 ;
while ( scan_dir [ i ] ! = ' : ' ) {
if ( scan_dir [ i + + ] = = 0 ) {
i = - 1 ;
break ;
}
}
if ( i ! = - 1 ) {
scan_dir [ i ] = 0 ;
}
2013-12-08 18:07:49 +00:00
2015-07-27 13:02:01 +00:00
ZEND_IGNORE_VALUE ( asprintf ( & init_file , " %s/%s " , scan_dir , PHPDBG_INIT_FILENAME ) ) ;
2014-12-13 22:06:14 +00:00
phpdbg_try_file_init ( init_file , strlen ( init_file ) , 1 ) ;
2013-11-25 16:15:51 +00:00
if ( i = = - 1 ) {
break ;
}
scan_dir + = i + 1 ;
}
2013-11-25 12:19:01 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_try_file_init ( PHPDBG_STRL ( PHPDBG_INIT_FILENAME ) , 0 ) ;
2013-11-25 12:19:01 +00:00
} else {
2014-12-13 22:06:14 +00:00
phpdbg_try_file_init ( init_file , init_file_len , 1 ) ;
2013-11-25 12:19:01 +00:00
}
}
2015-04-21 13:53:12 +00:00
/* }}} */
2013-11-25 12:19:01 +00:00
2015-08-03 23:22:04 +00:00
void phpdbg_clean ( zend_bool full ) /* { { { */
{
/* this is implicitly required */
if ( PHPDBG_G ( ops ) ) {
destroy_op_array ( PHPDBG_G ( ops ) ) ;
efree ( PHPDBG_G ( ops ) ) ;
PHPDBG_G ( ops ) = NULL ;
}
if ( full ) {
PHPDBG_G ( flags ) | = PHPDBG_IS_CLEANING ;
}
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( exec ) /* {{{ */
2013-11-10 18:29:05 +00:00
{
2014-12-16 10:46:06 +00:00
zend_stat_t sb ;
2013-11-17 12:07:01 +00:00
2014-02-21 20:42:15 +00:00
if ( VCWD_STAT ( param - > str , & sb ) ! = FAILURE ) {
if ( sb . st_mode & ( S_IFREG | S_IFLNK ) ) {
2014-12-13 22:06:14 +00:00
char * res = phpdbg_resolve_path ( param - > str ) ;
2014-02-21 20:42:15 +00:00
size_t res_len = strlen ( res ) ;
2013-11-23 15:34:36 +00:00
2014-02-21 20:42:15 +00:00
if ( ( res_len ! = PHPDBG_G ( exec_len ) ) | | ( memcmp ( res , PHPDBG_G ( exec ) , res_len ) ! = SUCCESS ) ) {
2014-10-26 23:34:56 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2014-12-13 22:06:14 +00:00
if ( phpdbg_ask_user_permission ( " Do you really want to stop execution to set a new execution context? " ) = = FAILURE ) {
2014-10-26 02:50:28 +00:00
return FAILURE ;
}
}
2013-11-23 15:34:36 +00:00
2014-02-21 20:42:15 +00:00
if ( PHPDBG_G ( exec ) ) {
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " exec " , " type= \" unset \" context= \" %s \" " , " Unsetting old execution context: %s " , PHPDBG_G ( exec ) ) ;
2014-02-21 20:42:15 +00:00
efree ( PHPDBG_G ( exec ) ) ;
PHPDBG_G ( exec ) = NULL ;
PHPDBG_G ( exec_len ) = 0L ;
}
2013-11-23 13:04:27 +00:00
2014-02-21 20:42:15 +00:00
if ( PHPDBG_G ( ops ) ) {
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " exec " , " type= \" unsetops \" " , " Destroying compiled opcodes " ) ;
2015-08-03 23:22:04 +00:00
phpdbg_clean ( 0 ) ;
2014-02-21 20:42:15 +00:00
}
2013-11-17 12:07:01 +00:00
2014-02-21 20:42:15 +00:00
PHPDBG_G ( exec ) = res ;
PHPDBG_G ( exec_len ) = res_len ;
2014-09-25 13:28:25 +00:00
2014-10-04 21:30:57 +00:00
VCWD_CHDIR_FILE ( res ) ;
2014-04-13 07:09:53 +00:00
* SG ( request_info ) . argv = PHPDBG_G ( exec ) ;
2015-07-24 15:17:09 +00:00
php_build_argv ( NULL , & PG ( http_globals ) [ TRACK_VARS_SERVER ] ) ;
2013-11-17 12:07:01 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " exec " , " type= \" set \" context= \" %s \" " , " Set execution context: %s " , PHPDBG_G ( exec ) ) ;
2014-04-20 10:54:50 +00:00
2014-10-26 23:34:56 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2015-08-03 23:22:04 +00:00
phpdbg_clean ( 1 ) ;
2015-07-24 15:17:09 +00:00
return SUCCESS ;
2014-04-20 10:54:50 +00:00
}
2014-10-26 02:50:28 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_compile ( ) ;
2013-11-17 12:07:01 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " exec " , " type= \" unchanged \" " , " Execution context not changed " ) ;
2013-11-17 12:07:01 +00:00
}
2014-02-21 20:42:15 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " exec " , " type= \" invalid \" context= \" %s \" " , " Cannot use %s as execution context, not a valid file or symlink " , param - > str ) ;
2014-02-21 20:42:15 +00:00
}
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " exec " , " type= \" notfound \" context= \" %s \" " , " Cannot stat %s, ensure the file exists " , param - > str ) ;
2013-11-17 12:07:01 +00:00
}
2013-11-10 18:29:05 +00:00
return SUCCESS ;
2013-11-10 11:35:59 +00:00
} /* }}} */
2014-12-13 22:06:14 +00:00
int phpdbg_compile ( void ) /* { { { */
2013-11-10 18:29:05 +00:00
{
zend_file_handle fh ;
2015-08-01 19:33:23 +00:00
char * buf ;
size_t len ;
2013-11-10 13:01:46 +00:00
2014-04-19 20:22:09 +00:00
if ( ! PHPDBG_G ( exec ) ) {
2014-09-25 20:01:31 +00:00
phpdbg_error ( " inactive " , " type= \" nocontext \" " , " No execution context " ) ;
2013-11-13 21:43:54 +00:00
return FAILURE ;
}
2013-11-11 22:02:34 +00:00
2015-08-01 19:33:23 +00:00
if ( php_stream_open_for_zend_ex ( PHPDBG_G ( exec ) , & fh , USE_PATH | STREAM_OPEN_FOR_INCLUDE ) = = SUCCESS & & zend_stream_fixup ( & fh , & buf , & len ) = = SUCCESS ) {
/* Skip #! line */
if ( len > = 3 & & buf [ 0 ] = = ' # ' & & buf [ 1 ] = = ' ! ' ) {
char * end = buf + len ;
do {
switch ( fh . handle . stream . mmap . buf + + [ 0 ] ) {
case ' \r ' :
if ( fh . handle . stream . mmap . buf [ 0 ] = = ' \n ' ) {
fh . handle . stream . mmap . buf + + ;
}
case ' \n ' :
CG ( start_lineno ) = 2 ;
fh . handle . stream . mmap . len - = fh . handle . stream . mmap . buf - buf ;
end = fh . handle . stream . mmap . buf ;
}
} while ( fh . handle . stream . mmap . buf + 1 < end ) ;
}
2014-12-13 22:06:14 +00:00
PHPDBG_G ( ops ) = zend_compile_file ( & fh , ZEND_INCLUDE ) ;
2015-08-01 19:33:23 +00:00
fh . handle . stream . mmap . buf = buf ;
fh . handle . stream . mmap . len = len ;
2014-12-13 22:06:14 +00:00
zend_destroy_file_handle ( & fh ) ;
2015-03-17 21:58:37 +00:00
if ( EG ( exception ) ) {
zend_exception_error ( EG ( exception ) , E_ERROR ) ;
zend_bailout ( ) ;
}
2013-11-13 21:43:54 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " compile " , " context= \" %s \" " , " Successful compilation of %s " , PHPDBG_G ( exec ) ) ;
2014-10-26 02:50:28 +00:00
2013-11-13 21:43:54 +00:00
return SUCCESS ;
2013-11-10 21:07:29 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " compile " , " type= \" openfailure \" context= \" %s \" " , " Could not open file %s " , PHPDBG_G ( exec ) ) ;
2013-11-10 21:07:29 +00:00
}
2013-11-10 21:38:58 +00:00
2013-11-10 18:29:05 +00:00
return FAILURE ;
2013-11-10 11:03:29 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( step ) /* {{{ */
2013-11-10 18:29:05 +00:00
{
2014-10-24 17:29:50 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2014-04-21 21:00:21 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_STEPPING ;
}
2013-11-12 02:19:43 +00:00
2014-04-20 14:47:24 +00:00
return PHPDBG_NEXT ;
2013-11-10 14:28:14 +00:00
} /* }}} */
2014-04-20 16:10:52 +00:00
PHPDBG_COMMAND ( continue ) /* {{{ */
2013-11-10 18:29:05 +00:00
{
return PHPDBG_NEXT ;
2013-11-10 15:32:24 +00:00
} /* }}} */
2015-04-21 13:53:12 +00:00
int phpdbg_skip_line_helper ( ) /* { { { */ {
2016-02-17 19:26:47 +00:00
zend_execute_data * ex = phpdbg_user_execute_data ( EG ( current_execute_data ) ) ;
const zend_op_array * op_array = & ex - > func - > op_array ;
2015-09-19 13:19:26 +00:00
const zend_op * opline = op_array - > opcodes ;
2013-11-18 01:44:46 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IN_UNTIL ;
2016-02-17 19:26:47 +00:00
PHPDBG_G ( seek_ex ) = ex ;
2015-09-19 13:19:26 +00:00
do {
2016-02-17 19:26:47 +00:00
if ( opline - > lineno ! = ex - > opline - > lineno
2015-09-19 13:19:26 +00:00
| | opline - > opcode = = ZEND_RETURN
| | opline - > opcode = = ZEND_FAST_RET
| | opline - > opcode = = ZEND_GENERATOR_RETURN
| | opline - > opcode = = ZEND_EXIT
| | opline - > opcode = = ZEND_YIELD
| | opline - > opcode = = ZEND_YIELD_FROM
) {
zend_hash_index_update_ptr ( & PHPDBG_G ( seek ) , ( zend_ulong ) opline , ( void * ) opline ) ;
2013-11-18 01:44:46 +00:00
}
2015-09-19 13:19:26 +00:00
} while ( + + opline < op_array - > opcodes + op_array - > last ) ;
2013-11-18 14:09:25 +00:00
2013-11-16 10:59:50 +00:00
return PHPDBG_UNTIL ;
2015-04-21 10:31:43 +00:00
}
2015-04-21 13:53:12 +00:00
/* }}} */
2015-04-21 10:31:43 +00:00
PHPDBG_COMMAND ( until ) /* {{{ */
{
if ( ! PHPDBG_G ( in_execution ) ) {
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Not executing " ) ;
return SUCCESS ;
}
return phpdbg_skip_line_helper ( ) ;
} /* }}} */
PHPDBG_COMMAND ( next ) /* {{{ */
{
if ( ! PHPDBG_G ( in_execution ) ) {
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Not executing " ) ;
return SUCCESS ;
}
PHPDBG_G ( flags ) | = PHPDBG_IS_STEPPING ;
return phpdbg_skip_line_helper ( ) ;
2013-11-16 10:59:50 +00:00
} /* }}} */
2015-04-21 13:53:12 +00:00
static void phpdbg_seek_to_end ( void ) /* { { { */ {
2016-02-17 19:26:47 +00:00
zend_execute_data * ex = phpdbg_user_execute_data ( EG ( current_execute_data ) ) ;
const zend_op_array * op_array = & ex - > func - > op_array ;
2015-09-19 12:57:21 +00:00
const zend_op * opline = op_array - > opcodes ;
2014-10-24 17:29:50 +00:00
2016-02-17 19:26:47 +00:00
PHPDBG_G ( seek_ex ) = ex ;
2015-09-19 12:57:21 +00:00
do {
2014-10-24 17:29:50 +00:00
switch ( opline - > opcode ) {
case ZEND_RETURN :
2015-04-21 23:11:59 +00:00
case ZEND_FAST_RET :
2015-04-21 10:31:43 +00:00
case ZEND_GENERATOR_RETURN :
2014-10-24 17:29:50 +00:00
case ZEND_EXIT :
case ZEND_YIELD :
2015-06-29 00:05:33 +00:00
case ZEND_YIELD_FROM :
2014-10-24 17:29:50 +00:00
zend_hash_index_update_ptr ( & PHPDBG_G ( seek ) , ( zend_ulong ) opline , ( void * ) opline ) ;
}
2015-09-19 12:57:21 +00:00
} while ( + + opline < op_array - > opcodes + op_array - > last ) ;
2014-10-24 17:29:50 +00:00
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-10-24 17:29:50 +00:00
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( finish ) /* {{{ */
2013-11-17 13:59:21 +00:00
{
2014-10-24 17:29:50 +00:00
if ( ! PHPDBG_G ( in_execution ) ) {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Not executing " ) ;
2013-11-18 01:44:46 +00:00
return SUCCESS ;
}
2013-11-18 14:09:25 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_seek_to_end ( ) ;
2016-02-17 19:26:47 +00:00
if ( zend_hash_index_exists ( & PHPDBG_G ( seek ) , ( zend_ulong ) phpdbg_user_execute_data ( EG ( current_execute_data ) ) - > opline ) ) {
2015-09-19 12:57:21 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
} else {
PHPDBG_G ( flags ) | = PHPDBG_IN_FINISH ;
}
2013-11-18 14:09:25 +00:00
2013-11-17 13:59:21 +00:00
return PHPDBG_FINISH ;
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( leave ) /* {{{ */
2013-11-17 15:39:23 +00:00
{
2014-10-24 17:29:50 +00:00
if ( ! PHPDBG_G ( in_execution ) ) {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Not executing " ) ;
2013-11-18 01:44:46 +00:00
return SUCCESS ;
}
2013-11-18 14:09:25 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_seek_to_end ( ) ;
2016-02-17 19:26:47 +00:00
if ( zend_hash_index_exists ( & PHPDBG_G ( seek ) , ( zend_ulong ) phpdbg_user_execute_data ( EG ( current_execute_data ) ) - > opline ) ) {
2015-09-19 12:57:21 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
phpdbg_notice ( " leave " , " type= \" end \" " , " Already at the end of the function " ) ;
return SUCCESS ;
} else {
PHPDBG_G ( flags ) | = PHPDBG_IN_LEAVE ;
return PHPDBG_LEAVE ;
}
2013-11-17 15:39:23 +00:00
} /* }}} */
2013-11-22 17:27:55 +00:00
PHPDBG_COMMAND ( frame ) /* {{{ */
{
2014-02-21 20:42:15 +00:00
if ( ! param ) {
2014-09-25 13:28:25 +00:00
phpdbg_notice ( " frame " , " id= \" %d \" " , " Currently in frame #%d " , PHPDBG_G ( frame ) . num ) ;
2014-09-21 02:17:19 +00:00
} else {
2014-12-13 22:06:14 +00:00
phpdbg_switch_frame ( param - > num ) ;
2014-09-21 02:17:19 +00:00
}
2013-11-22 18:24:27 +00:00
return SUCCESS ;
2013-11-22 17:27:55 +00:00
} /* }}} */
2015-04-21 13:53:12 +00:00
static inline void phpdbg_handle_exception ( void ) /* { { { */
2013-11-18 17:00:26 +00:00
{
2015-04-20 12:12:47 +00:00
zend_object * ex = EG ( exception ) ;
2015-07-16 08:28:59 +00:00
zend_string * msg , * file ;
zend_long line ;
zval zv , rv , tmp ;
2013-11-18 17:00:26 +00:00
2015-04-20 12:12:47 +00:00
EG ( exception ) = NULL ;
2015-07-16 08:28:59 +00:00
ZVAL_OBJ ( & zv , ex ) ;
zend_call_method_with_0_params ( & zv , ex - > ce , NULL , " __tostring " , & tmp ) ;
file = zval_get_string ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " file " ) , 1 , & rv ) ) ;
line = zval_get_long ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " line " ) , 1 , & rv ) ) ;
if ( EG ( exception ) ) {
EG ( exception ) = NULL ;
msg = ZSTR_EMPTY_ALLOC ( ) ;
2014-09-21 02:17:19 +00:00
} else {
2015-07-16 08:28:59 +00:00
zend_update_property_string ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " string " ) , Z_STRVAL ( tmp ) ) ;
zval_ptr_dtor ( & tmp ) ;
msg = zval_get_string ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " string " ) , 1 , & rv ) ) ;
2013-11-18 17:00:26 +00:00
}
2013-11-19 01:30:57 +00:00
2015-10-02 10:18:26 +00:00
phpdbg_error ( " exception " , " name= \" %s \" file= \" %s \" line= \" " ZEND_LONG_FMT " \" " , " Uncaught %s in %s on line " ZEND_LONG_FMT , ZSTR_VAL ( ex - > ce - > name ) , ZSTR_VAL ( file ) , line ) ;
2015-07-16 08:28:59 +00:00
zend_string_release ( file ) ;
2015-10-02 10:18:26 +00:00
phpdbg_writeln ( " exceptionmsg " , " msg= \" %s \" " , ZSTR_VAL ( msg ) ) ;
zend_string_release ( msg ) ;
2013-11-19 01:30:57 +00:00
2015-04-20 11:55:09 +00:00
if ( EG ( prev_exception ) ) {
OBJ_RELEASE ( EG ( prev_exception ) ) ;
EG ( prev_exception ) = 0 ;
}
2015-04-20 12:12:47 +00:00
OBJ_RELEASE ( ex ) ;
2015-04-20 11:55:09 +00:00
EG ( opline_before_exception ) = NULL ;
2015-10-02 10:18:26 +00:00
EG ( exit_status ) = 255 ;
2013-11-18 17:00:26 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( run ) /* {{{ */
2013-11-10 18:29:05 +00:00
{
if ( PHPDBG_G ( ops ) | | PHPDBG_G ( exec ) ) {
2014-02-02 15:16:01 +00:00
zend_execute_data * ex = EG ( current_execute_data ) ;
2014-10-24 17:29:50 +00:00
zend_bool restore = 1 ;
2014-09-25 13:28:25 +00:00
2014-10-26 23:34:56 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2014-12-13 22:06:14 +00:00
if ( phpdbg_ask_user_permission ( " Do you really want to restart execution? " ) = = SUCCESS ) {
2014-10-26 02:50:28 +00:00
phpdbg_startup_run + + ;
2015-08-03 23:22:04 +00:00
phpdbg_clean ( 1 ) ;
2014-10-26 02:50:28 +00:00
}
return SUCCESS ;
}
2013-11-10 18:29:05 +00:00
if ( ! PHPDBG_G ( ops ) ) {
2014-12-13 22:06:14 +00:00
if ( phpdbg_compile ( ) = = FAILURE ) {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " compile " , " type= \" compilefailure \" context= \" %s \" " , " Failed to compile %s, cannot run " , PHPDBG_G ( exec ) ) ;
2013-11-16 23:35:11 +00:00
goto out ;
2013-11-10 18:29:05 +00:00
}
}
2013-11-10 15:21:20 +00:00
2014-01-18 23:48:53 +00:00
/* clean up from last execution */
if ( ex & & ex - > symbol_table ) {
2015-02-13 19:20:39 +00:00
zend_hash_clean ( ex - > symbol_table ) ;
2014-10-24 17:29:50 +00:00
} else {
2014-12-13 22:06:14 +00:00
zend_rebuild_symbol_table ( ) ;
2014-01-18 23:48:53 +00:00
}
2015-04-21 21:09:09 +00:00
PHPDBG_G ( handled_exception ) = NULL ;
2014-01-18 23:48:53 +00:00
2013-11-18 03:18:37 +00:00
/* clean seek state */
PHPDBG_G ( flags ) & = ~ PHPDBG_SEEK_MASK ;
2014-10-24 17:29:50 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
2013-11-18 14:09:25 +00:00
2013-11-27 13:15:52 +00:00
/* reset hit counters */
2014-12-13 22:06:14 +00:00
phpdbg_reset_breakpoints ( ) ;
2013-11-27 13:15:52 +00:00
2014-04-16 18:55:02 +00:00
if ( param & & param - > type ! = EMPTY_PARAM & & param - > len ! = 0 ) {
2014-04-12 22:27:46 +00:00
char * * argv = emalloc ( 5 * sizeof ( char * ) ) ;
int argc = 0 ;
int i ;
2015-07-20 15:52:57 +00:00
/* TODO allow proper escaping with \, "" and '' here */
2014-04-13 07:43:19 +00:00
char * argv_str = strtok ( param - > str , " " ) ;
2014-09-25 13:28:25 +00:00
2014-04-12 22:27:46 +00:00
while ( argv_str ) {
if ( argc > = 4 & & argc = = ( argc & - argc ) ) {
argv = erealloc ( argv , ( argc * 2 + 1 ) * sizeof ( char * ) ) ;
}
argv [ + + argc ] = argv_str ;
argv_str = strtok ( 0 , " " ) ;
argv [ argc ] = estrdup ( argv [ argc ] ) ;
}
argv [ 0 ] = SG ( request_info ) . argv [ 0 ] ;
for ( i = SG ( request_info ) . argc ; - - i ; ) {
efree ( SG ( request_info ) . argv [ i ] ) ;
}
efree ( SG ( request_info ) . argv ) ;
SG ( request_info ) . argv = erealloc ( argv , + + argc * sizeof ( char * ) ) ;
SG ( request_info ) . argc = argc ;
2014-09-25 13:28:25 +00:00
2015-07-24 15:17:09 +00:00
php_build_argv ( NULL , & PG ( http_globals ) [ TRACK_VARS_SERVER ] ) ;
2014-04-12 22:27:46 +00:00
}
2013-11-10 18:29:05 +00:00
zend_try {
2013-11-23 17:09:52 +00:00
PHPDBG_G ( flags ) ^ = PHPDBG_IS_INTERACTIVE ;
2014-10-26 19:43:49 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_RUNNING ;
2014-12-13 22:06:14 +00:00
zend_execute ( PHPDBG_G ( ops ) , & PHPDBG_G ( retval ) ) ;
2013-11-23 17:09:52 +00:00
PHPDBG_G ( flags ) ^ = PHPDBG_IS_INTERACTIVE ;
2013-11-10 18:29:05 +00:00
} zend_catch {
2014-10-24 17:29:50 +00:00
PHPDBG_G ( in_execution ) = 0 ;
2013-11-23 22:03:17 +00:00
2014-10-26 02:50:28 +00:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) ) {
2014-01-17 21:08:35 +00:00
restore = 0 ;
2015-07-24 15:17:09 +00:00
} else {
zend_bailout ( ) ;
2013-11-16 23:35:11 +00:00
}
2013-11-10 18:29:05 +00:00
} zend_end_try ( ) ;
2014-10-04 21:21:34 +00:00
if ( PHPDBG_G ( socket_fd ) ! = - 1 ) {
close ( PHPDBG_G ( socket_fd ) ) ;
PHPDBG_G ( socket_fd ) = - 1 ;
}
2014-01-17 21:08:35 +00:00
if ( restore ) {
2015-09-23 15:53:22 +00:00
zend_exception_restore ( ) ;
2015-10-02 10:37:17 +00:00
zend_try {
zend_try_exception_handler ( ) ;
PHPDBG_G ( in_execution ) = 1 ;
} zend_catch {
PHPDBG_G ( in_execution ) = 0 ;
if ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) {
zend_bailout ( ) ;
}
} zend_end_try ( ) ;
2014-01-17 21:08:35 +00:00
if ( EG ( exception ) ) {
2014-12-13 22:06:14 +00:00
phpdbg_handle_exception ( ) ;
2014-01-17 21:08:35 +00:00
}
2015-07-24 15:17:09 +00:00
}
2014-10-28 11:27:19 +00:00
2014-10-26 19:43:49 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_RUNNING ;
2015-08-03 23:22:04 +00:00
phpdbg_clean ( 1 ) ;
2013-11-10 18:29:05 +00:00
} else {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " inactive " , " type= \" nocontext \" " , " Nothing to execute! " ) ;
2013-11-10 18:29:05 +00:00
}
2013-11-17 11:28:14 +00:00
2013-11-16 23:35:11 +00:00
out :
2013-11-22 22:15:04 +00:00
PHPDBG_FRAME ( num ) = 0 ;
2013-11-16 23:35:11 +00:00
return SUCCESS ;
2013-11-10 14:43:46 +00:00
} /* }}} */
2015-04-21 13:53:12 +00:00
int phpdbg_output_ev_variable ( char * name , size_t len , char * keyname , size_t keylen , HashTable * parent , zval * zv ) /* { { { */ {
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " eval " , " variable= \" %.*s \" " , " Printing variable %.*s " , ( int ) len , name ) ;
2014-10-09 10:24:52 +00:00
phpdbg_xml ( " <eval %r> " ) ;
2014-12-13 22:06:14 +00:00
zend_print_zval_r ( zv , 0 ) ;
2014-10-07 11:08:30 +00:00
phpdbg_xml ( " </eval> " ) ;
2014-10-19 18:09:39 +00:00
phpdbg_out ( " \n " ) ;
2014-10-07 11:08:30 +00:00
2014-10-03 10:43:32 +00:00
efree ( name ) ;
efree ( keyname ) ;
return SUCCESS ;
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-10-03 10:43:32 +00:00
2014-02-21 21:31:01 +00:00
PHPDBG_COMMAND ( ev ) /* {{{ */
2013-11-10 18:29:05 +00:00
{
2014-09-21 02:17:19 +00:00
zend_bool stepping = ( ( PHPDBG_G ( flags ) & PHPDBG_IS_STEPPING ) = = PHPDBG_IS_STEPPING ) ;
2014-02-21 21:31:01 +00:00
zval retval ;
2013-11-20 18:52:34 +00:00
2014-10-25 17:09:19 +00:00
zend_execute_data * original_execute_data = EG ( current_execute_data ) ;
2014-10-25 13:29:54 +00:00
zend_class_entry * original_scope = EG ( scope ) ;
2014-10-25 17:09:19 +00:00
zend_vm_stack original_stack = EG ( vm_stack ) ;
2015-07-24 15:17:09 +00:00
zend_object * ex = NULL ;
2014-10-25 13:29:54 +00:00
2014-10-25 16:48:43 +00:00
PHPDBG_OUTPUT_BACKUP ( ) ;
2014-12-16 11:20:29 +00:00
original_stack - > top = EG ( vm_stack_top ) ;
2014-10-03 10:43:32 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IN_SIGNAL_HANDLER ) {
phpdbg_try_access {
2015-02-13 19:20:39 +00:00
phpdbg_parse_variable ( param - > str , param - > len , & EG ( symbol_table ) , 0 , phpdbg_output_ev_variable , 0 ) ;
2014-10-03 10:43:32 +00:00
} phpdbg_catch_access {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " signalsegv " , " " , " Could not fetch data, invalid data source " ) ;
2014-10-03 10:43:32 +00:00
} phpdbg_end_try_access ( ) ;
2014-10-25 16:48:43 +00:00
PHPDBG_OUTPUT_BACKUP_RESTORE ( ) ;
2014-10-03 10:43:32 +00:00
return SUCCESS ;
}
2014-02-21 21:31:01 +00:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IS_STEPONEVAL ) ) {
2014-09-21 02:17:19 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_STEPPING ;
2014-02-21 21:31:01 +00:00
}
2013-11-23 15:34:36 +00:00
2014-02-21 21:31:01 +00:00
/* disable stepping while eval() in progress */
PHPDBG_G ( flags ) | = PHPDBG_IN_EVAL ;
zend_try {
2014-12-13 22:06:14 +00:00
if ( zend_eval_stringl ( param - > str , param - > len , & retval , " eval()'d code " ) = = SUCCESS ) {
2015-07-20 15:52:57 +00:00
if ( EG ( exception ) ) {
2015-07-24 15:17:09 +00:00
ex = EG ( exception ) ;
2015-07-20 15:52:57 +00:00
zend_exception_error ( EG ( exception ) , E_ERROR ) ;
} else {
phpdbg_xml ( " <eval %r> " ) ;
if ( PHPDBG_G ( flags ) & PHPDBG_WRITE_XML ) {
zval * zvp = & retval ;
phpdbg_xml_var_dump ( zvp ) ;
}
zend_print_zval_r ( & retval , 0 ) ;
phpdbg_xml ( " </eval> " ) ;
phpdbg_out ( " \n " ) ;
zval_ptr_dtor ( & retval ) ;
2014-10-23 15:19:26 +00:00
}
2014-02-21 21:31:01 +00:00
}
2014-10-25 13:29:54 +00:00
} zend_catch {
2015-07-24 15:17:09 +00:00
PHPDBG_G ( unclean_eval ) = 1 ;
if ( ex ) {
OBJ_RELEASE ( ex ) ;
}
2014-10-25 17:09:19 +00:00
EG ( current_execute_data ) = original_execute_data ;
2014-10-25 13:29:54 +00:00
EG ( scope ) = original_scope ;
2014-10-25 17:09:19 +00:00
EG ( vm_stack_top ) = original_stack - > top ;
EG ( vm_stack_end ) = original_stack - > end ;
EG ( vm_stack ) = original_stack ;
2015-07-26 16:11:45 +00:00
EG ( exit_status ) = 0 ;
2014-02-21 21:31:01 +00:00
} zend_end_try ( ) ;
2015-07-20 15:52:57 +00:00
2014-02-21 21:31:01 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_EVAL ;
2013-11-21 23:19:55 +00:00
2014-02-21 21:31:01 +00:00
/* switch stepping back on */
2014-09-21 02:17:19 +00:00
if ( stepping & & ! ( PHPDBG_G ( flags ) & PHPDBG_IS_STEPONEVAL ) ) {
2014-02-21 21:31:01 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_STEPPING ;
2013-11-17 12:07:01 +00:00
}
2013-11-16 14:34:49 +00:00
2014-02-21 21:31:01 +00:00
CG ( unclean_shutdown ) = 0 ;
2014-10-25 16:48:43 +00:00
PHPDBG_OUTPUT_BACKUP_RESTORE ( ) ;
2014-02-21 21:31:01 +00:00
2013-11-10 18:29:05 +00:00
return SUCCESS ;
2013-11-10 15:16:45 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( back ) /* {{{ */
2013-11-10 18:21:49 +00:00
{
2014-10-24 17:29:50 +00:00
if ( ! PHPDBG_G ( in_execution ) ) {
2014-10-02 09:18:36 +00:00
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Not executing! " ) ;
2013-11-17 12:07:01 +00:00
return SUCCESS ;
}
2013-11-10 17:49:25 +00:00
2014-02-21 20:42:15 +00:00
if ( ! param ) {
2014-12-13 22:06:14 +00:00
phpdbg_dump_backtrace ( 0 ) ;
2014-02-21 20:42:15 +00:00
} else {
2014-12-13 22:06:14 +00:00
phpdbg_dump_backtrace ( param - > num ) ;
2013-11-17 12:07:01 +00:00
}
return SUCCESS ;
2013-11-10 15:16:45 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( print ) /* {{{ */
2015-03-21 22:03:22 +00:00
{
if ( ! param | | param - > type = = EMPTY_PARAM ) {
2015-04-25 17:15:08 +00:00
return phpdbg_do_print_stack ( param ) ;
2015-03-21 22:03:22 +00:00
} else switch ( param - > type ) {
case STR_PARAM :
return phpdbg_do_print_func ( param ) ;
case METHOD_PARAM :
return phpdbg_do_print_method ( param ) ;
default :
phpdbg_error ( " print " , " type= \" invalidarg \" " , " Invalid arguments to print, expected nothing, function name or method name " ) ;
return SUCCESS ;
}
} /* }}} */
PHPDBG_COMMAND ( info ) /* {{{ */
2013-11-10 18:15:00 +00:00
{
2014-10-19 18:09:39 +00:00
phpdbg_out ( " Execution Context Information \n \n " ) ;
2014-10-09 10:24:52 +00:00
phpdbg_xml ( " <printinfo %r> " ) ;
2013-11-12 08:26:11 +00:00
# ifdef HAVE_LIBREADLINE
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " readline= \" yes \" " , " Readline yes " ) ;
2013-11-12 08:26:11 +00:00
# else
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " readline= \" no \" " , " Readline no " ) ;
2013-11-12 08:26:11 +00:00
# endif
2014-06-23 08:04:40 +00:00
# ifdef HAVE_LIBEDIT
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " libedit= \" yes \" " , " Libedit yes " ) ;
2014-06-23 08:04:40 +00:00
# else
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " libedit= \" no \" " , " Libedit no " ) ;
2014-06-23 08:04:40 +00:00
# endif
2013-11-15 16:12:27 +00:00
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " context= \" %s \" " , " Exec %s " , PHPDBG_G ( exec ) ? PHPDBG_G ( exec ) : " none " ) ;
phpdbg_writeln ( " info " , " compiled= \" %s \" " , " Compiled %s " , PHPDBG_G ( ops ) ? " yes " : " no " ) ;
phpdbg_writeln ( " info " , " stepping= \" %s \" " , " Stepping %s " , ( PHPDBG_G ( flags ) & PHPDBG_IS_STEPPING ) ? " on " : " off " ) ;
phpdbg_writeln ( " info " , " quiet= \" %s \" " , " Quietness %s " , ( PHPDBG_G ( flags ) & PHPDBG_IS_QUIET ) ? " on " : " off " ) ;
phpdbg_writeln ( " info " , " oplog= \" %s \" " , " Oplog %s " , PHPDBG_G ( oplog ) ? " on " : " off " ) ;
2013-11-17 12:07:01 +00:00
2014-02-21 20:42:15 +00:00
if ( PHPDBG_G ( ops ) ) {
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " ops= \" %d \" " , " Opcodes %d " , PHPDBG_G ( ops ) - > last ) ;
phpdbg_writeln ( " info " , " vars= \" %d \" " , " Variables %d " , PHPDBG_G ( ops ) - > last_var ? PHPDBG_G ( ops ) - > last_var - 1 : 0 ) ;
2014-02-21 20:42:15 +00:00
}
2013-11-24 11:43:05 +00:00
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " executing= \" %d \" " , " Executing %s " , PHPDBG_G ( in_execution ) ? " yes " : " no " ) ;
2014-10-24 17:29:50 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " vmret= \" %d \" " , " VM Return %d " , PHPDBG_G ( vmret ) ) ;
2014-02-21 20:42:15 +00:00
}
2013-12-08 18:07:49 +00:00
2015-03-21 22:03:22 +00:00
phpdbg_writeln ( " info " , " classes= \" %d \" " , " Classes %d " , zend_hash_num_elements ( EG ( class_table ) ) ) ;
phpdbg_writeln ( " info " , " functions= \" %d \" " , " Functions %d " , zend_hash_num_elements ( EG ( function_table ) ) ) ;
phpdbg_writeln ( " info " , " constants= \" %d \" " , " Constants %d " , zend_hash_num_elements ( EG ( zend_constants ) ) ) ;
phpdbg_writeln ( " info " , " includes= \" %d \" " , " Included %d " , zend_hash_num_elements ( & EG ( included_files ) ) ) ;
2014-09-21 02:17:19 +00:00
phpdbg_xml ( " </printinfo> " ) ;
2013-11-12 22:39:39 +00:00
2013-11-10 18:15:00 +00:00
return SUCCESS ;
2013-11-10 10:44:42 +00:00
} /* }}} */
2013-11-24 14:54:14 +00:00
PHPDBG_COMMAND ( set ) /* {{{ */
2013-11-17 15:42:34 +00:00
{
2014-09-21 02:17:19 +00:00
phpdbg_error ( " set " , " type= \" toofewargs \" expected= \" 1 \" " , " No set command selected! " ) ;
2013-11-21 23:19:55 +00:00
2013-11-17 15:42:34 +00:00
return SUCCESS ;
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( break ) /* {{{ */
2013-11-10 14:36:30 +00:00
{
2014-02-21 20:42:15 +00:00
if ( ! param ) {
2014-02-19 20:18:49 +00:00
phpdbg_set_breakpoint_file (
2014-12-13 22:06:14 +00:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( ) ) ;
2014-02-19 20:18:49 +00:00
} else switch ( param - > type ) {
2013-11-13 23:13:41 +00:00
case ADDR_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_opline ( param - > addr ) ;
2013-11-13 23:13:41 +00:00
break ;
case NUMERIC_PARAM :
2013-11-24 12:03:00 +00:00
if ( PHPDBG_G ( exec ) ) {
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_file ( phpdbg_current_file ( ) , param - > num ) ;
2013-11-24 12:03:00 +00:00
} else {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " inactive " , " type= \" noexec \" " , " Execution context not set! " ) ;
2013-11-24 12:03:00 +00:00
}
2013-11-13 23:13:41 +00:00
break ;
case METHOD_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_method ( param - > method . class , param - > method . name ) ;
2013-11-13 23:13:41 +00:00
break ;
2013-12-03 11:31:25 +00:00
case NUMERIC_METHOD_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_method_opline ( param - > method . class , param - > method . name , param - > num ) ;
2013-12-03 11:31:25 +00:00
break ;
case NUMERIC_FUNCTION_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_function_opline ( param - > str , param - > num ) ;
2013-12-03 11:31:25 +00:00
break ;
2013-11-13 23:13:41 +00:00
case FILE_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_file ( param - > file . name , param - > file . line ) ;
2013-11-14 00:30:03 +00:00
break ;
2014-02-21 18:01:50 +00:00
case NUMERIC_FILE_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_file_opline ( param - > file . name , param - > file . line ) ;
2014-02-21 18:01:50 +00:00
break ;
2014-02-21 14:44:16 +00:00
case COND_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_expression ( param - > str , param - > len ) ;
2014-02-21 14:44:16 +00:00
break ;
2013-11-13 23:13:41 +00:00
case STR_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_symbol ( param - > str , param - > len ) ;
2013-11-13 23:13:41 +00:00
break ;
2014-02-21 16:18:46 +00:00
case OP_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_set_breakpoint_opcode ( param - > str , param - > len ) ;
2014-02-21 16:18:46 +00:00
break ;
2013-11-17 11:28:14 +00:00
2013-11-16 22:58:30 +00:00
phpdbg_default_switch_case ( ) ;
2013-11-10 14:36:30 +00:00
}
2013-11-16 10:59:50 +00:00
2013-11-10 14:36:30 +00:00
return SUCCESS ;
2013-11-10 10:44:42 +00:00
} /* }}} */
2014-02-21 21:31:01 +00:00
PHPDBG_COMMAND ( sh ) /* {{{ */
2013-11-18 12:46:10 +00:00
{
2014-02-21 21:31:01 +00:00
FILE * fd = NULL ;
if ( ( fd = VCWD_POPEN ( ( char * ) param - > str , " w " ) ) ) {
2014-09-21 02:17:19 +00:00
/* TODO: do something perhaps ?? do we want input ?? */
2015-01-26 22:28:54 +00:00
pclose ( fd ) ;
2014-02-21 21:31:01 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " sh " , " type= \" failure \" smd= \" %s \" " , " Failed to execute %s " , param - > str ) ;
2013-11-18 12:46:10 +00:00
}
2014-09-21 02:17:19 +00:00
2013-11-18 12:46:10 +00:00
return SUCCESS ;
2013-11-19 01:18:43 +00:00
} /* }}} */
2015-04-21 13:53:12 +00:00
static int add_module_info ( zend_module_entry * module ) /* { { { */ {
2014-10-19 18:09:39 +00:00
phpdbg_write ( " module " , " name= \" %s \" " , " %s \n " , module - > name ) ;
2014-09-09 00:15:33 +00:00
return 0 ;
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-09-09 00:15:33 +00:00
2015-04-21 13:53:12 +00:00
static int add_zendext_info ( zend_extension * ext ) /* { { { */ {
2014-10-19 18:09:39 +00:00
phpdbg_write ( " extension " , " name= \" %s \" " , " %s \n " , ext - > name ) ;
2014-09-09 00:15:33 +00:00
return 0 ;
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-09-09 00:15:33 +00:00
2015-04-21 13:53:12 +00:00
PHPDBG_API const char * phpdbg_load_module_or_extension ( char * * path , char * * name ) /* { { { */ {
2014-09-09 00:15:33 +00:00
DL_HANDLE handle ;
char * extension_dir ;
extension_dir = INI_STR ( " extension_dir " ) ;
if ( strchr ( * path , ' / ' ) ! = NULL | | strchr ( * path , DEFAULT_SLASH ) ! = NULL ) {
/* path is fine */
} else if ( extension_dir & & extension_dir [ 0 ] ) {
char * libpath ;
int extension_dir_len = strlen ( extension_dir ) ;
if ( IS_SLASH ( extension_dir [ extension_dir_len - 1 ] ) ) {
spprintf ( & libpath , 0 , " %s%s " , extension_dir , * path ) ; /* SAFE */
} else {
spprintf ( & libpath , 0 , " %s%c%s " , extension_dir , DEFAULT_SLASH , * path ) ; /* SAFE */
}
efree ( * path ) ;
* path = libpath ;
} else {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" relpath \" " , " Not a full path given or extension_dir ini setting is not set " ) ;
2014-09-09 00:15:33 +00:00
return NULL ;
}
handle = DL_LOAD ( * path ) ;
if ( ! handle ) {
# if PHP_WIN32
char * err = GET_DL_ERROR ( ) ;
2014-10-07 11:08:30 +00:00
if ( err & & * err ! = " " ) {
phpdbg_error ( " dl " , " type= \" unknown \" " , " %s " , err ) ;
2014-09-09 00:15:33 +00:00
LocalFree ( err ) ;
} else {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" unknown \" " , " Unknown reason " ) ;
2014-09-09 00:15:33 +00:00
}
# else
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" unknown \" " , " %s " , GET_DL_ERROR ( ) ) ;
2014-09-09 00:15:33 +00:00
# endif
return NULL ;
}
# if ZEND_EXTENSIONS_SUPPORT
do {
zend_extension * new_extension ;
zend_extension_version_info * extension_version_info ;
extension_version_info = ( zend_extension_version_info * ) DL_FETCH_SYMBOL ( handle , " extension_version_info " ) ;
if ( ! extension_version_info ) {
extension_version_info = ( zend_extension_version_info * ) DL_FETCH_SYMBOL ( handle , " _extension_version_info " ) ;
}
new_extension = ( zend_extension * ) DL_FETCH_SYMBOL ( handle , " zend_extension_entry " ) ;
if ( ! new_extension ) {
new_extension = ( zend_extension * ) DL_FETCH_SYMBOL ( handle , " _zend_extension_entry " ) ;
}
if ( ! extension_version_info | | ! new_extension ) {
break ;
}
if ( extension_version_info - > zend_extension_api_no ! = ZEND_EXTENSION_API_NO & & ( ! new_extension - > api_no_check | | new_extension - > api_no_check ( ZEND_EXTENSION_API_NO ) ! = SUCCESS ) ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" wrongapi \" extension= \" %s \" apineeded= \" %d \" apiinstalled= \" %d \" " , " %s requires Zend Engine API version %d, which does not match the installed Zend Engine API version %d " , new_extension - > name , extension_version_info - > zend_extension_api_no , ZEND_EXTENSION_API_NO ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
} else if ( strcmp ( ZEND_EXTENSION_BUILD_ID , extension_version_info - > build_id ) & & ( ! new_extension - > build_id_check | | new_extension - > build_id_check ( ZEND_EXTENSION_BUILD_ID ) ! = SUCCESS ) ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" wrongbuild \" extension= \" %s \" buildneeded= \" %s \" buildinstalled= \" %s \" " , " %s was built with configuration %s, whereas running engine is %s " , new_extension - > name , extension_version_info - > build_id , ZEND_EXTENSION_BUILD_ID ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
2014-10-07 11:08:30 +00:00
* name = new_extension - > name ;
2014-09-09 00:15:33 +00:00
2014-12-13 22:06:14 +00:00
zend_register_extension ( new_extension , handle ) ;
2014-09-09 00:15:33 +00:00
if ( new_extension - > startup ) {
if ( new_extension - > startup ( new_extension ) ! = SUCCESS ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" startupfailure \" extension= \" %s \" " , " Unable to startup Zend extension %s " , new_extension - > name ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
zend_append_version_info ( new_extension ) ;
}
return " Zend extension " ;
} while ( 0 ) ;
# endif
do {
zend_module_entry * module_entry ;
zend_module_entry * ( * get_module ) ( void ) ;
get_module = ( zend_module_entry * ( * ) ( void ) ) DL_FETCH_SYMBOL ( handle , " get_module " ) ;
if ( ! get_module ) {
get_module = ( zend_module_entry * ( * ) ( void ) ) DL_FETCH_SYMBOL ( handle , " _get_module " ) ;
}
if ( ! get_module ) {
break ;
}
module_entry = get_module ( ) ;
2014-10-07 11:08:30 +00:00
* name = ( char * ) module_entry - > name ;
2014-09-09 00:15:33 +00:00
if ( strcmp ( ZEND_EXTENSION_BUILD_ID , module_entry - > build_id ) ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" wrongbuild \" module= \" %s \" buildneeded= \" %s \" buildinstalled= \" %s \" " , " %s was built with configuration %s, whereas running engine is %s " , module_entry - > name , module_entry - > build_id , ZEND_EXTENSION_BUILD_ID ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
module_entry - > type = MODULE_PERSISTENT ;
module_entry - > module_number = zend_next_free_module ( ) ;
module_entry - > handle = handle ;
2014-12-13 22:06:14 +00:00
if ( ( module_entry = zend_register_module_ex ( module_entry ) ) = = NULL ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" registerfailure \" module= \" %s \" " , " Unable to register module %s " , module_entry - > name ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
2014-12-13 22:06:14 +00:00
if ( zend_startup_module_ex ( module_entry ) = = FAILURE ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" startupfailure \" module= \" %s \" " , " Unable to startup module %s " , module_entry - > name ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
if ( module_entry - > request_startup_func ) {
2014-12-13 22:06:14 +00:00
if ( module_entry - > request_startup_func ( MODULE_PERSISTENT , module_entry - > module_number ) = = FAILURE ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" initfailure \" module= \" %s \" " , " Unable to initialize module %s " , module_entry - > name ) ;
2014-09-09 00:15:33 +00:00
goto quit ;
}
}
return " module " ;
} while ( 0 ) ;
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" nophpso \" " , " This shared object is nor a Zend extension nor a module " ) ;
2014-09-09 00:15:33 +00:00
quit :
DL_UNLOAD ( handle ) ;
return NULL ;
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-09-09 00:15:33 +00:00
PHPDBG_COMMAND ( dl ) /* {{{ */
{
const char * type ;
char * name , * path ;
if ( ! param | | param - > type = = EMPTY_PARAM ) {
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " dl " , " extensiontype= \" Zend extension \" " , " Zend extensions " ) ;
2014-12-13 22:06:14 +00:00
zend_llist_apply ( & zend_extensions , ( llist_apply_func_t ) add_zendext_info ) ;
2014-10-19 18:09:39 +00:00
phpdbg_out ( " \n " ) ;
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " dl " , " extensiontype= \" module \" " , " Modules " ) ;
2014-12-13 22:06:14 +00:00
zend_hash_apply ( & module_registry , ( apply_func_t ) add_module_info ) ;
2014-09-09 00:15:33 +00:00
} else switch ( param - > type ) {
case STR_PARAM :
# ifdef HAVE_LIBDL
path = estrndup ( param - > str , param - > len ) ;
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 1 ) ;
if ( ( type = phpdbg_load_module_or_extension ( & path , & name ) ) = = NULL ) {
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " path= \" %s \" %b " , " Could not load %s, not found or invalid zend extension / module: %b " , path ) ;
2014-09-09 00:15:33 +00:00
efree ( name ) ;
} else {
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " dl " , " extensiontype= \" %s \" name= \" %s \" path= \" %s \" " , " Successfully loaded the %s %s at path %s " , type , name , path ) ;
2014-09-09 00:15:33 +00:00
}
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
2014-09-09 00:15:33 +00:00
efree ( path ) ;
# else
2014-10-07 11:08:30 +00:00
phpdbg_error ( " dl " , " type= \" unsupported \" path= \" %.*s \" " , " Cannot dynamically load %.*s - dynamic modules are not supported " , ( int ) param - > len , param - > str ) ;
2014-09-09 00:15:33 +00:00
# endif
break ;
phpdbg_default_switch_case ( ) ;
2013-11-18 12:46:10 +00:00
}
2014-09-09 00:15:33 +00:00
2013-11-18 12:46:10 +00:00
return SUCCESS ;
2013-11-19 01:18:43 +00:00
} /* }}} */
2013-11-25 16:39:14 +00:00
PHPDBG_COMMAND ( source ) /* {{{ */
{
2014-12-16 11:20:29 +00:00
zend_stat_t sb ;
2014-09-21 02:17:19 +00:00
2014-02-21 20:42:15 +00:00
if ( VCWD_STAT ( param - > str , & sb ) ! = - 1 ) {
2014-12-13 22:06:14 +00:00
phpdbg_try_file_init ( param - > str , param - > len , 0 ) ;
2014-02-24 19:03:55 +00:00
} else {
2014-09-25 13:28:25 +00:00
phpdbg_error ( " source " , " type= \" notfound \" file= \" %s \" " , " Failed to stat %s, file does not exist " , param - > str ) ;
2014-02-24 19:03:55 +00:00
}
2014-09-21 02:17:19 +00:00
2013-11-25 16:39:14 +00:00
return SUCCESS ;
} /* }}} */
2014-02-24 19:03:55 +00:00
PHPDBG_COMMAND ( export ) /* {{{ */
{
FILE * handle = VCWD_FOPEN ( param - > str , " w+ " ) ;
2014-09-21 02:17:19 +00:00
2014-02-24 19:03:55 +00:00
if ( handle ) {
2014-12-13 22:06:14 +00:00
phpdbg_export_breakpoints ( handle ) ;
2014-02-24 19:03:55 +00:00
fclose ( handle ) ;
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " export " , " type= \" openfailure \" file= \" %s \" " , " Failed to open or create %s, check path and permissions " , param - > str ) ;
2013-11-25 16:39:14 +00:00
}
2014-09-21 02:17:19 +00:00
2013-11-25 16:39:14 +00:00
return SUCCESS ;
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( register ) /* {{{ */
2013-11-19 01:18:43 +00:00
{
2014-02-21 20:42:15 +00:00
zend_function * function ;
char * lcname = zend_str_tolower_dup ( param - > str , param - > len ) ;
size_t lcname_len = strlen ( lcname ) ;
2014-10-24 17:29:50 +00:00
if ( ! zend_hash_str_exists ( & PHPDBG_G ( registered ) , lcname , lcname_len ) ) {
if ( ( function = zend_hash_str_find_ptr ( EG ( function_table ) , lcname , lcname_len ) ) ) {
zend_hash_str_update_ptr ( & PHPDBG_G ( registered ) , lcname , lcname_len , function ) ;
2014-02-21 20:42:15 +00:00
function_add_ref ( function ) ;
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " register " , " function= \" %s \" " , " Registered %s " , lcname ) ;
2014-02-21 20:42:15 +00:00
} else {
2014-10-28 12:55:56 +00:00
phpdbg_error ( " register " , " type= \" notfound \" function= \" %s \" " , " The requested function (%s) could not be found " , param - > str ) ;
2014-02-21 20:42:15 +00:00
}
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error ( " register " , " type= \" inuse \" function= \" %s \" " , " The requested name (%s) is already in use " , lcname ) ;
2013-11-19 01:18:43 +00:00
}
2014-02-21 20:42:15 +00:00
efree ( lcname ) ;
2013-11-19 01:18:43 +00:00
return SUCCESS ;
} /* }}} */
2013-11-18 12:46:10 +00:00
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( quit ) /* {{{ */
2013-11-10 01:30:32 +00:00
{
2015-07-24 15:17:09 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_QUITTING ;
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_CLEANING ;
2013-11-10 11:36:57 +00:00
2015-07-24 15:17:09 +00:00
return SUCCESS ;
2013-11-10 01:30:32 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( clean ) /* {{{ */
2013-11-11 08:02:04 +00:00
{
2014-10-24 17:29:50 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2014-12-13 22:06:14 +00:00
if ( phpdbg_ask_user_permission ( " Do you really want to clean your current environment? " ) = = FAILURE ) {
2014-10-26 02:50:28 +00:00
return SUCCESS ;
}
2013-11-13 21:43:54 +00:00
}
2013-11-13 21:31:33 +00:00
2014-10-19 18:09:39 +00:00
phpdbg_out ( " Cleaning Execution Environment \n " ) ;
2014-10-09 10:24:52 +00:00
phpdbg_xml ( " <cleaninfo %r> " ) ;
2013-11-12 00:27:48 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_writeln ( " clean " , " classes= \" %d \" " , " Classes %d " , zend_hash_num_elements ( EG ( class_table ) ) ) ;
phpdbg_writeln ( " clean " , " functions= \" %d \" " , " Functions %d " , zend_hash_num_elements ( EG ( function_table ) ) ) ;
phpdbg_writeln ( " clean " , " constants= \" %d \" " , " Constants %d " , zend_hash_num_elements ( EG ( zend_constants ) ) ) ;
phpdbg_writeln ( " clean " , " includes= \" %d \" " , " Includes %d " , zend_hash_num_elements ( & EG ( included_files ) ) ) ;
2013-11-12 00:27:48 +00:00
2015-08-03 23:22:04 +00:00
phpdbg_clean ( 1 ) ;
2014-09-21 02:17:19 +00:00
phpdbg_xml ( " </cleaninfo> " ) ;
2013-11-17 12:07:01 +00:00
return SUCCESS ;
2013-11-11 08:02:04 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( clear ) /* {{{ */
2013-11-11 13:31:41 +00:00
{
2014-10-19 18:09:39 +00:00
phpdbg_out ( " Clearing Breakpoints \n " ) ;
2014-10-09 10:24:52 +00:00
phpdbg_xml ( " <clearinfo %r> " ) ;
2014-09-21 02:17:19 +00:00
phpdbg_writeln ( " clear " , " files= \" %d \" " , " File %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE ] ) ) ;
phpdbg_writeln ( " clear " , " functions= \" %d \" " , " Functions %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_SYM ] ) ) ;
phpdbg_writeln ( " clear " , " methods= \" %d \" " , " Methods %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD ] ) ) ;
phpdbg_writeln ( " clear " , " oplines= \" %d \" " , " Oplines %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_OPLINE ] ) ) ;
phpdbg_writeln ( " clear " , " fileoplines= \" %d \" " , " File oplines %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FILE_OPLINE ] ) ) ;
phpdbg_writeln ( " clear " , " functionoplines= \" %d \" " , " Function oplines %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_FUNCTION_OPLINE ] ) ) ;
phpdbg_writeln ( " clear " , " methodoplines= \" %d \" " , " Method oplines %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_METHOD_OPLINE ] ) ) ;
phpdbg_writeln ( " clear " , " eval= \" %d \" " , " Conditionals %d " , zend_hash_num_elements ( & PHPDBG_G ( bp ) [ PHPDBG_BREAK_COND ] ) ) ;
2013-11-13 21:31:33 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_clear_breakpoints ( ) ;
2013-11-11 22:02:34 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_xml ( " </clearinfo> " ) ;
2013-11-26 10:02:58 +00:00
return SUCCESS ;
2013-11-11 13:31:41 +00:00
} /* }}} */
2013-11-20 16:19:37 +00:00
PHPDBG_COMMAND ( list ) /* {{{ */
2013-11-11 23:40:03 +00:00
{
2014-02-21 20:42:15 +00:00
if ( ! param ) {
2014-02-18 19:48:33 +00:00
return PHPDBG_LIST_HANDLER ( lines ) ( PHPDBG_COMMAND_ARGS ) ;
} else switch ( param - > type ) {
2013-11-26 10:02:58 +00:00
case NUMERIC_PARAM :
2013-11-20 13:28:41 +00:00
return PHPDBG_LIST_HANDLER ( lines ) ( PHPDBG_COMMAND_ARGS ) ;
2013-11-17 11:28:14 +00:00
2013-11-16 23:11:39 +00:00
case FILE_PARAM :
2013-11-20 13:28:41 +00:00
return PHPDBG_LIST_HANDLER ( lines ) ( PHPDBG_COMMAND_ARGS ) ;
2013-11-17 11:28:14 +00:00
case STR_PARAM :
2014-12-13 22:06:14 +00:00
phpdbg_list_function_byname ( param - > str , param - > len ) ;
2013-11-17 11:28:14 +00:00
break ;
2013-11-16 23:11:39 +00:00
case METHOD_PARAM :
2013-11-26 10:02:58 +00:00
return PHPDBG_LIST_HANDLER ( method ) ( PHPDBG_COMMAND_ARGS ) ;
2013-11-17 11:28:14 +00:00
2013-11-16 23:11:39 +00:00
phpdbg_default_switch_case ( ) ;
2013-11-26 10:02:58 +00:00
}
2013-11-14 15:46:06 +00:00
2013-11-12 00:24:24 +00:00
return SUCCESS ;
2013-11-11 23:40:03 +00:00
} /* }}} */
2013-12-11 20:27:03 +00:00
PHPDBG_COMMAND ( watch ) /* {{{ */
{
2014-04-13 10:42:47 +00:00
if ( ! param | | param - > type = = EMPTY_PARAM ) {
2014-12-13 22:06:14 +00:00
phpdbg_list_watchpoints ( ) ;
2014-04-13 10:42:47 +00:00
} else switch ( param - > type ) {
2013-12-11 20:27:03 +00:00
case STR_PARAM :
2014-12-13 22:06:14 +00:00
if ( phpdbg_create_var_watchpoint ( param - > str , param - > len ) ! = FAILURE ) {
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " watch " , " variable= \" %.*s \" " , " Set watchpoint on %.*s " , ( int ) param - > len , param - > str ) ;
2014-04-13 15:34:27 +00:00
}
2013-12-11 20:27:03 +00:00
break ;
phpdbg_default_switch_case ( ) ;
}
return SUCCESS ;
} /* }}} */
2014-12-13 22:06:14 +00:00
int phpdbg_interactive ( zend_bool allow_async_unsafe ) /* { { { */
2013-11-10 01:30:32 +00:00
{
2013-11-17 12:07:01 +00:00
int ret = SUCCESS ;
2014-02-18 19:48:33 +00:00
char * input = NULL ;
phpdbg_param_t stack ;
2014-04-15 15:52:46 +00:00
2013-11-22 09:09:54 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IS_INTERACTIVE ;
2013-11-19 21:40:01 +00:00
2014-10-26 19:43:49 +00:00
while ( ret = = SUCCESS | | ret = = FAILURE ) {
2015-07-24 15:17:09 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) {
2014-10-26 02:50:28 +00:00
zend_bailout ( ) ;
}
2014-04-15 15:52:46 +00:00
2014-12-13 22:06:14 +00:00
if ( ! ( input = phpdbg_read_input ( NULL ) ) ) {
2014-10-26 02:50:28 +00:00
break ;
}
2014-04-15 15:52:46 +00:00
2014-10-26 02:50:28 +00:00
phpdbg_init_param ( & stack , STACK_PARAM ) ;
2014-12-13 22:06:14 +00:00
if ( phpdbg_do_parse ( & stack , input ) < = 0 ) {
phpdbg_activate_err_buf ( 1 ) ;
2014-09-21 02:17:19 +00:00
2014-10-21 07:55:22 +00:00
# ifdef PHP_WIN32
2014-10-21 09:46:32 +00:00
# define PARA ((phpdbg_param_t *)stack.next)->type
2014-10-26 02:50:28 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_REMOTE & & ( RUN_PARAM = = PARA | | EVAL_PARAM = = PARA ) ) {
sigio_watcher_start ( ) ;
}
2014-10-21 07:55:22 +00:00
# endif
2014-12-13 22:06:14 +00:00
switch ( ret = phpdbg_stack_execute ( & stack , allow_async_unsafe ) ) {
2014-10-26 02:50:28 +00:00
case FAILURE :
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) ) {
2014-12-13 22:06:14 +00:00
if ( ! allow_async_unsafe | | phpdbg_call_register ( & stack ) = = FAILURE ) {
phpdbg_output_err_buf ( NULL , " %b " , " %b " ) ;
2014-04-21 20:43:19 +00:00
}
2014-10-26 02:50:28 +00:00
}
break ;
2013-11-13 21:31:33 +00:00
2014-10-26 02:50:28 +00:00
case PHPDBG_LEAVE :
case PHPDBG_FINISH :
case PHPDBG_UNTIL :
case PHPDBG_NEXT : {
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
2014-10-26 23:34:56 +00:00
if ( ! PHPDBG_G ( in_execution ) & & ! ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) ) {
2014-10-26 02:50:28 +00:00
phpdbg_error ( " command " , " type= \" noexec \" " , " Not running " ) ;
2013-11-19 13:22:46 +00:00
}
2014-10-26 02:50:28 +00:00
break ;
2013-11-19 12:39:48 +00:00
}
2014-10-26 02:50:28 +00:00
}
2013-11-19 21:40:01 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_activate_err_buf ( 0 ) ;
phpdbg_free_err_buf ( ) ;
2014-10-21 07:55:22 +00:00
# ifdef PHP_WIN32
2014-10-26 02:50:28 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_REMOTE & & ( RUN_PARAM = = PARA | | EVAL_PARAM = = PARA ) ) {
sigio_watcher_stop ( ) ;
}
2014-10-21 09:46:32 +00:00
# undef PARA
2014-10-21 07:55:22 +00:00
# endif
2014-10-26 02:50:28 +00:00
}
2014-02-23 07:33:48 +00:00
2014-10-26 02:50:28 +00:00
phpdbg_stack_free ( & stack ) ;
2014-12-13 22:06:14 +00:00
phpdbg_destroy_input ( & input ) ;
2014-10-26 02:50:28 +00:00
PHPDBG_G ( req_id ) = 0 ;
2014-10-26 19:43:49 +00:00
input = NULL ;
2013-11-10 01:30:32 +00:00
}
2013-11-17 12:07:01 +00:00
2014-02-18 19:48:33 +00:00
if ( input ) {
2014-04-15 15:52:46 +00:00
phpdbg_stack_free ( & stack ) ;
2014-12-13 22:06:14 +00:00
phpdbg_destroy_input ( & input ) ;
2014-10-06 09:26:08 +00:00
PHPDBG_G ( req_id ) = 0 ;
2014-02-18 19:48:33 +00:00
}
2014-02-23 07:33:48 +00:00
2014-10-24 17:29:50 +00:00
if ( PHPDBG_G ( in_execution ) ) {
2014-12-13 22:06:14 +00:00
phpdbg_restore_frame ( ) ;
2013-11-22 18:16:25 +00:00
}
2013-11-22 09:09:54 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_INTERACTIVE ;
2013-11-12 09:52:59 +00:00
2014-12-13 22:06:14 +00:00
phpdbg_print_changed_zvals ( ) ;
2014-03-23 01:27:25 +00:00
2013-11-16 12:02:35 +00:00
return ret ;
2013-11-21 13:35:39 +00:00
} /* }}} */
2015-08-03 15:15:26 +00:00
/* code may behave weirdly if EG(exception) is set; thus backup it */
2014-10-02 23:29:41 +00:00
# define DO_INTERACTIVE(allow_async_unsafe) do { \
2015-07-27 22:10:08 +00:00
const zend_op * backup_opline ; \
2015-08-03 15:15:26 +00:00
const zend_op * before_ex ; \
2015-04-21 21:09:09 +00:00
if ( exception ) { \
2015-07-27 22:10:08 +00:00
if ( EG ( current_execute_data ) & & EG ( current_execute_data ) - > func & & ZEND_USER_CODE ( EG ( current_execute_data ) - > func - > common . type ) ) { \
backup_opline = EG ( current_execute_data ) - > opline ; \
} \
2015-08-03 15:15:26 +00:00
before_ex = EG ( opline_before_exception ) ; \
2015-04-21 21:09:09 +00:00
+ + GC_REFCOUNT ( exception ) ; \
zend_clear_exception ( ) ; \
} \
2014-10-02 23:29:41 +00:00
if ( ! ( PHPDBG_G ( flags ) & PHPDBG_IN_EVAL ) ) { \
2014-12-13 22:06:14 +00:00
const char * file_char = zend_get_executed_filename ( ) ; \
2014-10-24 17:29:50 +00:00
zend_string * file = zend_string_init ( file_char , strlen ( file_char ) , 0 ) ; \
2014-12-13 22:06:14 +00:00
phpdbg_list_file ( file , 3 , zend_get_executed_lineno ( ) - 1 , zend_get_executed_lineno ( ) ) ; \
2014-10-24 17:29:50 +00:00
efree ( file ) ; \
2014-10-02 23:29:41 +00:00
} \
\
2014-12-13 22:06:14 +00:00
switch ( phpdbg_interactive ( allow_async_unsafe ) ) { \
2015-04-21 21:09:09 +00:00
zval zv ; \
2015-07-20 15:52:57 +00:00
case PHPDBG_LEAVE : \
case PHPDBG_FINISH : \
case PHPDBG_UNTIL : \
case PHPDBG_NEXT : \
2015-04-21 21:09:09 +00:00
if ( exception ) { \
2015-07-27 22:10:08 +00:00
if ( EG ( current_execute_data ) & & EG ( current_execute_data ) - > func & & ZEND_USER_CODE ( EG ( current_execute_data ) - > func - > common . type ) \
& & ( backup_opline - > opcode = = ZEND_HANDLE_EXCEPTION | | backup_opline - > opcode = = ZEND_CATCH ) ) { \
EG ( current_execute_data ) - > opline = backup_opline ; \
EG ( exception ) = exception ; \
} else { \
Z_OBJ ( zv ) = exception ; \
zend_throw_exception_internal ( & zv ) ; \
} \
2015-08-03 15:15:26 +00:00
EG ( opline_before_exception ) = before_ex ; \
2015-04-21 21:09:09 +00:00
} \
/* fallthrough */ \
2015-07-20 15:52:57 +00:00
default : \
2014-10-02 23:29:41 +00:00
goto next ; \
} \
} while ( 0 )
2013-11-15 11:19:26 +00:00
2014-12-13 22:06:14 +00:00
void phpdbg_execute_ex ( zend_execute_data * execute_data ) /* { { { */
2013-11-10 13:01:46 +00:00
{
2014-10-24 17:29:50 +00:00
zend_bool original_in_execution = PHPDBG_G ( in_execution ) ;
2013-11-15 11:19:26 +00:00
2014-10-27 10:02:08 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) & & ! ( PHPDBG_G ( flags ) & PHPDBG_IS_RUNNING ) ) {
2014-10-26 22:33:54 +00:00
zend_bailout ( ) ;
}
2014-10-24 17:29:50 +00:00
PHPDBG_G ( in_execution ) = 1 ;
2013-11-10 13:01:46 +00:00
while ( 1 ) {
2015-04-21 21:09:09 +00:00
zend_object * exception = EG ( exception ) ;
2013-12-09 10:15:16 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_BP_RESOLVE_MASK ) ) {
/* resolve nth opline breakpoints */
2014-12-13 22:06:14 +00:00
phpdbg_resolve_op_array_breaks ( & execute_data - > func - > op_array ) ;
2013-12-09 10:15:16 +00:00
}
2014-10-02 23:29:41 +00:00
2013-11-10 13:01:46 +00:00
# ifdef ZEND_WIN32
if ( EG ( timed_out ) ) {
zend_timeout ( 0 ) ;
}
# endif
2015-09-23 16:30:13 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_PREVENT_INTERACTIVE ) {
phpdbg_print_opline_ex ( execute_data , 0 ) ;
goto next ;
}
2015-04-21 21:09:09 +00:00
/* check for uncaught exceptions */
2015-07-20 15:52:57 +00:00
if ( exception & & PHPDBG_G ( handled_exception ) ! = exception & & ! ( PHPDBG_G ( flags ) & PHPDBG_IN_EVAL ) ) {
2015-04-21 21:09:09 +00:00
zend_execute_data * prev_ex = execute_data ;
2015-06-28 23:41:04 +00:00
zval zv , rv ;
2015-07-16 08:28:59 +00:00
zend_string * file , * msg ;
2015-06-28 23:41:04 +00:00
zend_long line ;
2015-04-21 21:09:09 +00:00
do {
prev_ex = zend_generator_check_placeholder_frame ( prev_ex ) ;
/* assuming that no internal functions will silently swallow exceptions ... */
if ( ! prev_ex - > func | | ! ZEND_USER_CODE ( prev_ex - > func - > common . type ) ) {
continue ;
}
2015-04-21 23:07:52 +00:00
if ( phpdbg_check_caught_ex ( prev_ex , exception ) ) {
2015-04-21 21:09:09 +00:00
goto ex_is_caught ;
}
} while ( ( prev_ex = prev_ex - > prev_execute_data ) ) ;
2015-04-21 23:07:52 +00:00
PHPDBG_G ( handled_exception ) = exception ;
2015-06-28 23:41:04 +00:00
ZVAL_OBJ ( & zv , exception ) ;
file = zval_get_string ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " file " ) , 1 , & rv ) ) ;
line = zval_get_long ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " line " ) , 1 , & rv ) ) ;
2015-07-16 08:28:59 +00:00
msg = zval_get_string ( zend_read_property ( zend_get_exception_base ( & zv ) , & zv , ZEND_STRL ( " message " ) , 1 , & rv ) ) ;
2015-06-28 23:41:04 +00:00
2016-02-14 13:02:19 +00:00
phpdbg_error ( " exception " ,
" name= \" %s \" file= \" %s \" line= \" " ZEND_LONG_FMT " \" " ,
" Uncaught %s in %s on line " ZEND_LONG_FMT " : %.*s " ,
ZSTR_VAL ( exception - > ce - > name ) , ZSTR_VAL ( file ) , line ,
ZSTR_LEN ( msg ) < 80 ? ( int ) ZSTR_LEN ( msg ) : 80 , ZSTR_VAL ( msg ) ) ;
2015-07-16 08:28:59 +00:00
zend_string_release ( msg ) ;
2015-06-28 23:41:04 +00:00
zend_string_release ( file ) ;
2015-07-16 08:28:59 +00:00
2015-04-21 21:09:09 +00:00
DO_INTERACTIVE ( 1 ) ;
}
ex_is_caught :
2015-07-20 15:52:57 +00:00
/* allow conditional breakpoints and initialization to access the vm uninterrupted */
if ( PHPDBG_G ( flags ) & ( PHPDBG_IN_COND_BP | PHPDBG_IS_INITIALIZING ) ) {
2013-11-16 10:59:50 +00:00
/* skip possible breakpoints */
goto next ;
}
2013-11-17 16:10:43 +00:00
2013-11-18 02:14:17 +00:00
/* perform seek operation */
2015-07-20 15:52:57 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_SEEK_MASK ) & & ! ( PHPDBG_G ( flags ) & PHPDBG_IN_EVAL ) ) {
2013-11-18 03:18:37 +00:00
/* current address */
zend_ulong address = ( zend_ulong ) execute_data - > opline ;
2013-11-18 14:09:25 +00:00
2015-04-21 10:31:43 +00:00
if ( PHPDBG_G ( seek_ex ) ! = execute_data ) {
goto next ;
}
2015-04-21 23:07:52 +00:00
# define INDEX_EXISTS_CHECK (zend_hash_index_exists(&PHPDBG_G(seek), address) || (exception && phpdbg_check_caught_ex(execute_data, exception) == 0))
2015-04-21 10:31:43 +00:00
2013-11-18 02:14:17 +00:00
/* run to next line */
if ( PHPDBG_G ( flags ) & PHPDBG_IN_UNTIL ) {
2015-04-21 10:31:43 +00:00
if ( INDEX_EXISTS_CHECK ) {
2013-11-18 02:14:17 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_UNTIL ;
2014-09-21 02:17:19 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
2013-11-18 02:14:17 +00:00
} else {
/* skip possible breakpoints */
goto next ;
}
2013-11-17 13:59:21 +00:00
}
2013-11-17 16:10:43 +00:00
2013-11-18 02:14:17 +00:00
/* run to finish */
if ( PHPDBG_G ( flags ) & PHPDBG_IN_FINISH ) {
2015-04-21 10:31:43 +00:00
if ( INDEX_EXISTS_CHECK ) {
2013-11-18 02:14:17 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_FINISH ;
2014-09-21 02:17:19 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
2013-11-18 02:14:17 +00:00
}
2013-11-17 13:59:21 +00:00
/* skip possible breakpoints */
goto next ;
}
2013-11-18 14:09:25 +00:00
2013-11-18 02:14:17 +00:00
/* break for leave */
if ( PHPDBG_G ( flags ) & PHPDBG_IN_LEAVE ) {
2015-04-21 10:31:43 +00:00
if ( INDEX_EXISTS_CHECK ) {
2013-11-18 02:14:17 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_LEAVE ;
2014-09-21 02:17:19 +00:00
zend_hash_clean ( & PHPDBG_G ( seek ) ) ;
phpdbg_notice ( " breakpoint " , " id= \" leave \" file= \" %s \" line= \" %u \" " , " Breaking for leave at %s:%u " ,
2014-12-13 22:06:14 +00:00
zend_get_executed_filename ( ) ,
zend_get_executed_lineno ( )
2013-11-18 02:14:17 +00:00
) ;
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 1 ) ;
2013-11-18 02:14:17 +00:00
} else {
/* skip possible breakpoints */
goto next ;
}
}
2013-11-17 13:59:21 +00:00
}
2013-11-13 21:31:33 +00:00
2013-11-16 10:59:50 +00:00
/* not while in conditionals */
2015-07-06 14:56:48 +00:00
phpdbg_print_opline_ex ( execute_data , 0 ) ;
2013-11-17 16:10:43 +00:00
2014-04-20 18:20:59 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_STEPPING & & ( PHPDBG_G ( flags ) & PHPDBG_STEP_OPCODE | | execute_data - > opline - > lineno ! = PHPDBG_G ( last_line ) ) ) {
2014-04-20 14:47:24 +00:00
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_STEPPING ;
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 1 ) ;
2014-04-20 14:47:24 +00:00
}
2013-12-13 22:57:36 +00:00
/* check if some watchpoint was hit */
{
2014-12-13 22:06:14 +00:00
if ( phpdbg_print_changed_zvals ( ) = = SUCCESS ) {
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 1 ) ;
2013-12-13 22:57:36 +00:00
}
}
2013-11-27 13:01:57 +00:00
/* search for breakpoints */
{
phpdbg_breakbase_t * brake ;
2013-12-08 18:07:49 +00:00
2014-04-20 11:25:28 +00:00
if ( ( PHPDBG_G ( flags ) & PHPDBG_BP_MASK )
2014-12-13 22:06:14 +00:00
& & ( brake = phpdbg_find_breakpoint ( execute_data ) )
2014-04-20 11:25:28 +00:00
& & ( brake - > type ! = PHPDBG_BREAK_FILE | | execute_data - > opline - > lineno ! = PHPDBG_G ( last_line ) ) ) {
2014-12-13 22:06:14 +00:00
phpdbg_hit_breakpoint ( brake , 1 ) ;
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 1 ) ;
2013-11-27 13:01:57 +00:00
}
2013-11-23 22:03:17 +00:00
}
2013-11-20 19:16:07 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_SIGNALED ) {
PHPDBG_G ( flags ) & = ~ PHPDBG_IS_SIGNALED ;
2014-10-03 10:43:32 +00:00
2014-10-19 18:09:39 +00:00
phpdbg_out ( " \n " ) ;
2014-09-21 02:17:19 +00:00
phpdbg_notice ( " signal " , " type= \" SIGINT \" " , " Program received signal SIGINT " ) ;
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 1 ) ;
2013-11-20 19:16:07 +00:00
}
2014-10-02 23:29:41 +00:00
next :
2014-04-20 11:25:28 +00:00
PHPDBG_G ( last_line ) = execute_data - > opline - > lineno ;
2014-10-05 11:29:56 +00:00
/* stupid hack to make zend_do_fcall_common_helper return ZEND_VM_ENTER() instead of recursively calling zend_execute() and eventually segfaulting */
2015-02-25 07:37:21 +00:00
if ( ( execute_data - > opline - > opcode = = ZEND_DO_FCALL | |
execute_data - > opline - > opcode = = ZEND_DO_UCALL | |
execute_data - > opline - > opcode = = ZEND_DO_FCALL_BY_NAME ) & &
2015-06-16 21:37:23 +00:00
execute_data - > call - > func - > type = = ZEND_USER_FUNCTION ) {
2014-10-05 11:29:56 +00:00
zend_execute_ex = execute_ex ;
}
2015-03-13 08:29:43 +00:00
PHPDBG_G ( vmret ) = zend_vm_call_opcode_handler ( execute_data ) ;
2014-10-05 11:29:56 +00:00
zend_execute_ex = phpdbg_execute_ex ;
2013-11-21 23:19:55 +00:00
2014-10-24 17:29:50 +00:00
if ( PHPDBG_G ( vmret ) ! = 0 ) {
if ( PHPDBG_G ( vmret ) < 0 ) {
PHPDBG_G ( in_execution ) = original_in_execution ;
return ;
} else {
execute_data = EG ( current_execute_data ) ;
2013-11-10 13:01:46 +00:00
}
}
}
zend_error_noreturn ( E_ERROR , " Arrived at end of main loop which shouldn't happen " ) ;
2013-11-10 18:21:49 +00:00
} /* }}} */
2014-09-28 00:57:12 +00:00
2014-10-02 23:29:41 +00:00
/* only if *not* interactive and while executing */
2015-04-21 13:53:12 +00:00
void phpdbg_force_interruption ( void ) /* { { { */ {
2015-04-21 21:09:09 +00:00
zend_object * exception = EG ( exception ) ;
2014-09-28 00:57:12 +00:00
zend_execute_data * data = EG ( current_execute_data ) ; /* should be always readable if not NULL */
2014-10-02 23:29:41 +00:00
PHPDBG_G ( flags ) | = PHPDBG_IN_SIGNAL_HANDLER ;
2014-09-28 00:57:12 +00:00
if ( data ) {
2014-10-24 17:29:50 +00:00
if ( data - > func ) {
2015-08-21 22:36:31 +00:00
if ( ZEND_USER_CODE ( data - > func - > type ) ) {
2015-08-27 03:34:52 +00:00
phpdbg_notice ( " hardinterrupt " , " opline= \" %p \" num= \" %lu \" file= \" %s \" line= \" %u \" " , " Current opline: %p (op #%lu) in %s:%u " , data - > opline , ( data - > opline - data - > func - > op_array . opcodes ) / sizeof ( data - > opline ) , data - > func - > op_array . filename - > val , data - > opline - > lineno ) ;
2015-08-21 22:36:31 +00:00
} else if ( data - > func - > internal_function . function_name ) {
phpdbg_notice ( " hardinterrupt " , " func= \" %s \" " , " Current opline: in internal function %s " , data - > func - > internal_function . function_name - > val ) ;
} else {
phpdbg_notice ( " hardinterrupt " , " " , " Current opline: executing internal code " ) ;
}
2014-09-28 00:57:12 +00:00
} else {
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " hardinterrupt " , " opline= \" %p \" " , " Current opline: %p (op_array information unavailable) " , data - > opline ) ;
2014-09-28 00:57:12 +00:00
}
} else {
2014-10-07 11:08:30 +00:00
phpdbg_notice ( " hardinterrupt " , " " , " No information available about executing context " ) ;
2014-09-28 00:57:12 +00:00
}
2014-10-02 23:29:41 +00:00
DO_INTERACTIVE ( 0 ) ;
next :
PHPDBG_G ( flags ) & = ~ PHPDBG_IN_SIGNAL_HANDLER ;
2014-10-26 02:50:28 +00:00
if ( PHPDBG_G ( flags ) & PHPDBG_IS_STOPPING ) {
2014-10-02 23:29:41 +00:00
zend_bailout ( ) ;
}
2014-09-28 00:57:12 +00:00
}
2015-04-21 13:53:12 +00:00
/* }}} */
2014-10-21 08:35:20 +00:00
PHPDBG_COMMAND ( eol ) /* {{{ */
{
if ( ! param | | param - > type = = EMPTY_PARAM ) {
2014-10-21 13:50:55 +00:00
phpdbg_notice ( " eol " , " argument required " , " argument required " ) ;
2014-10-21 08:35:20 +00:00
} else switch ( param - > type ) {
case STR_PARAM :
2014-12-13 22:06:14 +00:00
if ( FAILURE = = phpdbg_eol_global_update ( param - > str ) ) {
2014-10-21 14:19:31 +00:00
phpdbg_notice ( " eol " , " unknown EOL name '%s', give crlf, lf, cr " , " unknown EOL name '%s', give crlf, lf, cr " , param - > str ) ;
2014-10-21 08:35:20 +00:00
}
break ;
phpdbg_default_switch_case ( ) ;
}
2014-10-21 09:46:32 +00:00
return SUCCESS ;
2014-10-21 08:35:20 +00:00
} /* }}} */