]> granicus.if.org Git - php/commitdiff
add opline logging and setup including command line option
authorkrakjoe <joe.watkins@live.co.uk>
Thu, 14 Nov 2013 21:10:44 +0000 (21:10 +0000)
committerkrakjoe <joe.watkins@live.co.uk>
Thu, 14 Nov 2013 21:10:44 +0000 (21:10 +0000)
phpdbg.c
phpdbg.h
phpdbg_help.c
phpdbg_help.h
phpdbg_prompt.c
phpdbg_utils.c
phpdbg_utils.h

index 443b603074e24b94675838caedef74c2fc6017d9..30a06e8a50c5637bea5495951584089a07e4972d 100644 (file)
--- a/phpdbg.c
+++ b/phpdbg.c
@@ -37,6 +37,7 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */
     pg->last_params = NULL;
     pg->last_params_len = 0;
     pg->flags = PHPDBG_DEFAULT_FLAGS;
+    pg->oplog = NULL;
 } /* }}} */
 
 static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */
@@ -103,6 +104,12 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
         efree(PHPDBG_G(exec));
         PHPDBG_G(exec) = NULL;
     }
+    
+    if (PHPDBG_G(oplog)) {
+        fclose(
+            PHPDBG_G(oplog));
+        PHPDBG_G(oplog) = NULL;
+    }
 
     if (PHPDBG_G(ops)) {
         destroy_op_array(PHPDBG_G(ops) TSRMLS_CC);
@@ -293,11 +300,12 @@ const opt_struct OPTIONS[] = { /* {{{ */
        {'z', 1, "load zend_extension"},
        /* phpdbg options */
        {'e', 1, "exec"},
-       {'v', 0, "verbose"},
-       {'s', 0, "step"},
+       {'v', 0, "disable quietness"},
+       {'s', 0, "enable stepping"},
        {'b', 0, "boring colours"},
-       {'i', 1, "init"},
-       {'I', 0, "ignore-init"},
+       {'i', 1, "specify init"},
+       {'I', 0, "ignore init"},
+       {'O', 1, "opline log"},
        {'-', 0, NULL}
 }; /* }}} */
 
@@ -333,6 +341,8 @@ int main(int argc, char **argv) /* {{{ */
        char *init_file;
        size_t init_file_len;
        zend_bool init_file_default;
+       char *oplog_file;
+       size_t oplog_file_len;
        zend_ulong flags;
        char *php_optarg;
     int php_optind;
@@ -364,6 +374,8 @@ phpdbg_main:
     init_file = NULL;
     init_file_len = 0;
     init_file_default = 1;
+    oplog_file = NULL;
+    oplog_file_len = 0;
     flags = PHPDBG_DEFAULT_FLAGS;
     php_optarg = NULL;
     php_optind = 1;
@@ -412,24 +424,33 @@ phpdbg_main:
             case 'z':
                 zend_load_extension(php_optarg);
             break;
+            
+            /* begin phpdbg options */
 
-            case 'e': /* set execution context */
+            case 'e': /* set execution context */
                 exec_len = strlen(php_optarg);
                 if (exec_len) {
                     exec = strdup(php_optarg);
                 }
-            break;
+            break;
             
             case 'I': { /* ignore .phpdbginit */
                 init_file_default = 0;
             } break;
             
-            case 'i': /* set init file */
+            case 'i': /* set init file */
                 init_file_len = strlen(php_optarg);
                 if (init_file_len) {
                     init_file = strdup(php_optarg);
                 }
-            break;
+            } break;
+            
+            case 'O': { /* set oplog output */
+                oplog_file_len = strlen(php_optarg);
+                if (oplog_file_len) {
+                    oplog_file = strdup(php_optarg);
+                }
+            } break;
 
             case 'v': /* set quietness off */
                 flags &= ~PHPDBG_IS_QUIET;
@@ -485,6 +506,15 @@ phpdbg_main:
 
             free(exec);
         }
+        
+        if (oplog_file) { /* open oplog */
+            PHPDBG_G(oplog) = fopen(oplog_file, "w+");
+            if (!PHPDBG_G(oplog)) {
+                phpdbg_error(
+                    "Failed to open oplog %s", oplog_file);
+            }
+            free(oplog_file);
+        }
 
         /* set flags from command line */
         PHPDBG_G(flags) = flags;
