diff options
author | Bob Weinand <bobwei9@hotmail.com> | 2014-04-21 23:29:25 +0200 |
---|---|---|
committer | Bob Weinand <bobwei9@hotmail.com> | 2014-04-21 23:30:08 +0200 |
commit | 708af5fd8e3b279aa2f6343e369e26a67d8bedc1 (patch) | |
tree | c3a3dc604892553cb5ad67bc6abcc15a50b189cc /sapi/phpdbg/phpdbg.c | |
parent | 32d5f269a03b554a0d3ebc96fcacc842e3344e4e (diff) | |
parent | 447ec05f3160628ef6dc7f7eee34bae866af8e5c (diff) | |
download | php-git-708af5fd8e3b279aa2f6343e369e26a67d8bedc1.tar.gz |
Merge sapi/phpdbg into PHP-5.6
Diffstat (limited to 'sapi/phpdbg/phpdbg.c')
-rw-r--r-- | sapi/phpdbg/phpdbg.c | 312 |
1 files changed, 198 insertions, 114 deletions
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 51a328d0b5..064e266082 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -#ifndef ZEND_SIGNALS +#if !defined(ZEND_SIGNALS) || defined(_WIN32) # include <signal.h> #endif #include "phpdbg.h" @@ -28,6 +28,7 @@ #include "phpdbg_list.h" #include "phpdbg_utils.h" #include "phpdbg_set.h" +#include "zend_alloc.h" /* {{{ remote console headers */ #ifndef _WIN32 @@ -61,16 +62,15 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ pg->exec = NULL; pg->exec_len = 0; + pg->buffer = NULL; pg->ops = NULL; pg->vmret = 0; pg->bp_count = 0; - pg->lcmd = NULL; pg->flags = PHPDBG_DEFAULT_FLAGS; pg->oplog = NULL; pg->io[PHPDBG_STDIN] = NULL; pg->io[PHPDBG_STDOUT] = NULL; pg->io[PHPDBG_STDERR] = NULL; - memset(&pg->lparam, 0, sizeof(phpdbg_param_t)); pg->frame.num = 0; } /* }}} */ @@ -145,6 +145,7 @@ static void php_phpdbg_destroy_registered(void *data) /* {{{ */ function TSRMLS_CC); } /* }}} */ + static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); @@ -157,7 +158,9 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], 8, NULL, NULL, 0); - + + phpdbg_setup_watchpoints(TSRMLS_C); + zend_hash_init(&PHPDBG_G(seek), 8, NULL, NULL, 0); zend_hash_init(&PHPDBG_G(registered), 8, NULL, php_phpdbg_destroy_registered, 0); @@ -178,7 +181,14 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); zend_hash_destroy(&PHPDBG_G(seek)); zend_hash_destroy(&PHPDBG_G(registered)); + zend_hash_destroy(&PHPDBG_G(watchpoints)); + zend_llist_destroy(&PHPDBG_G(watchlist_mem)); + if (PHPDBG_G(buffer)) { + efree(PHPDBG_G(buffer)); + PHPDBG_G(buffer) = NULL; + } + if (PHPDBG_G(exec)) { efree(PHPDBG_G(exec)); PHPDBG_G(exec) = NULL; @@ -209,24 +219,24 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ return SUCCESS; } /* }}} */ -/* {{{ proto mixed phpdbg_exec(string context) +/* {{{ proto mixed phpdbg_exec(string context) Attempt to set the execution context for phpdbg If the execution context was set previously it is returned - If the execution context was not set previously boolean true is returned + If the execution context was not set previously boolean true is returned If the request to set the context fails, boolean false is returned, and an E_WARNING raised */ -static PHP_FUNCTION(phpdbg_exec) +static PHP_FUNCTION(phpdbg_exec) { char *exec = NULL; - zend_ulong exec_len = 0L; + int exec_len = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &exec, &exec_len) == FAILURE) { return; } - + { struct stat sb; zend_bool result = 1; - + if (VCWD_STAT(exec, &sb) != FAILURE) { if (sb.st_mode & (S_IFREG|S_IFLNK)) { if (PHPDBG_G(exec)) { @@ -234,11 +244,11 @@ static PHP_FUNCTION(phpdbg_exec) efree(PHPDBG_G(exec)); result = 0; } - + PHPDBG_G(exec) = estrndup(exec, exec_len); PHPDBG_G(exec_len) = exec_len; - - if (result) + + if (result) ZVAL_BOOL(return_value, 1); } else { zend_error( @@ -259,9 +269,9 @@ static PHP_FUNCTION(phpdbg_exec) static PHP_FUNCTION(phpdbg_break) { if (ZEND_NUM_ARGS() > 0) { - long type; + long type = 0; char *expr = NULL; - zend_uint expr_len = 0; + int expr_len = 0; phpdbg_param_t param; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &type, &expr, &expr_len) == FAILURE) { @@ -269,28 +279,7 @@ static PHP_FUNCTION(phpdbg_break) } phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC); - - switch (type) { - case METHOD_PARAM: - phpdbg_do_break_method(¶m, NULL TSRMLS_CC); - break; - - case FILE_PARAM: - phpdbg_do_break_file(¶m, NULL TSRMLS_CC); - break; - - case NUMERIC_PARAM: - phpdbg_do_break_lineno(¶m, NULL TSRMLS_CC); - break; - - case STR_PARAM: - phpdbg_do_break_func(¶m, NULL TSRMLS_CC); - break; - - default: zend_error( - E_WARNING, "unrecognized parameter type %ld", type); - } - + phpdbg_do_break(¶m TSRMLS_CC); phpdbg_clear_param(¶m TSRMLS_CC); } else if (EG(current_execute_data) && EG(active_op_array)) { @@ -319,9 +308,9 @@ static PHP_FUNCTION(phpdbg_clear) /* {{{ proto void phpdbg_color(integer element, string color) */ static PHP_FUNCTION(phpdbg_color) { - long element; - char *color; - zend_uint color_len; + long element = 0L; + char *color = NULL; + int color_len = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &element, &color, &color_len) == FAILURE) { return; @@ -341,8 +330,8 @@ static PHP_FUNCTION(phpdbg_color) /* {{{ proto void phpdbg_prompt(string prompt) */ static PHP_FUNCTION(phpdbg_prompt) { - char *prompt; - zend_uint prompt_len; + char *prompt = NULL; + int prompt_len = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &prompt, &prompt_len) == FAILURE) { return; @@ -403,9 +392,9 @@ static inline int php_sapi_phpdbg_module_startup(sapi_module_struct *module) /* if (php_module_startup(module, &sapi_phpdbg_module_entry, 1) == FAILURE) { return FAILURE; } - + phpdbg_booted=1; - + return SUCCESS; } /* }}} */ @@ -585,7 +574,6 @@ const opt_struct OPTIONS[] = { /* {{{ */ {'z', 1, "load zend_extension"}, /* phpdbg options */ {'q', 0, "no banner"}, - {'e', 1, "exec"}, {'v', 0, "disable quietness"}, {'s', 0, "enable stepping"}, {'b', 0, "boring colours"}, @@ -615,10 +603,10 @@ const char phpdbg_ini_hardcoded[] = /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */ #define INI_DEFAULT(name, value) \ - 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); + 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); void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */ { @@ -666,11 +654,11 @@ static inline void phpdbg_sigint_handler(int signo) /* {{{ */ int phpdbg_open_socket(const char *interface, short port) /* {{{ */ { int fd = socket(AF_INET, SOCK_STREAM, 0); - + switch (fd) { case -1: return -1; - + default: { int reuse = 1; @@ -678,27 +666,27 @@ int phpdbg_open_socket(const char *interface, short port) /* {{{ */ case -1: close(fd); return -2; - + default: { struct sockaddr_in address; - + memset(&address, 0, sizeof(address)); - + address.sin_port = htons(port); address.sin_family = AF_INET; - + if ((*interface == '*')) { - address.sin_addr.s_addr = htonl(INADDR_ANY); + address.sin_addr.s_addr = htonl(INADDR_ANY); } else if (!inet_pton(AF_INET, interface, &address.sin_addr)) { close(fd); return -3; } - + switch (bind(fd, (struct sockaddr *)&address, sizeof(address))) { case -1: close(fd); return -4; - + default: { listen(fd, 5); } @@ -707,28 +695,28 @@ int phpdbg_open_socket(const char *interface, short port) /* {{{ */ } } } - + return fd; } /* }}} */ static inline void phpdbg_close_sockets(int (*socket)[2], FILE *streams[2]) /* {{{ */ -{ +{ if ((*socket)[0] >= 0) { shutdown( (*socket)[0], SHUT_RDWR); close((*socket)[0]); } - + if (streams[0]) { fclose(streams[0]); } - + if ((*socket)[1] >= 0) { shutdown( (*socket)[1], SHUT_RDWR); close((*socket)[1]); } - + if (streams[1]) { fclose(streams[1]); } @@ -798,14 +786,34 @@ int phpdbg_open_sockets(char *address, int port[2], int (*listen)[2], int (*sock dup2((*socket)[0], fileno(stdin)); dup2((*socket)[1], fileno(stdout)); - + setbuf(stdout, NULL); streams[0] = fdopen((*socket)[0], "r"); streams[1] = fdopen((*socket)[1], "w"); - + return SUCCESS; } /* }}} */ + +void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) { + int is_handled = FAILURE; + TSRMLS_FETCH(); + + switch (sig) { + case SIGBUS: + case SIGSEGV: + is_handled = phpdbg_watchpoint_segfault_handler(info, context TSRMLS_CC); + if (is_handled == FAILURE) { +#ifdef ZEND_SIGNALS + zend_sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL TSRMLS_CC); +#else + sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL); +#endif + } + break; + } + +} #endif int main(int argc, char **argv) /* {{{ */ @@ -852,6 +860,10 @@ int main(int argc, char **argv) /* {{{ */ #endif #ifndef _WIN32 + struct sigaction signal_struct; + signal_struct.sa_sigaction = phpdbg_signal_handler; + signal_struct.sa_flags = SA_SIGINFO | SA_NODEFER; + address = strdup("127.0.0.1"); socket[0] = -1; socket[1] = -1; @@ -888,17 +900,17 @@ phpdbg_main: bp_tmp_file = NULL; } } + + if (!bp_tmp_file) { + phpdbg_error("Unable to create temporary file"); + return 1; + } #else if (!mkstemp(bp_tmp_file)) { memset(bp_tmp_file, 0, sizeof(bp_tmp_file)); } #endif - if (!bp_tmp_file) { - phpdbg_error( - "Unable to create temporary file"); - return 1; - } } ini_entries = NULL; ini_entries_len = 0; @@ -920,8 +932,7 @@ phpdbg_main: run = 0; step = 0; sapi_name = NULL; - - + while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (opt) { case 'r': @@ -965,7 +976,7 @@ phpdbg_main: ini_entries_len += len + sizeof("=1\n\0") - 2; } } break; - + case 'z': zend_extensions_len++; if (zend_extensions) { @@ -976,16 +987,6 @@ phpdbg_main: /* begin phpdbg options */ - case 'e': { /* set execution context */ - exec_len = strlen(php_optarg); - if (exec_len) { - if (exec) { - free(exec); - } - exec = strdup(php_optarg); - } - } break; - case 'S': { /* set SAPI name */ if (sapi_name) { free(sapi_name); @@ -1001,7 +1002,7 @@ phpdbg_main: if (init_file) { free(init_file); } - + init_file_len = strlen(php_optarg); if (init_file_len) { init_file = strdup(php_optarg); @@ -1038,7 +1039,7 @@ phpdbg_main: #ifndef _WIN32 /* if you pass a listen port, we will accept input on listen port */ /* and write output to listen port * 2 */ - + case 'l': { /* set listen ports */ if (sscanf(php_optarg, "%d/%d", &listen[0], &listen[1]) != 2) { if (sscanf(php_optarg, "%d", &listen[0]) != 1) { @@ -1050,7 +1051,7 @@ phpdbg_main: } } } break; - + case 'a': { /* set bind address */ free(address); if (!php_optarg) { @@ -1076,6 +1077,19 @@ phpdbg_main: } break; } } + + /* set exec if present on command line */ + if ((argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) + { + exec_len = strlen(argv[php_optind]); + if (exec_len) { + if (exec) { + free(exec); + } + exec = strdup(argv[php_optind]); + } + php_optind++; + } #ifndef _WIN32 /* setup remote server if necessary */ @@ -1093,7 +1107,7 @@ phpdbg_main: if (sapi_name) { phpdbg->name = sapi_name; } - + phpdbg->ini_defaults = phpdbg_ini_defaults; phpdbg->phpinfo_as_text = 1; phpdbg->php_ini_ignore_cwd = 1; @@ -1114,14 +1128,14 @@ phpdbg_main: memcpy(ini_entries, phpdbg_ini_hardcoded, sizeof(phpdbg_ini_hardcoded)); } ini_entries_len += sizeof(phpdbg_ini_hardcoded) - 2; - + if (zend_extensions_len) { zend_ulong zend_extension = 0L; - + while (zend_extension < zend_extensions_len) { const char *ze = zend_extensions[zend_extension]; size_t ze_len = strlen(ze); - + ini_entries = realloc( ini_entries, ini_entries_len + (ze_len + (sizeof("zend_extension=\n")))); memcpy(&ini_entries[ini_entries_len], "zend_extension=", (sizeof("zend_extension=\n")-1)); @@ -1133,40 +1147,81 @@ phpdbg_main: free(zend_extensions[zend_extension]); zend_extension++; } - + free(zend_extensions); } phpdbg->ini_entries = ini_entries; - + if (phpdbg->startup(phpdbg) == SUCCESS) { - php_request_startup(TSRMLS_C); +#ifdef _WIN32 + EXCEPTION_POINTERS *xp; + __try { +#endif + zend_mm_heap *mm_heap = zend_mm_set_heap(NULL TSRMLS_CC); +#if ZEND_DEBUG + if (!mm_heap->use_zend_alloc) { + mm_heap->_malloc = malloc; + mm_heap->_realloc = realloc; + mm_heap->_free = free; +#endif + PHPDBG_G(original_free_function) = mm_heap->_free; + mm_heap->_free = phpdbg_watch_efree; + mm_heap->use_zend_alloc = 0; +#if ZEND_DEBUG + } +#endif + zend_mm_set_heap(mm_heap TSRMLS_CC); + + zend_activate(TSRMLS_C); + +#if defined(ZEND_SIGNALS) && !defined(_WIN32) + zend_try { + zend_signal_activate(TSRMLS_C); + } zend_end_try(); +#endif + +#if defined(ZEND_SIGNALS) && !defined(_WIN32) + zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try(); + zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try(); +#elif !defined(_WIN32) + sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); + sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); +#endif + + if (php_request_startup(TSRMLS_C) == SUCCESS) { + int i; + + SG(request_info).argc = argc - php_optind + 1; + SG(request_info).argv = emalloc(SG(request_info).argc * sizeof(char *)); + for (i = SG(request_info).argc; --i;) { + SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]); + } + SG(request_info).argv[i] = exec ? estrndup(exec, exec_len) : estrdup(""); + + php_hash_environment(TSRMLS_C); + } + + /* make sure to turn off buffer for ev command */ + php_output_activate(TSRMLS_C); + php_output_deactivate(TSRMLS_C); /* do not install sigint handlers for remote consoles */ /* sending SIGINT then provides a decent way of shutting down the server */ -#ifdef ZEND_SIGNALS -# ifndef _WIN32 +#if defined(ZEND_SIGNALS) && !defined(_WIN32) if (listen[0] < 0) { -# endif - zend_try { - zend_signal_activate(TSRMLS_C); - zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); - } zend_end_try(); -# ifndef _WIN32 + zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try(); } -# endif -#else -# ifndef _WIN32 +#elif !defined(_WIN32) if (listen[0] < 0) { -# endif +#endif signal(SIGINT, phpdbg_sigint_handler); #ifndef _WIN32 } #endif -#endif PG(modules_activated) = 0; - + /* set flags from command line */ PHPDBG_G(flags) = flags; @@ -1182,10 +1237,9 @@ phpdbg_main: PHPDBG_G(io)[PHPDBG_STDIN] = stdin; PHPDBG_G(io)[PHPDBG_STDOUT] = stdout; PHPDBG_G(io)[PHPDBG_STDERR] = stderr; - + if (exec) { /* set execution context */ - PHPDBG_G(exec) = phpdbg_resolve_path( - exec TSRMLS_CC); + PHPDBG_G(exec) = phpdbg_resolve_path(exec TSRMLS_CC); PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); free(exec); @@ -1213,6 +1267,11 @@ phpdbg_main: phpdbg_welcome((cleaning > 0) TSRMLS_CC); } + /* auto compile */ + if (PHPDBG_G(exec)) { + phpdbg_compile(TSRMLS_C); + } + /* initialize from file */ PHPDBG_G(flags) |= PHPDBG_IS_INITIALIZING; zend_try { @@ -1233,14 +1292,17 @@ phpdbg_main: if (run) { /* no need to try{}, run does it ... */ - PHPDBG_COMMAND_HANDLER(run)(NULL, NULL TSRMLS_CC); + PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC); if (run > 1) { /* if -r is on the command line more than once just quit */ goto phpdbg_out; } } +/* #ifndef for making compiler shutting up */ +#ifndef _WIN32 phpdbg_interact: +#endif /* phpdbg main() */ do { zend_try { @@ -1282,21 +1344,42 @@ phpdbg_interact: } zend_end_try(); } while(!cleaning && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); -phpdbg_out: + /* this must be forced */ + CG(unclean_shutdown) = 0; + + /* 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("Access violation (Segementation fault) encountered\ntrying to abort cleanly..."); + } +phpdbg_out: +#endif + + { + int i; + /* free argv */ + for (i = SG(request_info).argc; --i;) { + efree(SG(request_info).argv[i]); + } + efree(SG(request_info).argv); + } + #ifndef ZTS /* force cleanup of auto and core globals */ zend_hash_clean(CG(auto_globals)); memset( &core_globals, 0, sizeof(php_core_globals)); #endif - if (ini_entries) { free(ini_entries); } @@ -1318,6 +1401,7 @@ phpdbg_out: } zend_end_try(); sapi_shutdown(); + } if (cleaning || remote) { @@ -1331,7 +1415,7 @@ phpdbg_out: #ifndef _WIN32 if (address) { - free(address); + free(address); } #endif |