From f83ee6a05d9b0213ba43831a5c55ad7992a825c0 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 21 Apr 2015 12:31:43 +0200 Subject: [PATCH] Add next command / Fix recursion/exceptions with u/F/L --- sapi/phpdbg/phpdbg.h | 1 + sapi/phpdbg/phpdbg_prompt.c | 55 +++++++++++++++++++++++++++---------- sapi/phpdbg/phpdbg_prompt.h | 1 + sapi/phpdbg/phpdbg_utils.c | 22 +++++++++++++++ sapi/phpdbg/phpdbg_utils.h | 2 ++ 5 files changed, 67 insertions(+), 14 deletions(-) diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index c636a7c791..6de6e9e2b8 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -232,6 +232,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable bp[PHPDBG_BREAK_TABLES]; /* break points */ HashTable registered; /* registered */ HashTable seek; /* seek oplines */ + zend_execute_data *seek_ex; /* call frame of oplines to seek to */ phpdbg_frame_t frame; /* frame */ uint32_t last_line; /* last executed line */ diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 6dfc8a8c80..f9e1cdfe2e 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -90,6 +90,7 @@ const phpdbg_command_t phpdbg_prompt_commands[] = { PHPDBG_COMMAND_D(quit, "exit phpdbg", 'q', NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_COMMAND_D(wait, "wait for other process", 'W', NULL, 0, 0), PHPDBG_COMMAND_D(watch, "set watchpoint", 'w', phpdbg_watch_commands, "|ss", 0), + PHPDBG_COMMAND_D(next, "step over next line", 'n', NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_COMMAND_D(eol, "set EOL", 'E', NULL, "|s", 0), PHPDBG_END_COMMAND }; /* }}} */ @@ -473,20 +474,20 @@ PHPDBG_COMMAND(continue) /* {{{ */ return PHPDBG_NEXT; } /* }}} */ -PHPDBG_COMMAND(until) /* {{{ */ -{ - if (!PHPDBG_G(in_execution)) { - phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); - return SUCCESS; - } - +int phpdbg_skip_line_helper() { PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; + PHPDBG_G(seek_ex) = EG(current_execute_data); { const zend_op *opline = EG(current_execute_data)->opline; const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; while (++opline < op_array->opcodes + op_array->last) { - if (opline->lineno != EG(current_execute_data)->opline->lineno) { + if (opline->lineno != EG(current_execute_data)->opline->lineno + || opline->opcode == ZEND_RETURN + || opline->opcode == ZEND_GENERATOR_RETURN + || opline->opcode == ZEND_EXIT + || opline->opcode == ZEND_YIELD + ) { zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); break; } @@ -494,20 +495,40 @@ PHPDBG_COMMAND(until) /* {{{ */ } return PHPDBG_UNTIL; +} + +PHPDBG_COMMAND(until) /* {{{ */ +{ + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); + return SUCCESS; + } + + return phpdbg_skip_line_helper(); +} /* }}} */ + +PHPDBG_COMMAND(next) /* {{{ */ +{ + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); + return SUCCESS; + } + + PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; + return phpdbg_skip_line_helper(); } /* }}} */ static void phpdbg_seek_to_end(void) { const zend_op *opline = EG(current_execute_data)->opline; const zend_op_array *op_array = &EG(current_execute_data)->func->op_array - 1; + PHPDBG_G(seek_ex) = EG(current_execute_data); while (++opline < op_array->opcodes + op_array->last) { switch (opline->opcode) { case ZEND_RETURN: - case ZEND_THROW: + case ZEND_GENERATOR_RETURN: case ZEND_EXIT: -#ifdef ZEND_YIELD case ZEND_YIELD: -#endif zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); return; } @@ -1402,9 +1423,15 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ /* current address */ zend_ulong address = (zend_ulong) execute_data->opline; + if (PHPDBG_G(seek_ex) != execute_data) { + goto next; + } + +#define INDEX_EXISTS_CHECK (zend_hash_index_exists(&PHPDBG_G(seek), address) || (EG(exception) && phpdbg_check_caught_ex(execute_data) == 0)) + /* run to next line */ if (PHPDBG_G(flags) & PHPDBG_IN_UNTIL) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_UNTIL; zend_hash_clean(&PHPDBG_G(seek)); } else { @@ -1415,7 +1442,7 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ /* run to finish */ if (PHPDBG_G(flags) & PHPDBG_IN_FINISH) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_FINISH; zend_hash_clean(&PHPDBG_G(seek)); } @@ -1425,7 +1452,7 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ /* break for leave */ if (PHPDBG_G(flags) & PHPDBG_IN_LEAVE) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_LEAVE; zend_hash_clean(&PHPDBG_G(seek)); phpdbg_notice("breakpoint", "id=\"leave\" file=\"%s\" line=\"%u\"", "Breaking for leave at %s:%u", diff --git a/sapi/phpdbg/phpdbg_prompt.h b/sapi/phpdbg/phpdbg_prompt.h index 88d7b08f12..25c0b4f71f 100644 --- a/sapi/phpdbg/phpdbg_prompt.h +++ b/sapi/phpdbg/phpdbg_prompt.h @@ -57,6 +57,7 @@ PHPDBG_COMMAND(export); PHPDBG_COMMAND(register); PHPDBG_COMMAND(quit); PHPDBG_COMMAND(watch); +PHPDBG_COMMAND(next); PHPDBG_COMMAND(eol); PHPDBG_COMMAND(wait); /* }}} */ diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index a4725bd744..e1f6c59502 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -712,3 +712,25 @@ head_done: } } phpdbg_end_try_access(); } + +PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex) { + const zend_op *op; + uint32_t op_num, i; + zend_op_array *op_array = &ex->func->op_array; + + if (ex->opline >= EG(exception_op) && ex->opline < EG(exception_op) + 3) { + op = EG(opline_before_exception); + } else { + op = ex->opline; + } + + op_num = op - op_array->opcodes; + + for (i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op > op_num; i++) { + if (op_num < op_array->try_catch_array[i].catch_op || op_num < op_array->try_catch_array[i].finally_op) { + return 1; + } + } + + return 0; +} diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h index b835ace703..5ed2353987 100644 --- a/sapi/phpdbg/phpdbg_utils.h +++ b/sapi/phpdbg/phpdbg_utils.h @@ -94,6 +94,8 @@ int phpdbg_is_auto_global(char *name, int len); PHPDBG_API void phpdbg_xml_var_dump(zval *zv); +PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex); + #ifdef ZTS #define PHPDBG_OUTPUT_BACKUP_DEFINES() \ zend_output_globals *output_globals_ptr; \ -- 2.50.1