]> granicus.if.org Git - php/commitdiff
stepping
authorkrakjoe <joe.watkins@live.co.uk>
Sun, 10 Nov 2013 14:28:14 +0000 (14:28 +0000)
committerkrakjoe <joe.watkins@live.co.uk>
Sun, 10 Nov 2013 14:28:14 +0000 (14:28 +0000)
phpdbg.c
phpdbg.h
phpdbg_help.c
phpdbg_help.h
phpdbg_prompt.c
phpdbg_prompt.h

index 3b1a93b172ff4c64c721836919fa23f9b67ac8de..1379b6b7bf208be060456b7aaace8f28d6ecd5c0 100644 (file)
--- a/phpdbg.c
+++ b/phpdbg.c
@@ -26,6 +26,7 @@ void (*zend_execute_internal_old)(zend_execute_data *execute_data_ptr, zend_fcal
 static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) {
     pg->exec = NULL;
     pg->ops = NULL;
+    pg->stepping = 0;
 }
 
 static PHP_MINIT_FUNCTION(phpdbg) {
index a3da778520d4210e04b597f8c8fa192c6140c42a..0b1f2daa88508a53d82ee88fdb93677284360b51 100644 (file)
--- a/phpdbg.h
+++ b/phpdbg.h
 # define PHPDBG_G(v) (phpdbg_globals.v)
 #endif
 
+#define PHPDBG_NEXT 2
+
 ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
   HashTable breaks;
   char *exec;             /* file to execute */
   size_t exec_len;        /* size of exec */
   zend_op_array *ops;     /* op_array */
   zval *retval;           /* return value */
+  zend_bool stepping;     /* stepping */
+  int vmret;              /* return from last opcode handler execution */
 ZEND_END_MODULE_GLOBALS(phpdbg)
 
 #include "phpdbg_prompt.h"
index d5ec6fd40c3ed28b9f91bea6b139d8aed4e80e33..a72f53fd13c6ad11c4a03dfa221b60b1d0e12a10 100644 (file)
@@ -30,6 +30,20 @@ PHPDBG_HELP(exec) /* {{{ */
   return SUCCESS;
 } /* }}} */
 
