]> granicus.if.org Git - php/commitdiff
Add next command / Fix recursion/exceptions with u/F/L
authorBob Weinand <bobwei9@hotmail.com>
Tue, 21 Apr 2015 10:31:43 +0000 (12:31 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Tue, 21 Apr 2015 10:31:57 +0000 (12:31 +0200)
sapi/phpdbg/phpdbg.h
sapi/phpdbg/phpdbg_prompt.c
sapi/phpdbg/phpdbg_prompt.h
sapi/phpdbg/phpdbg_utils.c
sapi/phpdbg/phpdbg_utils.h

index c636a7c791cf99e0b9a74b8e29a309de7ced82df..6de6e9e2b8235f43ee1cac17d286320dda393075 100644 (file)
@@ -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 */
 
index 6dfc8a8c80785d29270301970a18d8d822dc6464..f9e1cdfe2e8527e12fce82df8303df202d0e5da9 100644 (file)
@@ -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",
index 88d7b08f12b6b32545487cdba09751a19ac6e861..25c0b4f71fc8f26ce1eb1b26458730153712dfd5 100644 (file)
@@ -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); /* }}} */
 
index a4725bd7440bd46a0bf868e52ec135128109057d..e1f6c59502b0a9073e6b6f065de83cdc8395df7a 100644 (file)
@@ -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;
+}
index b835ace7034e5bcf9b549601a5c3e59c3dff473c..5ed235398793542cde57452c7ae2f6980f194dab 100644 (file)
@@ -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; \