diff options
Diffstat (limited to 'sapi/phpdbg')
29 files changed, 1506 insertions, 2098 deletions
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index f09dc4ee13..d70e512751 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -52,7 +52,7 @@ static PHP_INI_MH(OnUpdateEol) return FAILURE; } - return phpdbg_eol_global_update(new_value TSRMLS_CC); + return phpdbg_eol_global_update(new_value->val TSRMLS_CC); } PHP_INI_BEGIN() @@ -83,6 +83,7 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ pg->last_was_newline = 1; pg->ops = NULL; pg->vmret = 0; + pg->in_execution = 0; pg->bp_count = 0; pg->flags = PHPDBG_DEFAULT_FLAGS; pg->oplog = NULL; @@ -135,50 +136,49 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ return SUCCESS; } /* }}} */ -static void php_phpdbg_destroy_bp_file(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */ { - zend_hash_destroy((HashTable*)brake); + zend_hash_destroy(Z_ARRVAL_P(brake)); } /* }}} */ -static void php_phpdbg_destroy_bp_symbol(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_symbol(zval *brake) /* {{{ */ { - efree((char*)((phpdbg_breaksymbol_t*)brake)->symbol); + efree((char *) ((phpdbg_breaksymbol_t *) Z_PTR_P(brake))->symbol); } /* }}} */ -static void php_phpdbg_destroy_bp_opcode(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_opcode(zval *brake) /* {{{ */ { - efree((char*)((phpdbg_breakop_t*)brake)->name); + efree((char *) ((phpdbg_breakop_t *) Z_PTR_P(brake))->name); } /* }}} */ -static void php_phpdbg_destroy_bp_methods(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_methods(zval *brake) /* {{{ */ { - zend_hash_destroy((HashTable*)brake); + zend_hash_destroy(Z_ARRVAL_P(brake)); } /* }}} */ -static void php_phpdbg_destroy_bp_condition(void *data) /* {{{ */ +static void php_phpdbg_destroy_bp_condition(zval *data) /* {{{ */ { - phpdbg_breakcond_t *brake = (phpdbg_breakcond_t*) data; + phpdbg_breakcond_t *brake = (phpdbg_breakcond_t *) Z_PTR_P(data); if (brake) { if (brake->ops) { TSRMLS_FETCH(); - destroy_op_array( - brake->ops TSRMLS_CC); + destroy_op_array(brake->ops TSRMLS_CC); efree(brake->ops); } - efree((char*)brake->code); + efree((char*) brake->code); } } /* }}} */ -static void php_phpdbg_destroy_registered(void *data) /* {{{ */ +static void php_phpdbg_destroy_registered(zval *data) /* {{{ */ { - zend_function *function = (zend_function*) data; + zend_function *function = (zend_function *) Z_PTR_P(data); + TSRMLS_FETCH(); - destroy_zend_function( - function TSRMLS_CC); + destroy_zend_function(function TSRMLS_CC); } /* }}} */ @@ -261,10 +261,9 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ If the request to set the context fails, boolean false is returned, and an E_WARNING raised */ static PHP_FUNCTION(phpdbg_exec) { - char *exec = NULL; - int exec_len = 0; + zend_string *exec; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &exec, &exec_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &exec) == FAILURE) { return; } @@ -272,27 +271,26 @@ static PHP_FUNCTION(phpdbg_exec) struct stat sb; zend_bool result = 1; - if (VCWD_STAT(exec, &sb) != FAILURE) { + if (VCWD_STAT(exec->val, &sb) != FAILURE) { if (sb.st_mode & (S_IFREG|S_IFLNK)) { if (PHPDBG_G(exec)) { - ZVAL_STRINGL(return_value, PHPDBG_G(exec), PHPDBG_G(exec_len), 1); + ZVAL_STRINGL(return_value, PHPDBG_G(exec), PHPDBG_G(exec_len)); efree(PHPDBG_G(exec)); result = 0; } - PHPDBG_G(exec) = estrndup(exec, exec_len); - PHPDBG_G(exec_len) = exec_len; + PHPDBG_G(exec) = estrndup(exec->val, exec->len); + PHPDBG_G(exec_len) = exec->len; - if (result) + if (result) { ZVAL_BOOL(return_value, 1); + } } else { - zend_error( - E_WARNING, "Failed to set execution context (%s), not a regular file or symlink", exec); + zend_error(E_WARNING, "Failed to set execution context (%s), not a regular file or symlink", exec); ZVAL_BOOL(return_value, 0); } } else { - zend_error( - E_WARNING, "Failed to set execution context (%s) the file does not exist", exec); + zend_error(E_WARNING, "Failed to set execution context (%s) the file does not exist", exec); ZVAL_BOOL(return_value, 0); } @@ -316,13 +314,8 @@ static PHP_FUNCTION(phpdbg_break) phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC); phpdbg_do_break(¶m TSRMLS_CC); phpdbg_clear_param(¶m TSRMLS_CC); - - } else if (EG(current_execute_data) && EG(active_op_array)) { - zend_ulong opline_num = (EG(current_execute_data)->opline - - EG(active_op_array)->opcodes); - - phpdbg_set_breakpoint_opline_ex( - &EG(active_op_array)->opcodes[opline_num+1] TSRMLS_CC); + } else if (EG(current_execute_data) && EG(current_execute_data)->func->type != ZEND_INTERNAL_FUNCTION) { + phpdbg_set_breakpoint_opline_ex((phpdbg_opline_ptr_t) EG(current_execute_data)->opline + 1 TSRMLS_CC); } } /* }}} */ @@ -478,13 +471,10 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ case E_PARSE: case E_RECOVERABLE_ERROR: if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { - phpdbg_list_file( - zend_get_executed_filename(TSRMLS_C), - 3, - zend_get_executed_lineno(TSRMLS_C)-1, - zend_get_executed_lineno(TSRMLS_C) - TSRMLS_CC - ); + const char *file_char = zend_get_executed_filename(TSRMLS_C); + zend_string *file = zend_string_init(file_char, strlen(file_char), 0); + phpdbg_list_file(file, 3, zend_get_executed_lineno(TSRMLS_C) - 1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); + efree(file); } do { @@ -515,8 +505,8 @@ static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */ static void php_sapi_phpdbg_register_vars(zval *track_vars_array TSRMLS_DC) /* {{{ */ { - unsigned int len; - char *docroot = ""; + size_t len; + char *docroot = ""; /* In phpdbg mode, we consider the environment to be a part of the server variables */ @@ -524,39 +514,30 @@ static void php_sapi_phpdbg_register_vars(zval *track_vars_array TSRMLS_DC) /* { if (PHPDBG_G(exec)) { len = PHPDBG_G(exec_len); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("PHP_SELF", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { + php_register_variable("PHP_SELF", PHPDBG_G(exec), track_vars_array TSRMLS_CC); } - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("SCRIPT_NAME", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { + php_register_variable("SCRIPT_NAME", PHPDBG_G(exec), track_vars_array TSRMLS_CC); } - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("SCRIPT_FILENAME", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { + php_register_variable("SCRIPT_FILENAME", PHPDBG_G(exec), track_vars_array TSRMLS_CC); } - if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("PATH_TRANSLATED", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { + php_register_variable("PATH_TRANSLATED", PHPDBG_G(exec), track_vars_array TSRMLS_CC); } } - /* any old docroot will doo */ - len = 0U; - if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", - &docroot, len, &len TSRMLS_CC)) { + /* any old docroot will do */ + len = 0; + if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len TSRMLS_CC)) { php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array TSRMLS_CC); } } /* }}} */ -static inline int php_sapi_phpdbg_ub_write(const char *message, unsigned int length TSRMLS_DC) /* {{{ */ +static inline size_t php_sapi_phpdbg_ub_write(const char *message, size_t length TSRMLS_DC) /* {{{ */ { if (PHPDBG_G(socket_fd) != -1 && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { send(PHPDBG_G(socket_fd), message, length, 0); @@ -611,23 +592,16 @@ static inline void php_sapi_phpdbg_flush(void *context) /* {{{ */ /* copied from sapi/cli/php_cli.c cli_register_file_handles */ static void phpdbg_register_file_handles(TSRMLS_D) /* {{{ */ { - zval *zin, *zout, *zerr; + zval zin, zout, zerr; php_stream *s_in, *s_out, *s_err; php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL; zend_constant ic, oc, ec; - MAKE_STD_ZVAL(zin); - MAKE_STD_ZVAL(zout); - MAKE_STD_ZVAL(zerr); - s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in); s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); if (s_in==NULL || s_out==NULL || s_err==NULL) { - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); if (s_in) php_stream_close(s_in); if (s_out) php_stream_close(s_out); if (s_err) php_stream_close(s_err); @@ -640,34 +614,27 @@ static void phpdbg_register_file_handles(TSRMLS_D) /* {{{ */ s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; #endif - php_stream_to_zval(s_in, zin); - php_stream_to_zval(s_out, zout); - php_stream_to_zval(s_err, zerr); + php_stream_to_zval(s_in, &zin); + php_stream_to_zval(s_out, &zout); + php_stream_to_zval(s_err, &zerr); - ic.value = *zin; + ic.value = zin; ic.flags = CONST_CS; - ic.name = zend_strndup(ZEND_STRL("STDIN")); - ic.name_len = sizeof("STDIN"); + ic.name = zend_string_init(ZEND_STRL("STDIN"), 0); ic.module_number = 0; zend_register_constant(&ic TSRMLS_CC); - oc.value = *zout; + oc.value = zout; oc.flags = CONST_CS; - oc.name = zend_strndup(ZEND_STRL("STDOUT")); - oc.name_len = sizeof("STDOUT"); + oc.name = zend_string_init(ZEND_STRL("STDOUT"), 0); oc.module_number = 0; zend_register_constant(&oc TSRMLS_CC); - ec.value = *zerr; + ec.value = zerr; ec.flags = CONST_CS; - ec.name = zend_strndup(ZEND_STRL("STDERR")); - ec.name_len = sizeof("STDERR"); + ec.name = zend_string_init(ZEND_STRL("STDERR"), 0); ec.module_number = 0; zend_register_constant(&ec TSRMLS_CC); - - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); } /* }}} */ @@ -721,8 +688,10 @@ const opt_struct OPTIONS[] = { /* {{{ */ {'r', 0, "run"}, {'E', 0, "step-through-eval"}, {'S', 1, "sapi-name"}, +#ifndef _WIN32 {'l', 1, "listen"}, {'a', 1, "address-or-any"}, +#endif {'x', 0, "xml output"}, {'V', 0, "version"}, {'-', 0, NULL} @@ -740,10 +709,9 @@ const char phpdbg_ini_hardcoded[] = /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */ #define INI_DEFAULT(name, value) \ + ZVAL_STRINGL(&tmp, value, sizeof(value) - 1); \ Z_SET_REFCOUNT(tmp, 0); \ - Z_UNSET_ISREF(tmp); \ - ZVAL_STRINGL(&tmp, zend_strndup(value, sizeof(value)-1), sizeof(value)-1, 0); \ - zend_hash_update(configuration_hash, name, sizeof(name), &tmp, sizeof(zval), NULL); + zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp); void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */ { @@ -805,7 +773,6 @@ static inline void phpdbg_sigint_handler(int signo) /* {{{ */ } } /* }}} */ - static void phpdbg_remote_close(int socket, FILE *stream) { if (socket >= 0) { phpdbg_close_socket(socket); @@ -990,11 +957,13 @@ int main(int argc, char **argv) /* {{{ */ char bp_tmp_file[] = "/tmp/phpdbg.XXXXXX"; #endif +#ifndef _WIN32 char *address; int listen = -1; int server = -1; int socket = -1; FILE* stream = NULL; +#endif #ifdef ZTS void ***tsrm_ls; @@ -1007,9 +976,10 @@ int main(int argc, char **argv) /* {{{ */ signal_struct.sa_flags = SA_SIGINFO | SA_NODEFER; sigio_struct.sa_sigaction = phpdbg_sigio_handler; sigio_struct.sa_flags = SA_SIGINFO; -#endif + address = strdup("127.0.0.1"); +#endif #ifdef PHP_WIN32 _fmode = _O_BINARY; /* sets default for file streams to binary */ @@ -1172,6 +1142,7 @@ phpdbg_main: show_banner = 0; break; +#ifndef _WIN32 /* if you pass a listen port, we will read and write on listen port */ case 'l': /* set listen ports */ if (sscanf(php_optarg, "%d", &listen) != 1) { @@ -1185,6 +1156,7 @@ phpdbg_main: address = strdup("*"); } else address = strdup(php_optarg); } break; +#endif case 'x': flags |= PHPDBG_WRITE_XML; @@ -1276,7 +1248,11 @@ phpdbg_main: __try { #endif zend_mm_heap *mm_heap; + void* (*_malloc)(size_t); + void (*_free)(void*); + void* (*_realloc)(void*, size_t); +#ifndef _WIN32 /* setup remote server if necessary */ if (!cleaning && listen > 0) { server = phpdbg_open_socket(address, listen TSRMLS_CC); @@ -1284,29 +1260,34 @@ phpdbg_main: exit(0); } -#ifndef _WIN32 sigaction(SIGIO, &sigio_struct, NULL); -#endif /* set remote flag to stop service shutting down upon quit */ remote = 1; } +#endif mm_heap = phpdbg_mm_get_heap(); + zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc); - if (mm_heap->use_zend_alloc) { - mm_heap->_malloc = phpdbg_malloc_wrapper; - mm_heap->_realloc = phpdbg_realloc_wrapper; - mm_heap->_free = phpdbg_free_wrapper; - mm_heap->use_zend_alloc = 0; + if (!_malloc) { + _malloc = phpdbg_malloc_wrapper; + } + if (!_realloc) { + _realloc = phpdbg_realloc_wrapper; + } + if (!_free) { + _free = phpdbg_free_wrapper; } zend_activate(TSRMLS_C); phpdbg_init_list(TSRMLS_C); - PHPDBG_G(original_free_function) = mm_heap->_free; - mm_heap->_free = phpdbg_watch_efree; + PHPDBG_G(original_free_function) = _free; + _free = phpdbg_watch_efree; + + zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc); phpdbg_setup_watchpoints(TSRMLS_C); @@ -1363,13 +1344,14 @@ phpdbg_main: /* set flags from command line */ PHPDBG_G(flags) = flags; +#ifndef _WIN32 /* setup io here */ if (remote) { PHPDBG_G(flags) |= PHPDBG_IS_REMOTE; -#ifndef _WIN32 + signal(SIGPIPE, SIG_IGN); -#endif } +#endif #ifndef _WIN32 PHPDBG_G(io)[PHPDBG_STDIN].ptr = stdin; @@ -1465,7 +1447,10 @@ phpdbg_main: } } +/* #ifndef for making compiler shutting up */ +#ifndef _WIN32 phpdbg_interact: +#endif /* phpdbg main() */ do { zend_try { @@ -1480,6 +1465,7 @@ phpdbg_interact: cleaning = 0; } +#ifndef _WIN32 if (!cleaning) { /* remote client disconnected */ if ((PHPDBG_G(flags) & PHPDBG_IS_DISCONNECTED)) { @@ -1501,6 +1487,7 @@ phpdbg_interact: } } } +#endif } zend_end_try(); } while(!cleaning && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); @@ -1510,17 +1497,19 @@ phpdbg_interact: /* this is just helpful */ PG(report_memleaks) = 0; +#ifndef _WIN32 phpdbg_out: if ((PHPDBG_G(flags) & PHPDBG_IS_DISCONNECTED)) { PHPDBG_G(flags) &= ~PHPDBG_IS_DISCONNECTED; goto phpdbg_interact; } +#endif #ifdef _WIN32 } __except(phpdbg_exception_handler_win32(xp = GetExceptionInformation())) { phpdbg_error("segfault", "", "Access violation (Segementation fault) encountered\ntrying to abort cleanly..."); } -/* phpdbg_out: */ +phpdbg_out: #endif { diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index 8c0dbb4afa..f3e8ba3107 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -67,6 +67,29 @@ # include "TSRM.h" #endif +#define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_FOREACH(ht, 0); \ + _h = _p->h; \ + _ptr = Z_PTR_P(_z); + +#undef zend_hash_str_add +#define zend_hash_str_add_tmp(ht, key, len, pData) \ + _zend_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC) +#define zend_hash_str_add(...) zend_hash_str_add_tmp(__VA_ARGS__) + +static zend_always_inline void *zend_hash_index_add_mem(HashTable *ht, zend_ulong h, void *pData, size_t size) +{ + zval tmp, *zv; + + ZVAL_PTR(&tmp, NULL); + if ((zv = zend_hash_index_add(ht, h, &tmp))) { + Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT); + memcpy(Z_PTR_P(zv), pData, size); + return Z_PTR_P(zv); + } + return NULL; +} + #ifdef HAVE_LIBREADLINE # include <readline/readline.h> # include <readline/history.h> @@ -225,7 +248,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable registered; /* registered */ HashTable seek; /* seek oplines */ phpdbg_frame_t frame; /* frame */ - zend_uint last_line; /* last executed line */ + uint32_t last_line; /* last executed line */ phpdbg_lexer_data lexer; /* lexer data */ phpdbg_param_t *parser_stack; /* param stack during lexer / parser phase */ @@ -236,6 +259,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) phpdbg_btree watchpoint_tree; /* tree with watchpoints */ phpdbg_btree watch_HashTables; /* tree with original dtors of watchpoints */ HashTable watchpoints; /* watchpoints */ + HashTable watch_collisions; /* collision table to check if multiple watches share the same recursive watchpoint */ zend_llist watchlist_mem; /* triggered watchpoints */ zend_bool watchpoint_hit; /* a watchpoint was hit */ void (*original_free_function)(void *); /* the original AG(mm_heap)->_free function */ @@ -243,9 +267,10 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) char *exec; /* file to execute */ size_t exec_len; /* size of exec */ zend_op_array *ops; /* op_array */ - zval *retval; /* return value */ + zval retval; /* return value */ int bp_count; /* breakpoint count */ int vmret; /* return from last opcode handler execution */ + zend_bool in_execution; /* in execution? */ zend_op_array *(*compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); HashTable file_sources; diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 81674a0daf..aaeaee13fd 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -43,7 +43,7 @@ static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execut */ static inline void _phpdbg_break_mapping(int id, HashTable *table TSRMLS_DC) { - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id), (void**) &table, sizeof(void*), NULL); + zend_hash_index_update_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table); } #define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table TSRMLS_CC) @@ -57,29 +57,29 @@ static inline void _phpdbg_break_mapping(int id, HashTable *table TSRMLS_DC) b.hits = 0; \ } while(0) -static void phpdbg_file_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_file_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) data; + phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) Z_PTR_P(data); efree((char*)bp->filename); } /* }}} */ -static void phpdbg_class_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_class_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakmethod_t *bp = (phpdbg_breakmethod_t*) data; + phpdbg_breakmethod_t *bp = (phpdbg_breakmethod_t *) Z_PTR_P(data); efree((char*)bp->class_name); efree((char*)bp->func_name); } /* }}} */ -static void phpdbg_opline_class_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_opline_class_breaks_dtor(zval *data) /* {{{ */ { - zend_hash_destroy((HashTable *)data); + zend_hash_destroy((HashTable *) Z_PTR_P(data)); } /* }}} */ -static void phpdbg_opline_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_opline_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) data; + phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) Z_PTR_P(data); if (bp->class_name) { efree((char*)bp->class_name); @@ -91,43 +91,30 @@ static void phpdbg_opline_breaks_dtor(void *data) /* {{{ */ PHPDBG_API void phpdbg_reset_breakpoints(TSRMLS_D) /* {{{ */ { - if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { - HashPosition position[2]; - HashTable **table = NULL; + HashTable *table; - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0]); - 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])) { - phpdbg_breakbase_t *brake; + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], table) { + phpdbg_breakbase_t *brake; - 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])) { - brake->hits = 0; - } - } - } + ZEND_HASH_FOREACH_PTR(table, brake) { + brake->hits = 0; + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } /* }}} */ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ { - HashPosition position[2]; - HashTable **table = NULL; + HashTable *table; zend_ulong id = 0L; if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { phpdbg_notice("exportbreakpoint", "count=\"%d\"", "Exporting %d breakpoints", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])); + /* this only looks like magic, it isn't */ - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0]); - 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])) { + ZEND_HASH_FOREACH_NUM_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table) { phpdbg_breakbase_t *brake; - zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], NULL, NULL, &id, 0, &position[0]); - - 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])) { + ZEND_HASH_FOREACH_PTR(table, brake) { if (brake->id == id) { switch (brake->type) { case PHPDBG_BREAK_FILE: { @@ -152,7 +139,7 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ case PHPDBG_BREAK_METHOD_OPLINE: { fprintf(handle, - "break %s::%s#%ld\n", + "break %s::%s#%llu\n", ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); @@ -160,14 +147,14 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ case PHPDBG_BREAK_FUNCTION_OPLINE: { fprintf(handle, - "break %s#%ld\n", + "break %s#%llu\n", ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FILE_OPLINE: { fprintf(handle, - "break %s:#%ld\n", + "break %s:#%llu\n", ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; @@ -211,8 +198,8 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ } break; } } - } - } + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } } /* }}} */ @@ -232,15 +219,12 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML } path_len = strlen(path); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, (void**)&broken) == FAILURE) { + if (!(broken = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len))) { HashTable breaks; zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, &breaks, sizeof(HashTable), - (void**)&broken); + broken = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len, &breaks, sizeof(HashTable)); } if (!zend_hash_index_exists(broken, line_num)) { @@ -250,10 +234,9 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML new_break.filename = estrndup(path, path_len); new_break.line = line_num; - zend_hash_index_update( broken, line_num, (void**)&new_break, sizeof(phpdbg_breakfile_t), NULL); + zend_hash_index_update_mem(broken, line_num, &new_break, sizeof(phpdbg_breakfile_t)); - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", - new_break.id, new_break.filename, new_break.line); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); PHPDBG_BREAK_MAPPING(new_break.id, broken); } else { @@ -270,7 +253,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len TSRMLS_DC) /* {{{ */ { - if (!zend_hash_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { + if (!zend_hash_str_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { phpdbg_breaksymbol_t new_break; PHPDBG_G(flags) |= PHPDBG_HAS_SYM_BP; @@ -278,11 +261,9 @@ PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len T PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_SYM); new_break.symbol = estrndup(name, name_len); - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], new_break.symbol, - name_len, &new_break, sizeof(phpdbg_breaksymbol_t), NULL); + zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], new_break.symbol, name_len, &new_break, sizeof(phpdbg_breaksymbol_t)); - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" function=\"%s\"", "Breakpoint #%d added at %s", - new_break.id, new_break.symbol); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" function=\"%s\"", "Breakpoint #%d added at %s", new_break.id, new_break.symbol); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); } else { @@ -297,16 +278,12 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char size_t func_len = strlen(func_name); char *lcname = zend_str_tolower_dup(func_name, func_len); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, - class_len, (void**)&class_table) != SUCCESS) { + if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, class_len))) { 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); + class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, class_len, &class_breaks, sizeof(HashTable)); } - if (!zend_hash_exists(class_table, lcname, func_len)) { + if (!zend_hash_str_exists(class_table, lcname, func_len)) { phpdbg_breakmethod_t new_break; PHPDBG_G(flags) |= PHPDBG_HAS_METHOD_BP; @@ -317,11 +294,9 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char new_break.func_name = estrndup(func_name, func_len); new_break.func_len = func_len; - zend_hash_update(class_table, lcname, func_len, - &new_break, sizeof(phpdbg_breakmethod_t), NULL); + zend_hash_str_update_mem(class_table, lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t)); - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" method=\"%s::%s\"", "Breakpoint #%d added at %s::%s", - new_break.id, class_name, func_name); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" method=\"%s::%s\"", "Breakpoint #%d added at %s::%s", new_break.id, class_name, func_name); PHPDBG_BREAK_MAPPING(new_break.id, class_table); } else { @@ -343,11 +318,9 @@ PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ new_break.opline = opline; new_break.base = NULL; - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, - &new_break, sizeof(phpdbg_breakline_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, &new_break, sizeof(phpdbg_breakline_t)); - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" opline=\"%#lx\"", "Breakpoint #%d added at %#lx", - new_break.id, new_break.opline); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" opline=\"%#lx\"", "Breakpoint #%d added at %#lx", new_break.id, new_break.opline); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); } else { phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" opline=\"%#lx\"", "Breakpoint exists at %#lx", opline); @@ -385,7 +358,7 @@ PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_o 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); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline_break.opline, &opline_break, sizeof(phpdbg_breakline_t)); return SUCCESS; } /* }}} */ @@ -394,40 +367,36 @@ PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array TSRMLS_DC { 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) { + if (op_array->scope != NULL && !(func_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], op_array->scope->name))) { return; } 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) { + if (!(oplines_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], op_array->filename))) { 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) { + } else if (!op_array->function_name || !(oplines_table = zend_hash_find_ptr(func_table, op_array->function_name))) { 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)) { + ZEND_HASH_FOREACH_PTR(oplines_table, brake) { 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); + opline_break = zend_hash_get_current_data_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" symbol=\"%s\" num=\"%ld\" opline=\"%#lx\"", "Breakpoint #%d resolved at %s%s%s#%ld (opline %#lx)", brake->id, - brake->class_name?brake->class_name:"", - brake->class_name&&brake->func_name?"::":"", - brake->func_name?brake->func_name:"", + brake->class_name ? brake->class_name : "", + brake->class_name && brake->func_name ? "::" : "", + brake->func_name ? brake->func_name : "", brake->opline_num, brake->opline); } - } + } ZEND_HASH_FOREACH_END(); } /* }}} */ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRMLS_DC) /* {{{ */ @@ -448,8 +417,9 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML } 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) { + zend_op_array *op_array = &execute_data->func->op_array; + if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == op_array->filename->len && !memcmp(op_array->filename->val, new_break->class_name, new_break->class_len)) { + if (phpdbg_resolve_op_array_break(new_break, op_array TSRMLS_CC) == SUCCESS) { return SUCCESS; } else { return 2; @@ -461,14 +431,14 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML } if (new_break->class_name != NULL) { - zend_class_entry **ce; - 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) { + zend_class_entry *ce; + if (!(ce = zend_hash_str_find_ptr(EG(class_table), zend_str_tolower_dup(new_break->class_name, new_break->class_len), new_break->class_len))) { return FAILURE; } - func_table = &(*ce)->function_table; + func_table = &ce->function_table; } - 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) { + if (!(func = zend_hash_str_find_ptr(func_table, zend_str_tolower_dup(new_break->func_name, new_break->func_len), new_break->func_len))) { if (new_break->class_name != NULL && new_break->func_name != NULL) { phpdbg_error("breakpoint", "type=\"nomethod\" method=\"%s::%s\"", "Method %s doesn't exist in class %s", new_break->func_name, new_break->class_name); return 2; @@ -519,22 +489,14 @@ PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const cha return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len, (void **)&class_table) == FAILURE) { + if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len))) { 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); + class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len, &class_breaks, sizeof(HashTable)); } - if (zend_hash_find(class_table, new_break.func_name, new_break.func_len, (void **)&method_table) == FAILURE) { + if (!(method_table = zend_hash_str_find_ptr(class_table, new_break.func_name, new_break.func_len))) { 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); + method_table = zend_hash_str_update_mem(class_table, new_break.func_name, new_break.func_len, &method_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(method_table, opline)) { @@ -549,7 +511,7 @@ PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const cha PHPDBG_BREAK_MAPPING(new_break.id, method_table); - zend_hash_index_update(method_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(method_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline TSRMLS_DC) /* {{{ */ @@ -578,13 +540,9 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len, (void **)&func_table) == FAILURE) { + if (!(func_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len))) { 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); + func_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len, &func_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(func_table, opline)) { @@ -598,7 +556,7 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend PHPDBG_G(flags) |= PHPDBG_HAS_FUNCTION_OPLINE_BP; - zend_hash_index_update(func_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(func_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline TSRMLS_DC) /* {{{ */ @@ -627,13 +585,9 @@ PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong o return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, (void **)&file_table) == FAILURE) { + if (!(file_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len))) { 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); + file_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, &file_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(file_table, opline)) { @@ -647,7 +601,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong o PHPDBG_G(flags) |= PHPDBG_HAS_FILE_OPLINE_BP; - zend_hash_index_update(file_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(file_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len TSRMLS_DC) /* {{{ */ @@ -664,8 +618,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len T new_break.hash = hash; new_break.name = estrndup(name, name_len); - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, - &new_break, sizeof(phpdbg_breakop_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, &new_break, sizeof(phpdbg_breakop_t)); PHPDBG_G(flags) |= PHPDBG_HAS_OPCODE_BP; @@ -683,8 +636,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRML PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_OPLINE); new_break.opline = (zend_ulong) opline; - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], - (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t)); phpdbg_notice("breakpoint", "id=\"%d\" opline=\"%#lx\"", "Breakpoint #%d added at %#lx", new_break.id, new_break.opline); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); @@ -696,7 +648,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRML 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) /* {{{ */ { phpdbg_breakcond_t new_break; - zend_uint cops = CG(compiler_options); + uint32_t cops = CG(compiler_options); zval pv; PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_COND); @@ -717,22 +669,19 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co new_break.code = estrndup(expr, expr_len); new_break.code_len = expr_len; - Z_STRLEN(pv) = expr_len + sizeof("return ;") - 1; - Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1); + Z_STR(pv) = zend_string_alloc(expr_len + sizeof("return ;") - 1, 0); 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; + Z_TYPE_INFO(pv) = IS_STRING; new_break.ops = zend_compile_string(&pv, "Conditional Breakpoint Code" TSRMLS_CC); zval_dtor(&pv); if (new_break.ops) { - zend_hash_index_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash, &new_break, - sizeof(phpdbg_breakcond_t), (void**)&brake); + brake = zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash, &new_break, sizeof(phpdbg_breakcond_t)); phpdbg_notice("breakpoint", "id=\"%d\" expression=\"%s\" ptr=\"%p\"", "Conditional breakpoint #%d added %s/%p", brake->id, brake->code, brake->ops); @@ -743,6 +692,7 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co efree((char*)new_break.code); PHPDBG_G(bp_count)--; } + CG(compiler_options) = cops; } /* }}} */ @@ -782,14 +732,12 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ { HashTable *breaks; phpdbg_breakbase_t *brake; - size_t name_len = strlen(op_array->filename); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename, - name_len, (void**)&breaks) == FAILURE) { + if (!(breaks = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename))) { return NULL; } - if (zend_hash_index_find(breaks, (*EG(opline_ptr))->lineno, (void**)&brake) == SUCCESS) { + if (EG(current_execute_data) && (brake = zend_hash_index_find_ptr(breaks, EG(current_execute_data)->opline->lineno))) { return brake; } @@ -799,88 +747,73 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *fbc TSRMLS_DC) /* {{{ */ { const char *fname; + size_t flen; zend_op_array *ops; - phpdbg_breakbase_t *brake; if (fbc->type != ZEND_USER_FUNCTION) { return NULL; } - ops = (zend_op_array*)fbc; + ops = (zend_op_array *) fbc; if (ops->scope) { /* find method breaks here */ return phpdbg_find_breakpoint_method(ops TSRMLS_CC); } - fname = ops->function_name; - - if (!fname) { + if (ops->function_name) { + fname = ops->function_name->val; + flen = ops->function_name->len; + } else { fname = "main"; + flen = 4; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname, strlen(fname), (void**)&brake) == SUCCESS) { - return brake; - } - - return NULL; + return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname, flen); } /* }}} */ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *ops TSRMLS_DC) /* {{{ */ { HashTable *class_table; - phpdbg_breakbase_t *brake; + phpdbg_breakbase_t *brake = NULL; - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], ops->scope->name, - ops->scope->name_length, (void**)&class_table) == SUCCESS) { - char *lcname = zend_str_tolower_dup(ops->function_name, strlen(ops->function_name)); - size_t lcname_len = strlen(lcname); - - if (zend_hash_find( - class_table, - lcname, - lcname_len, (void**)&brake) == SUCCESS) { - efree(lcname); - return brake; - } + if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], ops->scope->name))) { + size_t lcname_len = ops->function_name->len; + char *lcname = zend_str_tolower_dup(ops->function_name->val, lcname_len); + + brake = zend_hash_str_find_ptr(class_table, lcname, lcname_len); efree(lcname); } - return NULL; + return brake; } /* }}} */ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t opline TSRMLS_DC) /* {{{ */ { phpdbg_breakline_t *brake; - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], - (zend_ulong) opline, (void**)&brake) == SUCCESS) { - return (brake->base?(phpdbg_breakbase_t *)brake->base:(phpdbg_breakbase_t *)brake); + if ((brake = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) && brake->base) { + return (phpdbg_breakbase_t *)brake->base; } - return NULL; + return (phpdbg_breakbase_t *) brake; } /* }}} */ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(zend_uchar opcode TSRMLS_DC) /* {{{ */ { - phpdbg_breakbase_t *brake; const char *opname = phpdbg_decode_opcode(opcode); if (memcmp(opname, PHPDBG_STRL("UNKNOWN")) == 0) { return NULL; } - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], - zend_hash_func(opname, strlen(opname)), (void**)&brake) == SUCCESS) { - return brake; - } - return NULL; + return zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], zend_hash_func(opname, strlen(opname))); } /* }}} */ 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; + zend_function *function = execute_data->func; switch (param->type) { case NUMERIC_FUNCTION_PARAM: @@ -895,8 +828,8 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend const char *str = NULL; size_t len = 0L; zend_op_array *ops = (zend_op_array*)function; - str = ops->function_name ? ops->function_name : "main"; - len = strlen(str); + str = ops->function_name ? ops->function_name->val : "main"; + len = ops->function_name ? ops->function_name->len : strlen(str); if (len == param->len && memcmp(param->str, str, len) == SUCCESS) { return param->type == STR_PARAM || execute_data->opline - ops->opcodes == param->num; @@ -926,10 +859,10 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend zend_op_array *ops = (zend_op_array*) function; if (ops->scope) { - size_t lengths[2] = {strlen(param->method.class), ops->scope->name_length}; + size_t lengths[2] = { strlen(param->method.class), ops->scope->name->len }; 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); + lengths[1] = ops->function_name->len; 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; @@ -953,16 +886,13 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ { phpdbg_breakcond_t *bp; - 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; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position)) { - 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); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], bp) { + zval retval; + const zend_op *orig_opline = EG(current_execute_data)->opline; + zend_function *orig_func = EG(current_execute_data)->func; + zval *orig_retval = EG(current_execute_data)->return_value; if (((phpdbg_breakbase_t*)bp)->disabled) { continue; @@ -974,49 +904,37 @@ static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execut } } - 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_rebuild_symbol_table(TSRMLS_C); zend_try { PHPDBG_G(flags) |= PHPDBG_IN_COND_BP; - zend_execute(EG(active_op_array) TSRMLS_CC); + zend_execute(bp->ops, &retval TSRMLS_CC); #if PHP_VERSION_ID >= 50700 - if (zend_is_true(retval TSRMLS_CC)) { + if (zend_is_true(&retval TSRMLS_CC)) { #else - if (zend_is_true(retval)) { + if (zend_is_true(&retval)) { #endif 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; + EG(no_extensions) = 1; + EG(current_execute_data)->opline = orig_opline; + EG(current_execute_data)->func = orig_func; + EG(current_execute_data)->return_value = orig_retval; PHPDBG_G(flags) &= ~PHPDBG_IN_COND_BP; if (breakpoint == SUCCESS) { break; } - } + } ZEND_HASH_FOREACH_END(); - return (breakpoint == SUCCESS) ? ((phpdbg_breakbase_t*)bp) : NULL; + return (breakpoint == SUCCESS) ? ((phpdbg_breakbase_t *) bp) : NULL; } /* }}} */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data* execute_data TSRMLS_DC) /* {{{ */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ { phpdbg_breakbase_t *base = NULL; @@ -1031,28 +949,24 @@ PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data* execute goto result; } - if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) && - (base = phpdbg_find_breakpoint_file(execute_data->op_array TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) && (base = phpdbg_find_breakpoint_file(&execute_data->func->op_array TSRMLS_CC))) { goto result; } 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) { - if ((base = phpdbg_find_breakpoint_symbol( - execute_data->function_state.function TSRMLS_CC))) { + if (execute_data->opline == execute_data->func->op_array.opcodes) { + if ((base = phpdbg_find_breakpoint_symbol(execute_data->func TSRMLS_CC))) { goto result; } } } - if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) && - (base = phpdbg_find_breakpoint_opline(execute_data->opline TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) && (base = phpdbg_find_breakpoint_opline((phpdbg_opline_ptr_t) execute_data->opline TSRMLS_CC))) { goto result; } - if ((PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) && - (base = phpdbg_find_breakpoint_opcode(execute_data->opline->opcode TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) && (base = phpdbg_find_breakpoint_opcode(execute_data->opline->opcode TSRMLS_CC))) { goto result; } @@ -1069,14 +983,12 @@ result: PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ { - HashTable **table; - HashPosition position; + HashTable *table; phpdbg_breakbase_t *brake; + zend_string *strkey; + zend_ulong numkey; - if ((brake = phpdbg_find_breakbase_ex(num, &table, &position TSRMLS_CC))) { - char *key; - zend_uint klen; - zend_ulong idx; + if ((brake = phpdbg_find_breakbase_ex(num, &table, &numkey, &strkey TSRMLS_CC))) { int type = brake->type; char *name = NULL; size_t name_len = 0L; @@ -1084,7 +996,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ switch (type) { case PHPDBG_BREAK_FILE: case PHPDBG_BREAK_METHOD: - if (zend_hash_num_elements((*table)) == 1) { + 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) { @@ -1094,7 +1006,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ break; default: { - if (zend_hash_num_elements((*table)) == 1) { + if (zend_hash_num_elements(table) == 1) { PHPDBG_G(flags) &= ~(1<<(brake->type+1)); } } @@ -1107,25 +1019,20 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]) == 1) { PHPDBG_G(flags) &= PHPDBG_HAS_OPLINE_BP; } - zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], ((phpdbg_breakopline_t*)brake)->opline); + zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], ((phpdbg_breakopline_t *) brake)->opline); } - switch (zend_hash_get_current_key_ex( - (*table), &key, &klen, &idx, 0, &position)) { - - case HASH_KEY_IS_STRING: - zend_hash_del((*table), key, klen); - break; - - default: - zend_hash_index_del((*table), idx); + if (strkey) { + zend_hash_del(table, strkey); + } else { + zend_hash_index_del(table, numkey); } switch (type) { case PHPDBG_BREAK_FILE: case PHPDBG_BREAK_METHOD: if (name) { - zend_hash_del(&PHPDBG_G(bp)[type], name, name_len); + zend_hash_str_del(&PHPDBG_G(bp)[type], name, name_len); efree(name); } break; @@ -1307,26 +1214,25 @@ PHPDBG_API void phpdbg_disable_breakpoints(TSRMLS_D) { /* {{{ */ PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id TSRMLS_DC) /* {{{ */ { - HashTable **table; - HashPosition position; + HashTable *table; + zend_string *strkey; + zend_ulong numkey; - return phpdbg_find_breakbase_ex(id, &table, &position TSRMLS_CC); + return phpdbg_find_breakbase_ex(id, &table, &numkey, &strkey TSRMLS_CC); } /* }}} */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable ***table, HashPosition *position TSRMLS_DC) /* {{{ */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey TSRMLS_DC) /* {{{ */ { - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, (void**)table) == SUCCESS) { + if ((*table = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id))) { 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)) { - + ZEND_HASH_FOREACH_KEY_PTR(*table, *numkey, *strkey, brake) { if (brake->id == id) { return brake; } - } + } ZEND_HASH_FOREACH_END(); } + return NULL; } /* }}} */ @@ -1336,259 +1242,182 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ switch (type) { case PHPDBG_BREAK_SYM: if ((PHPDBG_G(flags) & PHPDBG_HAS_SYM_BP)) { - HashPosition position; phpdbg_breaksymbol_t *brake; phpdbg_out(SEPARATE "\n"); phpdbg_out("Function Breakpoints:\n"); - 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)) { + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], brake) { phpdbg_writeln("function", "id=\"%d\" name=\"%s\" disabled=\"%s\"", "#%d\t\t%s%s", brake->id, brake->symbol, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_METHOD: if ((PHPDBG_G(flags) & PHPDBG_HAS_METHOD_BP)) { - HashPosition position[2]; HashTable *class_table; - char *class_name = NULL; - zend_uint class_len = 0; - zend_ulong class_idx = 0L; phpdbg_out(SEPARATE "\n"); phpdbg_out("Method Breakpoints:\n"); - 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])) { - phpdbg_writeln("method", "id=\"%d\" name=\"%s::%s\" disabled=\"%s\"", "#%d\t\t%s::%s%s", - brake->id, brake->class_name, brake->func_name, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_table) { + phpdbg_breakmethod_t *brake; + + ZEND_HASH_FOREACH_PTR(class_table, brake) { + phpdbg_writeln("method", "id=\"%d\" name=\"%s::%s\" disabled=\"%s\"", "#%d\t\t%s::%s%s", + brake->id, brake->class_name, brake->func_name, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_FILE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP)) { - HashPosition position[2]; HashTable *points; phpdbg_out(SEPARATE "\n"); phpdbg_out("File Breakpoints:\n"); - 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])) { + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], points) { phpdbg_breakfile_t *brake; - 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])) { + ZEND_HASH_FOREACH_PTR(points, brake) { phpdbg_writeln("file", "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\"", "#%d\t\t%s:%lu%s", brake->id, brake->filename, brake->line, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)) { - HashPosition position; phpdbg_breakline_t *brake; phpdbg_out(SEPARATE "\n"); phpdbg_out("Opline Breakpoints:\n"); - 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)) { + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], brake) { + const char *type; switch (brake->type) { case PHPDBG_BREAK_METHOD_OPLINE: + type = "method"; + goto print_opline; case PHPDBG_BREAK_FUNCTION_OPLINE: + type = "function"; + goto print_opline; case PHPDBG_BREAK_FILE_OPLINE: - phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" type=\"%s\" disabled=\"%s\"", "#%d\t\t%#lx\t\t(%s breakpoint)%s", brake->id, brake->opline, - brake->type == PHPDBG_BREAK_METHOD_OPLINE ? "method" : - brake->type == PHPDBG_BREAK_FUNCTION_OPLINE ? "function" : - brake->type == PHPDBG_BREAK_FILE_OPLINE ? "file" : - "--- error ---", - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - break; + type = "method"; + + print_opline: { + if (brake->type == PHPDBG_BREAK_METHOD_OPLINE) { + type = "method"; + } else if (brake->type == PHPDBG_BREAK_FUNCTION_OPLINE) { + type = "function"; + } else if (brake->type == PHPDBG_BREAK_FILE_OPLINE) { + type = "file"; + } + + phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" type=\"%s\" disabled=\"%s\"", "#%d\t\t%#lx\t\t(%s breakpoint)%s", + brake->id, brake->opline, type, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } break; default: - phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" disabled=\"%s\"", "#%d\t\t%#lx%s", brake->id, brake->opline, ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" disabled=\"%s\"", "#%d\t\t%#lx%s", + brake->id, brake->opline, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; } - } + } ZEND_HASH_FOREACH_END(); } 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; - zend_uint class_len = 0, method_len = 0; - zend_ulong class_idx = 0L, method_idx = 0L; phpdbg_out(SEPARATE "\n"); phpdbg_out("Method opline Breakpoints:\n"); - 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])) { - phpdbg_writeln("methodopline", "id=\"%d\" name=\"%s::%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s::%s opline %ld%s", - brake->id, brake->class_name, brake->func_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - } - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], class_table) { + ZEND_HASH_FOREACH_PTR(class_table, method_table) { + phpdbg_breakopline_t *brake; - } + ZEND_HASH_FOREACH_PTR(method_table, brake) { + phpdbg_writeln("methodopline", "id=\"%d\" name=\"%s::%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s::%s opline %ld%s", + brake->id, brake->class_name, brake->func_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } 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; - zend_uint function_len = 0; - zend_ulong function_idx = 0L; phpdbg_out(SEPARATE "\n"); phpdbg_out("Function opline Breakpoints:\n"); - 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])) { - phpdbg_writeln("functionopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", - brake->id, brake->func_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], function_table) { + phpdbg_breakopline_t *brake; + + ZEND_HASH_FOREACH_PTR(function_table, brake) { + phpdbg_writeln("functionopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", + brake->id, brake->func_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } 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; - zend_uint file_len = 0; - zend_ulong file_idx = 0L; phpdbg_out(SEPARATE "\n"); phpdbg_out("File opline Breakpoints:\n"); - 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])) { - phpdbg_writeln("fileopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", - brake->id, brake->class_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], file_table) { + phpdbg_breakopline_t *brake; + + ZEND_HASH_FOREACH_PTR(file_table, brake) { + phpdbg_writeln("fileopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", + brake->id, brake->class_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_COND: if ((PHPDBG_G(flags) & PHPDBG_HAS_COND_BP)) { - HashPosition position; phpdbg_breakcond_t *brake; phpdbg_out(SEPARATE "\n"); phpdbg_out("Conditional Breakpoints:\n"); - 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)) { + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], brake) { if (brake->paramed) { switch (brake->param.type) { case STR_PARAM: phpdbg_writeln("evalfunction", "id=\"%d\" name=\"%s\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s if %s%s", - brake->id, - brake->param.str, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + brake->id, brake->param.str, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case NUMERIC_FUNCTION_PARAM: phpdbg_writeln("evalfunctionopline", "id=\"%d\" name=\"%s\" num=\"%ld\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s#%ld if %s%s", - brake->id, - brake->param.str, - brake->param.num, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + brake->id, brake->param.str, brake->param.num, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case METHOD_PARAM: phpdbg_writeln("evalmethod", "id=\"%d\" name=\"%s::%s\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s::%s if %s%s", - brake->id, - brake->param.method.class, - brake->param.method.name, - brake->code, + brake->id, brake->param.method.class, brake->param.method.name, brake->code, ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); break; case NUMERIC_METHOD_PARAM: phpdbg_writeln("evalmethodopline", "id=\"%d\" name=\"%s::%s\" num=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s::%s#%ld if %s%s", - brake->id, - brake->param.method.class, - brake->param.method.name, - brake->param.num, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + brake->id, brake->param.method.class, brake->param.method.name, brake->param.num, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case FILE_PARAM: phpdbg_writeln("evalfile", "id=\"%d\" name=\"%s\" line=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s:%lu if %s%s", - brake->id, - brake->param.file.name, - brake->param.file.line, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + brake->id, brake->param.file.name, brake->param.file.line, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case ADDR_PARAM: phpdbg_writeln("evalopline", "id=\"%d\" opline=\"%#lx\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat #%lx if %s%s", - brake->id, - brake->param.addr, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + brake->id, brake->param.addr, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; default: @@ -1598,24 +1427,21 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ } else { phpdbg_writeln("eval", "id=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tif %s%s", brake->id, brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); } - } + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_OPCODE: if (PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) { - HashPosition position; phpdbg_breakop_t *brake; phpdbg_out(SEPARATE "\n"); phpdbg_out("Opcode Breakpoints:\n"); - 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)) { + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], brake) { phpdbg_writeln("opcode", "id=\"%d\" name=\"%s\" disabled=\"%s\"", "#%d\t\t%s%s", brake->id, brake->name, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); } break; } diff --git a/sapi/phpdbg/phpdbg_bp.h b/sapi/phpdbg/phpdbg_bp.h index a6227cba6c..4090d90f91 100644 --- a/sapi/phpdbg/phpdbg_bp.h +++ b/sapi/phpdbg/phpdbg_bp.h @@ -151,7 +151,7 @@ PHPDBG_API void phpdbg_disable_breakpoints(TSRMLS_D); /* }}} */ /* {{{ Breakbase API */ PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id TSRMLS_DC); -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable ***table, HashPosition *position TSRMLS_DC); /* }}} */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey TSRMLS_DC); /* }}} */ /* {{{ Breakpoint Exportation API */ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC); /* }}} */ diff --git a/sapi/phpdbg/phpdbg_btree.c b/sapi/phpdbg/phpdbg_btree.c index 491445399b..918bc0d68f 100644 --- a/sapi/phpdbg/phpdbg_btree.c +++ b/sapi/phpdbg/phpdbg_btree.c @@ -219,3 +219,18 @@ check_branch_existence: return SUCCESS; } + +void phpdbg_btree_branch_dump(phpdbg_btree_branch *branch, zend_ulong depth) { + if (branch) { + if (depth--) { + phpdbg_btree_branch_dump(branch->branches[0], depth); + phpdbg_btree_branch_dump(branch->branches[1], depth); + } else { + fprintf(stderr, "%p: %p\n", (void *) branch->result.idx, branch->result.ptr); + } + } +} + +void phpdbg_btree_dump(phpdbg_btree *tree) { + phpdbg_btree_branch_dump(tree->branch, tree->depth); +} diff --git a/sapi/phpdbg/phpdbg_btree.h b/sapi/phpdbg/phpdbg_btree.h index af2a6ac314..27230572f7 100644 --- a/sapi/phpdbg/phpdbg_btree.h +++ b/sapi/phpdbg/phpdbg_btree.h @@ -62,4 +62,9 @@ int phpdbg_btree_insert_or_update(phpdbg_btree *tree, zend_ulong idx, void *ptr, #define phpdbg_btree_update(tree, idx, ptr) phpdbg_btree_insert_or_update(tree, idx, ptr, PHPDBG_BTREE_UPDATE) #define phpdbg_btree_overwrite(tree, idx, ptr) phpdbg_btree_insert_or_update(tree, idx, ptr, PHPDBG_BTREE_OWERWRITE) + +/* debugging functions */ +void phpdbg_btree_branch_dump(phpdbg_btree_branch *branch, zend_ulong depth); +void phpdbg_btree_dump(phpdbg_btree *tree); + #endif diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c index 30ea48cfbe..729babefca 100644 --- a/sapi/phpdbg/phpdbg_cmd.c +++ b/sapi/phpdbg/phpdbg_cmd.c @@ -168,59 +168,39 @@ PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **point { switch (param->type) { case STR_PARAM: - asprintf(pointer, - "%s", param->str); + asprintf(pointer, "%s", param->str); break; case ADDR_PARAM: - asprintf(pointer, - "%#lx", param->addr); + asprintf(pointer, "%#llx", param->addr); break; case NUMERIC_PARAM: - asprintf(pointer, - "%li", - param->num); + asprintf(pointer, "%li", param->num); break; case METHOD_PARAM: - asprintf(pointer, - "%s::%s", - param->method.class, - param->method.name); + asprintf(pointer, "%s::%s", param->method.class, param->method.name); break; case FILE_PARAM: if (param->num) { - asprintf(pointer, - "%s:%lu#%lu", - param->file.name, - param->file.line, - param->num); + asprintf(pointer, "%s:%lu#%lu", param->file.name, param->file.line, param->num); } else { - asprintf(pointer, - "%s:%lu", - param->file.name, - param->file.line); + asprintf(pointer, "%s:%lu", param->file.name, param->file.line); } break; case NUMERIC_FUNCTION_PARAM: - asprintf(pointer, - "%s#%lu", param->str, param->num); + asprintf(pointer, "%s#%lu", param->str, param->num); break; case NUMERIC_METHOD_PARAM: - asprintf(pointer, - "%s::%s#%lu", - param->method.class, - param->method.name, - param->num); + asprintf(pointer, "%s::%s#%lu", param->method.class, param->method.name, param->num); break; default: - asprintf(pointer, - "%s", "unknown"); + *pointer = strdup("unknown"); } return *pointer; @@ -422,7 +402,7 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) break; case ADDR_PARAM: - fprintf(stderr, "%s ADDR_PARAM(%lu)\n", msg, param->addr); + fprintf(stderr, "%s ADDR_PARAM(%llu)\n", msg, param->addr); break; case NUMERIC_FILE_PARAM: @@ -692,7 +672,7 @@ PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t * default: { char *list = NULL; - zend_uint it = 0; + uint32_t it = 0; size_t pos = 0; while (it < matches) { diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index df304e3541..4429a7fb73 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -37,13 +37,7 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */ /* move things back */ EG(current_execute_data) = PHPDBG_FRAME(execute_data); - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); + EG(scope) = PHPDBG_EX(scope); } /* }}} */ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */ @@ -85,89 +79,72 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */ PHPDBG_FRAME(execute_data) = EG(current_execute_data); EG(current_execute_data) = execute_data; - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - PHPDBG_FRAME(execute_data)->original_return_value = EG(return_value_ptr_ptr); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); + EG(scope) = PHPDBG_EX(scope); } phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); - phpdbg_list_file( - zend_get_executed_filename(TSRMLS_C), - 3, - zend_get_executed_lineno(TSRMLS_C)-1, - zend_get_executed_lineno(TSRMLS_C) - TSRMLS_CC - ); + + { + const char *file_chr = zend_get_executed_filename(TSRMLS_C); + zend_string *file = zend_string_init(file_chr, strlen(file_chr), 0); + phpdbg_list_file(file, 3, zend_get_executed_lineno(TSRMLS_C) - 1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); + efree(file); + } } /* }}} */ -static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */ +static void phpdbg_dump_prototype(zval *tmp TSRMLS_DC) /* {{{ */ { - zval **funcname, **class, **type, **args, **argstmp; - char is_class; - int has_args = FAILURE; + zval *funcname, *class, class_zv, *type, *args, *argstmp; - zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), (void **) &funcname); + funcname = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("function")); - if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "object", sizeof("object"), (void **) &class)) == FAILURE) { - is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"), (void **)&class); + if ((class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("object")))) { + ZVAL_NEW_STR(&class_zv, Z_OBJCE_P(class)->name); + class = &class_zv; } else { - zend_get_object_classname(*class, (const char **) &Z_STRVAL_PP(class), (zend_uint *) &Z_STRLEN_PP(class) TSRMLS_CC); + class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("class")); } - if (is_class == SUCCESS) { - zend_hash_find(Z_ARRVAL_PP(tmp), "type", sizeof("type"), (void **)&type); + if (class) { + type = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("type")); } - has_args = zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"), (void **)&args) == SUCCESS; + args = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("args")); + + phpdbg_xml(" symbol=\"%s%s%s\"", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); - phpdbg_xml(" symbol=\"%s%s%s\"", - is_class == FAILURE?"":Z_STRVAL_PP(class), - is_class == FAILURE?"":Z_STRVAL_PP(type), - Z_STRVAL_PP(funcname) - ); - if (has_args) { + if (args) { phpdbg_xml(">"); } else { phpdbg_xml(" />"); } - phpdbg_out("%s%s%s(", - is_class == FAILURE?"":Z_STRVAL_PP(class), - is_class == FAILURE?"":Z_STRVAL_PP(type), - Z_STRVAL_PP(funcname) - ); + phpdbg_out("%s%s%s(", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); - if (has_args) { - HashPosition iterator; + if (args) { const zend_function *func = NULL; const zend_arg_info *arginfo = NULL; - int j = 0, m; zend_bool is_variadic = 0; + int j = 0, m; phpdbg_try_access { /* assuming no autoloader call is necessary, class should have been loaded if it's in backtrace ... */ - if ((func = phpdbg_get_function(Z_STRVAL_PP(funcname), is_class == FAILURE ? NULL : Z_STRVAL_PP(class) TSRMLS_CC))) { + if ((func = phpdbg_get_function(Z_STRVAL_P(funcname), class ? Z_STRVAL_P(class) : NULL TSRMLS_CC))) { arginfo = func->common.arg_info; } } phpdbg_end_try_access(); m = func ? func->common.num_args : 0; - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args), (void **) &argstmp, &iterator) == SUCCESS) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), argstmp) { if (j) { phpdbg_out(", "); } phpdbg_xml("<arg %r"); if (m && j < m) { -#if PHP_VERSION_ID >= 50600 - is_variadic = arginfo ? arginfo[j].is_variadic : 0; -#endif + if (!is_variadic) { + is_variadic = arginfo ? arginfo[j].is_variadic : 0; + } phpdbg_xml(" variadic=\"%s\" name=\"%s\">", is_variadic ? "variadic" : "", arginfo ? arginfo[j].name : ""); phpdbg_out("%s=%s", arginfo ? arginfo[j].name : "?", is_variadic ? "[": ""); @@ -176,11 +153,11 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */ } ++j; - zend_print_flat_zval_r(*argstmp TSRMLS_CC); - zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator); + zend_print_flat_zval_r(argstmp TSRMLS_CC); phpdbg_xml("</arg>"); - } + } ZEND_HASH_FOREACH_END(); + if (is_variadic) { phpdbg_out("]"); } @@ -191,12 +168,11 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */ void phpdbg_dump_backtrace(size_t num TSRMLS_DC) /* {{{ */ { - zval zbacktrace; - zval **tmp; - zval **file, **line; HashPosition position; + zval zbacktrace; + zval *tmp; + zval *file, *line; int i = 0, limit = num; - int user_defined; if (limit < 0) { phpdbg_error("backtrace", "type=\"minnum\"", "Invalid backtrace size %d", limit); @@ -213,22 +189,22 @@ void phpdbg_dump_backtrace(size_t num TSRMLS_DC) /* {{{ */ phpdbg_xml("<backtrace %r>"); zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); - zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void **) &tmp, &position); + tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position); while (1) { - user_defined = zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **) &file); - zend_hash_find(Z_ARRVAL_PP(tmp), "line", sizeof("line"), (void **) &line); + file = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("file")); + line = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("line")); zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); - if (zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void **) &tmp, &position) == FAILURE) { - phpdbg_write("frame", "id=\"%d\" symbol=\"{main}\" file=\"%s\" line=\"%d\"", "frame #%d: {main} at %s:%ld", i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); + if (!(tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) { + phpdbg_write("frame", "id=\"%d\" symbol=\"{main}\" file=\"%s\" line=\"%d\"", "frame #%d: {main} at %s:%ld", i, Z_STRVAL_P(file), Z_LVAL_P(line)); break; } - if (user_defined == SUCCESS) { + if (file) { /* userland */ phpdbg_out("frame #%d: ", i); - phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"%d\"", i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); + phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"%d\"", i, Z_STRVAL_P(file), Z_LVAL_P(line)); phpdbg_dump_prototype(tmp TSRMLS_CC); - phpdbg_out(" at %s:%ld\n", Z_STRVAL_PP(file), Z_LVAL_PP(line)); + phpdbg_out(" at %s:%ld\n", Z_STRVAL_P(file), Z_LVAL_P(line)); i++; } else { phpdbg_out(" => "); diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index 4774fa5a9e..01633e4feb 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -61,21 +61,19 @@ PHPDBG_INFO(break) /* {{{ */ PHPDBG_INFO(files) /* {{{ */ { - HashPosition pos; - char *fname; + zend_string *fname; phpdbg_try_access { phpdbg_notice("includedfilecount", "num=\"%d\"", "Included files: %d", zend_hash_num_elements(&EG(included_files))); } phpdbg_catch_access { phpdbg_error("signalsegv", "", "Could not fetch included file count, invalid data source"); + return SUCCESS; } phpdbg_end_try_access(); phpdbg_try_access { - zend_hash_internal_pointer_reset_ex(&EG(included_files), &pos); - while (zend_hash_get_current_key_ex(&EG(included_files), &fname, NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) { + ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), fname) { phpdbg_writeln("includedfile", "name=\"%s\"", "File: %s", fname); - zend_hash_move_forward_ex(&EG(included_files), &pos); - } + } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { phpdbg_error("signalsegv", "", "Could not fetch file name, invalid data source, aborting included file listing"); } phpdbg_end_try_access(); @@ -99,7 +97,6 @@ PHPDBG_INFO(error) /* {{{ */ PHPDBG_INFO(constants) /* {{{ */ { - HashPosition pos; HashTable consts; zend_constant *data; @@ -107,13 +104,11 @@ PHPDBG_INFO(constants) /* {{{ */ if (EG(zend_constants)) { phpdbg_try_access { - zend_hash_internal_pointer_reset_ex(EG(zend_constants), &pos); - while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &data, &pos) == SUCCESS) { + ZEND_HASH_FOREACH_PTR(EG(zend_constants), data) { if (data->module_number == PHP_USER_CONSTANT) { - zend_hash_update(&consts, data->name, data->name_len, (void **) &data, sizeof(zend_constant *), NULL); + zend_hash_update_ptr(&consts, data->name, data); } - zend_hash_move_forward_ex(EG(zend_constants), &pos); - } + } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { phpdbg_error("signalsegv", "", "Cannot fetch all the constants, invalid data source"); } phpdbg_end_try_access(); @@ -123,12 +118,9 @@ PHPDBG_INFO(constants) /* {{{ */ if (zend_hash_num_elements(&consts)) { phpdbg_out("Address Refs Type Constant\n"); - for (zend_hash_internal_pointer_reset_ex(&consts, &pos); - zend_hash_get_current_data_ex(&consts, (void **) &data, &pos) == SUCCESS; - zend_hash_move_forward_ex(&consts, &pos)) { - data = *(zend_constant **) data; + ZEND_HASH_FOREACH_PTR(&consts, data) { -#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("constant", "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %.*s" msg, &data->value, Z_REFCOUNT(data->value), zend_zval_type_name(&data->value), data->name_len - 1, data->name, ##__VA_ARGS__) +#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("constant", "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %.*s" msg, &data->value, Z_REFCOUNT(data->value), zend_zval_type_name(&data->value), data->name->len, data->name->val, ##__VA_ARGS__) switch (Z_TYPE(data->value)) { case IS_STRING: @@ -138,8 +130,11 @@ PHPDBG_INFO(constants) /* {{{ */ VARIABLEINFO("", ""); } phpdbg_end_try_access(); break; - case IS_BOOL: - VARIABLEINFO("value=\"%s\"", "\nbool (%s)", Z_LVAL(data->value) ? "true" : "false"); + case IS_TRUE: + VARIABLEINFO("value=\"true\"", "\nbool (true)"); + break; + case IS_FALSE: + VARIABLEINFO("value=\"false\"", "\nbool (false)"); break; case IS_LONG: VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL(data->value)); @@ -152,7 +147,7 @@ PHPDBG_INFO(constants) /* {{{ */ #undef VARIABLEINFO } - } + } ZEND_HASH_FOREACH_END(); } return SUCCESS; @@ -161,9 +156,9 @@ PHPDBG_INFO(constants) /* {{{ */ static int phpdbg_arm_auto_global(zend_auto_global *auto_global TSRMLS_DC) { if (auto_global->armed) { if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { - phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", auto_global->name_len, auto_global->name); + phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", auto_global->name->len, auto_global->name->val); } else { - auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC); + auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC); } } @@ -171,45 +166,33 @@ static int phpdbg_arm_auto_global(zend_auto_global *auto_global TSRMLS_DC) { } static int phpdbg_print_symbols(zend_bool show_globals TSRMLS_DC) { - HashTable vars, *symtable; - HashPosition pos; - char *var; - zval **data; + HashTable vars; + zend_array *symtable; + zend_string *var; + zval *data; - if (!EG(active_op_array)) { + if (!EG(current_execute_data) || !EG(current_execute_data)->func) { phpdbg_error("inactive", "type=\"op_array\"", "No active op array!"); return SUCCESS; } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - - if (!EG(active_symbol_table)) { - phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); - return SUCCESS; - } - } - - if (show_globals) { /* that array should only be manipulated during init, so safe for async access during execution */ zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_arm_auto_global TSRMLS_CC); symtable = &EG(symbol_table); - } else { - symtable = EG(active_symbol_table); + } else if (!(symtable = zend_rebuild_symbol_table(TSRMLS_C))) { + phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); + return SUCCESS; } zend_hash_init(&vars, 8, NULL, NULL, 0); phpdbg_try_access { - zend_hash_internal_pointer_reset_ex(symtable, &pos); - while (zend_hash_get_current_key_ex(symtable, &var, NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) { - zend_hash_get_current_data_ex(symtable, (void **)&data, &pos); - if (zend_is_auto_global(var, strlen(var) TSRMLS_CC) ^ !show_globals) { - zend_hash_update(&vars, var, strlen(var)+1, (void**)data, sizeof(zval*), NULL); + ZEND_HASH_FOREACH_STR_KEY_VAL(&symtable->ht, var, data) { + if (zend_is_auto_global(var TSRMLS_CC) ^ !show_globals) { + zend_hash_update(&vars, var, data); } - zend_hash_move_forward_ex(symtable, &pos); - } + } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { phpdbg_error("signalsegv", "", "Cannot fetch all data from the symbol table, invalid data source"); } phpdbg_end_try_access(); @@ -217,7 +200,7 @@ static int phpdbg_print_symbols(zend_bool show_globals TSRMLS_DC) { if (show_globals) { phpdbg_notice("variableinfo", "num=\"%d\"", "Superglobal variables (%d)", zend_hash_num_elements(&vars)); } else { - zend_op_array *ops = EG(active_op_array); + zend_op_array *ops = &EG(current_execute_data)->func->op_array; if (ops->function_name) { if (ops->scope) { @@ -227,7 +210,7 @@ static int phpdbg_print_symbols(zend_bool show_globals TSRMLS_DC) { } } else { if (ops->filename) { - phpdbg_notice("variableinfo", "file=\"%s\" num=\"%d\"", "Variables in %s (%d)", ops->filename, zend_hash_num_elements(&vars)); + phpdbg_notice("variableinfo", "file=\"%s\" num=\"%d\"", "Variables in %s (%d)", ops->filename->val, zend_hash_num_elements(&vars)); } else { phpdbg_notice("variableinfo", "opline=\"%p\" num=\"%d\"", "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars)); } @@ -236,62 +219,54 @@ static int phpdbg_print_symbols(zend_bool show_globals TSRMLS_DC) { if (zend_hash_num_elements(&vars)) { phpdbg_out("Address Refs Type Variable\n"); - for (zend_hash_internal_pointer_reset_ex(&vars, &pos); - zend_hash_get_current_data_ex(&vars, (void**) &data, &pos) == SUCCESS; - zend_hash_move_forward_ex(&vars, &pos)) { - char *var; - zend_bool invalid_data = 1; - - zend_hash_get_current_key_ex(&vars, &var, NULL, NULL, 0, &pos); - + ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) { phpdbg_try_access { - if (!(invalid_data = !*data)) { -#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("variable", "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%s\" " attrs, "%-18p %-7d %-9s %s$%s" msg, *data, Z_REFCOUNT_PP(data), zend_zval_type_name(*data), Z_ISREF_PP(data) ? "&": "", var, ##__VA_ARGS__) - - switch (Z_TYPE_PP(data)) { - case IS_RESOURCE: - phpdbg_try_access { - int type; - VARIABLEINFO("type=\"%s\"", "\n|-------(typeof)------> (%s)\n", zend_list_find(Z_RESVAL_PP(data), &type) ? zend_rsrc_list_get_rsrc_type(type TSRMLS_CC) : "unknown"); - } phpdbg_catch_access { - VARIABLEINFO("type=\"unknown\"", "\n|-------(typeof)------> (unknown)\n"); - } phpdbg_end_try_access(); - break; - case IS_OBJECT: - phpdbg_try_access { - VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", Z_OBJCE_PP(data)->name); - } phpdbg_catch_access { - VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n"); - } phpdbg_end_try_access(); - break; - case IS_STRING: - phpdbg_try_access { - VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN_PP(data), Z_STRLEN_PP(data) < 255 ? Z_STRLEN_PP(data) : 255, Z_STRVAL_PP(data), Z_STRLEN_PP(data) > 255 ? "..." : ""); - } phpdbg_catch_access { - VARIABLEINFO("", ""); - } phpdbg_end_try_access(); - break; - case IS_BOOL: - VARIABLEINFO("value=\"%s\"", "\nbool (%s)", Z_LVAL_PP(data) ? "true" : "false"); - break; - case IS_LONG: - VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL_PP(data)); - break; - case IS_DOUBLE: - VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL_PP(data)); - break; - default: +#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("variable", "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNT_P(data), zend_zval_type_name(data), Z_ISREF_P(data) ? "&": "", var->len, var->val, ##__VA_ARGS__) + + switch (Z_TYPE_P(data)) { + case IS_RESOURCE: + phpdbg_try_access { + const char *type = zend_rsrc_list_get_rsrc_type(Z_RES_P(data) TSRMLS_CC); + VARIABLEINFO("type=\"%s\"", "\n|-------(typeof)------> (%s)\n", type ? type : "unknown"); + } phpdbg_catch_access { + VARIABLEINFO("type=\"unknown\"", "\n|-------(typeof)------> (unknown)\n"); + } phpdbg_end_try_access(); + break; + case IS_OBJECT: + phpdbg_try_access { + VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", Z_OBJCE_P(data)->name); + } phpdbg_catch_access { + VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n"); + } phpdbg_end_try_access(); + break; + case IS_STRING: + phpdbg_try_access { + VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : ""); + } phpdbg_catch_access { VARIABLEINFO("", ""); - } + } phpdbg_end_try_access(); + break; + case IS_TRUE: + VARIABLEINFO("value=\"true\"", "\nbool (true)"); + break; + case IS_FALSE: + VARIABLEINFO("value=\"false\"", "\nbool (false)"); + break; + case IS_LONG: + VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL_P(data)); + break; + case IS_DOUBLE: + VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL_P(data)); + break; + default: + VARIABLEINFO("", ""); } #undef VARIABLEINFO + } phpdbg_catch_access { + phpdbg_writeln("variable", "address=\"%p\" name=\"%s\"", "%p\tn/a\tn/a\t$%s", data, var); } phpdbg_end_try_access(); - - if (invalid_data) { - phpdbg_writeln("variable", "name=\"%s\"", "n/a\tn/a\tn/a\t$%s", var); - } - } + } ZEND_HASH_FOREACH_END(); } zend_hash_destroy(&vars); @@ -312,8 +287,9 @@ PHPDBG_INFO(globals) /* {{{ */ PHPDBG_INFO(literal) /* {{{ */ { /* literals are assumed to not be manipulated during executing of their op_array and as such async safe */ - if ((EG(in_execution) && EG(active_op_array)) || PHPDBG_G(ops)) { - zend_op_array *ops = EG(active_op_array) ? EG(active_op_array) : PHPDBG_G(ops); + zend_bool in_executor = PHPDBG_G(in_execution) && EG(current_execute_data) && EG(current_execute_data)->func; + if (in_executor || PHPDBG_G(ops)) { + zend_op_array *ops = in_executor ? &EG(current_execute_data)->func->op_array : PHPDBG_G(ops); int literal = 0, count = ops->last_literal-1; if (ops->function_name) { @@ -324,16 +300,16 @@ PHPDBG_INFO(literal) /* {{{ */ } } else { if (ops->filename) { - phpdbg_notice("literalinfo", "file=\"%s\" num=\"%d\"", "Literal Constants in %s (%d)", ops->filename, count); + phpdbg_notice("literalinfo", "file=\"%s\" num=\"%d\"", "Literal Constants in %s (%d)", ops->filename->val, count); } else { phpdbg_notice("literalinfo", "opline=\"%p\" num=\"%d\"", "Literal Constants @ %p (%d)", ops, count); } } while (literal < ops->last_literal) { - if (Z_TYPE(ops->literals[literal].constant) != IS_NULL) { + if (Z_TYPE(ops->literals[literal]) != IS_NULL) { phpdbg_write("literal", "id=\"%u\"", "|-------- C%u -------> [", literal); - zend_print_zval(&ops->literals[literal].constant, 0); + zend_print_zval(&ops->literals[literal], 0 TSRMLS_CC); phpdbg_out("]\n"); } literal++; @@ -378,35 +354,27 @@ PHPDBG_INFO(memory) /* {{{ */ return SUCCESS; } /* }}} */ -static inline void phpdbg_print_class_name(zend_class_entry **ce TSRMLS_DC) /* {{{ */ +static inline void phpdbg_print_class_name(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { - phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%s\" methodcount=\"%d\"", "%s %s %s (%d)", - ((*ce)->type == ZEND_USER_CLASS) ? - "User" : "Internal", - ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? - "Interface" : - ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? - "Abstract Class" : - "Class", - (*ce)->name, zend_hash_num_elements(&(*ce)->function_table)); + const char *visibility = ce->type == ZEND_USER_CLASS ? "User" : "Internal"; + const char *type = (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class"; + + phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, ce->name->len, ce->name->val, zend_hash_num_elements(&ce->function_table)); } /* }}} */ PHPDBG_INFO(classes) /* {{{ */ { - HashPosition position; - zend_class_entry **ce; + zend_class_entry *ce; HashTable classes; zend_hash_init(&classes, 8, NULL, NULL, 0); phpdbg_try_access { - for (zend_hash_internal_pointer_reset_ex(EG(class_table), &position); - zend_hash_get_current_data_ex(EG(class_table), (void**)&ce, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(class_table), &position)) { - if ((*ce)->type == ZEND_USER_CLASS) { - zend_hash_next_index_insert(&classes, ce, sizeof(ce), NULL); + ZEND_HASH_FOREACH_PTR(EG(class_table), ce) { + if (ce->type == ZEND_USER_CLASS) { + zend_hash_next_index_insert_ptr(&classes, ce); } - } + } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { phpdbg_notice("signalsegv", "", "Not all classes could be fetched, possibly invalid data source"); } phpdbg_end_try_access(); @@ -414,30 +382,25 @@ PHPDBG_INFO(classes) /* {{{ */ phpdbg_notice("classinfo", "num=\"%d\"", "User Classes (%d)", zend_hash_num_elements(&classes)); /* once added, assume that classes are stable... until shutdown. */ - for (zend_hash_internal_pointer_reset_ex(&classes, &position); - zend_hash_get_current_data_ex(&classes, (void**)&ce, &position) == SUCCESS; - zend_hash_move_forward_ex(&classes, &position)) { - + ZEND_HASH_FOREACH_PTR(&classes, ce) { phpdbg_print_class_name(ce TSRMLS_CC); - if ((*ce)->parent) { - zend_class_entry *pce; - + if (ce->parent) { phpdbg_xml("<parents %r>"); - pce = (*ce)->parent; + zend_class_entry *pce = ce->parent; do { phpdbg_out("|-------- "); - phpdbg_print_class_name(&pce TSRMLS_CC); + phpdbg_print_class_name(pce TSRMLS_CC); } while ((pce = pce->parent)); phpdbg_xml("</parents>"); } - if ((*ce)->info.user.filename) { - phpdbg_writeln("classsource", "file=\"%s\" line=\"%u\"", "|---- in %s on line %u", (*ce)->info.user.filename, (*ce)->info.user.line_start); + if (ce->info.user.filename) { + phpdbg_writeln("classsource", "file=\"%s\" line=\"%u\"", "|---- in %s on line %u", ce->info.user.filename->val, ce->info.user.line_start); } else { phpdbg_writeln("classsource", "", "|---- no source code"); } - } + } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&classes); @@ -446,41 +409,34 @@ PHPDBG_INFO(classes) /* {{{ */ PHPDBG_INFO(funcs) /* {{{ */ { - HashPosition position; - zend_function *zf, **pzf; + zend_function *zf; HashTable functions; zend_hash_init(&functions, 8, NULL, NULL, 0); phpdbg_try_access { - for (zend_hash_internal_pointer_reset_ex(EG(function_table), &position); - zend_hash_get_current_data_ex(EG(function_table), (void**)&zf, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(function_table), &position)) { + ZEND_HASH_FOREACH_PTR(EG(function_table), zf) { if (zf->type == ZEND_USER_FUNCTION) { - zend_hash_next_index_insert(&functions, (void**) &zf, sizeof(zend_function), NULL); + zend_hash_next_index_insert_ptr(&functions, zf); } - } + } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { phpdbg_notice("signalsegv", "", "Not all functions could be fetched, possibly invalid data source"); } phpdbg_end_try_access(); phpdbg_notice("functioninfo", "num=\"%d\"", "User Functions (%d)", zend_hash_num_elements(&functions)); - for (zend_hash_internal_pointer_reset_ex(&functions, &position); - zend_hash_get_current_data_ex(&functions, (void**)&pzf, &position) == SUCCESS; - zend_hash_move_forward_ex(&functions, &position)) { - zend_op_array *op_array = &((*pzf)->op_array); + ZEND_HASH_FOREACH_PTR(&functions, zf) { + zend_op_array *op_array = &zf->op_array; - phpdbg_write("function", "name=\"%s\"", "|-------- %s", op_array->function_name ? op_array->function_name : "{main}"); + phpdbg_write("function", "name=\"%s\"", "|-------- %s", op_array->function_name ? op_array->function_name->val : "{main}"); if (op_array->filename) { - phpdbg_writeln("functionsource", "file=\"%s\" line=\"%d\"", " in %s on line %d", - op_array->filename, - op_array->line_start); + phpdbg_writeln("functionsource", "file=\"%s\" line=\"%d\"", " in %s on line %d", op_array->filename->val, op_array->line_start); } else { phpdbg_writeln("functionsource", "", " (no source code)"); } - } + } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&functions); diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index 80b5d2b189..de03a3651e 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -53,16 +53,18 @@ PHPDBG_LIST(lines) /* {{{ */ } switch (param->type) { - case NUMERIC_PARAM: - phpdbg_list_file(phpdbg_current_file(TSRMLS_C), - (param->num < 0 ? 1 - param->num : param->num), - (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(TSRMLS_C), - 0 TSRMLS_CC); - break; - - case FILE_PARAM: - phpdbg_list_file(param->file.name, param->file.line, 0, 0 TSRMLS_CC); - break; + case NUMERIC_PARAM: { + const char *char_file = phpdbg_current_file(TSRMLS_C); + zend_string *file = zend_string_init(char_file, strlen(char_file), 0); + phpdbg_list_file(file, param->num < 0 ? 1 - param->num : param->num, (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(TSRMLS_C), 0 TSRMLS_CC); + efree(file); + } break; + + case FILE_PARAM: { + zend_string *file = zend_string_init(param->file.name, strlen(param->file.name), 0); + phpdbg_list_file(file, param->file.line, 0, 0 TSRMLS_CC); + efree(file); + } break; phpdbg_default_switch_case(); } @@ -79,13 +81,13 @@ PHPDBG_LIST(func) /* {{{ */ PHPDBG_LIST(method) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { zend_function *function; char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**) &function) == SUCCESS) { + if ((function = zend_hash_str_find_ptr(&ce->function_table, lcname, strlen(lcname)))) { phpdbg_list_function(function TSRMLS_CC); } else { phpdbg_error("list", "type=\"notfound\" method=\"%s::%s\"", "Could not find %s::%s", param->method.class, param->method.name); @@ -101,21 +103,17 @@ PHPDBG_LIST(method) /* {{{ */ PHPDBG_LIST(class) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; if (phpdbg_safe_class_lookup(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { - if ((*ce)->type == ZEND_USER_CLASS) { - if ((*ce)->info.user.filename) { - phpdbg_list_file( - (*ce)->info.user.filename, - (*ce)->info.user.line_end - (*ce)->info.user.line_start + 1, - (*ce)->info.user.line_start, 0 TSRMLS_CC - ); + if (ce->type == ZEND_USER_CLASS) { + if (ce->info.user.filename) { + phpdbg_list_file(ce->info.user.filename, ce->info.user.line_end - ce->info.user.line_start + 1, ce->info.user.line_start, 0 TSRMLS_CC); } else { - phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", (*ce)->name); + phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ce->name); } } else { - phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", (*ce)->name); + phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ce->name); } } else { phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "The requested class (%s) could not be found", param->str); @@ -124,12 +122,12 @@ PHPDBG_LIST(class) /* {{{ */ return SUCCESS; } /* }}} */ -void phpdbg_list_file(const char *filename, uint count, int offset, uint highlight TSRMLS_DC) /* {{{ */ +void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highlight TSRMLS_DC) /* {{{ */ { uint line, lastline; - phpdbg_file_source **data; + phpdbg_file_source *data; - if (zend_hash_find(&PHPDBG_G(file_sources), filename, strlen(filename), (void **) &data) == FAILURE) { + if (!(data = zend_hash_find_ptr(&PHPDBG_G(file_sources), filename))) { phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file..."); return; } @@ -141,16 +139,16 @@ void phpdbg_list_file(const char *filename, uint count, int offset, uint highlig lastline = offset + count; - if (lastline > (*data)->lines) { - lastline = (*data)->lines; + if (lastline > data->lines) { + lastline = data->lines; } phpdbg_xml("<list %r file=\"%s\">", filename); for (line = offset; line < lastline;) { - uint linestart = (*data)->line[line++]; - uint linelen = (*data)->line[line] - linestart; - char *buffer = (*data)->buf + linestart; + uint linestart = data->line[line++]; + uint linelen = data->line[line] - linestart; + char *buffer = data->buf + linestart; if (!highlight) { phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer); @@ -179,7 +177,7 @@ void phpdbg_list_function(const zend_function *fbc TSRMLS_DC) /* {{{ */ return; } - ops = (zend_op_array *)fbc; + ops = (zend_op_array *) fbc; phpdbg_list_file(ops->filename, ops->line_end - ops->line_start + 1, ops->line_start, 0 TSRMLS_CC); } /* }}} */ @@ -213,7 +211,7 @@ void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) /* {{{ * func_name = zend_str_tolower_dup(func_name, func_name_len); phpdbg_try_access { - if (zend_hash_find(func_table, func_name, func_name_len+1, (void**)&fbc) == SUCCESS) { + if ((fbc = zend_hash_str_find_ptr(func_table, func_name, func_name_len))) { phpdbg_list_function(fbc TSRMLS_CC); } else { phpdbg_error("list", "type=\"nofunction\" function=\"%s\"", "Function %s not found", func_name); @@ -227,7 +225,7 @@ void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) /* {{{ * zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type TSRMLS_DC) { phpdbg_file_source data, *dataptr; - zend_file_handle fake = {0}; + zend_file_handle fake = {{0}}; zend_op_array *ret; char *filename = (char *)(file->opened_path ? file->opened_path : file->filename); uint line; @@ -258,7 +256,6 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type TSRMLS_DC) { fake.opened_path = file->opened_path; *(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data; - zend_hash_add(&PHPDBG_G(file_sources), filename, strlen(filename), &dataptr, sizeof(phpdbg_file_source *), NULL); for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) { if (*bufptr == '\n') { @@ -269,6 +266,8 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type TSRMLS_DC) { dataptr->line[line] = endptr - data.buf; dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + zend_hash_str_add_ptr(&PHPDBG_G(file_sources), filename, strlen(filename), dataptr); + ret = PHPDBG_G(compile_file)(&fake, type TSRMLS_CC); fake.opened_path = NULL; diff --git a/sapi/phpdbg/phpdbg_list.h b/sapi/phpdbg/phpdbg_list.h index c88328bfea..43a2d474d5 100644 --- a/sapi/phpdbg/phpdbg_list.h +++ b/sapi/phpdbg/phpdbg_list.h @@ -33,8 +33,8 @@ PHPDBG_LIST(method); PHPDBG_LIST(func); void phpdbg_list_function_byname(const char *, size_t TSRMLS_DC); -void phpdbg_list_function(const zend_function* TSRMLS_DC); -void phpdbg_list_file(const char*, uint, int, uint TSRMLS_DC); +void phpdbg_list_function(const zend_function * TSRMLS_DC); +void phpdbg_list_file(zend_string *, uint, int, uint TSRMLS_DC); extern const phpdbg_command_t phpdbg_list_commands[]; diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c index 331718accc..99f43344a4 100644 --- a/sapi/phpdbg/phpdbg_opcode.c +++ b/sapi/phpdbg/phpdbg_opcode.c @@ -26,7 +26,7 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ +static inline uint32_t phpdbg_decode_literal(zend_op_array *ops, zval *literal TSRMLS_DC) /* {{{ */ { int iter = 0; @@ -40,32 +40,31 @@ static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal * return 0; } /* }}} */ -static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */ +static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t type, HashTable *vars TSRMLS_DC) /* {{{ */ { char *decode = NULL; switch (type &~ EXT_TYPE_UNUSED) { case IS_CV: - asprintf(&decode, "$%s", ops->vars[op->var].name); + asprintf(&decode, "$%s", ops->vars[EX_VAR_TO_NUM(op->var)]->val); break; case IS_VAR: case IS_TMP_VAR: { zend_ulong id = 0, *pid = NULL; if (vars != NULL) { - if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { + if ((pid = zend_hash_index_find_ptr(vars, (zend_ulong) ops->vars - op->var))) { + id = *pid; + } else { id = zend_hash_num_elements(vars); - zend_hash_index_update( - vars, (zend_ulong) ops->vars - op->var, - (void**) &id, - sizeof(zend_ulong), NULL); - } else id = *pid; + zend_hash_index_update_mem(vars, (zend_ulong) ops->vars - op->var, &id, sizeof(zend_ulong)); + } } - asprintf(&decode, "@%lu", id); + asprintf(&decode, "@%llu", id); } break; case IS_CONST: - asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); + asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->zv TSRMLS_CC)); break; case IS_UNUSED: @@ -92,7 +91,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRM case ZEND_JMPZNZ: decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf(&decode[2], "J%u or J%lu", op->op2.opline_num, op->extended_value); + asprintf(&decode[2], "J%u or J%llu", op->op2.opline_num, op->extended_value); goto result; case ZEND_JMPZ: @@ -142,8 +141,8 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) || (PHPDBG_G(oplog)))) { - zend_op *opline = execute_data->opline; - char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC); + zend_op *opline = (zend_op *) execute_data->opline; + char *decode = phpdbg_decode_opline(&execute_data->func->op_array, opline, vars TSRMLS_CC); if (ignore_flags || (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) { /* output line info */ @@ -152,7 +151,7 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze opline, phpdbg_decode_opcode(opline->opcode), decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + execute_data->func->op_array.filename ? execute_data->func->op_array.filename->val : "unknown"); } if (!ignore_flags && PHPDBG_G(oplog)) { @@ -161,7 +160,7 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze opline, phpdbg_decode_opcode(opline->opcode), decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + execute_data->func->op_array.filename ? execute_data->func->op_array.filename->val : "unknown"); } if (decode) { @@ -177,180 +176,6 @@ void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ { -#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO -#define CASE(s) case s: return #s - switch (opcode) { - CASE(ZEND_NOP); - CASE(ZEND_ADD); - CASE(ZEND_SUB); - CASE(ZEND_MUL); - CASE(ZEND_DIV); - CASE(ZEND_MOD); - CASE(ZEND_SL); - CASE(ZEND_SR); - CASE(ZEND_CONCAT); - CASE(ZEND_BW_OR); - CASE(ZEND_BW_AND); - CASE(ZEND_BW_XOR); - CASE(ZEND_BW_NOT); - CASE(ZEND_BOOL_NOT); - CASE(ZEND_BOOL_XOR); - CASE(ZEND_IS_IDENTICAL); - CASE(ZEND_IS_NOT_IDENTICAL); - CASE(ZEND_IS_EQUAL); - CASE(ZEND_IS_NOT_EQUAL); - CASE(ZEND_IS_SMALLER); - CASE(ZEND_IS_SMALLER_OR_EQUAL); - CASE(ZEND_CAST); - CASE(ZEND_QM_ASSIGN); - CASE(ZEND_ASSIGN_ADD); - CASE(ZEND_ASSIGN_SUB); - CASE(ZEND_ASSIGN_MUL); - CASE(ZEND_ASSIGN_DIV); - CASE(ZEND_ASSIGN_MOD); - CASE(ZEND_ASSIGN_SL); - CASE(ZEND_ASSIGN_SR); - CASE(ZEND_ASSIGN_CONCAT); - CASE(ZEND_ASSIGN_BW_OR); - CASE(ZEND_ASSIGN_BW_AND); - CASE(ZEND_ASSIGN_BW_XOR); - CASE(ZEND_PRE_INC); - CASE(ZEND_PRE_DEC); - CASE(ZEND_POST_INC); - CASE(ZEND_POST_DEC); - CASE(ZEND_ASSIGN); - CASE(ZEND_ASSIGN_REF); - CASE(ZEND_ECHO); - CASE(ZEND_PRINT); - CASE(ZEND_JMP); - CASE(ZEND_JMPZ); - CASE(ZEND_JMPNZ); - CASE(ZEND_JMPZNZ); - CASE(ZEND_JMPZ_EX); - CASE(ZEND_JMPNZ_EX); - CASE(ZEND_CASE); - CASE(ZEND_SWITCH_FREE); - CASE(ZEND_BRK); - CASE(ZEND_CONT); - CASE(ZEND_BOOL); - CASE(ZEND_INIT_STRING); - CASE(ZEND_ADD_CHAR); - CASE(ZEND_ADD_STRING); - CASE(ZEND_ADD_VAR); - CASE(ZEND_BEGIN_SILENCE); - CASE(ZEND_END_SILENCE); - CASE(ZEND_INIT_FCALL_BY_NAME); - CASE(ZEND_DO_FCALL); - CASE(ZEND_DO_FCALL_BY_NAME); - CASE(ZEND_RETURN); - CASE(ZEND_RECV); - CASE(ZEND_RECV_INIT); - CASE(ZEND_SEND_VAL); - CASE(ZEND_SEND_VAR); - CASE(ZEND_SEND_REF); - CASE(ZEND_NEW); - CASE(ZEND_INIT_NS_FCALL_BY_NAME); - CASE(ZEND_FREE); - CASE(ZEND_INIT_ARRAY); - CASE(ZEND_ADD_ARRAY_ELEMENT); - CASE(ZEND_INCLUDE_OR_EVAL); - CASE(ZEND_UNSET_VAR); - CASE(ZEND_UNSET_DIM); - CASE(ZEND_UNSET_OBJ); - CASE(ZEND_FE_RESET); - CASE(ZEND_FE_FETCH); - CASE(ZEND_EXIT); - CASE(ZEND_FETCH_R); - CASE(ZEND_FETCH_DIM_R); - CASE(ZEND_FETCH_OBJ_R); - CASE(ZEND_FETCH_W); - CASE(ZEND_FETCH_DIM_W); - CASE(ZEND_FETCH_OBJ_W); - CASE(ZEND_FETCH_RW); - CASE(ZEND_FETCH_DIM_RW); - CASE(ZEND_FETCH_OBJ_RW); - CASE(ZEND_FETCH_IS); - CASE(ZEND_FETCH_DIM_IS); - CASE(ZEND_FETCH_OBJ_IS); - CASE(ZEND_FETCH_FUNC_ARG); - CASE(ZEND_FETCH_DIM_FUNC_ARG); - CASE(ZEND_FETCH_OBJ_FUNC_ARG); - CASE(ZEND_FETCH_UNSET); - CASE(ZEND_FETCH_DIM_UNSET); - CASE(ZEND_FETCH_OBJ_UNSET); - CASE(ZEND_FETCH_DIM_TMP_VAR); - CASE(ZEND_FETCH_CONSTANT); - CASE(ZEND_GOTO); - CASE(ZEND_EXT_STMT); - CASE(ZEND_EXT_FCALL_BEGIN); - CASE(ZEND_EXT_FCALL_END); - CASE(ZEND_EXT_NOP); - CASE(ZEND_TICKS); - CASE(ZEND_SEND_VAR_NO_REF); - CASE(ZEND_CATCH); - CASE(ZEND_THROW); - CASE(ZEND_FETCH_CLASS); - CASE(ZEND_CLONE); - CASE(ZEND_RETURN_BY_REF); - CASE(ZEND_INIT_METHOD_CALL); - CASE(ZEND_INIT_STATIC_METHOD_CALL); - CASE(ZEND_ISSET_ISEMPTY_VAR); - CASE(ZEND_ISSET_ISEMPTY_DIM_OBJ); - CASE(ZEND_PRE_INC_OBJ); - CASE(ZEND_PRE_DEC_OBJ); - CASE(ZEND_POST_INC_OBJ); - CASE(ZEND_POST_DEC_OBJ); - CASE(ZEND_ASSIGN_OBJ); - CASE(ZEND_INSTANCEOF); - CASE(ZEND_DECLARE_CLASS); - CASE(ZEND_DECLARE_INHERITED_CLASS); - CASE(ZEND_DECLARE_FUNCTION); - CASE(ZEND_RAISE_ABSTRACT_ERROR); - CASE(ZEND_DECLARE_CONST); - CASE(ZEND_ADD_INTERFACE); - CASE(ZEND_DECLARE_INHERITED_CLASS_DELAYED); - CASE(ZEND_VERIFY_ABSTRACT_CLASS); - CASE(ZEND_ASSIGN_DIM); - CASE(ZEND_ISSET_ISEMPTY_PROP_OBJ); - CASE(ZEND_HANDLE_EXCEPTION); - CASE(ZEND_USER_OPCODE); -#ifdef ZEND_JMP_SET - CASE(ZEND_JMP_SET); -#endif - CASE(ZEND_DECLARE_LAMBDA_FUNCTION); -#ifdef ZEND_ADD_TRAIT - CASE(ZEND_ADD_TRAIT); -#endif -#ifdef ZEND_BIND_TRAITS - CASE(ZEND_BIND_TRAITS); -#endif -#ifdef ZEND_SEPARATE - CASE(ZEND_SEPARATE); -#endif -#ifdef ZEND_DISCARD_EXCEPTION - CASE(ZEND_DISCARD_EXCEPTION); -#endif -#ifdef ZEND_YIELD - CASE(ZEND_YIELD); -#endif -#ifdef ZEND_GENERATOR_RETURN - CASE(ZEND_GENERATOR_RETURN); -#endif -#ifdef ZEND_FAST_CALL - CASE(ZEND_FAST_CALL); -#endif -#ifdef ZEND_FAST_RET - CASE(ZEND_FAST_RET); -#endif -#ifdef ZEND_RECV_VARIADIC - CASE(ZEND_RECV_VARIADIC); -#endif - CASE(ZEND_OP_DATA); - default: - return "UNKNOWN"; - } -#else const char *ret = zend_get_opcode_name(opcode); return ret?ret:"UNKNOWN"; -#endif } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c index a4793f144f..4d70381533 100644 --- a/sapi/phpdbg/phpdbg_out.c +++ b/sapi/phpdbg/phpdbg_out.c @@ -136,7 +136,8 @@ static int format_converter(register buffy *odp, const char *fmt, zend_bool esca int i; char *s = NULL, *free_s = NULL; - int s_len, free_zcopy; + size_t s_len; + zend_bool free_zcopy; zval *zvp, zcopy; int min_width = 0; @@ -331,8 +332,8 @@ static int format_converter(register buffy *odp, const char *fmt, zend_bool esca */ switch (*fmt) { case 'Z': - zvp = (zval*) va_arg(ap, zval*); - zend_make_printable_zval(zvp, &zcopy, &free_zcopy); + zvp = (zval *) va_arg(ap, zval *); + free_zcopy = zend_make_printable_zval(zvp, &zcopy TSRMLS_CC); if (free_zcopy) { zvp = &zcopy; } @@ -1021,6 +1022,8 @@ static int phpdbg_process_print(int fd, int type, const char *tag, const char *m if (msg) { PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n'; if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + zend_string *encoded; + if (PHPDBG_G(in_script_xml) != type) { char *stream_buf; int stream_buflen = phpdbg_asprintf(&stream_buf, "<stream type=\"%s\">", type == P_STDERR ? "stderr" : "stdout"); @@ -1028,11 +1031,9 @@ static int phpdbg_process_print(int fd, int type, const char *tag, const char *m efree(stream_buf); PHPDBG_G(in_script_xml) = type; } -#if PHP_VERSION_ID >= 50600 - buf = php_escape_html_entities((unsigned char *) msg, msglen, (size_t *) &buflen, 0, ENT_NOQUOTES, PG(internal_encoding) && PG(internal_encoding)[0] ? PG(internal_encoding) : (SG(default_charset) ? SG(default_charset) : "UTF-8") TSRMLS_CC); -#else - buf = php_escape_html_entities((unsigned char *) msg, msglen, (size_t *) &buflen, 0, ENT_NOQUOTES, SG(default_charset) ? SG(default_charset) : "UTF-8" TSRMLS_CC); -#endif + encoded = php_escape_html_entities((unsigned char *) msg, msglen, 0, ENT_NOQUOTES, PG(internal_encoding) && PG(internal_encoding)[0] ? PG(internal_encoding) : (SG(default_charset) ? SG(default_charset) : "UTF-8") TSRMLS_CC); + buflen = encoded->len; + memcpy(buf = emalloc(buflen + 1), encoded->val, buflen); phpdbg_encode_ctrl_chars(&buf, &buflen); phpdbg_mixed_write(fd, buf, buflen TSRMLS_CC); efree(buf); diff --git a/sapi/phpdbg/phpdbg_parser.c b/sapi/phpdbg/phpdbg_parser.c index c766868369..8bb9103a98 100644 --- a/sapi/phpdbg/phpdbg_parser.c +++ b/sapi/phpdbg/phpdbg_parser.c @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.6. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.6" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse phpdbg_parse @@ -70,11 +68,10 @@ #define yydebug phpdbg_debug #define yynerrs phpdbg_nerrs - /* Copy the first part of user declarations. */ -/* Line 268 of yacc.c */ -#line 1 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 336 of yacc.c */ +#line 1 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" /* @@ -102,13 +99,16 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -/* Line 268 of yacc.c */ -#line 107 "sapi/phpdbg/phpdbg_parser.c" +/* Line 336 of yacc.c */ +#line 104 "sapi/phpdbg/phpdbg_parser.c" -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -118,15 +118,21 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); # define YYERROR_VERBOSE 1 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "phpdbg_parser.h". */ +#ifndef PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H +# define PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int phpdbg_debug; #endif - /* "%code requires" blocks. */ -/* Line 288 of yacc.c */ -#line 31 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 350 of yacc.c */ +#line 31 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -136,8 +142,8 @@ typedef void* yyscan_t; -/* Line 288 of yacc.c */ -#line 141 "sapi/phpdbg/phpdbg_parser.c" +/* Line 350 of yacc.c */ +#line 147 "sapi/phpdbg/phpdbg_parser.c" /* Tokens. */ #ifndef YYTOKENTYPE @@ -189,7 +195,6 @@ typedef void* yyscan_t; - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -198,11 +203,27 @@ typedef int YYSTYPE; #endif +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *YYPARSE_PARAM); +#else +int phpdbg_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *tsrm_ls); +#else +int phpdbg_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H */ + /* Copy the second part of user declarations. */ -/* Line 343 of yacc.c */ -#line 206 "sapi/phpdbg/phpdbg_parser.c" +/* Line 353 of yacc.c */ +#line 227 "sapi/phpdbg/phpdbg_parser.c" #ifdef short # undef short @@ -308,6 +329,7 @@ YYID (yyi) # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -399,20 +421,20 @@ union yyalloc #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ while (YYID (0)) # endif # endif @@ -505,7 +527,7 @@ static const yytype_uint8 yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -519,7 +541,7 @@ static const char *const yytname[] = "\"opcode\"", "\"identifier (command or function name)\"", "\"input (input string or data)\"", "\"input\"", "\"request id (-r %d)\"", "$accept", "input", "parameters", "parameter", - "req_id", "full_expression", 0 + "req_id", "full_expression", YY_NULL }; #endif @@ -652,17 +674,18 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (tsrm_ls, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ @@ -672,32 +695,33 @@ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 - /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ while (YYID (0)) #endif +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + + /* This macro is provided for backward compatibility. */ @@ -758,6 +782,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls) void *tsrm_ls; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; YYUSE (tsrm_ls); @@ -1012,12 +1038,12 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULL; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1077,7 +1103,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; @@ -1171,20 +1197,6 @@ yydestruct (yymsg, yytype, yyvaluep, tsrm_ls) } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void *tsrm_ls); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /*----------. @@ -1230,7 +1242,7 @@ YYSTYPE yylval; `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1463,36 +1475,36 @@ yyreduce: { case 3: -/* Line 1806 of yacc.c */ -#line 68 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 68 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } break; case 5: -/* Line 1806 of yacc.c */ -#line 73 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 73 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } break; case 6: -/* Line 1806 of yacc.c */ -#line 74 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 74 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(2) - (2)])); } break; case 7: -/* Line 1806 of yacc.c */ -#line 75 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 75 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (2)]); } break; case 8: -/* Line 1806 of yacc.c */ -#line 79 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 79 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = FILE_PARAM; (yyval).file.name = (yyvsp[(2) - (3)]).str; @@ -1502,8 +1514,8 @@ yyreduce: case 9: -/* Line 1806 of yacc.c */ -#line 84 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 84 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = (yyvsp[(1) - (4)]).str; @@ -1513,8 +1525,8 @@ yyreduce: case 10: -/* Line 1806 of yacc.c */ -#line 89 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 89 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (4)]).len + (yyvsp[(2) - (4)]).len + 1); @@ -1529,8 +1541,8 @@ yyreduce: case 11: -/* Line 1806 of yacc.c */ -#line 99 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 99 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (5)]).len + (yyvsp[(2) - (5)]).len + 1); @@ -1545,8 +1557,8 @@ yyreduce: case 12: -/* Line 1806 of yacc.c */ -#line 109 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 109 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (3)]).str; @@ -1556,8 +1568,8 @@ yyreduce: case 13: -/* Line 1806 of yacc.c */ -#line 114 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 114 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (5)]).str; @@ -1568,8 +1580,8 @@ yyreduce: case 14: -/* Line 1806 of yacc.c */ -#line 120 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 120 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FUNCTION_PARAM; (yyval).str = (yyvsp[(1) - (3)]).str; @@ -1580,8 +1592,8 @@ yyreduce: case 15: -/* Line 1806 of yacc.c */ -#line 126 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 126 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = COND_PARAM; (yyval).str = (yyvsp[(2) - (2)]).str; @@ -1591,64 +1603,64 @@ yyreduce: case 16: -/* Line 1806 of yacc.c */ -#line 131 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 131 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 17: -/* Line 1806 of yacc.c */ -#line 132 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 132 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 18: -/* Line 1806 of yacc.c */ -#line 133 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 133 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 19: -/* Line 1806 of yacc.c */ -#line 134 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 134 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 20: -/* Line 1806 of yacc.c */ -#line 135 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 135 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 21: -/* Line 1806 of yacc.c */ -#line 136 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 136 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 22: -/* Line 1806 of yacc.c */ -#line 137 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 137 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 23: -/* Line 1806 of yacc.c */ -#line 141 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 141 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { PHPDBG_G(req_id) = (yyvsp[(1) - (1)]).num; } break; case 25: -/* Line 1806 of yacc.c */ -#line 146 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 146 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = EVAL_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1658,8 +1670,8 @@ yyreduce: case 26: -/* Line 1806 of yacc.c */ -#line 151 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 151 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = SHELL_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1669,8 +1681,8 @@ yyreduce: case 27: -/* Line 1806 of yacc.c */ -#line 156 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 156 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = RUN_PARAM; (yyval).len = 0; @@ -1679,8 +1691,8 @@ yyreduce: case 28: -/* Line 1806 of yacc.c */ -#line 160 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1803 of yacc.c */ +#line 160 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = RUN_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1690,8 +1702,8 @@ yyreduce: -/* Line 1806 of yacc.c */ -#line 1695 "sapi/phpdbg/phpdbg_parser.c" +/* Line 1803 of yacc.c */ +#line 1707 "sapi/phpdbg/phpdbg_parser.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1878,7 +1890,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -1921,8 +1933,8 @@ yyreturn: -/* Line 2067 of yacc.c */ -#line 167 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 2049 of yacc.c */ +#line 167 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" static int yyerror(void ***tsrm_ls, const char *msg) { diff --git a/sapi/phpdbg/phpdbg_parser.h b/sapi/phpdbg/phpdbg_parser.h index dfa155d718..e8ab7a6503 100644 --- a/sapi/phpdbg/phpdbg_parser.h +++ b/sapi/phpdbg/phpdbg_parser.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.6. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,10 +30,19 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H +# define PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int phpdbg_debug; +#endif /* "%code requires" blocks. */ -/* Line 2068 of yacc.c */ -#line 31 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 2056 of yacc.c */ +#line 31 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -43,8 +52,8 @@ typedef void* yyscan_t; -/* Line 2068 of yacc.c */ -#line 48 "sapi/phpdbg/phpdbg_parser.h" +/* Line 2056 of yacc.c */ +#line 57 "sapi/phpdbg/phpdbg_parser.h" /* Tokens. */ #ifndef YYTOKENTYPE @@ -96,7 +105,6 @@ typedef void* yyscan_t; - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -105,5 +113,18 @@ typedef int YYSTYPE; #endif +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *YYPARSE_PARAM); +#else +int phpdbg_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *tsrm_ls); +#else +int phpdbg_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ - +#endif /* !PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H */ diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index 80eeddb39d..62a614281d 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -41,7 +41,7 @@ const phpdbg_command_t phpdbg_print_commands[] = { PHPDBG_PRINT(opline) /* {{{ */ { - if (EG(in_execution) && EG(current_execute_data)) { + if (PHPDBG_G(in_execution) && EG(current_execute_data)) { phpdbg_print_opline(EG(current_execute_data), 1 TSRMLS_CC); } else { phpdbg_error("inactive", "type=\"execution\"", "Not Executing!"); @@ -59,22 +59,22 @@ static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) if (op_array) { zend_op *opline = &(op_array->opcodes[0]); - zend_uint opcode = 0, + uint32_t opcode = 0, end = op_array->last-1; if (method->common.scope) { phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" method=\"%s::%s\" file=\"%s\"", "\tL%d-%d %s::%s() %s", op_array->line_start, op_array->line_end, - method->common.scope->name, - method->common.function_name, - op_array->filename ? op_array->filename : "unknown"); + method->common.scope->name->val, + method->common.function_name->val, + op_array->filename ? op_array->filename->val : "unknown"); } else { phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" function=\"%s\" file=\"%s\"", "\tL%d-%d %s() %s", method->common.function_name ? op_array->line_start : 0, method->common.function_name ? op_array->line_end : 0, - method->common.function_name ? method->common.function_name : "{main}", - op_array->filename ? op_array->filename : "unknown"); + method->common.function_name ? method->common.function_name->val : "{main}", + op_array->filename ? op_array->filename->val : "unknown"); } zend_hash_init(&vars, op_array->last, NULL, NULL, 0); @@ -98,9 +98,9 @@ static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) default: { if (method->common.scope) { - phpdbg_writeln("printoplineinfo", "type=\"Internal\" method=\"%s::%s\"", "Internal %s::%s()", method->common.scope->name, method->common.function_name); + phpdbg_writeln("printoplineinfo", "type=\"Internal\" method=\"%s::%s\"", "\tInternal %s::%s()", method->common.scope->name->val, method->common.function_name->val); } else { - phpdbg_writeln("printoplineinfo", "type=\"Internal\" function=\"%s\"", "\tInternal %s()", method->common.function_name); + phpdbg_writeln("printoplineinfo", "type=\"Internal\" function=\"%s\"", "\tInternal %s()", method->common.function_name->val); } } } @@ -127,18 +127,17 @@ return SUCCESS; PHPDBG_PRINT(stack) /* {{{ */ { - zend_op_array *ops = EG(active_op_array); - - if (EG(in_execution) && ops) { + if (PHPDBG_G(in_execution) && EG(current_execute_data)) { + zend_op_array *ops = &EG(current_execute_data)->func->op_array; if (ops->function_name) { if (ops->scope) { - phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ops->scope->name, ops->function_name, ops->last); + phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ops->scope->name->val, ops->function_name->val, ops->last); } else { - phpdbg_notice("printinfo", "function=\"%s\" num=\"%d\"", "Stack in %s() (%d ops)", ops->function_name, ops->last); + phpdbg_notice("printinfo", "function=\"%s\" num=\"%d\"", "Stack in %s() (%d ops)", ops->function_name->val, ops->last); } } else { if (ops->filename) { - phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Stack in %s (%d ops)", ops->filename, ops->last); + phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Stack in %s (%d ops)", ops->filename->val, ops->last); } else { phpdbg_notice("printinfo", "opline=\"%p\" num=\"%d\"", "Stack @ %p (%d ops)", ops, ops->last); } @@ -153,31 +152,28 @@ PHPDBG_PRINT(stack) /* {{{ */ PHPDBG_PRINT(class) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; if (phpdbg_safe_class_lookup(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { phpdbg_notice("printinfo", "type=\"%s\" flag=\"%s\" class=\"%s\" num=\"%d\"", "%s %s: %s (%d methods)", - ((*ce)->type == ZEND_USER_CLASS) ? + (ce->type == ZEND_USER_CLASS) ? "User" : "Internal", - ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? + (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : - ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? + (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class", - (*ce)->name, - zend_hash_num_elements(&(*ce)->function_table)); + ce->name->val, + zend_hash_num_elements(&ce->function_table)); phpdbg_xml("<printmethods %r>"); - if (zend_hash_num_elements(&(*ce)->function_table)) { - HashPosition position; + if (zend_hash_num_elements(&ce->function_table)) { zend_function *method; - for (zend_hash_internal_pointer_reset_ex(&(*ce)->function_table, &position); - zend_hash_get_current_data_ex(&(*ce)->function_table, (void**) &method, &position) == SUCCESS; - zend_hash_move_forward_ex(&(*ce)->function_table, &position)) { + ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { phpdbg_print_function_helper(method TSRMLS_CC); - } + } ZEND_HASH_FOREACH_END(); } phpdbg_xml("</printmethods>"); @@ -190,16 +186,17 @@ PHPDBG_PRINT(class) /* {{{ */ PHPDBG_PRINT(method) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { zend_function *fbc; - char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); + zend_string *lcname = zend_string_alloc(strlen(param->method.name), 0); + zend_str_tolower_copy(lcname->val, param->method.name, lcname->len); - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { + if ((fbc = zend_hash_find_ptr(&ce->function_table, lcname))) { phpdbg_notice("printinfo", "type=\"%s\" flags=\"Method\" symbol=\"%s\" num=\"%d\"", "%s Method %s (%d ops)", (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", - fbc->common.function_name, + fbc->common.function_name->val, (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0); phpdbg_print_function_helper(fbc TSRMLS_CC); @@ -207,7 +204,7 @@ PHPDBG_PRINT(method) /* {{{ */ phpdbg_error("print", "type=\"nomethod\" method=\"%s::%s\"", "The method %s::%s could not be found", param->method.class, param->method.name); } - efree(lcname); + zend_string_release(lcname); } else { phpdbg_error("print", "type=\"noclass\" class=\"%s\"", "The class %s could not be found", param->method.class); } @@ -221,7 +218,7 @@ PHPDBG_PRINT(func) /* {{{ */ zend_function* fbc; const char *func_name = param->str; size_t func_name_len = param->len; - char *lcname; + zend_string *lcname; /* search active scope if begins with period */ if (func_name[0] == '.') { if (EG(scope)) { @@ -240,14 +237,15 @@ PHPDBG_PRINT(func) /* {{{ */ func_table = EG(function_table); } - lcname = zend_str_tolower_dup(func_name, func_name_len); + lcname = zend_string_alloc(func_name_len, 0); + zend_str_tolower_copy(lcname->val, func_name, lcname->len); phpdbg_try_access { - if (zend_hash_find(func_table, lcname, func_name_len + 1, (void **) &fbc) == SUCCESS) { + if ((fbc = zend_hash_find_ptr(func_table, lcname))) { phpdbg_notice("printinfo", "type=\"%s\" flags=\"%s\" symbol=\"%s\" num=\"%d\"", "%s %s %s (%d ops)", (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", (fbc->common.scope) ? "Method" : "Function", - fbc->common.function_name, + fbc->common.function_name->val, (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0); phpdbg_print_function_helper(fbc TSRMLS_CC); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 82444fbf1d..190907e687 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -22,6 +22,7 @@ #include <string.h> #include "zend.h" #include "zend_compile.h" +#include "zend_exceptions.h" #include "phpdbg.h" #include "phpdbg_help.h" @@ -103,20 +104,18 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ * lc_name = zend_str_tolower_dup(name->str, name->len); - if (zend_hash_exists(&PHPDBG_G(registered), lc_name, name->len+1)) { - zval fname, *fretval; + if (zend_hash_str_exists(&PHPDBG_G(registered), lc_name, name->len)) { + zval fretval; zend_fcall_info fci; - ZVAL_STRINGL(&fname, lc_name, name->len, 1); - memset(&fci, 0, sizeof(zend_fcall_info)); + ZVAL_STRINGL(&fci.function_name, lc_name, name->len); fci.size = sizeof(zend_fcall_info); fci.function_table = &PHPDBG_G(registered); - fci.function_name = &fname; - fci.symbol_table = EG(active_symbol_table); - fci.object_ptr = NULL; - fci.retval_ptr_ptr = &fretval; + fci.symbol_table = zend_rebuild_symbol_table(TSRMLS_C); + fci.object = NULL; + fci.retval = &fretval; fci.no_separation = 1; if (name->next) { @@ -132,7 +131,7 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ * case OP_PARAM: case COND_PARAM: case STR_PARAM: - add_next_index_stringl(¶ms, next->str, next->len, 1); + add_next_index_stringl(¶ms, next->str, next->len); break; case NUMERIC_PARAM: @@ -140,33 +139,28 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ * break; case METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s", - next->method.class, next->method.name); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s::%s", next->method.class, next->method.name); + add_next_index_string(¶ms, buffered); break; case NUMERIC_METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s#%ld", - next->method.class, next->method.name, next->num); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s::%s#%ld", next->method.class, next->method.name, next->num); + add_next_index_string(¶ms, buffered); break; case NUMERIC_FUNCTION_PARAM: - spprintf(&buffered, 0, "%s#%ld", - next->str, next->num); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s#%ld", next->str, next->num); + add_next_index_string(¶ms, buffered); break; case FILE_PARAM: - spprintf(&buffered, 0, "%s:%ld", - next->file.name, next->file.line); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s:%ld", next->file.name, next->file.line); + add_next_index_string(¶ms, buffered); break; case NUMERIC_FILE_PARAM: - spprintf(&buffered, 0, "%s:#%ld", - next->file.name, next->file.line); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s:#%ld", next->file.name, next->file.line); + add_next_index_string(¶ms, buffered); break; default: { @@ -188,14 +182,13 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ * phpdbg_debug("created %d params from arguments", fci.param_count); - zend_call_function(&fci, NULL TSRMLS_CC); - - if (fretval) { - zend_print_zval_r(fretval, 0 TSRMLS_CC); + if (zend_call_function(&fci, NULL TSRMLS_CC) == SUCCESS) { + zend_print_zval_r(&fretval, 0 TSRMLS_CC); phpdbg_out("\n"); + zval_ptr_dtor(&fretval); } - zval_dtor(&fname); + zval_dtor(&fci.function_name); efree(lc_name); return SUCCESS; @@ -401,13 +394,12 @@ int phpdbg_compile(TSRMLS_D) /* {{{ */ return SUCCESS; } - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"isrunning\"", "Cannot compile while in execution"); return FAILURE; } if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC) == SUCCESS) { - PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE TSRMLS_CC); zend_destroy_file_handle(&fh TSRMLS_CC); @@ -422,7 +414,7 @@ int phpdbg_compile(TSRMLS_D) /* {{{ */ PHPDBG_COMMAND(step) /* {{{ */ { - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } @@ -436,19 +428,19 @@ PHPDBG_COMMAND(continue) /* {{{ */ PHPDBG_COMMAND(until) /* {{{ */ { - if (!EG(in_execution)) { + if (!PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; { - zend_uint next = 0, self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - zend_op *opline = &EG(active_op_array)->opcodes[self]; + const zend_op *opline = EG(current_execute_data)->opline; + const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; - for (next = self; next < EG(active_op_array)->last; next++) { - if (EG(active_op_array)->opcodes[next].lineno != opline->lineno) { - zend_hash_index_update(&PHPDBG_G(seek), (zend_ulong) &EG(active_op_array)->opcodes[next], &EG(active_op_array)->opcodes[next], sizeof(zend_op), NULL); + while (++opline < op_array->opcodes + op_array->last) { + if (opline->lineno != EG(current_execute_data)->opline->lineno) { + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); break; } } @@ -457,58 +449,46 @@ PHPDBG_COMMAND(until) /* {{{ */ return PHPDBG_UNTIL; } /* }}} */ +static void phpdbg_seek_to_end(TSRMLS_D) { + const zend_op *opline = EG(current_execute_data)->opline; + const zend_op_array *op_array = &EG(current_execute_data)->func->op_array - 1; + + while (++opline < op_array->opcodes + op_array->last) { + switch (opline->opcode) { + case ZEND_RETURN: + case ZEND_THROW: + case ZEND_EXIT: +#ifdef ZEND_YIELD + case ZEND_YIELD: +#endif + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); + return; + } + } +} + PHPDBG_COMMAND(finish) /* {{{ */ { - if (!EG(in_execution)) { + if (!PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } PHPDBG_G(flags) |= PHPDBG_IN_FINISH; - { - zend_uint next = 0, self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - - for (next = self; next < EG(active_op_array)->last; next++) { - switch (EG(active_op_array)->opcodes[next].opcode) { - case ZEND_RETURN: - case ZEND_THROW: - case ZEND_EXIT: -#ifdef ZEND_YIELD - case ZEND_YIELD: -#endif - zend_hash_index_update(&PHPDBG_G(seek), (zend_ulong) &EG(active_op_array)->opcodes[next], &EG(active_op_array)->opcodes[next], sizeof(zend_op), NULL); - break; - } - } - } + phpdbg_seek_to_end(TSRMLS_C); return PHPDBG_FINISH; } /* }}} */ PHPDBG_COMMAND(leave) /* {{{ */ { - if (!EG(in_execution)) { + if (!PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } PHPDBG_G(flags) |= PHPDBG_IN_LEAVE; - { - zend_uint next = 0, self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - - for (next = self; next < EG(active_op_array)->last; next++) { - switch (EG(active_op_array)->opcodes[next].opcode) { - case ZEND_RETURN: - case ZEND_THROW: - case ZEND_EXIT: -#ifdef ZEND_YIELD - case ZEND_YIELD: -#endif - zend_hash_index_update(&PHPDBG_G(seek), (zend_ulong) &EG(active_op_array)->opcodes[next], &EG(active_op_array)->opcodes[next], sizeof(zend_op), NULL); - break; - } - } - } + phpdbg_seek_to_end(TSRMLS_C); return PHPDBG_LEAVE; } /* }}} */ @@ -527,59 +507,47 @@ PHPDBG_COMMAND(frame) /* {{{ */ static inline void phpdbg_handle_exception(TSRMLS_D) /* }}} */ { zend_fcall_info fci; - - zval fname, *trace, exception; + zval trace; /* get filename and linenumber before unsetting exception */ const char *filename = zend_get_executed_filename(TSRMLS_C); - zend_uint lineno = zend_get_executed_lineno(TSRMLS_C); - - /* copy exception */ - exception = *EG(exception); - zval_copy_ctor(&exception); - EG(exception) = NULL; + uint32_t lineno = zend_get_executed_lineno(TSRMLS_C); /* call __toString */ - ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring")-1, 1); + ZVAL_STRINGL(&fci.function_name, "__tostring", sizeof("__tostring") - 1); fci.size = sizeof(fci); - fci.function_table = &Z_OBJCE(exception)->function_table; - fci.function_name = &fname; + fci.function_table = &EG(exception)->ce->function_table; fci.symbol_table = NULL; - fci.object_ptr = &exception; - fci.retval_ptr_ptr = &trace; + fci.object = EG(exception); + fci.retval = &trace; fci.param_count = 0; fci.params = NULL; fci.no_separation = 1; - zend_call_function(&fci, NULL TSRMLS_CC); - - if (trace) { - phpdbg_writeln("exception", "name=\"%s\" trace=\"%.*s\"", "Uncaught %s!\n%.*s", Z_OBJCE(exception)->name, Z_STRLEN_P(trace), Z_STRVAL_P(trace)); + if (zend_call_function(&fci, NULL TSRMLS_CC) == SUCCESS) { + phpdbg_writeln("exception", "name=\"%s\" trace=\"%.*s\"", "Uncaught %s!\n%.*s", EG(exception)->ce->name->val, Z_STRLEN(trace), Z_STRVAL(trace)); zval_ptr_dtor(&trace); } else { - phpdbg_error("exception", "name=\"%s\"", "Uncaught %s!", Z_OBJCE(exception)->name); + phpdbg_error("exception", "name=\"%s\"" "Uncaught %s!", EG(exception)->ce->name->val); } /* output useful information about address */ - phpdbg_writeln("exception", "opline=\"%p\" file=\"%s\" line=\"%u\"", "Stack entered at %p in %s on line %u", EG(active_op_array)->opcodes, filename, lineno); + phpdbg_writeln("exception", "opline=\"%p\" file=\"%s\" line=\"%u\"", "Stack entered at %p in %s on line %u", EG(current_execute_data)->func->op_array.opcodes, filename, lineno); - zval_dtor(&fname); - zval_dtor(&exception); + zval_dtor(&fci.function_name); + zend_clear_exception(TSRMLS_C); } /* }}} */ PHPDBG_COMMAND(run) /* {{{ */ { - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"isrunning\"", "Cannot start another execution while one is in progress"); return SUCCESS; } if (PHPDBG_G(ops) || PHPDBG_G(exec)) { - zend_op **orig_opline = EG(opline_ptr); - zend_op_array *orig_op_array = EG(active_op_array); - zval **orig_retval_ptr = EG(return_value_ptr_ptr); - zend_bool restore = 1; zend_execute_data *ex = EG(current_execute_data); + zend_bool restore = 1; if (!PHPDBG_G(ops)) { if (phpdbg_compile(TSRMLS_C) == FAILURE) { @@ -588,21 +556,16 @@ PHPDBG_COMMAND(run) /* {{{ */ } } - EG(active_op_array) = PHPDBG_G(ops); - EG(return_value_ptr_ptr) = &PHPDBG_G(retval); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - /* clean up from last execution */ if (ex && ex->symbol_table) { - zend_hash_clean(ex->symbol_table); + zend_hash_clean(&ex->symbol_table->ht); + } else { + zend_rebuild_symbol_table(TSRMLS_C); } /* clean seek state */ PHPDBG_G(flags) &= ~PHPDBG_SEEK_MASK; - zend_hash_clean( - &PHPDBG_G(seek)); + zend_hash_clean(&PHPDBG_G(seek)); /* reset hit counters */ phpdbg_reset_breakpoints(TSRMLS_C); @@ -634,14 +597,11 @@ PHPDBG_COMMAND(run) /* {{{ */ zend_try { PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; - zend_execute(EG(active_op_array) TSRMLS_CC); + zend_execute(PHPDBG_G(ops), &PHPDBG_G(retval) TSRMLS_CC); PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); } zend_catch { - EG(active_op_array) = orig_op_array; - EG(opline_ptr) = orig_opline; - EG(return_value_ptr_ptr) = orig_retval_ptr; - + PHPDBG_G(in_execution) = 0; if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { phpdbg_error("stop", "type=\"bailout\"", "Caught exit/error from VM"); restore = 0; @@ -657,10 +617,6 @@ PHPDBG_COMMAND(run) /* {{{ */ if (EG(exception)) { phpdbg_handle_exception(TSRMLS_C); } - - EG(active_op_array) = orig_op_array; - EG(opline_ptr) = orig_opline; - EG(return_value_ptr_ptr) = orig_retval_ptr; } } else { phpdbg_error("inactive", "type=\"nocontext\"", "Nothing to execute!"); @@ -671,10 +627,10 @@ out: return SUCCESS; } /* }}} */ -int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv TSRMLS_DC) { +int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv TSRMLS_DC) { phpdbg_notice("eval", "variable=\"%.*s\"", "Printing variable %.*s", (int) len, name); phpdbg_xml("<eval %r>"); - zend_print_zval_r(*zv, 0 TSRMLS_CC); + zend_print_zval_r(zv, 0 TSRMLS_CC); phpdbg_xml("</eval>"); phpdbg_out("\n"); @@ -691,7 +647,7 @@ PHPDBG_COMMAND(ev) /* {{{ */ if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { phpdbg_try_access { - phpdbg_parse_variable(param->str, param->len, &EG(symbol_table), 0, phpdbg_output_ev_variable, 0 TSRMLS_CC); + phpdbg_parse_variable(param->str, param->len, &EG(symbol_table).ht, 0, phpdbg_output_ev_variable, 0 TSRMLS_CC); } phpdbg_catch_access { phpdbg_error("signalsegv", "", "Could not fetch data, invalid data source"); } phpdbg_end_try_access(); @@ -705,16 +661,16 @@ PHPDBG_COMMAND(ev) /* {{{ */ /* disable stepping while eval() in progress */ PHPDBG_G(flags) |= PHPDBG_IN_EVAL; zend_try { - if (zend_eval_stringl(param->str, param->len,&retval, "eval()'d code" TSRMLS_CC) == SUCCESS) { + if (zend_eval_stringl(param->str, param->len, &retval, "eval()'d code" TSRMLS_CC) == SUCCESS) { phpdbg_xml("<eval %r>"); if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { zval *zvp = &retval; - phpdbg_xml_var_dump(&zvp TSRMLS_CC); + phpdbg_xml_var_dump(zvp TSRMLS_CC); } zend_print_zval_r(&retval, 0 TSRMLS_CC); phpdbg_xml("</eval>"); phpdbg_out("\n"); - zval_dtor(&retval); + zval_ptr_dtor(&retval); } } zend_end_try(); PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL; @@ -731,7 +687,7 @@ PHPDBG_COMMAND(ev) /* {{{ */ PHPDBG_COMMAND(back) /* {{{ */ { - if (!EG(in_execution)) { + if (!PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"noexec\"", "Not executing!"); return SUCCESS; } @@ -771,8 +727,8 @@ PHPDBG_COMMAND(print) /* {{{ */ phpdbg_writeln("print", "vars=\"%d\"", "Variables %d", PHPDBG_G(ops)->last_var ? PHPDBG_G(ops)->last_var - 1 : 0); } - phpdbg_writeln("print", "executing=\"%d\"", "Executing %s", EG(in_execution) ? "yes" : "no"); - if (EG(in_execution)) { + phpdbg_writeln("print", "executing=\"%d\"", "Executing %s", PHPDBG_G(in_execution) ? "yes" : "no"); + if (PHPDBG_G(in_execution)) { phpdbg_writeln("print", "vmret=\"%d\"", "VM Return %d", PHPDBG_G(vmret)); } @@ -939,7 +895,7 @@ PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, char **name *name = new_extension->name; - zend_register_extension(new_extension, handle); + zend_register_extension(new_extension, handle TSRMLS_CC); if (new_extension->startup) { if (new_extension->startup(new_extension) != SUCCESS) { @@ -1080,9 +1036,9 @@ PHPDBG_COMMAND(register) /* {{{ */ char *lcname = zend_str_tolower_dup(param->str, param->len); size_t lcname_len = strlen(lcname); - if (!zend_hash_exists(&PHPDBG_G(registered), lcname, lcname_len+1)) { - if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void**) &function) == SUCCESS) { - zend_hash_update(&PHPDBG_G(registered), lcname, lcname_len+1, (void*)&function, sizeof(zend_function), NULL); + 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); function_add_ref(function); phpdbg_notice("register", "function=\"%s\"", "Registered %s", lcname); @@ -1110,7 +1066,7 @@ PHPDBG_COMMAND(quit) /* {{{ */ PHPDBG_COMMAND(clean) /* {{{ */ { - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { phpdbg_error("inactive", "type=\"isrunning\"", "Cannot clean environment while executing"); return SUCCESS; } @@ -1230,7 +1186,7 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */ case PHPDBG_NEXT: { phpdbg_activate_err_buf(0 TSRMLS_CC); phpdbg_free_err_buf(TSRMLS_C); - if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + if (!PHPDBG_G(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { phpdbg_error("command", "type=\"noexec\"", "Not running"); } goto out; @@ -1260,7 +1216,7 @@ out: PHPDBG_G(req_id) = 0; } - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { phpdbg_restore_frame(TSRMLS_C); } @@ -1287,76 +1243,12 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ } } /* }}} */ -static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ -{ -#if PHP_VERSION_ID >= 50500 - return zend_create_execute_data_from_op_array(op_array, nested TSRMLS_CC); -#else - -#undef EX -#define EX(element) execute_data->element -#undef EX_CV -#define EX_CV(var) EX(CVs)[var] -#undef EX_CVs -#define EX_CVs() EX(CVs) -#undef EX_T -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -#undef EX_Ts -#define EX_Ts() EX(Ts) - - zend_execute_data *execute_data = (zend_execute_data *)zend_vm_stack_alloc( - ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + - ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + - ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - - EX(CVs) = (zval ***)((char *)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); - memset(EX(CVs), 0, sizeof(zval **) * op_array->last_var); - EX(Ts) = (temp_variable *)(((char *) EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); - EX(fbc) = NULL; - EX(called_scope) = NULL; - EX(object) = NULL; - EX(old_error_reporting) = NULL; - EX(op_array) = op_array; - EX(symbol_table) = EG(active_symbol_table); - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - EX(nested) = nested; - - if (!op_array->run_time_cache && op_array->last_cache_slot) { - op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); - } - - if (op_array->this_var != -1 && EG(This)) { - Z_ADDREF_P(EG(This)); /* For $this pointer */ - if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**) EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); - } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) &EX_CV(op_array->this_var))==FAILURE) { - Z_DELREF_P(EG(This)); - } - } - } - - EX(opline) = op_array->opcodes; - EG(opline_ptr) = &EX(opline); - - EX(function_state).function = (zend_function *) op_array; - EX(function_state).arguments = NULL; - - return execute_data; -#endif -} /* }}} */ - #define DO_INTERACTIVE(allow_async_unsafe) do { \ if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \ - phpdbg_list_file( \ - zend_get_executed_filename(TSRMLS_C), \ - 3, \ - zend_get_executed_lineno(TSRMLS_C)-1, \ - zend_get_executed_lineno(TSRMLS_C) \ - TSRMLS_CC \ - ); \ + const char *file_char = zend_get_executed_filename(TSRMLS_C); \ + zend_string *file = zend_string_init(file_char, strlen(file_char), 0); \ + phpdbg_list_file(file, 3, zend_get_executed_lineno(TSRMLS_C)-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); \ + efree(file); \ } \ \ switch (phpdbg_interactive(allow_async_unsafe TSRMLS_CC)) { \ @@ -1369,45 +1261,19 @@ static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_ar } \ } while (0) -#if PHP_VERSION_ID >= 50500 void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ { -#else -void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */ -{ - long long flags = 0; - zend_ulong address = 0L; - zend_execute_data *execute_data; - zend_bool nested = 0; -#endif - zend_bool original_in_execution = EG(in_execution); + zend_bool original_in_execution = PHPDBG_G(in_execution); HashTable vars; -#if PHP_VERSION_ID < 50500 - if (EG(exception)) { - return; - } -#endif + zend_hash_init(&vars, execute_data->func->op_array.last, NULL, NULL, 0); - EG(in_execution) = 1; - -#if PHP_VERSION_ID >= 50500 - if (0) { -zend_vm_enter: - execute_data = phpdbg_create_execute_data(EG(active_op_array), 1 TSRMLS_CC); - } - zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0); -#else -zend_vm_enter: - execute_data = phpdbg_create_execute_data(op_array, nested TSRMLS_CC); - nested = 1; - zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0); -#endif + PHPDBG_G(in_execution) = 1; while (1) { if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) { /* resolve nth opline breakpoints */ - phpdbg_resolve_op_array_breaks(EG(active_op_array) TSRMLS_CC); + phpdbg_resolve_op_array_breaks(&execute_data->func->op_array TSRMLS_CC); } #ifdef ZEND_WIN32 @@ -1507,38 +1373,19 @@ next: PHPDBG_G(last_line) = execute_data->opline->lineno; /* stupid hack to make zend_do_fcall_common_helper return ZEND_VM_ENTER() instead of recursively calling zend_execute() and eventually segfaulting */ - if ((execute_data->opline->opcode == ZEND_DO_FCALL_BY_NAME || execute_data->opline->opcode == ZEND_DO_FCALL) && execute_data->function_state.function->type == ZEND_USER_FUNCTION) { -#if PHP_VERSION_ID < 50500 - zend_execute = execute; -#else + if (execute_data->opline->opcode == ZEND_DO_FCALL && execute_data->func->type == ZEND_USER_FUNCTION) { zend_execute_ex = execute_ex; -#endif } PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC); -#if PHP_VERSION_ID < 50500 - zend_execute = phpdbg_execute_ex; -#else zend_execute_ex = phpdbg_execute_ex; -#endif - if (PHPDBG_G(vmret) > 0) { - switch (PHPDBG_G(vmret)) { - case 1: - EG(in_execution) = original_in_execution; - zend_hash_destroy(&vars); - return; - case 2: -#if PHP_VERSION_ID < 50500 - op_array = EG(active_op_array); -#endif - zend_hash_destroy(&vars); - goto zend_vm_enter; - break; - case 3: - execute_data = EG(current_execute_data); - break; - default: - break; + if (PHPDBG_G(vmret) != 0) { + if (PHPDBG_G(vmret) < 0) { + zend_hash_destroy(&vars); + PHPDBG_G(in_execution) = original_in_execution; + return; + } else { + execute_data = EG(current_execute_data); } } } @@ -1552,8 +1399,8 @@ void phpdbg_force_interruption(TSRMLS_D) { PHPDBG_G(flags) |= PHPDBG_IN_SIGNAL_HANDLER; if (data) { - if (data->op_array) { - phpdbg_notice("hardinterrupt", "opline=\"%p\" num=\"%lu\" file=\"%s\" line=\"%u\"", "Current opline: %p (op #%lu) in %s:%u", data->opline, (data->opline - data->op_array->opcodes) / sizeof(data->opline), data->op_array->filename, data->opline->lineno); + if (data->func) { + 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, data->opline->lineno); } else { phpdbg_notice("hardinterrupt", "opline=\"%p\"", "Current opline: %p (op_array information unavailable)", data->opline); } diff --git a/sapi/phpdbg/phpdbg_rinit_hook.c b/sapi/phpdbg/phpdbg_rinit_hook.c index 049a782d9d..1bf891654d 100644 --- a/sapi/phpdbg/phpdbg_rinit_hook.c +++ b/sapi/phpdbg/phpdbg_rinit_hook.c @@ -45,10 +45,10 @@ static PHP_MINIT_FUNCTION(phpdbg_webhelper) /* {{{ */ static PHP_RINIT_FUNCTION(phpdbg_webhelper) /* {{{ */ { - zval *cookies = PG(http_globals)[TRACK_VARS_COOKIE]; - zval **auth; + zval cookies = PG(http_globals)[TRACK_VARS_COOKIE]; + zval *auth; - if (!cookies || zend_hash_find(Z_ARRVAL_P(cookies), PHPDBG_NAME "_AUTH_COOKIE", sizeof(PHPDBG_NAME "_AUTH_COOKIE"), (void **) &auth) == FAILURE || Z_STRLEN_PP(auth) != strlen(PHPDBG_WG(auth)) || strcmp(Z_STRVAL_PP(auth), PHPDBG_WG(auth))) { + if (Z_TYPE(cookies) == IS_ARRAY || (auth = zend_hash_str_find(Z_ARRVAL(cookies), PHPDBG_NAME "_AUTH_COOKIE", sizeof(PHPDBG_NAME "_AUTH_COOKIE"))) || Z_STRLEN_P(auth) != strlen(PHPDBG_WG(auth)) || strcmp(Z_STRVAL_P(auth), PHPDBG_WG(auth))) { return SUCCESS; } diff --git a/sapi/phpdbg/phpdbg_set.c b/sapi/phpdbg/phpdbg_set.c index fc7e788fa0..82b9f69f7a 100644 --- a/sapi/phpdbg/phpdbg_set.c +++ b/sapi/phpdbg/phpdbg_set.c @@ -215,9 +215,9 @@ PHPDBG_SET(stepping) /* {{{ */ phpdbg_writeln("setstepping", "type=\"%s\"", "Stepping %s", PHPDBG_G(flags) & PHPDBG_STEP_OPCODE ? "opcode" : "line"); } else switch (param->type) { case STR_PARAM: { - if ((param->len == sizeof("opcode") - 1) && memcmp(param->str, "opcode", sizeof("opcode")) == SUCCESS) { + if (param->len == sizeof("opcode") - 1 && !memcmp(param->str, "opcode", sizeof("opcode"))) { PHPDBG_G(flags) |= PHPDBG_STEP_OPCODE; - } else if ((param->len == sizeof("line")-1) && memcmp(param->str, "line", sizeof("line")) == SUCCESS) { + } else if (param->len == sizeof("line") - 1 && !memcmp(param->str, "line", sizeof("line"))) { PHPDBG_G(flags) &= ~PHPDBG_STEP_OPCODE; } else { phpdbg_error("setstepping", "type=\"wrongargs\"", "usage set stepping [<opcode|line>]"); diff --git a/sapi/phpdbg/phpdbg_sigsafe.c b/sapi/phpdbg/phpdbg_sigsafe.c index 7238ad102f..1ca7bf230c 100644 --- a/sapi/phpdbg/phpdbg_sigsafe.c +++ b/sapi/phpdbg/phpdbg_sigsafe.c @@ -3,50 +3,15 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -static inline void zend_mm_init(zend_mm_heap *heap) { - zend_mm_free_block *p; - int i; - - heap->free_bitmap = 0; - heap->large_free_bitmap = 0; -#if ZEND_MM_CACHE - heap->cached = 0; - memset(heap->cache, 0, sizeof(heap->cache)); -#endif -#if ZEND_MM_CACHE_STAT - for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { - heap->cache_stat[i].count = 0; - } -#endif - p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); - for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { - p->next_free_block = p; - p->prev_free_block = p; - p = (zend_mm_free_block *)((char *)p + sizeof(zend_mm_free_block *) * 2); - heap->large_free_buckets[i] = NULL; - } - heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap); - heap->rest_count = 0; -} - -static zend_mm_storage* zend_mm_mem_init(void *params) { - TSRMLS_FETCH(); - - return &PHPDBG_G(sigsafe_mem).storage; -} - -static void zend_mm_mem_dummy(zend_mm_storage *storage) { -} - #define STR(x) #x #define EXP_STR(x) STR(x) -static zend_mm_segment* zend_mm_mem_alloc(zend_mm_storage *storage, size_t size) { +static void* zend_mm_mem_alloc(zend_mm_storage *storage, size_t size, size_t alignment) { TSRMLS_FETCH(); if (EXPECTED(size == PHPDBG_SIGSAFE_MEM_SIZE && !PHPDBG_G(sigsafe_mem).allocated)) { PHPDBG_G(sigsafe_mem).allocated = 1; - return (zend_mm_segment *) PHPDBG_G(sigsafe_mem).mem; + return PHPDBG_G(sigsafe_mem).mem; } write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("Tried to allocate more than " EXP_STR(PHPDBG_SIGSAFE_MEM_SIZE) " bytes from stack memory in signal handler ... bailing out of signal handler\n")); @@ -60,40 +25,20 @@ static zend_mm_segment* zend_mm_mem_alloc(zend_mm_storage *storage, size_t size) return NULL; } -static zend_mm_segment* zend_mm_mem_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size) { - return zend_mm_mem_alloc(storage, size); -} - -static void zend_mm_mem_free(zend_mm_storage *storage, zend_mm_segment *ptr) { +static void zend_mm_mem_free(zend_mm_storage *storage, void *ptr, size_t size) { } -static const zend_mm_mem_handlers phpdbg_handlers_sigsafe_mem = { "stack", zend_mm_mem_init, zend_mm_mem_dummy, zend_mm_mem_dummy, zend_mm_mem_alloc, zend_mm_mem_realloc, zend_mm_mem_free }; - void phpdbg_set_sigsafe_mem(char *buffer TSRMLS_DC) { phpdbg_signal_safe_mem *mem = &PHPDBG_G(sigsafe_mem); - mem->old_heap = zend_mm_set_heap(&mem->heap TSRMLS_CC); mem->mem = buffer; mem->allocated = 0; - mem->storage.handlers = &phpdbg_handlers_sigsafe_mem; - mem->heap.storage = &mem->storage; - mem->heap.block_size = PHPDBG_SIGSAFE_MEM_SIZE; - mem->heap.compact_size = 0; - mem->heap.segments_list = NULL; - zend_mm_init(&mem->heap); -#if ZEND_MM_CACHE_STAT - memset(mem->heap.cache_stat, 0, sizeof(mem->heap.cache_stat)); -#endif - mem->heap.use_zend_alloc = 1; - mem->heap.real_size = 0; - mem->heap.overflow = 0; - mem->heap.real_peak = 0; - mem->heap.limit = PHPDBG_SIGSAFE_MEM_SIZE; - mem->heap.size = 0; - mem->heap.peak = 0; - mem->heap.internal = 0; - mem->heap.reserve = NULL; - mem->heap.reserve_size = 0; + mem->storage.chunk_alloc = zend_mm_mem_alloc; + mem->storage.chunk_free = zend_mm_mem_free; + + mem->heap = zend_mm_startup_ex(&mem->storage); + + mem->old_heap = zend_mm_set_heap(mem->heap TSRMLS_CC); } zend_mm_heap *phpdbg_original_heap_sigsafe_mem(TSRMLS_D) { diff --git a/sapi/phpdbg/phpdbg_sigsafe.h b/sapi/phpdbg/phpdbg_sigsafe.h index 6ed74f53db..9ef723fdca 100644 --- a/sapi/phpdbg/phpdbg_sigsafe.h +++ b/sapi/phpdbg/phpdbg_sigsafe.h @@ -1,14 +1,17 @@ #ifndef PHPDBG_SIGSAFE_H #define PHPDBG_SIGSAFE_H -#include "zend_mm_structs.h" +//#include "zend_mm_structs.h" -#define PHPDBG_SIGSAFE_MEM_SIZE (1 << 20) +#define PHPDBG_SIGSAFE_MEM_SIZE ZEND_MM_CHUNK_SIZE +//(1 << 20) + +#include "zend.h" typedef struct { char *mem; zend_bool allocated; - zend_mm_heap heap; + zend_mm_heap *heap; zend_mm_heap *old_heap; zend_mm_storage storage; } phpdbg_signal_safe_mem; diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 85b6eeb3b5..bff971d4cf 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -165,27 +165,25 @@ PHPDBG_API const char *phpdbg_current_file(TSRMLS_D) /* {{{ */ PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname TSRMLS_DC) /* {{{ */ { zend_function *func = NULL; - size_t fname_len = strlen(fname); - char *lcname = zend_str_tolower_dup(fname, fname_len); + zend_string *lfname = zend_string_alloc(strlen(fname), 0); + memcpy(lfname->val, zend_str_tolower_dup(fname, lfname->len), lfname->len + 1); if (cname) { - zend_class_entry **ce; - size_t cname_len = strlen(cname); - char *lc_cname = zend_str_tolower_dup(cname, cname_len); - int ret = zend_lookup_class(lc_cname, cname_len, &ce TSRMLS_CC); + zend_class_entry *ce; + zend_string *lcname = zend_string_alloc(strlen(cname), 0); + memcpy(lcname->val, zend_str_tolower_dup(cname, lcname->len), lcname->len + 1); + ce = zend_lookup_class(lcname TSRMLS_CC); - efree(lc_cname); + efree(lcname); - if (ret == SUCCESS) { - zend_hash_find(&(*ce)->function_table, lcname, fname_len+1, - (void**)&func); + if (ce) { + func = zend_hash_find_ptr(&ce->function_table, lfname); } } else { - zend_hash_find(EG(function_table), lcname, fname_len+1, - (void**)&func); + func = zend_hash_find_ptr(EG(function_table), lfname); } - efree(lcname); + efree(lfname); return func; } /* }}} */ @@ -315,18 +313,14 @@ PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */ } /* }}} */ int phpdbg_rebuild_symtable(TSRMLS_D) { - if (!EG(active_op_array)) { + if (!EG(current_execute_data) || !EG(current_execute_data)->func) { phpdbg_error("inactive", "type=\"op_array\"", "No active op array!"); return FAILURE; } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - - if (!EG(active_symbol_table)) { - phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); - return FAILURE; - } + if (!zend_rebuild_symbol_table(TSRMLS_C)) { + phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); + return FAILURE; } return SUCCESS; @@ -359,10 +353,10 @@ PHPDBG_API void phpdbg_set_async_io(int fd) { #endif } -int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) { +int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce TSRMLS_DC) { if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { char *lc_name, *lc_free; - int lc_length, ret = FAILURE; + int lc_length; if (name == NULL || !name_length) { return FAILURE; @@ -378,16 +372,19 @@ int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry } phpdbg_try_access { - ret = zend_hash_find(EG(class_table), lc_name, lc_length, (void **) &ce); + *ce = zend_hash_str_find_ptr(EG(class_table), lc_name, lc_length); } phpdbg_catch_access { phpdbg_error("signalsegv", "class=\"%.*s\"", "Could not fetch class %.*s, invalid data source", name_length, name); } phpdbg_end_try_access(); efree(lc_free); - return ret; } else { - return zend_lookup_class(name, name_length, ce TSRMLS_CC); + zend_string *str_name = zend_string_init(name, name_length, 0); + *ce = zend_lookup_class(str_name TSRMLS_CC); + efree(str_name); } + + return ce ? SUCCESS : FAILURE; } char *phpdbg_get_property_key(char *key) { @@ -397,7 +394,7 @@ char *phpdbg_get_property_key(char *key) { return strchr(key + 1, 0) + 1; } -static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, phpdbg_parse_var_func callback TSRMLS_DC) { +static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, phpdbg_parse_var_func callback TSRMLS_DC) { return callback(name, len, keyname, keylen, parent, zv TSRMLS_CC); } @@ -410,7 +407,7 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable zend_bool new_index = 1; char *last_index; size_t index_len = 0; - zval **zv; + zval *zv; if (len < 2 || *input != '$') { goto error; @@ -446,50 +443,64 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable } if (new_index && index_len == 0) { - HashPosition position; - for (zend_hash_internal_pointer_reset_ex(parent, &position); - zend_hash_get_current_data_ex(parent, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(parent, &position)) { + zend_ulong numkey; + zend_string *strkey; + ZEND_HASH_FOREACH_KEY_PTR(parent, numkey, strkey, zv) { + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (i == len || (i == len - 1 && input[len - 1] == ']')) { - zval *key = emalloc(sizeof(zval)); - size_t namelen; + char *key, *propkey; + size_t namelen, keylen; char *name; char *keyname = estrndup(last_index, index_len); - zend_hash_get_current_key_zval_ex(parent, key, &position); - convert_to_string(key); - name = emalloc(i + Z_STRLEN_P(key) + 2); - namelen = sprintf(name, "%.*s%s%s", (int)i, input, phpdbg_get_property_key(Z_STRVAL_P(key)), input[len - 1] == ']'?"]":""); - efree(key); + if (strkey) { + key = strkey->val; + keylen = strkey->len; + } else { + keylen = spprintf(&key, 0, "%llu", numkey); + } + propkey = phpdbg_get_property_key(key); + name = emalloc(i + keylen + 2); + namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, keylen - (propkey - key), propkey, input[len - 1] == ']'?"]":""); + if (!strkey) { + efree(key); + } ret = callback(name, namelen, keyname, index_len, parent, zv, arg TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; - } else if (Z_TYPE_PP(zv) == IS_OBJECT) { - phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_PP(zv), i, callback, silent, arg TSRMLS_CC); - } else if (Z_TYPE_PP(zv) == IS_ARRAY) { - phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_PP(zv), i, callback, silent, arg TSRMLS_CC); + } else if (Z_TYPE_P(zv) == IS_OBJECT) { + phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_P(zv), i, callback, silent, arg TSRMLS_CC); + } else if (Z_TYPE_P(zv) == IS_ARRAY) { + phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_P(zv), i, callback, silent, arg TSRMLS_CC); } else { /* Ignore silently */ } - } + } ZEND_HASH_FOREACH_END(); return ret; } else if (new_index) { char last_chr = last_index[index_len]; last_index[index_len] = 0; - if (zend_symtable_find(parent, last_index, index_len + 1, (void **)&zv) == FAILURE) { + if (!(zv = zend_symtable_str_find(parent, last_index, index_len))) { if (!silent) { phpdbg_error("variable", "type=\"undefined\" variable=\"%.*s\"", "%.*s is undefined", (int) i, input); } return FAILURE; } + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + last_index[index_len] = last_chr; if (i == len) { char *name = estrndup(input, len); char *keyname = estrndup(last_index, index_len); ret = callback(name, len, keyname, index_len, parent, zv, arg TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; - } else if (Z_TYPE_PP(zv) == IS_OBJECT) { - parent = Z_OBJPROP_PP(zv); - } else if (Z_TYPE_PP(zv) == IS_ARRAY) { - parent = Z_ARRVAL_PP(zv); + } else if (Z_TYPE_P(zv) == IS_OBJECT) { + parent = Z_OBJPROP_P(zv); + } else if (Z_TYPE_P(zv) == IS_ARRAY) { + parent = Z_ARRVAL_P(zv); } else { phpdbg_error("variable", "type=\"notiterable\" variable=\"%.*s\"", "%.*s is nor an array nor an object", (int) i, input); return FAILURE; @@ -504,14 +515,22 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable return FAILURE; } -static int phpdbg_xml_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) { +int phpdbg_is_auto_global(char *name, int len TSRMLS_DC) { + int ret; + zend_string *str = zend_string_init(name, len, 0); + ret = zend_is_auto_global(str TSRMLS_CC); + efree(str); + return ret; +} + +static int phpdbg_xml_array_element_dump(zval *zv, zend_string *key, zend_ulong num TSRMLS_DC) { phpdbg_xml("<element"); phpdbg_try_access { - if (hash_key->nKeyLength == 0) { /* numeric key */ - phpdbg_xml(" name=\"%ld\"", hash_key->h); - } else { /* string key */ - phpdbg_xml(" name=\"%.*s\"", hash_key->nKeyLength - 1, hash_key->arKey); + if (key) { /* string key */ + phpdbg_xml(" name=\"%.*s\"", key->len, key->val); + } else { /* numeric key */ + phpdbg_xml(" name=\"%ld\"", num); } } phpdbg_catch_access { phpdbg_xml(" severity=\"error\" ></element>"); @@ -527,15 +546,13 @@ static int phpdbg_xml_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_l return 0; } -static int phpdbg_xml_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) { +static int phpdbg_xml_object_property_dump(zval *zv, zend_string *key, zend_ulong num TSRMLS_DC) { phpdbg_xml("<property"); phpdbg_try_access { - if (hash_key->nKeyLength == 0) { /* numeric key */ - phpdbg_xml(" name=\"%ld\"", hash_key->h); - } else { /* string key */ + if (key) { /* string key */ const char *prop_name, *class_name; - int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name); + int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name); if (class_name && unmangle == SUCCESS) { phpdbg_xml(" name=\"%s\"", prop_name); @@ -545,8 +562,10 @@ static int phpdbg_xml_object_property_dump(zval **zv TSRMLS_DC, int num_args, va phpdbg_xml(" class=\"%s\" protection=\"private\"", class_name); } } else { - phpdbg_xml(" name=\"%.*s\" protection=\"public\"", hash_key->nKeyLength - 1, hash_key->arKey); + phpdbg_xml(" name=\"%.*s\" protection=\"public\"", key->len, key->val); } + } else { /* numeric key */ + phpdbg_xml(" name=\"%ld\" protection=\"public\"", num); } } phpdbg_catch_access { phpdbg_xml(" severity=\"error\" ></property>"); @@ -562,37 +581,46 @@ static int phpdbg_xml_object_property_dump(zval **zv TSRMLS_DC, int num_args, va return 0; } -#define COMMON (Z_ISREF_PP(zv) ? "&" : "") +#define COMMON (is_ref ? "&" : "") -PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) { +PHPDBG_API void phpdbg_xml_var_dump(zval *zv TSRMLS_DC) { HashTable *myht; - const char *class_name; - zend_uint class_name_len; - int (*element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*); + zend_string *class_name, *key; + zend_ulong num; + zval *val; + int (*element_dump_func)(zval *zv, zend_string *key, zend_ulong num TSRMLS_DC); + zend_bool is_ref = 0; + int is_temp; phpdbg_try_access { - switch (Z_TYPE_PP(zv)) { - case IS_BOOL: - phpdbg_xml("<bool refstatus=\"%s\" value=\"%s\" />", COMMON, Z_LVAL_PP(zv) ? "true" : "false"); + is_ref = Z_ISREF_P(zv) && GC_REFCOUNT(Z_COUNTED_P(zv)) > 1; + ZVAL_DEREF(zv); + + switch (Z_TYPE_P(zv)) { + case IS_TRUE: + phpdbg_xml("<bool refstatus=\"%s\" value=\"true\" />", COMMON); + break; + case IS_FALSE: + phpdbg_xml("<bool refstatus=\"%s\" value=\"false\" />", COMMON); break; case IS_NULL: phpdbg_xml("<null refstatus=\"%s\" />", COMMON); break; case IS_LONG: - phpdbg_xml("<int refstatus=\"%s\" value=\"%ld\" />", COMMON, Z_LVAL_PP(zv)); + phpdbg_xml("<int refstatus=\"%s\" value=\"" ZEND_LONG_FMT "\" />", COMMON, Z_LVAL_P(zv)); break; case IS_DOUBLE: - phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_PP(zv)); + phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_P(zv)); break; case IS_STRING: - phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_PP(zv), Z_STRLEN_PP(zv), Z_STRVAL_PP(zv)); - break; + phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), Z_STRLEN_P(zv), Z_STRVAL_P(zv)); + break; case IS_ARRAY: - myht = Z_ARRVAL_PP(zv); - if (++myht->nApplyCount > 1) { + myht = Z_ARRVAL_P(zv); + if (ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) { phpdbg_xml("<recursion />"); - --myht->nApplyCount; + --myht->u.v.nApplyCount; break; } phpdbg_xml("<array refstatus=\"%s\" num=\"%d\">", COMMON, zend_hash_num_elements(myht)); @@ -600,39 +628,39 @@ PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) { is_temp = 0; goto head_done; case IS_OBJECT: - myht = Z_OBJDEBUG_PP(zv, is_temp); - if (myht && ++myht->nApplyCount > 1) { + myht = Z_OBJDEBUG_P(zv, is_temp); + if (myht && ++myht->u.v.nApplyCount > 1) { phpdbg_xml("<recursion />"); - --myht->nApplyCount; + --myht->u.v.nApplyCount; break; } - - if (Z_OBJ_HANDLER(**zv, get_class_name)) { - Z_OBJ_HANDLER(**zv, get_class_name)(*zv, &class_name, &class_name_len, 0 TSRMLS_CC); - phpdbg_xml("<object refstatus=\"%s\" class=\"%s\" id=\"%d\" num=\"%d\">", COMMON, class_name, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0); - efree((char*)class_name); - } else { - phpdbg_xml("<object refstatus=\"%s\" class=\"\" id=\"%d\" num=\"%d\">", COMMON, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0); - } + + class_name = Z_OBJ_HANDLER_P(zv, get_class_name)(Z_OBJ_P(zv) TSRMLS_CC); + phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, class_name->len, class_name->val, Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0); + zend_string_release(class_name); + element_dump_func = phpdbg_xml_object_property_dump; head_done: if (myht) { + ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { + element_dump_func(val, key, num TSRMLS_CC); + } ZEND_HASH_FOREACH_END(); zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) element_dump_func, 0); - --myht->nApplyCount; + --myht->u.v.nApplyCount; if (is_temp) { zend_hash_destroy(myht); efree(myht); } } - if (Z_TYPE_PP(zv) == IS_ARRAY) { + if (Z_TYPE_P(zv) == IS_ARRAY) { phpdbg_xml("</array>"); } else { phpdbg_xml("</object>"); } break; case IS_RESOURCE: { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(zv) TSRMLS_CC); - phpdbg_xml("<resource refstatus=\"%s\" id=\"%ld\" type=\"%ld\" />", COMMON, Z_LVAL_PP(zv), type_name ? type_name : "unknown"); + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(zv) TSRMLS_CC); + phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%ld\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown"); break; } default: diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h index d657dc79fd..83dc8e9694 100644 --- a/sapi/phpdbg/phpdbg_utils.h +++ b/sapi/phpdbg/phpdbg_utils.h @@ -80,36 +80,18 @@ PHPDBG_API void phpdbg_set_async_io(int fd); int phpdbg_rebuild_symtable(TSRMLS_D); -#if PHP_VERSION_ID < 50500 -/* copy from zend_hash.c PHP 5.5 for 5.4 compatibility */ -static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { - Bucket *p; - - p = pos ? (*pos) : ht->pInternalPointer; - - if (!p) { - Z_TYPE_P(key) = IS_NULL; - } else if (p->nKeyLength) { - Z_TYPE_P(key) = IS_STRING; - Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char*)p->arKey : estrndup(p->arKey, p->nKeyLength - 1); - Z_STRLEN_P(key) = p->nKeyLength - 1; - } else { - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = p->h; - } -} -#endif - -int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC); +int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce TSRMLS_DC); char *phpdbg_get_property_key(char *key); -typedef int (*phpdbg_parse_var_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv TSRMLS_DC); -typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, void *arg TSRMLS_DC); +typedef int (*phpdbg_parse_var_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv TSRMLS_DC); +typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, void *arg TSRMLS_DC); PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent TSRMLS_DC); PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg TSRMLS_DC); -PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC); +int phpdbg_is_auto_global(char *name, int len TSRMLS_DC); + +PHPDBG_API void phpdbg_xml_var_dump(zval *zv TSRMLS_DC); #endif /* PHPDBG_UTILS_H */ diff --git a/sapi/phpdbg/phpdbg_wait.c b/sapi/phpdbg/phpdbg_wait.c index ea506a2d93..9051ca379f 100644 --- a/sapi/phpdbg/phpdbg_wait.c +++ b/sapi/phpdbg/phpdbg_wait.c @@ -25,19 +25,19 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); ZEND_EXTERN_MODULE_GLOBALS(json); static void phpdbg_rebuild_http_globals_array(int type, const char *name TSRMLS_DC) { - zval **zvpp; - if (PG(http_globals)[type]) { - zval_dtor(PG(http_globals)[type]); + zval *zvp; + if (Z_TYPE(PG(http_globals)[type]) != IS_UNDEF) { + zval_dtor(&PG(http_globals)[type]); } - if (zend_hash_find(&EG(symbol_table), name, strlen(name) + 1, (void **) &zvpp) == SUCCESS) { - Z_SET_REFCOUNT_PP(zvpp, 2); - PG(http_globals)[type] = *zvpp; + if ((zvp = zend_hash_str_find(&EG(symbol_table).ht, name, strlen(name)))) { + Z_ADDREF_P(zvp); + PG(http_globals)[type] = *zvp; } } static int phpdbg_dearm_autoglobals(zend_auto_global *auto_global TSRMLS_DC) { - if (auto_global->name_len != sizeof("GLOBALS") - 1 || memcmp(auto_global->name, "GLOBALS", sizeof("GLOBALS") - 1)) { + if (auto_global->name->len != sizeof("GLOBALS") - 1 || memcmp(auto_global->name->val, "GLOBALS", sizeof("GLOBALS") - 1)) { auto_global->armed = 0; } @@ -57,8 +57,8 @@ static int phpdbg_array_data_compare(const void *a, const void *b TSRMLS_DC) { f = *((Bucket **) a); s = *((Bucket **) b); - first = *((zval **) f->pData); - second = *((zval **) s->pData); + first = &f->val; + second = &s->val; if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) { return 0; @@ -85,16 +85,15 @@ static void phpdbg_array_intersect_init(phpdbg_intersect_ptr *info, HashTable *h } /* -1 => first array, 0 => both arrays equal, 1 => second array */ -static int phpdbg_array_intersect(phpdbg_intersect_ptr *info, zval ***ptr) { +static int phpdbg_array_intersect(phpdbg_intersect_ptr *info, zval **ptr) { int ret; - zval **zvpp[2]; + zval *zvp[2]; int invalid = !info->ht[0] + !info->ht[1]; if (invalid > 0) { invalid = !info->ht[0]; - if (zend_hash_get_current_data_ex(info->ht[invalid], (void **) ptr, &info->pos[invalid]) == FAILURE) { - *ptr = NULL; + if (!(*ptr = zend_hash_get_current_data_ex(info->ht[invalid], &info->pos[invalid]))) { return 0; } @@ -103,23 +102,23 @@ static int phpdbg_array_intersect(phpdbg_intersect_ptr *info, zval ***ptr) { return invalid ? 1 : -1; } - if (zend_hash_get_current_data_ex(info->ht[0], (void **) &zvpp[0], &info->pos[0]) == FAILURE) { + if (!(zvp[0] = zend_hash_get_current_data_ex(info->ht[0], &info->pos[0]))) { info->ht[0] = NULL; return phpdbg_array_intersect(info, ptr); } - if (zend_hash_get_current_data_ex(info->ht[1], (void **) &zvpp[1], &info->pos[1]) == FAILURE) { + if (!(zvp[1] = zend_hash_get_current_data_ex(info->ht[1], &info->pos[1]))) { info->ht[1] = NULL; return phpdbg_array_intersect(info, ptr); } - ret = zend_binary_zval_strcmp(*zvpp[0], *zvpp[1]); + ret = zend_binary_zval_strcmp(zvp[0], zvp[1]); if (ret <= 0) { - *ptr = zvpp[0]; + *ptr = zvp[0]; zend_hash_move_forward_ex(info->ht[0], &info->pos[0]); } if (ret >= 0) { - *ptr = zvpp[1]; + *ptr = zvp[1]; zend_hash_move_forward_ex(info->ht[1], &info->pos[1]); } @@ -129,7 +128,7 @@ static int phpdbg_array_intersect(phpdbg_intersect_ptr *info, zval ***ptr) { void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { #ifdef HAVE_JSON zval *free_zv = NULL; - zval zv, **zvpp; + zval zv, *zvp; HashTable *ht; php_json_decode(&zv, msg, len, 1, 1000 /* enough */ TSRMLS_CC); @@ -141,14 +140,14 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { ht = Z_ARRVAL(zv); /* Reapply symbol table */ - if (zend_hash_find(ht, "GLOBALS", sizeof("GLOBALS"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_ARRAY) { + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("GLOBALS"))) && Z_TYPE_P(zvp) == IS_ARRAY) { { - zval **srv; - if (zend_hash_find(Z_ARRVAL_PP(zvpp), "_SERVER", sizeof("_SERVER"), (void **) &srv) == SUCCESS && Z_TYPE_PP(srv) == IS_ARRAY) { - zval **script; - if (zend_hash_find(Z_ARRVAL_PP(srv), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &script) == SUCCESS && Z_TYPE_PP(script) == IS_STRING) { + zval *srv; + if ((srv = zend_hash_str_find(Z_ARRVAL_P(zvp), ZEND_STRL("_SERVER"))) && Z_TYPE_P(srv) == IS_ARRAY) { + zval *script; + if ((script = zend_hash_str_find(Z_ARRVAL_P(srv), ZEND_STRL("SCRIPT_FILENAME"))) && Z_TYPE_P(script) == IS_STRING) { phpdbg_param_t param; - param.str = Z_STRVAL_PP(script); + param.str = Z_STRVAL_P(script); PHPDBG_COMMAND_HANDLER(exec)(¶m TSRMLS_CC); } } @@ -157,8 +156,8 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { PG(auto_globals_jit) = 0; zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_dearm_autoglobals TSRMLS_CC); - zend_hash_clean(&EG(symbol_table)); - EG(symbol_table) = *Z_ARRVAL_PP(zvpp); + zend_hash_clean(&EG(symbol_table).ht); + EG(symbol_table) = *Z_ARR_P(zvp); /* Rebuild cookies, env vars etc. from GLOBALS (PG(http_globals)) */ phpdbg_rebuild_http_globals_array(TRACK_VARS_POST, "_POST" TSRMLS_CC); @@ -168,21 +167,21 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { phpdbg_rebuild_http_globals_array(TRACK_VARS_ENV, "_ENV" TSRMLS_CC); phpdbg_rebuild_http_globals_array(TRACK_VARS_FILES, "_FILES" TSRMLS_CC); - Z_ADDREF_PP(zvpp); - free_zv = *zvpp; + Z_ADDREF_P(zvp); + free_zv = zvp; } - if (zend_hash_find(ht, "input", sizeof("input"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_STRING) { + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("input"))) && Z_TYPE_P(zvp) == IS_STRING) { if (SG(request_info).request_body) { php_stream_close(SG(request_info).request_body); } SG(request_info).request_body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); php_stream_truncate_set_size(SG(request_info).request_body, 0); - php_stream_write(SG(request_info).request_body, Z_STRVAL_PP(zvpp), Z_STRLEN_PP(zvpp)); + php_stream_write(SG(request_info).request_body, Z_STRVAL_P(zvp), Z_STRLEN_P(zvp)); } - if (zend_hash_find(ht, "cwd", sizeof("cwd"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_STRING) { - if (VCWD_CHDIR(Z_STRVAL_PP(zvpp)) == SUCCESS) { + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("cwd"))) && Z_TYPE_P(zvp) == IS_STRING) { + if (VCWD_CHDIR(Z_STRVAL_P(zvp)) == SUCCESS) { if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) { efree(BG(CurrentStatFile)); BG(CurrentStatFile) = NULL; @@ -194,50 +193,46 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { } } - if (zend_hash_find(ht, "sapi_name", sizeof("sapi_name"), (void **) &zvpp) == SUCCESS && (Z_TYPE_PP(zvpp) == IS_STRING || Z_TYPE_PP(zvpp) == IS_NULL)) { + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("sapi_name"))) && (Z_TYPE_P(zvp) == IS_STRING || Z_TYPE_P(zvp) == IS_NULL)) { if (PHPDBG_G(sapi_name_ptr)) { free(PHPDBG_G(sapi_name_ptr)); } - if (Z_TYPE_PP(zvpp) == IS_STRING) { - PHPDBG_G(sapi_name_ptr) = sapi_module.name = strdup(Z_STRVAL_PP(zvpp)); + if (Z_TYPE_P(zvp) == IS_STRING) { + PHPDBG_G(sapi_name_ptr) = sapi_module.name = strdup(Z_STRVAL_P(zvp)); } else { PHPDBG_G(sapi_name_ptr) = sapi_module.name = NULL; } } - if (zend_hash_find(ht, "modules", sizeof("modules"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_ARRAY) { - HashPosition position; + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("modules"))) && Z_TYPE_P(zvp) == IS_ARRAY) { phpdbg_intersect_ptr pos; - zval **module; + zval *module; zend_module_entry *mod; HashTable zv_registry; /* intersect modules, unregister modules loaded "too much", announce not yet registered modules (phpdbg_notice) */ zend_hash_init(&zv_registry, zend_hash_num_elements(&module_registry), 0, ZVAL_PTR_DTOR, 0); - for (zend_hash_internal_pointer_reset_ex(&module_registry, &position); - zend_hash_get_current_data_ex(&module_registry, (void **) &mod, &position) == SUCCESS; - zend_hash_move_forward_ex(&module_registry, &position)) { + ZEND_HASH_FOREACH_PTR(&module_registry, mod) { if (mod->name) { - zval **value = emalloc(sizeof(zval *)); - MAKE_STD_ZVAL(*value); - ZVAL_STRING(*value, mod->name, 1); - zend_hash_next_index_insert(&zv_registry, value, sizeof(zval *), NULL); + zval value; + ZVAL_NEW_STR(&value, zend_string_init(mod->name, strlen(mod->name), 0)); + zend_hash_next_index_insert(&zv_registry, &value); } - } + } ZEND_HASH_FOREACH_END(); - phpdbg_array_intersect_init(&pos, &zv_registry, Z_ARRVAL_PP(zvpp) TSRMLS_CC); + phpdbg_array_intersect_init(&pos, &zv_registry, Z_ARRVAL_P(zvp) TSRMLS_CC); do { int mode = phpdbg_array_intersect(&pos, &module); if (mode < 0) { // loaded module, but not needed - if (strcmp(PHPDBG_NAME, Z_STRVAL_PP(module))) { - zend_hash_del(&module_registry, Z_STRVAL_PP(module), Z_STRLEN_PP(module) + 1); + if (strcmp(PHPDBG_NAME, Z_STRVAL_P(module))) { + zend_hash_del(&module_registry, Z_STR_P(module)); } } else if (mode > 0) { // not loaded module - if (!sapi_module.name || strcmp(sapi_module.name, Z_STRVAL_PP(module))) { - phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", Z_STRLEN_PP(module), Z_STRVAL_PP(module), Z_STRLEN_PP(module), Z_STRVAL_PP(module)); + if (!sapi_module.name || strcmp(sapi_module.name, Z_STRVAL_P(module))) { + phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", Z_STRLEN_P(module), Z_STRVAL_P(module), Z_STRLEN_P(module), Z_STRVAL_P(module)); } } } while (module); @@ -245,26 +240,25 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { zend_hash_clean(&zv_registry); } - if (zend_hash_find(ht, "extensions", sizeof("extensions"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_ARRAY) { + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("extensions"))) && Z_TYPE_P(zvp) == IS_ARRAY) { zend_extension *extension; zend_llist_position pos; - HashPosition hpos; - zval **name, key; + zval *name = NULL; + zend_string *strkey; extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos); while (extension) { extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos); - /* php_serach_array() body should be in some ZEND_API function */ - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(zvpp), &hpos); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(zvpp), (void **) &name, &hpos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(zvpp), &hpos)) { - if (Z_TYPE_PP(name) == IS_STRING && !zend_binary_strcmp(extension->name, strlen(extension->name), Z_STRVAL_PP(name), Z_STRLEN_PP(name))) { + /* php_serach_array() body should be in some ZEND_API function... */ + ZEND_HASH_FOREACH_STR_KEY_PTR(Z_ARRVAL_P(zvp), strkey, name) { + if (Z_TYPE_P(name) == IS_STRING && !zend_binary_strcmp(extension->name, strlen(extension->name), Z_STRVAL_P(name), Z_STRLEN_P(name))) { break; } - } + name = NULL; + } ZEND_HASH_FOREACH_END(); - if (zend_hash_get_current_data_ex(Z_ARRVAL_PP(zvpp), (void **) &zvpp, &hpos) == FAILURE) { + if (name) { /* sigh, breaking the encapsulation, there aren't any functions manipulating the llist at the place of the zend_llist_position */ zend_llist_element *elm = pos; if (elm->prev) { @@ -288,66 +282,53 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) { pefree(elm, zend_extensions.persistent); zend_extensions.count--; } else { - zend_hash_get_current_key_zval_ex(Z_ARRVAL_PP(zvpp), &key, &hpos); +/* zend_hash_get_current_key_zval_ex(Z_ARRVAL_PP(zvpp), &key, &hpos); if (Z_TYPE(key) == IS_LONG) { zend_hash_index_del(Z_ARRVAL_PP(zvpp), Z_LVAL(key)); } +*/ + zend_hash_del(Z_ARRVAL_P(zvp), strkey); } + } - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(zvpp), &hpos); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(zvpp), (void **) &name, &hpos) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(zvpp), &hpos)) { - phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", Z_STRLEN_PP(name), Z_STRVAL_PP(name)); + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zvp), name) { + if (Z_TYPE_P(name) == IS_STRING) { + phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", Z_STRLEN_P(name), Z_STRVAL_P(name)); } - } + } ZEND_HASH_FOREACH_END(); } zend_ini_deactivate(TSRMLS_C); - if (zend_hash_find(ht, "systemini", sizeof("systemini"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_ARRAY) { - HashPosition position; - zval **ini_entry; + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("systemini"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + zval *ini_entry; zend_ini_entry *original_ini; - zval key; - - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(zvpp), &position); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(zvpp), (void**) &ini_entry, &position) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(zvpp), &position)) { - zend_hash_get_current_key_zval_ex(Z_ARRVAL_PP(zvpp), &key, &position); - if (Z_TYPE(key) == IS_STRING) { - if (Z_TYPE_PP(ini_entry) == IS_STRING) { - if (zend_hash_find(EG(ini_directives), Z_STRVAL(key), Z_STRLEN(key) + 1, (void **) &original_ini) == SUCCESS) { - if (!original_ini->on_modify || original_ini->on_modify(original_ini, Z_STRVAL_PP(ini_entry), Z_STRLEN_PP(ini_entry), original_ini->mh_arg1, original_ini->mh_arg2, original_ini->mh_arg3, ZEND_INI_STAGE_ACTIVATE TSRMLS_CC) == SUCCESS) { - if (original_ini->modified && original_ini->orig_value != original_ini->value) { - efree(original_ini->value); - } - original_ini->value = Z_STRVAL_PP(ini_entry); - original_ini->value_length = Z_STRLEN_PP(ini_entry); - Z_TYPE_PP(ini_entry) = IS_NULL; /* don't free the value */ + zend_string *key; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zvp), key, ini_entry) { + if (key && Z_TYPE_P(ini_entry) == IS_STRING) { + if ((original_ini = zend_hash_find_ptr(EG(ini_directives), key))) { + if (!original_ini->on_modify || original_ini->on_modify(original_ini, Z_STR_P(ini_entry), original_ini->mh_arg1, original_ini->mh_arg2, original_ini->mh_arg3, ZEND_INI_STAGE_ACTIVATE TSRMLS_CC) == SUCCESS) { + if (original_ini->modified && original_ini->orig_value != original_ini->value) { + efree(original_ini->value); } + original_ini->value = Z_STR_P(ini_entry); + Z_ADDREF_P(ini_entry); /* don't free the string */ } } - efree(Z_STRVAL(key)); } - } + } ZEND_HASH_FOREACH_END(); } - if (zend_hash_find(ht, "userini", sizeof("userini"), (void **) &zvpp) == SUCCESS && Z_TYPE_PP(zvpp) == IS_ARRAY) { - HashPosition position; - zval **ini_entry; - zval key; - - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(zvpp), &position); - zend_hash_get_current_data_ex(Z_ARRVAL_PP(zvpp), (void**) &ini_entry, &position) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL_PP(zvpp), &position)) { - zend_hash_get_current_key_zval_ex(Z_ARRVAL_PP(zvpp), &key, &position); - if (Z_TYPE(key) == IS_STRING) { - if (Z_TYPE_PP(ini_entry) == IS_STRING) { - zend_alter_ini_entry_ex(Z_STRVAL(key), Z_STRLEN(key) + 1, Z_STRVAL_PP(ini_entry), Z_STRLEN_PP(ini_entry), ZEND_INI_PERDIR, ZEND_INI_STAGE_HTACCESS, 1 TSRMLS_CC); - } - efree(Z_STRVAL(key)); + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("userini"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + zval *ini_entry; + zend_string *key; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zvp), key, ini_entry) { + if (key && Z_TYPE_P(ini_entry) == IS_STRING) { + zend_alter_ini_entry_ex(key, Z_STR_P(ini_entry), ZEND_INI_PERDIR, ZEND_INI_STAGE_HTACCESS, 1 TSRMLS_CC); } - } + } ZEND_HASH_FOREACH_END(); } zval_dtor(&zv); diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index de6cddf5b3..7a39d3ee1a 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -30,6 +30,16 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +const phpdbg_command_t phpdbg_watch_commands[] = { + PHPDBG_COMMAND_D_EX(array, "create watchpoint on an array", 'a', watch_array, NULL, "s", 0), + PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, NULL, "s", 0), + PHPDBG_COMMAND_D_EX(recursive, "create recursive watchpoints", 'r', watch_recursive, NULL, "s", 0), + PHPDBG_END_COMMAND +}; + +//#define HT_FROM_WATCH(watch) (watch->type == WATCH_ON_OBJECT ? watch->addr.obj->handlers->get_properties(watch->parent_container.zv TSRMLS_CC) : watch->type == WATCH_ON_ARRAY ? &watch->addr.arr->ht : NULL) +#define HT_FROM_ZVP(zvp) (Z_TYPE_P(zvp) == IS_OBJECT ? Z_OBJPROP_P(zvp) : Z_TYPE_P(zvp) == IS_ARRAY ? Z_ARRVAL_P(zvp) : NULL) + typedef struct { void *page; size_t size; @@ -52,7 +62,7 @@ static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) { watch = result->ptr; /* check if that addr is in a mprotect()'ed memory area */ - if ((char *)phpdbg_get_page_boundary(watch->addr.ptr) > (char *)addr || (char *)phpdbg_get_page_boundary(watch->addr.ptr) + phpdbg_get_total_page_size(watch->addr.ptr, watch->size) < (char *)addr) { + if ((char *) phpdbg_get_page_boundary(watch->addr.ptr) > (char *) addr || (char *) phpdbg_get_page_boundary(watch->addr.ptr) + phpdbg_get_total_page_size(watch->addr.ptr, watch->size) < (char *) addr) { /* failure */ return NULL; } @@ -61,10 +71,8 @@ static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) { } static void phpdbg_change_watchpoint_access(phpdbg_watchpoint_t *watch, int access TSRMLS_DC) { - int m; - /* pagesize is assumed to be in the range of 2^x */ - m = mprotect(phpdbg_get_page_boundary(watch->addr.ptr), phpdbg_get_total_page_size(watch->addr.ptr, watch->size), access); + mprotect(phpdbg_get_page_boundary(watch->addr.ptr), phpdbg_get_total_page_size(watch->addr.ptr, watch->size), access); } static inline void phpdbg_activate_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { @@ -76,11 +84,11 @@ static inline void phpdbg_deactivate_watchpoint(phpdbg_watchpoint_t *watch TSRML } static inline void phpdbg_store_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong)watch->addr.ptr, watch); + phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr, watch); } static inline void phpdbg_remove_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong)watch->addr.ptr); + phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr); } void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch) { @@ -98,17 +106,95 @@ void phpdbg_create_ht_watchpoint(HashTable *ht, phpdbg_watchpoint_t *watch) { watch->type = WATCH_ON_HASHTABLE; } -void phpdbg_watch_HashTable_dtor(zval **ptr); +void phpdbg_watch_HashTable_dtor(zval *ptr); + +static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC); +static void phpdbg_delete_ht_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC); +static void phpdbg_delete_zval_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC); +static void phpdbg_delete_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC); + +/* TODO: Store all the possible watches the refcounted may refer to (for displaying & deleting by identifier) */ + +static phpdbg_watchpoint_t *phpdbg_create_refcounted_watchpoint(phpdbg_watchpoint_t *parent, zend_refcounted *ref) { + phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); + watch->flags = parent->flags; + watch->parent = parent; + phpdbg_create_addr_watchpoint(&ref->refcount, sizeof(uint32_t), watch); + watch->type = WATCH_ON_REFCOUNTED; + + return watch; +} + +static void phpdbg_add_watch_collision(phpdbg_watchpoint_t *watch TSRMLS_DC) { + phpdbg_watch_collision *cur; + if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref))) { + cur->num++; + if (watch->flags == PHPDBG_WATCH_RECURSIVE) { + cur->refs++; + } + } else { + phpdbg_watch_collision coll; + coll.num = 1; + coll.refs = watch->flags == PHPDBG_WATCH_RECURSIVE; + coll.watch = *watch; + zend_hash_init(&coll.watches, 8, NULL, NULL, 0); + cur = zend_hash_index_add_mem(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref, &coll, sizeof(phpdbg_watch_collision)); + phpdbg_store_watchpoint(&cur->watch TSRMLS_CC); + phpdbg_activate_watchpoint(&cur->watch TSRMLS_CC); + } + + zend_hash_str_add_ptr(&cur->watches, watch->parent->str, watch->parent->str_len, watch->parent); +} + +static void phpdbg_remove_watch_collision(zend_refcounted *ref TSRMLS_DC) { + phpdbg_watch_collision *cur; + if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) ref))) { + phpdbg_watchpoint_t *watch = cur->watch.parent; + + if (watch->flags == PHPDBG_WATCH_RECURSIVE && !--cur->refs) { + phpdbg_delete_watchpoints_recursive(watch TSRMLS_CC); + } + + zend_hash_str_del(&cur->watches, watch->str, watch->str_len); + + if (!--cur->num) { + phpdbg_deactivate_watchpoint(&cur->watch TSRMLS_CC); + phpdbg_remove_watchpoint(&cur->watch TSRMLS_CC); + + phpdbg_delete_watchpoint(watch TSRMLS_CC); + + zend_hash_index_del(&PHPDBG_G(watch_collisions), (zend_ulong) ref); + } + } +} static int phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { watch->flags |= PHPDBG_WATCH_SIMPLE; phpdbg_store_watchpoint(watch TSRMLS_CC); - zend_hash_add(&PHPDBG_G(watchpoints), watch->str, watch->str_len, &watch, sizeof(phpdbg_watchpoint_t *), NULL); + zend_hash_str_add_ptr(&PHPDBG_G(watchpoints), watch->str, watch->str_len, watch); + + if (watch->parent && watch->parent->type == WATCH_ON_ZVAL && Z_REFCOUNTED_P(watch->parent->addr.zv)) { + phpdbg_add_watch_collision(phpdbg_create_refcounted_watchpoint(watch, Z_COUNTED_P(watch->parent->addr.zv)) TSRMLS_CC); + } if (watch->type == WATCH_ON_ZVAL) { - phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong)watch->parent_container, watch->parent_container->pDestructor); - watch->parent_container->pDestructor = (dtor_func_t)phpdbg_watch_HashTable_dtor; + if (watch->parent_container) { + phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong) watch->parent_container, watch->parent_container->pDestructor); + watch->parent_container->pDestructor = (dtor_func_t) phpdbg_watch_HashTable_dtor; + } + + if (Z_ISREF_P(watch->addr.zv)) { + phpdbg_watchpoint_t *ref = emalloc(sizeof(phpdbg_watchpoint_t)); + ref->flags = watch->flags; + ref->str = watch->str; + ref->str_len = watch->str_len; + ref->parent = watch; + ref->parent_container = NULL; + phpdbg_create_zval_watchpoint(Z_REFVAL_P(watch->addr.zv), ref); + + phpdbg_create_watchpoint(ref TSRMLS_CC); + } } phpdbg_activate_watchpoint(watch TSRMLS_CC); @@ -116,29 +202,35 @@ static int phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { return SUCCESS; } -static int phpdbg_create_array_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - HashTable *ht; +static int phpdbg_create_array_watchpoint(phpdbg_watchpoint_t *zv_watch TSRMLS_DC) { + zval *zv = zv_watch->addr.zv; + phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); + HashTable *ht = HT_FROM_ZVP(zv); - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - default: - return FAILURE; + watch->parent = zv_watch; + + if (!ht) { + return FAILURE; } phpdbg_create_ht_watchpoint(ht, watch); phpdbg_create_watchpoint(watch TSRMLS_CC); + if (Z_TYPE_P(zv) == IS_ARRAY) { + watch->flags |= PHPDBG_WATCH_ARRAY; + } else { + watch->flags |= PHPDBG_WATCH_OBJECT; + } + + phpdbg_add_watch_collision(phpdbg_create_refcounted_watchpoint(watch, Z_COUNTED_P(zv)) TSRMLS_CC); + return SUCCESS; } static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { HashTable *ht; + zval *zvp = watch->addr.zv; if (watch->type != WATCH_ON_ZVAL) { return FAILURE; @@ -147,25 +239,18 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ watch->flags |= PHPDBG_WATCH_RECURSIVE; phpdbg_create_watchpoint(watch TSRMLS_CC); - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - default: - return SUCCESS; + ZVAL_DEREF(zvp); + + if (!(ht = HT_FROM_ZVP(zvp))) { + return SUCCESS; } { HashPosition position; - zval **zv; + zval *zv; zval key; - for (zend_hash_internal_pointer_reset_ex(ht, &position); - zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(ht, &position)) { + ZEND_HASH_FOREACH_VAL(ht, zv) { phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); new_watch->flags = PHPDBG_WATCH_RECURSIVE; @@ -174,19 +259,21 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ zend_hash_get_current_key_zval_ex(ht, &key, &position); if (Z_TYPE(key) == IS_STRING) { - new_watch->name_in_parent = zend_strndup(Z_STRVAL(key), Z_STRLEN(key)); + new_watch->name_in_parent = estrndup(Z_STRVAL(key), Z_STRLEN(key)); new_watch->name_in_parent_len = Z_STRLEN(key); } else { - new_watch->name_in_parent = NULL; - new_watch->name_in_parent_len = asprintf(&new_watch->name_in_parent, "%ld", Z_LVAL(key)); + new_watch->name_in_parent_len = spprintf(&new_watch->name_in_parent, 0, "%lld", Z_LVAL(key)); } - new_watch->str = NULL; - new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%s%s", (int) watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY ? "[" : "->", phpdbg_get_property_key(new_watch->name_in_parent), Z_TYPE_P(watch->addr.zv) == IS_ARRAY ? "]" : ""); + new_watch->str_len = spprintf(&new_watch->str, 0, "%.*s%s%s%s", (int) watch->str_len, watch->str, Z_TYPE_P(zvp) == IS_ARRAY ? "[" : "->", phpdbg_get_property_key(new_watch->name_in_parent), Z_TYPE_P(zvp) == IS_ARRAY ? "]" : ""); + + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } - phpdbg_create_zval_watchpoint(*zv, new_watch); + phpdbg_create_zval_watchpoint(zv, new_watch); phpdbg_create_recursive_watchpoint(new_watch TSRMLS_CC); - } + } ZEND_HASH_FOREACH_END(); } { @@ -194,12 +281,18 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ new_watch->parent = watch; new_watch->parent_container = watch->parent_container; - new_watch->name_in_parent = zend_strndup(watch->name_in_parent, watch->name_in_parent_len); + new_watch->name_in_parent = estrndup(watch->name_in_parent, watch->name_in_parent_len); new_watch->name_in_parent_len = watch->name_in_parent_len; new_watch->str = NULL; - new_watch->str_len = asprintf(&new_watch->str, "%.*s[]", (int)watch->str_len, watch->str); + new_watch->str_len = spprintf(&new_watch->str, 0, "%.*s[]", (int) watch->str_len, watch->str); new_watch->flags = PHPDBG_WATCH_RECURSIVE; + if (Z_TYPE_P(zvp) == IS_ARRAY) { + new_watch->flags |= PHPDBG_WATCH_ARRAY; + } else { + new_watch->flags |= PHPDBG_WATCH_OBJECT; + } + phpdbg_create_ht_watchpoint(ht, new_watch); phpdbg_create_watchpoint(new_watch TSRMLS_CC); } @@ -208,52 +301,58 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ } static int phpdbg_delete_watchpoint_recursive(phpdbg_watchpoint_t *watch, zend_bool user_request TSRMLS_DC) { - if (watch->type == WATCH_ON_HASHTABLE || (watch->type == WATCH_ON_ZVAL && (Z_TYPE_P(watch->addr.zv) == IS_ARRAY || Z_TYPE_P(watch->addr.zv) == IS_OBJECT))) { + if (watch->type == WATCH_ON_HASHTABLE) { HashTable *ht; phpdbg_btree_result *result; if (watch->type == WATCH_ON_HASHTABLE && user_request) { - HashPosition position; - zval **zv; - zval key; - char *str; - int str_len; - phpdbg_watchpoint_t **watchpoint; - - ht = watch->addr.ht; - - for (zend_hash_internal_pointer_reset_ex(ht, &position); - zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(ht, &position)) { - zend_hash_get_current_key_zval_ex(ht, &key, &position); - str = NULL; - if (Z_TYPE(key) == IS_STRING) { - str_len = asprintf(&str, "%.*s%s%s%s", (int) watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY ? "[" : "->", phpdbg_get_property_key(Z_STRVAL(key)), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY ? "]" : ""); - } else { - str_len = asprintf(&str, "%.*s%s%li%s", (int) watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY ? "[" : "->", Z_LVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY ? "]" : ""); - } - - if (zend_hash_find(&PHPDBG_G(watchpoints), str, str_len, (void **) &watchpoint) == SUCCESS) { - phpdbg_delete_watchpoint_recursive(*watchpoint, 1 TSRMLS_CC); - } - } + phpdbg_delete_ht_watchpoints_recursive(watch TSRMLS_CC); } else { - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - } + ht = HT_FROM_ZVP(watch->addr.zv); if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) ht))) { phpdbg_delete_watchpoint_recursive((phpdbg_watchpoint_t *) result->ptr, user_request TSRMLS_CC); } } + } else if (watch->type == WATCH_ON_ZVAL) { + phpdbg_delete_zval_watchpoints_recursive(watch TSRMLS_CC); } - return zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + return zend_hash_str_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); +} + +static void phpdbg_delete_ht_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC) { + zend_string *strkey; + zend_long numkey; + char *str; + int str_len; + phpdbg_watchpoint_t *watchpoint; + + ZEND_HASH_FOREACH_KEY(watch->addr.ht, numkey, strkey) { + if (strkey) { + str_len = asprintf(&str, "%.*s%s%s%s", (int) watch->str_len, watch->str, (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", phpdbg_get_property_key(strkey->val), (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : ""); + } else { + str_len = asprintf(&str, "%.*s%s%lli%s", (int) watch->str_len, watch->str, (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", numkey, (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : ""); + } + + if ((watchpoint = zend_hash_str_find_ptr(&PHPDBG_G(watchpoints), str, str_len))) { + phpdbg_delete_watchpoint_recursive(watchpoint, 1 TSRMLS_CC); + } + } ZEND_HASH_FOREACH_END(); +} + +static void phpdbg_delete_zval_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC) { + if (Z_REFCOUNTED_P(watch->addr.zv)) { + phpdbg_remove_watch_collision(Z_COUNTED_P(watch->addr.zv) TSRMLS_CC); + } +} + +static void phpdbg_delete_watchpoints_recursive(phpdbg_watchpoint_t *watch TSRMLS_DC) { + if (watch->type == WATCH_ON_ZVAL) { + phpdbg_delete_zval_watchpoints_recursive(watch TSRMLS_CC); + } else if (watch->type == WATCH_ON_HASHTABLE) { + phpdbg_delete_ht_watchpoints_recursive(watch TSRMLS_CC); + } } static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { @@ -261,7 +360,7 @@ static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { phpdbg_watchpoint_t *watch; phpdbg_btree_result *result; - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)tmp_watch->addr.ptr)) == NULL) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) tmp_watch->addr.ptr)) == NULL) { return FAILURE; } @@ -270,7 +369,7 @@ static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { if (watch->flags & PHPDBG_WATCH_RECURSIVE) { ret = phpdbg_delete_watchpoint_recursive(watch, 1 TSRMLS_CC); } else { - ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + ret = zend_hash_str_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); } efree(tmp_watch->str); @@ -280,7 +379,7 @@ static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { return ret; } -static int phpdbg_watchpoint_parse_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) { +static int phpdbg_watchpoint_parse_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) { int ret; phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); watch->flags = 0; @@ -289,7 +388,7 @@ static int phpdbg_watchpoint_parse_wrapper(char *name, size_t len, char *keyname watch->name_in_parent = keyname; watch->name_in_parent_len = keylen; watch->parent_container = parent; - phpdbg_create_zval_watchpoint(*zv, watch); + phpdbg_create_zval_watchpoint(zv, watch); ret = callback(watch TSRMLS_CC); @@ -307,15 +406,15 @@ PHPDBG_API int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable } static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) { - if (EG(This) && len >= 5 && !memcmp("$this", input, 5)) { - zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL); + if (EG(scope) && len >= 5 && !memcmp("$this", input, 5)) { + zend_hash_str_add(&EG(current_execute_data)->symbol_table->ht, ZEND_STRL("this"), &EG(current_execute_data)->This); } - if (zend_is_auto_global(input, len TSRMLS_CC) && phpdbg_watchpoint_parse_input(input, len, &EG(symbol_table), 0, callback, 1 TSRMLS_CC) != FAILURE) { + if (phpdbg_is_auto_global(input, len TSRMLS_CC) && phpdbg_watchpoint_parse_input(input, len, &EG(symbol_table).ht, 0, callback, 1 TSRMLS_CC) != FAILURE) { return SUCCESS; } - return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, callback, 0 TSRMLS_CC); + return phpdbg_watchpoint_parse_input(input, len, &EG(current_execute_data)->symbol_table->ht, 0, callback, 0 TSRMLS_CC); } PHPDBG_WATCH(delete) /* {{{ */ @@ -373,23 +472,23 @@ PHPDBG_WATCH(array) /* {{{ */ return SUCCESS; } /* }}} */ -void phpdbg_watch_HashTable_dtor(zval **zv) { +void phpdbg_watch_HashTable_dtor(zval *zv) { phpdbg_btree_result *result; TSRMLS_FETCH(); zval_ptr_dtor_wrapper(zv); - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)*zv))) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) zv))) { phpdbg_watchpoint_t *watch = result->ptr; PHPDBG_G(watchpoint_hit) = 1; - phpdbg_notice("watchdelete", "variable=\"%.*s\" recursive=\"%s\"", "%.*s was removed, removing watchpoint%s", (int)watch->str_len, watch->str, watch->flags & PHPDBG_WATCH_RECURSIVE ? " recursively" : ""); + phpdbg_notice("watchdelete", "variable=\"%.*s\" recursive=\"%s\"", "%.*s was removed, removing watchpoint%s", (int) watch->str_len, watch->str, (watch->flags & PHPDBG_WATCH_RECURSIVE) ? " recursively" : ""); if (watch->flags & PHPDBG_WATCH_RECURSIVE) { phpdbg_delete_watchpoint_recursive(watch, 0 TSRMLS_CC); } else { - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + zend_hash_str_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); } } } @@ -454,8 +553,8 @@ void phpdbg_watchpoints_clean(TSRMLS_D) { zend_hash_clean(&PHPDBG_G(watchpoints)); } -static void phpdbg_watch_dtor(void *pDest) { - phpdbg_watchpoint_t *watch = *(phpdbg_watchpoint_t **)pDest; +static void phpdbg_watch_dtor(zval *pDest) { + phpdbg_watchpoint_t *watch = (phpdbg_watchpoint_t *) Z_PTR_P(pDest); TSRMLS_FETCH(); phpdbg_deactivate_watchpoint(watch TSRMLS_CC); @@ -463,18 +562,17 @@ static void phpdbg_watch_dtor(void *pDest) { efree(watch->str); efree(watch->name_in_parent); - efree(watch); } static void phpdbg_watch_mem_dtor(void *llist_data) { - phpdbg_watch_memdump *dump = *(phpdbg_watch_memdump **)llist_data; + phpdbg_watch_memdump *dump = *(phpdbg_watch_memdump **) llist_data; /* Disble writing again */ if (dump->reenable_writing) { mprotect(dump->page, dump->size, PROT_READ); } - free(*(void **)llist_data); + free(*(void **) llist_data); } void phpdbg_setup_watchpoints(TSRMLS_D) { @@ -491,60 +589,79 @@ void phpdbg_setup_watchpoints(TSRMLS_D) { zend_llist_init(&PHPDBG_G(watchlist_mem), sizeof(void *), phpdbg_watch_mem_dtor, 1); phpdbg_btree_init(&PHPDBG_G(watchpoint_tree), sizeof(void *) * 8); phpdbg_btree_init(&PHPDBG_G(watch_HashTables), sizeof(void *) * 8); - zend_hash_init(&PHPDBG_G(watchpoints), 8, NULL, phpdbg_watch_dtor, 0 ZEND_FILE_LINE_CC); + zend_hash_init(&PHPDBG_G(watchpoints), 8, NULL, phpdbg_watch_dtor, 0); + zend_hash_init(&PHPDBG_G(watch_collisions), 8, NULL, NULL, 0); } static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) { /* fetch all changes between dump->page and dump->page + dump->size */ phpdbg_btree_position pos = phpdbg_btree_find_between(&PHPDBG_G(watchpoint_tree), (zend_ulong) dump->page, (zend_ulong) dump->page + dump->size); - phpdbg_btree_result *result, *htresult; + phpdbg_btree_result *result; int elementDiff; void *curTest; dump->reenable_writing = 0; while ((result = phpdbg_btree_next(&pos))) { - phpdbg_watchpoint_t *watch = result->ptr, *htwatch; - void *oldPtr = (char *)&dump->data + ((size_t)watch->addr.ptr - (size_t)dump->page); + phpdbg_watchpoint_t *watch = result->ptr; + void *oldPtr = (char *) &dump->data + ((size_t) watch->addr.ptr - (size_t) dump->page); char reenable = 1; + int removed = 0; - if ((size_t)watch->addr.ptr < (size_t)dump->page || (size_t)watch->addr.ptr + watch->size > (size_t) dump->page + dump->size) { + if ((size_t) watch->addr.ptr < (size_t) dump->page || (size_t) watch->addr.ptr + watch->size > (size_t) dump->page + dump->size) { continue; } /* Test if the zval was separated and if necessary move the watchpoint */ - if (zend_hash_find(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len + 1, &curTest) == SUCCESS) { - if (watch->type == WATCH_ON_HASHTABLE) { - switch (Z_TYPE_PP((zval **)curTest)) { - case IS_ARRAY: - curTest = (void *)Z_ARRVAL_PP((zval **)curTest); - break; - case IS_OBJECT: - curTest = (void *)Z_OBJPROP_PP((zval **)curTest); - break; + if ((watch->type == WATCH_ON_HASHTABLE || watch->type == WATCH_ON_ZVAL) && watch->parent_container) { + if ((curTest = zend_hash_str_find(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len))) { + while (Z_TYPE_P((zval *) curTest) == IS_INDIRECT) { + curTest = Z_INDIRECT_P((zval *) curTest); } - } else { - curTest = *(void **)curTest; - } - if (curTest != watch->addr.ptr) { - phpdbg_deactivate_watchpoint(watch TSRMLS_CC); - phpdbg_remove_watchpoint(watch TSRMLS_CC); - watch->addr.ptr = curTest; - phpdbg_store_watchpoint(watch TSRMLS_CC); - phpdbg_activate_watchpoint(watch TSRMLS_CC); + if (watch->type == WATCH_ON_HASHTABLE) { + switch (Z_TYPE_P((zval *) curTest)) { + case IS_ARRAY: + curTest = (void *) Z_ARRVAL_P((zval *) curTest); + break; + case IS_OBJECT: + curTest = (void *) Z_OBJPROP_P((zval *) curTest); + break; + } + } - reenable = 0; + if (curTest != watch->addr.ptr) { + phpdbg_deactivate_watchpoint(watch TSRMLS_CC); + phpdbg_remove_watchpoint(watch TSRMLS_CC); + watch->addr.ptr = curTest; + phpdbg_store_watchpoint(watch TSRMLS_CC); + phpdbg_activate_watchpoint(watch TSRMLS_CC); + + reenable = 0; + } + } else { + removed = 1; } } /* Show to the user what changed and delete watchpoint upon removal */ if (memcmp(oldPtr, watch->addr.ptr, watch->size) != SUCCESS) { - zend_bool do_break = PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS || (watch->type == WATCH_ON_ZVAL && memcmp(oldPtr, watch->addr.zv, sizeof(zvalue_value))) || (watch->type == WATCH_ON_HASHTABLE -#if ZEND_DEBUG - && !watch->addr.ht->inconsistent -#endif - && zend_hash_num_elements((HashTable *)oldPtr) != zend_hash_num_elements(watch->addr.ht)); + zend_bool do_break = 0; + + switch (watch->type) { + case WATCH_ON_ZVAL: + do_break = memcmp(oldPtr, watch->addr.zv, sizeof(zend_value) + sizeof(uint32_t) /* value + typeinfo */); + break; + case WATCH_ON_HASHTABLE: + do_break = zend_hash_num_elements((HashTable *) oldPtr) != zend_hash_num_elements(watch->addr.ht); + break; + case WATCH_ON_REFCOUNTED: + if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS) { + do_break = memcmp(oldPtr, watch->addr.ref, sizeof(uint32_t) /* no zend_refcounted metadata info */); + } + break; + } + if (do_break) { PHPDBG_G(watchpoint_hit) = 1; @@ -555,12 +672,10 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) { switch (watch->type) { case WATCH_ON_ZVAL: { - int removed = ((zval *)oldPtr)->refcount__gc != watch->addr.zv->refcount__gc && !zend_symtable_exists(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len + 1); - int show_value = memcmp(oldPtr, watch->addr.zv, sizeof(zvalue_value)); - int show_ref = ((zval *)oldPtr)->refcount__gc != watch->addr.zv->refcount__gc || ((zval *)oldPtr)->is_ref__gc != watch->addr.zv->is_ref__gc; + int show_value = memcmp(oldPtr, watch->addr.zv, sizeof(zval) - sizeof(uint32_t) /* no metadata info */); if (removed || show_value) { - if ((Z_TYPE_P((zval *)oldPtr) == IS_ARRAY || Z_TYPE_P((zval *)oldPtr) == IS_OBJECT) && removed) { + if (removed && (Z_TYPE_P((zval *) oldPtr) == IS_ARRAY || Z_TYPE_P((zval *) oldPtr) == IS_OBJECT)) { phpdbg_writeln("watchvalue", "type=\"old\" inaccessible=\"inaccessible\"", "Old value inaccessible, array or object (HashTable) already destroyed"); } else { phpdbg_out("Old value: "); @@ -570,21 +685,17 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) { phpdbg_out("\n"); } } - if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS && (removed || show_ref)) { - phpdbg_write("watchrefcount", "type=\"old\" refcount=\"%d\" isref=\"%d\"", "Old refcount: %d; Old is_ref: %d", ((zval *) oldPtr)->refcount__gc, ((zval *) oldPtr)->is_ref__gc); - } /* check if zval was removed */ if (removed) { phpdbg_notice("watchdelete", "variable=\"%.*s\"", "Watchpoint %.*s was unset, removing watchpoint", (int) watch->str_len, watch->str); - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + zend_hash_str_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); reenable = 0; - if (Z_TYPE_P((zval *) oldPtr) == IS_ARRAY || Z_TYPE_P((zval *) oldPtr) == IS_OBJECT) { - goto remove_ht_watch; + if (Z_REFCOUNTED_P((zval *) oldPtr)) { + phpdbg_remove_watch_collision(Z_COUNTED_P((zval *) oldPtr) TSRMLS_CC); } - break; } @@ -595,33 +706,27 @@ static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) { phpdbg_xml("</watchvalue>"); phpdbg_out("\n"); } - if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS && show_ref) { - phpdbg_writeln("watchrefcount", "type=\"new\" refcount=\"%d\" isref=\"%d\"", "New refcount: %d; New is_ref: %d", watch->addr.zv->refcount__gc, watch->addr.zv->is_ref__gc); - } - if ((Z_TYPE_P(watch->addr.zv) == IS_ARRAY && Z_ARRVAL_P(watch->addr.zv) != Z_ARRVAL_P((zval *) oldPtr)) || (Z_TYPE_P(watch->addr.zv) != IS_OBJECT && Z_OBJ_HANDLE_P(watch->addr.zv) == Z_OBJ_HANDLE_P((zval *) oldPtr))) { - /* add new watchpoints if necessary */ - if (watch->flags & PHPDBG_WATCH_RECURSIVE) { - phpdbg_create_recursive_watchpoint(watch TSRMLS_CC); + /* add new watchpoints if necessary */ + if (Z_PTR_P(watch->addr.zv) != Z_PTR_P((zval *) oldPtr)) { + if (Z_REFCOUNTED_P((zval *) oldPtr)) { + phpdbg_remove_watch_collision(Z_COUNTED_P((zval *) oldPtr) TSRMLS_CC); + } + if (Z_REFCOUNTED_P(watch->addr.zv)) { + if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS) { + phpdbg_writeln("watchrefcount", "type=\"new\" refcount=\"%d\"", "New refcount: %d", Z_COUNTED_P(watch->addr.zv)->refcount); + } + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + phpdbg_create_recursive_watchpoint(watch TSRMLS_CC); + } } - } - - if ((Z_TYPE_P((zval *) oldPtr) != IS_ARRAY || Z_ARRVAL_P(watch->addr.zv) == Z_ARRVAL_P((zval *) oldPtr)) && (Z_TYPE_P((zval *)oldPtr) != IS_OBJECT || Z_OBJ_HANDLE_P(watch->addr.zv) == Z_OBJ_HANDLE_P((zval *) oldPtr))) { - break; - } - -remove_ht_watch: - if ((htresult = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)Z_ARRVAL_P((zval *)oldPtr)))) { - htwatch = htresult->ptr; - zend_hash_del(&PHPDBG_G(watchpoints), htwatch->str, htwatch->str_len); } break; } case WATCH_ON_HASHTABLE: - -#if ZEND_DEBUG - if (watch->addr.ht->inconsistent) { +#if 0 && ZEND_DEBUG + if (watch->addr.arr->ht->inconsistent) { phpdbg_notice("watchdelete", "variable=\"%.*s\"", "Watchpoint %.*s was unset, removing watchpoint", (int) watch->str_len, watch->str); zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); @@ -630,7 +735,6 @@ remove_ht_watch: break; } #endif - elementDiff = zend_hash_num_elements((HashTable *) oldPtr) - zend_hash_num_elements(watch->addr.ht); if (elementDiff) { if (elementDiff > 0) { @@ -644,10 +748,21 @@ remove_ht_watch: } } } - if (((HashTable *) oldPtr)->pInternalPointer != watch->addr.ht->pInternalPointer) { + if (watch->addr.ht->nInternalPointer != ((HashTable *) oldPtr)->nInternalPointer) { phpdbg_writeln("watcharrayptr", "", "Internal pointer of array was changed"); } break; + case WATCH_ON_REFCOUNTED: { + if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS) { + phpdbg_writeln("watchrefcount", "type=\"old\" refcount=\"%d\"", "Old refcount: %d", ((zend_refcounted *) oldPtr)->refcount); + + if (!removed) { + phpdbg_writeln("watchrefcount", "type=\"old\" refcount=\"%d\"", "Old refcount: %d", ((zend_refcounted *) oldPtr)->refcount); + } + } + + break; + } } if (do_break) { @@ -683,16 +798,13 @@ int phpdbg_print_changed_zvals(TSRMLS_D) { } void phpdbg_list_watchpoints(TSRMLS_D) { - HashPosition position; - phpdbg_watchpoint_t **watch; + phpdbg_watchpoint_t *watch; phpdbg_xml("<watchlist %r>"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(watchpoints), &position); - zend_hash_get_current_data_ex(&PHPDBG_G(watchpoints), (void**) &watch, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(watchpoints), &position)) { - phpdbg_writeln("watchvariable", "variable=\"%.*s\" on=\"%s\" type=\"%s\"", "%.*s (%s, %s)", (int) (*watch)->str_len, (*watch)->str, (*watch)->type == WATCH_ON_HASHTABLE ? "array" : "variable", (*watch)->flags == PHPDBG_WATCH_RECURSIVE ? "recursive" : "simple"); - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(watchpoints), watch) { + phpdbg_writeln("watchvariable", "variable=\"%.*s\" on=\"%s\" type=\"%s\"", "%.*s (%s, %s)", (int) watch->str_len, watch->str, watch->type == WATCH_ON_HASHTABLE ? "array" : watch->type == WATCH_ON_REFCOUNTED ? "refcount" : "variable", watch->flags == PHPDBG_WATCH_RECURSIVE ? "recursive" : "simple"); + } ZEND_HASH_FOREACH_END(); phpdbg_xml("</watchlist>"); } @@ -706,8 +818,11 @@ void phpdbg_watch_efree(void *ptr) { if (result) { phpdbg_watchpoint_t *watch = result->ptr; - if ((size_t)watch->addr.ptr + watch->size > (size_t) ptr) { - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + if ((size_t) watch->addr.ptr + watch->size > (size_t) ptr) { + if (watch->type == WATCH_ON_ZVAL) { + phpdbg_remove_watch_collision(Z_COUNTED_P(watch->addr.zv) TSRMLS_CC); + } + zend_hash_str_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); } } diff --git a/sapi/phpdbg/phpdbg_watch.h b/sapi/phpdbg/phpdbg_watch.h index 5c0079057c..35cab10dc1 100644 --- a/sapi/phpdbg/phpdbg_watch.h +++ b/sapi/phpdbg/phpdbg_watch.h @@ -25,7 +25,7 @@ #include "phpdbg_cmd.h" #ifdef _WIN32 -# include "phpdbg_win.h" +# include "phpdbg_win.h" #endif #define PHPDBG_WATCH(name) PHPDBG_COMMAND(watch_##name) @@ -37,47 +37,49 @@ PHPDBG_WATCH(array); PHPDBG_WATCH(delete); PHPDBG_WATCH(recursive); -/** - * Commands - */ - -static const phpdbg_command_t phpdbg_watch_commands[] = { - PHPDBG_COMMAND_D_EX(array, "create watchpoint on an array", 'a', watch_array, NULL, "s", 0), - PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, NULL, "s", 0), - PHPDBG_COMMAND_D_EX(recursive, "create recursive watchpoints", 'r', watch_recursive, NULL, "s", 0), - PHPDBG_END_COMMAND -}; +extern const phpdbg_command_t phpdbg_watch_commands[]; /* Watchpoint functions/typedefs */ typedef enum { WATCH_ON_ZVAL, WATCH_ON_HASHTABLE, + WATCH_ON_REFCOUNTED, } phpdbg_watchtype; -#define PHPDBG_WATCH_SIMPLE 0x0 -#define PHPDBG_WATCH_RECURSIVE 0x1 +#define PHPDBG_WATCH_SIMPLE 0x0 +#define PHPDBG_WATCH_RECURSIVE 0x1 +#define PHPDBG_WATCH_ARRAY 0x2 +#define PHPDBG_WATCH_OBJECT 0x4 typedef struct _phpdbg_watchpoint_t phpdbg_watchpoint_t; struct _phpdbg_watchpoint_t { - phpdbg_watchpoint_t *parent; - HashTable *parent_container; - char *name_in_parent; - size_t name_in_parent_len; - char *str; - size_t str_len; union { zval *zv; HashTable *ht; + zend_refcounted *ref; void *ptr; } addr; size_t size; phpdbg_watchtype type; char flags; + phpdbg_watchpoint_t *parent; + HashTable *parent_container; + char *name_in_parent; + size_t name_in_parent_len; + char *str; + size_t str_len; }; +typedef struct { + phpdbg_watchpoint_t watch; + unsigned int num; + unsigned int refs; + HashTable watches; +} phpdbg_watch_collision; + void phpdbg_setup_watchpoints(TSRMLS_D); #ifndef _WIN32 @@ -102,11 +104,11 @@ void phpdbg_watch_efree(void *ptr); static long phpdbg_pagesize; static zend_always_inline void *phpdbg_get_page_boundary(void *addr) { - return (void *)((size_t)addr & ~(phpdbg_pagesize - 1)); + return (void *) ((size_t) addr & ~(phpdbg_pagesize - 1)); } static zend_always_inline size_t phpdbg_get_total_page_size(void *addr, size_t size) { - return (size_t)phpdbg_get_page_boundary((void *)((size_t)addr + size - 1)) - (size_t)phpdbg_get_page_boundary(addr) + phpdbg_pagesize; + return (size_t) phpdbg_get_page_boundary((void *) ((size_t) addr + size - 1)) - (size_t) phpdbg_get_page_boundary(addr) + phpdbg_pagesize; } #endif diff --git a/sapi/phpdbg/phpdbg_webdata_transfer.c b/sapi/phpdbg/phpdbg_webdata_transfer.c index e7438ea01a..2f18b9d082 100644 --- a/sapi/phpdbg/phpdbg_webdata_transfer.c +++ b/sapi/phpdbg/phpdbg_webdata_transfer.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2014 The PHP Group | +----------------------------------------------------------------------+ @@ -19,93 +19,87 @@ #include "phpdbg_webdata_transfer.h" #include "ext/json/php_json.h" +static int phpdbg_is_auto_global(char *name, int len TSRMLS_DC) { + int ret; + zend_string *str = zend_string_init(name, len, 0); + ret = zend_is_auto_global(str TSRMLS_CC); + efree(str); + return ret; +} + PHPDBG_API void phpdbg_webdata_compress(char **msg, int *len TSRMLS_DC) { #ifdef HAVE_JSON smart_str buf = {0}; zval array; HashTable *ht; - /* I really need to change that to an array of zvals... */ - zval zv1 = {{0}}, *zvp1 = &zv1; - zval zv2 = {{0}}, *zvp2 = &zv2; - zval zv3 = {{0}}, *zvp3 = &zv3; - zval zv4 = {{0}}, *zvp4 = &zv4; - zval zv5 = {{0}}, *zvp5 = &zv5; - zval zv6 = {{0}}, *zvp6 = &zv6; - zval zv7 = {{0}}, *zvp7 = &zv7; - zval zv8 = {{0}}, *zvp8 = &zv8; + zval zv[9] = {{{0}}}; array_init(&array); ht = Z_ARRVAL(array); /* fetch superglobals */ { - zend_is_auto_global(ZEND_STRL("GLOBALS") TSRMLS_CC); + phpdbg_is_auto_global(ZEND_STRL("GLOBALS") TSRMLS_CC); /* might be JIT */ - zend_is_auto_global(ZEND_STRL("_ENV") TSRMLS_CC); - zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC); - zend_is_auto_global(ZEND_STRL("_REQUEST") TSRMLS_CC); - array_init(&zv1); - zend_hash_copy(Z_ARRVAL(zv1), &EG(symbol_table), NULL, (void *) NULL, sizeof(zval *)); - Z_ARRVAL(zv1)->pDestructor = NULL; /* we're operating on a copy! Don't double free zvals */ - zend_hash_del(Z_ARRVAL(zv1), "GLOBALS", sizeof("GLOBALS")); /* do not use the reference to itself in json */ - zend_hash_add(ht, "GLOBALS", sizeof("GLOBALS"), &zvp1, sizeof(zval *), NULL); + phpdbg_is_auto_global(ZEND_STRL("_ENV") TSRMLS_CC); + phpdbg_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC); + phpdbg_is_auto_global(ZEND_STRL("_REQUEST") TSRMLS_CC); + array_init(&zv[1]); + zend_hash_copy(Z_ARRVAL(zv[1]), &EG(symbol_table).ht, NULL); + Z_ARRVAL(zv[1])->pDestructor = NULL; /* we're operating on a copy! Don't double free zvals */ + zend_hash_str_del(Z_ARRVAL(zv[1]), ZEND_STRL("GLOBALS")); /* do not use the reference to itself in json */ + zend_hash_str_add(ht, ZEND_STRL("GLOBALS"), &zv[1]); } /* save php://input */ { php_stream *stream; - int len; - char *contents; + zend_string *str; stream = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); - if ((len = php_stream_copy_to_mem(stream, &contents, PHP_STREAM_COPY_ALL, 0)) > 0) { - ZVAL_STRINGL(&zv2, contents, len, 0); + if ((str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0))) { + ZVAL_STR(&zv[2], str); } else { - ZVAL_EMPTY_STRING(&zv2); + ZVAL_EMPTY_STRING(&zv[2]); } - Z_SET_REFCOUNT(zv2, 2); - zend_hash_add(ht, "input", sizeof("input"), &zvp2, sizeof(zval *), NULL); + Z_SET_REFCOUNT(zv[2], 1); + zend_hash_str_add(ht, ZEND_STRL("input"), &zv[2]); } /* change sapi name */ { if (sapi_module.name) { - ZVAL_STRING(&zv6, sapi_module.name, 0); + ZVAL_STRING(&zv[6], sapi_module.name); } else { - Z_TYPE(zv6) = IS_NULL; + Z_TYPE_INFO(zv[6]) = IS_NULL; } - Z_SET_REFCOUNT(zv6, 2); - zend_hash_add(ht, "sapi_name", sizeof("sapi_name"), &zvp6, sizeof(zval *), NULL); + zend_hash_str_add(ht, ZEND_STRL("sapi_name"), &zv[6]); + Z_SET_REFCOUNT(zv[6], 1); } /* handle modules / extensions */ { - HashPosition position; zend_module_entry *module; zend_extension *extension; zend_llist_position pos; - array_init(&zv7); - for (zend_hash_internal_pointer_reset_ex(&module_registry, &position); - zend_hash_get_current_data_ex(&module_registry, (void**) &module, &position) == SUCCESS; - zend_hash_move_forward_ex(&module_registry, &position)) { - zval **value = emalloc(sizeof(zval *)); - ALLOC_ZVAL(*value); - ZVAL_STRING(*value, module->name, 1); - zend_hash_next_index_insert(Z_ARRVAL(zv7), value, sizeof(zval *), NULL); - } - zend_hash_add(ht, "modules", sizeof("modules"), &zvp7, sizeof(zval *), NULL); + array_init(&zv[7]); + ZEND_HASH_FOREACH_PTR(&module_registry, module) { + zval *value = ecalloc(sizeof(zval), 1); + ZVAL_STRING(value, module->name); + zend_hash_next_index_insert(Z_ARRVAL(zv[7]), value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("modules"), &zv[7]); - array_init(&zv8); + array_init(&zv[8]); extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos); while (extension) { - zval **value = emalloc(sizeof(zval *)); - ALLOC_ZVAL(*value); - ZVAL_STRING(*value, extension->name, 1); - zend_hash_next_index_insert(Z_ARRVAL(zv8), value, sizeof(zval *), NULL); + zval *value = ecalloc(sizeof(zval), 1); + ZVAL_STRING(value, extension->name); + zend_hash_next_index_insert(Z_ARRVAL(zv[8]), value); extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos); } - zend_hash_add(ht, "extensions", sizeof("extensions"), &zvp8, sizeof(zval *), NULL); + zend_hash_str_add(ht, ZEND_STRL("extensions"), &zv[8]); } /* switch cwd */ @@ -119,67 +113,58 @@ PHPDBG_API void phpdbg_webdata_compress(char **msg, int *len TSRMLS_DC) { ret = VCWD_GETWD(path); #endif if (ret) { - ZVAL_STRING(&zv5, path, 1); - Z_SET_REFCOUNT(zv5, 1); - zend_hash_add(ht, "cwd", sizeof("cwd"), &zvp5, sizeof(zval *), NULL); + ZVAL_STRING(&zv[5], path); + Z_SET_REFCOUNT(zv[5], 1); + zend_hash_str_add(ht, ZEND_STRL("cwd"), &zv[5]); } } /* get system ini entries */ { - HashPosition position; zend_ini_entry *ini_entry; - array_init(&zv3); - for (zend_hash_internal_pointer_reset_ex(EG(ini_directives), &position); - zend_hash_get_current_data_ex(EG(ini_directives), (void**) &ini_entry, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(ini_directives), &position)) { - zval **value = emalloc(sizeof(zval *)); + array_init(&zv[3]); + ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + zval *value = ecalloc(sizeof(zval), 1); if (ini_entry->modified) { if (!ini_entry->orig_value) { efree(value); continue; } - ALLOC_ZVAL(*value); - ZVAL_STRINGL(*value, ini_entry->orig_value, ini_entry->orig_value_length, 1); + ZVAL_STR(value, ini_entry->orig_value); } else { if (!ini_entry->value) { efree(value); continue; } - ALLOC_ZVAL(*value); - ZVAL_STRINGL(*value, ini_entry->value, ini_entry->value_length, 1); + ZVAL_STR(value, ini_entry->value); } - zend_hash_add(Z_ARRVAL(zv3), ini_entry->name, ini_entry->name_length, value, sizeof(zval *), NULL); - } - zend_hash_add(ht, "systemini", sizeof("systemini"), &zvp3, sizeof(zval *), NULL); + zend_hash_add(Z_ARRVAL(zv[3]), ini_entry->name, value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("systemini"), &zv[3]); } /* get perdir ini entries */ if (EG(modified_ini_directives)) { - HashPosition position; zend_ini_entry *ini_entry; - array_init(&zv4); - for (zend_hash_internal_pointer_reset_ex(EG(modified_ini_directives), &position); - zend_hash_get_current_data_ex(EG(modified_ini_directives), (void**) &ini_entry, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(modified_ini_directives), &position)) { - zval **value = emalloc(sizeof(zval *)); + array_init(&zv[4]); + ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + zval *value = ecalloc(sizeof(zval), 1); if (!ini_entry->value) { efree(value); continue; } - ALLOC_ZVAL(*value); - ZVAL_STRINGL(*value, ini_entry->value, ini_entry->value_length, 1); - zend_hash_add(Z_ARRVAL(zv4), ini_entry->name, ini_entry->name_length, value, sizeof(zval *), NULL); - } - zend_hash_add(ht, "userini", sizeof("userini"), &zvp4, sizeof(zval *), NULL); + ZVAL_STR(value, ini_entry->value); + zend_hash_add(Z_ARRVAL(zv[4]), ini_entry->name, value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("userini"), &zv[4]); } /* encode data */ php_json_encode(&buf, &array, 0 TSRMLS_CC); - *msg = buf.c; - *len = buf.len; + *msg = buf.s->val; + *len = buf.s->len; zval_dtor(&array); #endif } diff --git a/sapi/phpdbg/tests/run-tests.php b/sapi/phpdbg/tests/run-tests.php index 1cc31d815e..4afb64561c 100644 --- a/sapi/phpdbg/tests/run-tests.php +++ b/sapi/phpdbg/tests/run-tests.php @@ -389,7 +389,7 @@ namespace phpdbg\testing { } break; default: { - $this->$chunks[0] = $chunks[1]; + $this->{$chunks[0]} = $chunks[1]; } } } else switch(substr($trim, 1, 1)) { diff --git a/sapi/phpdbg/xml.md b/sapi/phpdbg/xml.md index 0556fb2415..7871b31376 100644 --- a/sapi/phpdbg/xml.md +++ b/sapi/phpdbg/xml.md @@ -60,7 +60,6 @@ type - general attribute for most errors, describes the genre of the error - General tags ============ @@ -78,11 +77,6 @@ intro - help: command name for help - report: URL for bug reporting -prompt ------- - -- msg tag contains the text prompt -- indicates that a new command may be accepted phpdbg ------ @@ -257,23 +251,6 @@ info (subcommands) - <lasterror error="" (file="" line="") /> - error attribute contains the last error as a string, is empty if there's no last error -### constants ### - -- <constantinfo num="" /> with num having an integer value, indicating the number of (local or superglobal) variables -- if info vars was used it'll have also one of these attributes: - - method - - function - - file - - opline -- for each variable there is a <constant> element -- <constant address="" refcount="" type="" name="" /> - - address: pointer to zval (hexadecimal) - - refcount: refcount of zval - - type: the variable type (long, string, ...). If the value is "unknown", the other attributes are meaningless - - name: the name of the variable - - value: the value of primitive types (scalars) => string/int/bool/double - - length: if string, then the length of that string - ### vars / globals ### - <variableinfo num="" /> with num having an integer value, indicating the number of (local or superglobal) variables @@ -282,7 +259,7 @@ info (subcommands) - function - file - opline -- for each variable there is a <variable> element +- for each variable there is a <variable> followed by a <variabledetails> element - <variable address="" refcount="" type="" name="" /> - address: pointer to zval (hexadecimal) - refcount: refcount of zval @@ -291,8 +268,6 @@ info (subcommands) - refstatus: empty if the zval is not a reference - class: the class the object in the zval is an instance of - resource: the type of the resource in the zval - - value: the value of primitive types (scalars) => string/int/bool/double - - length: if string, then the length of that string ### literal ### @@ -461,8 +436,6 @@ ev - eval()uates some code - output wrapped in <eval> tags -- output is here first a dump of xml tags (see "Variable Dump" section), then a dump wrapped in <stream> tags -- if there's an error, the tag will be <eval>, instead of the usual <php> tag sh -- @@ -636,7 +609,6 @@ dl - errors may have the module or extension attribute when their name is already known at the point of failure - Other tags ========== @@ -677,83 +649,3 @@ Other tags - generally emitted when data couldn't be fetched (e.g. by accessing inconsistent data); only used in hard interrupt mode - it might mean that data couldn't be fetched at all, or that only incomplete data was fetched (e.g. when a fixed number of following attributes are fetched, this tag will mark a stop of fetching if none or not all tags were printed) - - -Variable Dump -============= - -- all except property and element tags have a refstatus attribute, is set to non-empty if it's a reference - -object properties ------------------ - -- wrapped in a property tag <property name="" protection=""> - - name: name of key - - protection: one of these three values: public / protected / private - - class: only present if protection attribute is set to "private", contains the name of the class to which the property belongs -- if the property tag contains any serverity="error" attribute, there was some crucial error to read it, just skip it - -array elements --------------- -- wrapped in an element tag <property name="" protection=""> - - name: name of key -- if the element tag contains any serverity="error" attribute, there was some crucial error to read it, jsut skip it - -int ---- - -- <int refstatus="" value="" /> - - value is the integer - -float ------ - -- <float refstatus="" value="" /> - - value is the float - -bool ----- - -- <bool refstatus="" value="" /> - -value: true or false - -string ------- - -- <string refstatus="" length="" value="" /> - - length: length or string - - value: the string - -null ----- - -- <null refstatus="" /> - -array ------ - -- <array refstatus="" num=""> - - num: number of elements - - contains <element> tags - -object ------- - -- <object refstatus="" class="" id="" num=""> - - class: name of the class the object is an instance of (may be empty if unknown) - - id: id of the object - - num: number of properties - - contains <property> tags - -resource --------- - -- <resource refstatus="" id="" type="" /> - - id: resource id - - type: type of resource - -recursion ---------- - -- <recursion /> -- if that tag appears, there's a recursive reference inside the value to be printed |