+PHPDBG_HELP(step) { /* {{{ */
+    printf("You can enable and disable stepping at any phpdbg prompt during execution\n");
+    printf("For example:\n");
+    printf("phpdbg> stepping 1\n");
+    printf("Will enable stepping\n");
+    printf("While stepping is enabled you are presented with a prompt after the execution of each opcode\n");
+    return SUCCESS;
+} /* }}} */
+
+PHPDBG_HELP(next) { /* {{{ */
+    printf("While stepping through execution, use the next command to step back into the vm and execute the next opcode");
+    return SUCCESS;
+} /* }}} */
+
 PHPDBG_HELP(compile) /* {{{ */
 {
   printf("Pre-compilation of the execution context provides the opportunity to inspect the opcodes before they are executed\n");
@@ -43,7 +57,7 @@ PHPDBG_HELP(print) /* {{{ */
 {
   printf("By default, print will show information about the current execution environment\n");
   printf("To show specific information pass an expression to print, for example:\n");
-  printf("\tprint opcodes[0]\n");
+  printf("\tphpdbg> print opcodes[0]\n");
   printf("Will show the opline @ 0\n");
   printf("Available print commands:\n");
   printf("\tNone\n");
index 1ab558725ce9074675dd07eaa1b99f09af5d3457..69b710f782ddfea77c7c99d4245effe459b38030 100644 (file)
@@ -33,6 +33,8 @@
  */
 PHPDBG_HELP(exec);
 PHPDBG_HELP(compile);
+PHPDBG_HELP(step);
+PHPDBG_HELP(next);
 PHPDBG_HELP(run);
 PHPDBG_HELP(print);
 PHPDBG_HELP(break);
@@ -43,6 +45,8 @@ PHPDBG_HELP(break);
 static const phpdbg_command_t phpdbg_help_commands[] = {
   PHPDBG_HELP_D(exec,     "the execution context should be a valid phpdbg path"),
   PHPDBG_HELP_D(compile,  "pre-compilation allows inspection of code before execution"),
+  PHPDBG_HELP_D(step,     "stepping through execution allows inspection of the opline after every opcode"),
+  PHPDBG_HELP_D(next,     "execute the next opcode"),
   PHPDBG_HELP_D(run,      "execution inside the phpdbg vm allows detailed inspection and debugging"),
   PHPDBG_HELP_D(print,    "printing allows inspection of the execution environment"),
   PHPDBG_HELP_D(break,    "breakpoints allow execution interruption"),
index 31722665b3ed11b386ca063b811d64ec39a972b1..0dfe14b1befd3295bbd6b12450e6b1ce6ee67a24 100644 (file)
@@ -85,6 +85,15 @@ static PHPDBG_COMMAND(compile) { /* {{{ */
   }
 } /* }}} */
 
+static PHPDBG_COMMAND(step) { /* {{{ */
+    PHPDBG_G(stepping) = atoi(expr);
+    return SUCCESS;
+} /* }}} */
+
+static PHPDBG_COMMAND(next) { /* {{{ */
+    return PHPDBG_NEXT;
+} /* }}} */
+
 static PHPDBG_COMMAND(run) { /* {{{ */
     if (PHPDBG_G(ops) || PHPDBG_G(exec)) {
         if (!PHPDBG_G(ops)) {
@@ -116,9 +125,12 @@ static PHPDBG_COMMAND(print) { /* {{{ */
     printf("Showing Execution Context Information:\n");
     printf("Exec\t\t%s\n", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
     printf("Compiled\t%s\n", PHPDBG_G(ops) ? "yes" : "no");
+    printf("Stepping\t%s\n", PHPDBG_G(stepping) ? "on" : "off");
     if (PHPDBG_G(ops)) {
-      printf("Opcodes\t\t%d\n", PHPDBG_G(ops)->last-1);
-      printf("Variables\t%d\n", PHPDBG_G(ops)->last_var-1);
+      printf("Opcodes\t\t%d\n", PHPDBG_G(ops)->last);
+      if (PHPDBG_G(ops)->last_var) {
+        printf("Variables\t%d\n", PHPDBG_G(ops)->last_var-1);
+      } else printf("Variables\tNone\n");
     }
   } else {
     printf(
@@ -175,6 +187,8 @@ static PHPDBG_COMMAND(help) /* {{{ */
 static const phpdbg_command_t phpdbg_prompt_commands[] = {
        PHPDBG_COMMAND_D(exec,      "set execution context"),
        PHPDBG_COMMAND_D(compile,   "attempt to pre-compile execution context"),
+       PHPDBG_COMMAND_D(step,      "step through execution"),
+       PHPDBG_COMMAND_D(next,      "next opcode"),
        PHPDBG_COMMAND_D(run,       "attempt execution"),
        PHPDBG_COMMAND_D(print,     "print something"),
        PHPDBG_COMMAND_D(break,     "set breakpoint"),
@@ -200,7 +214,7 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le
        return FAILURE;
 } /* }}} */
 
-void phpdbg_interactive(int argc, char **argv TSRMLS_DC) /* {{{ */
+int phpdbg_interactive(int argc, char **argv TSRMLS_DC) /* {{{ */
 {
        char cmd[PHPDBG_MAX_CMD];
 
@@ -214,13 +228,20 @@ void phpdbg_interactive(int argc, char **argv TSRMLS_DC) /* {{{ */
                }
 
                if (cmd_len) {
-                       if (phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC) == FAILURE) {
-                         printf("error executing %s !\n", cmd);
-                       }
+                   switch (phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) {
+                       case FAILURE:
+                           printf("error executing %s !\n", cmd);
+                       break;
+                       
+                       case PHPDBG_NEXT:
+                           return PHPDBG_NEXT;
+                   }
                }
 
                printf("phpdbg> ");
        }
+       
+       return SUCCESS;
 } /* }}} */
 
 void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
@@ -236,7 +257,6 @@ zend_vm_enter:
        }
 
        while (1) {
-       int ret;
 #ifdef ZEND_WIN32
                if (EG(timed_out)) {
                        zend_timeout(0);
@@ -245,8 +265,17 @@ zend_vm_enter:
 
         printf("[OPLINE: %p]\n", execute_data->opline);
         
-               if ((ret = execute_data->opline->handler(execute_data TSRMLS_CC)) > 0) {
-                       switch (ret) {
+        PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);
+        
+        if (PHPDBG_G(stepping)) {
+            while (phpdbg_interactive(
+                0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
+                continue;
+            }
+        }
+        
+               if (PHPDBG_G(vmret) > 0) {
+                       switch (PHPDBG_G(vmret)) {
                                case 1:
                                        EG(in_execution) = original_in_execution;
                                        return;
index 028f2c080afa0f598a0d0fd1d932eb33f8de5bdf..b6921d671e446c223327bfd26f4cda130566bc54 100644 (file)
@@ -56,7 +56,7 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le
 #define PHPDBG_COMMAND(name) \
   int phpdbg_do_##name(const char *expr, size_t expr_len TSRMLS_DC)
 
-void phpdbg_interactive(int argc, char **argv TSRMLS_DC);
+int phpdbg_interactive(int argc, char **argv TSRMLS_DC);
 void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
 
 #endif /* PHPDBG_PROMPT_H */