index 48b3ab44c918ab100b984956baeb2e3d2aed49b6..8577624eb94ec088e5b56d3d1cf77e42225f6f01 100644 (file)
--- a/phpdbg.h
+++ b/phpdbg.h
@@ -109,6 +109,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
        const char *last_params;            /* last expression */
        size_t last_params_len;             /* last expression length */
        zend_ulong flags;                   /* phpdbg flags */
+       FILE *oplog;                        /* opline log */
 ZEND_END_MODULE_GLOBALS(phpdbg)
 
 #endif /* PHPDBG_H */
index fb987d131ac5715d1e245998d65740e02405b23d..244b435df043a0d1d470d99535bf01474ff45241 100644 (file)
@@ -26,7 +26,7 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
 
 PHPDBG_HELP(exec) /* {{{ */
 {
-       phpdbg_writeln("Will attempt execution, if compilation has not yet taken place, it occurs now.");
+       phpdbg_writeln("Will attempt execution, if compilation has not yet taken place, it occurs now");
        phpdbg_writeln("The execution context must be set before execution can take place");
        return SUCCESS;
 } /* }}} */
@@ -53,7 +53,7 @@ PHPDBG_HELP(compile) /* {{{ */
 {
        phpdbg_writeln("Pre-compilation of the execution context provides the opportunity to inspect the opcodes before they are executed");
        phpdbg_writeln("The execution context must be set for compilation to succeed");
-       phpdbg_writeln("If errors occur during compilation they must be resolved before execution can take place.");
+       phpdbg_writeln("If errors occur during compilation they must be resolved before execution can take place");
        phpdbg_writeln("It is a good idea to clean the environment between each compilation with the clean command");
        phpdbg_writeln("You do not need to exit phpdbg to retry compilation");
        return SUCCESS;
@@ -99,13 +99,13 @@ PHPDBG_HELP(run) /* {{{ */
 PHPDBG_HELP(eval) /* {{{ */
 {
        phpdbg_writeln("Access to eval() allows you to change the environment during execution, careful though !!");
-       phpdbg_writeln("Note: When using eval in phpdbg do not prefix the code with return.");
+       phpdbg_writeln("Note: When using eval in phpdbg do not prefix the code with return");
        return SUCCESS;
 } /* }}} */
 
 PHPDBG_HELP(break) /* {{{ */
 {
-       phpdbg_writeln("Setting a breakpoint stops execution at a specific stage.");
+       phpdbg_writeln("Setting a breakpoint stops execution at a specific stage");
        phpdbg_writeln(EMPTY);
        phpdbg_writeln("Examples:");
        phpdbg_writeln("\t%sbreak test.php:1", PROMPT);
@@ -131,8 +131,8 @@ PHPDBG_HELP(break) /* {{{ */
 
 PHPDBG_HELP(clean) /* {{{ */
 {
-    phpdbg_writeln("While debugging you may experience errors because of attempts to redeclare classes, constants or functions.");
-    phpdbg_writeln("Cleaning the environment cleans these tables, so that files can be recompiled without exiting phpdbg.");
+    phpdbg_writeln("While debugging you may experience errors because of attempts to redeclare classes, constants or functions");
+    phpdbg_writeln("Cleaning the environment cleans these tables, so that files can be recompiled without exiting phpdbg");
     return SUCCESS;
 } /* }}} */
 
@@ -159,7 +159,7 @@ PHPDBG_HELP(quiet) /* {{{ */
 
 PHPDBG_HELP(back) /* {{{ */
 {
-       phpdbg_writeln("The backtrace is gathered with the default debug_backtrace functionality.");
+       phpdbg_writeln("The backtrace is gathered with the default debug_backtrace functionality");
     phpdbg_writeln(EMPTY);
     phpdbg_writeln("Examples:");
        phpdbg_writeln("You can set the limit on the trace");
@@ -170,7 +170,7 @@ PHPDBG_HELP(back) /* {{{ */
 
 PHPDBG_HELP(list) /* {{{ */
 {
-       phpdbg_writeln("The list command displays N line from current context file.");
+       phpdbg_writeln("The list command displays N line from current context file");
        phpdbg_writeln(EMPTY);
        phpdbg_writeln("Examples:");
        phpdbg_writeln("\t%slist 2", PROMPT);
@@ -183,3 +183,20 @@ PHPDBG_HELP(list) /* {{{ */
        phpdbg_writeln("Note: before listing functions you must have a populated function table, try compile !!");
        return SUCCESS;
 } /* }}} */
+
+PHPDBG_HELP(oplog) /* {{{ */
+{
+    phpdbg_writeln("Even when quietness is enabled you may wish to save opline logs to a file");
+    phpdbg_writeln("Setting a new oplog closes the previously open log");
+    phpdbg_writeln("The log includes a high resolution timestamp on each entry");
+       phpdbg_writeln(EMPTY);
+    phpdbg_writeln("Example:");
+    phpdbg_writeln("\t%soplog /path/to/my.oplog", PROMPT);
+    phpdbg_writeln("Will open the file /path/to/my.oplog for writing, creating it if it does not exist");
+    phpdbg_writeln("Example:");
+    phpdbg_writeln("\t%soplog 0", PROMPT);
+    phpdbg_writeln("Will open the currently open log file, disabling oplog");
+       phpdbg_writeln(EMPTY);
+    phpdbg_writeln("Note: upon failure to open a new oplog, the last oplog is held open");
+    return SUCCESS;
+} /* }}} */
index 4e15bda22484dc7ea839c1ea5afaddee6edaabab..c5706f65f39fe48dbd99be9fc2c5447f4c7e5544 100644 (file)
@@ -47,6 +47,7 @@ PHPDBG_HELP(clear);
 PHPDBG_HELP(back);
 PHPDBG_HELP(quiet);
 PHPDBG_HELP(list);
+PHPDBG_HELP(oplog);
 
 /**
  * Commands
@@ -65,6 +66,7 @@ static const phpdbg_command_t phpdbg_help_commands[] = {
        PHPDBG_HELP_D(back,     "show debug backtrace information during execution"),
     PHPDBG_HELP_D(quiet,    "be quiet during execution"),
        PHPDBG_HELP_D(list,     "listing code gives you quick access to code while executing"),
+       PHPDBG_HELP_D(oplog,    "sets a file for, or disables oplog"),
        {NULL, 0, 0}
 };
 
index 7b2c603668798fd442613013fdf5efbb92a9419f..bf016ea8a3196c149526fc738e0dbd6671177982 100644 (file)
@@ -46,6 +46,7 @@ static PHPDBG_COMMAND(clear);
 static PHPDBG_COMMAND(help);
 static PHPDBG_COMMAND(quiet);
 static PHPDBG_COMMAND(aliases);
+static PHPDBG_COMMAND(oplog);
 static PHPDBG_COMMAND(quit); /* }}} */
 
 /* {{{ command declarations */
@@ -65,6 +66,7 @@ static const phpdbg_command_t phpdbg_prompt_commands[] = {
        PHPDBG_COMMAND_EX_D(help,       "show help menu", 'h'),
        PHPDBG_COMMAND_EX_D(quiet,      "silence some output", 'Q'),
        PHPDBG_COMMAND_EX_D(aliases,    "show alias list", 'a'),
+       PHPDBG_COMMAND_EX_D(oplog,      "sets oplog output", 'O'),
        PHPDBG_COMMAND_EX_D(quit,       "exit phpdbg", 'q'),
        {NULL, 0, 0}
 }; /* }}} */
@@ -496,6 +498,45 @@ static PHPDBG_COMMAND(aliases) /* {{{ */
        return SUCCESS;
 } /* }}} */
 
+static PHPDBG_COMMAND(oplog) /* {{{ */
+{
+    if (expr && expr_len > 0L) {
+        /* disable oplog */
+        if (expr[0] == '0' && expr_len == 1) {
+            if (PHPDBG_G(oplog)) {
+                phpdbg_notice("Disabling oplog");
+                fclose(
+                    PHPDBG_G(oplog));
+                return SUCCESS;
+            } else {
+                phpdbg_error("No oplog currently open");
+                return FAILURE;
+            }
+        } else {
+            /* open oplog */
+            FILE *old = PHPDBG_G(oplog);
+
+            PHPDBG_G(oplog) = fopen(expr, "w+");
+            if (!PHPDBG_G(oplog)) {
+                phpdbg_error("Failed to open %s for oplog", expr);
+                PHPDBG_G(oplog) = old;
+                return FAILURE;
+            } else {
+                if (old) {
+                    phpdbg_notice("Closing previously open oplog");
+                    fclose(old);
+                }
+                phpdbg_notice("Successfully opened oplog");
+                
+                return SUCCESS;
+            }
+        }
+    } else {
+        phpdbg_error("No expression provided");
+        return FAILURE;
+    }
+} /* }}} */
+
 static PHPDBG_COMMAND(help) /* {{{ */
 {
        phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s",
@@ -538,6 +579,7 @@ static PHPDBG_COMMAND(help) /* {{{ */
            phpdbg_writeln("\t-b\tN/A\t\t\tDisable the use of colours");
            phpdbg_writeln("\t-i\t-imy.init\t\tSet the phpdbginit file");
            phpdbg_writeln("\t-I\tN/A\t\t\tDisable loading .phpdbginit");
+           phpdbg_writeln("\t-O\t-Omy.oplog\t\tSets oplog output file");
        }
 
        phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES);
@@ -687,14 +729,27 @@ void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags
     /* force out a line while stepping so the user knows what is happening */
     if (ignore_flags ||
         (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) ||
-        (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) {
+        (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ||
+        (PHPDBG_G(oplog)))) {
 
         zend_op *opline = execute_data->opline;
-        /* output line info */
-               phpdbg_notice("#%lu %p %s %s",
-           opline->lineno,
-           opline, phpdbg_decode_opcode(opline->opcode),
-           execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
+
+        if (ignore_flags ||
+            (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) ||
+            (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) {
+             /* output line info */
+                   phpdbg_notice("#%lu %p %s %s",
+               opline->lineno,
+               opline, phpdbg_decode_opcode(opline->opcode),
+               execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
+        }
+
+        if (!ignore_flags && PHPDBG_G(oplog)) {
+            phpdbg_log_ex(PHPDBG_G(oplog), "#%lu %p %s %s",
+                opline->lineno,
+                opline, phpdbg_decode_opcode(opline->opcode),
+                execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
+        }
     }
 } /* }}} */
 
index 91e7ec2b5034967f16b547981d58202cda1c544a..7538c774dcbbce54c8db927da2224fa5c7e89481 100644 (file)
@@ -159,7 +159,7 @@ void phpdbg_clear_param(int type, phpdbg_param_t *param TSRMLS_DC) /* {{{ */
        }
 } /* }}} */
 
-int phpdbg_print(int type TSRMLS_DC, const char *format, ...) /* {{{ */
+int phpdbg_print(int type TSRMLS_DC, FILE *fp, const char *format, ...) /* {{{ */
 {
     int rc = 0;
        char *buffer = NULL;
@@ -175,36 +175,45 @@ int phpdbg_print(int type TSRMLS_DC, const char *format, ...) /* {{{ */
 
        switch (type) {
                case P_ERROR:
-                       rc = printf("%s%s%s\n",
-                                   ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[1;31m[" : "["),
-                                   buffer,
-                                   ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "]\033[0m" : "]"));
+                       rc = fprintf(fp, "%s%s%s\n",
+                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[1;31m[" : "["),
+                                       buffer,
+                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "]\033[0m" : "]"));
                break;
 
                case P_NOTICE:
-                       rc = printf("%s%s%s\n",
-                                   ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[1;64m[" : "["),
-                                   buffer,
-                                   ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "]\033[0m" : "]"));
+                       rc = fprintf(fp, "%s%s%s\n",
+                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[1;64m[" : "["),
+                                       buffer,
+                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "]\033[0m" : "]"));
                break;
 
                case P_WRITELN: {
                    if (buffer) {
-                           rc = printf("%s%s%s\n",
-                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[37m" : ""),
-                                       buffer,
-                                       ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[0m" : ""));
+                           rc = fprintf(fp, "%s%s%s\n",
+                                           ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[37m" : ""),
+                                           buffer,
+                                           ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[0m" : ""));
                        } else {
-                           rc = printf("\n");
+                           rc = fprintf(fp, "\n");
                        }
                } break;
 
                case P_WRITE: if (buffer) {
-                   rc = printf("%s%s%s",
-                           ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[37m" : ""),
-                           buffer,
-                           ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[0m" : ""));
+                   rc = fprintf(fp, "%s%s%s",
+                               ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[37m" : ""),
+                               buffer,
+                               ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED) ? "\033[0m" : ""));
                } break;
+               
+               /* no formatting on logging output */
+           case P_LOG: if (buffer) {
+               struct timeval tp;
+               if (gettimeofday(&tp, NULL) == SUCCESS) {
+                   rc = fprintf(
+                       fp, "[%ld %.8F]: %s\n", tp.tv_sec, tp.tv_usec / 1000000.00, buffer);
+               } else rc = FAILURE;
+           } break;
        }
 
        if (buffer) {
index 9ae3f8d136c520658faedd6bfbe5595c3e9d59da..57fa23c509b3db576c3f6c18736c2cf38605ecf8 100644 (file)
@@ -66,15 +66,23 @@ enum {
        P_ERROR  = 1,
        P_NOTICE,
        P_WRITELN,
-       P_WRITE
+       P_WRITE,
+       P_LOG
 };
 
-int phpdbg_print(int TSRMLS_DC, const char*, ...);
+int phpdbg_print(int TSRMLS_DC, FILE*, const char*, ...);
 
-#define phpdbg_error(fmt, ...)   phpdbg_print(P_ERROR   TSRMLS_CC, fmt, ##__VA_ARGS__)
-#define phpdbg_notice(fmt, ...)  phpdbg_print(P_NOTICE  TSRMLS_CC, fmt, ##__VA_ARGS__)
-#define phpdbg_writeln(fmt, ...) phpdbg_print(P_WRITELN TSRMLS_CC, fmt, ##__VA_ARGS__)
-#define phpdbg_write(fmt, ...)   phpdbg_print(P_WRITE   TSRMLS_CC, fmt, ##__VA_ARGS__)
+#define phpdbg_error(fmt, ...)              phpdbg_print(P_ERROR   TSRMLS_CC, stderr, fmt, ##__VA_ARGS__)
+#define phpdbg_notice(fmt, ...)             phpdbg_print(P_NOTICE  TSRMLS_CC, stderr, fmt, ##__VA_ARGS__)
+#define phpdbg_writeln(fmt, ...)            phpdbg_print(P_WRITELN TSRMLS_CC, stderr, fmt, ##__VA_ARGS__)
+#define phpdbg_write(fmt, ...)              phpdbg_print(P_WRITE   TSRMLS_CC, stderr, fmt, ##__VA_ARGS__)
+#define phpdbg_log(fmt, ...)                phpdbg_print(P_LOG     TSRMLS_CC, stderr, fmt, ##__VA_ARGS__)
+
+#define phpdbg_error_ex(out, fmt, ...)      phpdbg_print(P_ERROR   TSRMLS_CC, out, fmt, ##__VA_ARGS__)
+#define phpdbg_notice_ex(out, fmt, ...)     phpdbg_print(P_NOTICE  TSRMLS_CC, out, fmt, ##__VA_ARGS__)
+#define phpdbg_writeln_ex(out, fmt, ...)    phpdbg_print(P_WRITELN TSRMLS_CC, out, fmt, ##__VA_ARGS__)
+#define phpdbg_write_ex(out, fmt, ...)      phpdbg_print(P_WRITE   TSRMLS_CC, out, fmt, ##__VA_ARGS__)
+#define phpdbg_log_ex(out, fmt, ...)        phpdbg_print(P_LOG     TSRMLS_CC, out, fmt, ##__VA_ARGS__)
 
 /* {{{ For writing blank lines */
 #define EMPTY "" /* }}} */