summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2015-04-21 12:31:43 +0200
committerBob Weinand <bobwei9@hotmail.com>2015-04-21 12:31:57 +0200
commitf83ee6a05d9b0213ba43831a5c55ad7992a825c0 (patch)
tree442021febad15273bce93a3264929c89ec88a19a
parentca76a86fe62ef87dc25905c5ca90244d9b84a81f (diff)
downloadphp-git-f83ee6a05d9b0213ba43831a5c55ad7992a825c0.tar.gz
Add next command / Fix recursion/exceptions with u/F/L
-rw-r--r--sapi/phpdbg/phpdbg.h1
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c55
-rw-r--r--sapi/phpdbg/phpdbg_prompt.h1
-rw-r--r--sapi/phpdbg/phpdbg_utils.c22
-rw-r--r--sapi/phpdbg/phpdbg_utils.h2
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; \