]> granicus.if.org Git - php/commitdiff
- Initial code for breakpoint on function
authorFelipe Pena <felipensp@gmail.com>
Sun, 10 Nov 2013 17:49:25 +0000 (15:49 -0200)
committerFelipe Pena <felipensp@gmail.com>
Sun, 10 Nov 2013 17:49:25 +0000 (15:49 -0200)
phpdbg.h
phpdbg_prompt.c
phpdbg_prompt.h
test.php

index f34fa4c84e008ca2ae53e58a9d73d53b1db2000f..68c987a4295194bcf7dd345c5ab510ffc6eee358 100644 (file)
--- a/phpdbg.h
+++ b/phpdbg.h
@@ -40,8 +40,8 @@
 #define PHPDBG_NEXT 2
 
 ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
-       HashTable break_files;
-       HashTable break_symbols;
+       HashTable bp_files;
+       HashTable bp_symbols;
        char *exec;             /* file to execute */
        size_t exec_len;        /* size of exec */
        zend_op_array *ops;     /* op_array */
@@ -49,6 +49,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
        zend_bool stepping;     /* stepping */
        int vmret;              /* return from last opcode handler execution */
        zend_bool has_file_bp;  /* file-based breakpoint has been set */
+       zend_bool has_sym_bp;   /* symbol-based breakpoint has been set */
 ZEND_END_MODULE_GLOBALS(phpdbg)
 
 #include "phpdbg_prompt.h"
index 4a145ac78a2a38ec10db32dc08d52be3f4cc9223..c941fc94836e4a8b4b8b9698eb128935e81cc486 100644 (file)
@@ -35,6 +35,13 @@ static void phpdbg_llist_breakfile_dtor(void *data)
        efree((char*)bp->filename);
 }
 
+static void phpdbg_llist_breaksym_dtor(void *data)
+{
+       phpdbg_breaksymbol_t *bp = (phpdbg_breaksymbol_t*) data;
+
+       efree((char*)bp->symbol);
+}
+
 static PHPDBG_COMMAND(exec) { /* {{{ */
   if (PHPDBG_G(exec)) {
     printf(
@@ -154,10 +161,10 @@ static PHPDBG_COMMAND(back) { /* {{{ */
         HashPosition position;
         int i = 0;
         int limit = (expr != NULL) ? atoi(expr) : 0;
-        
+
         zend_fetch_debug_backtrace(
             &zbacktrace, 0, 0, limit TSRMLS_CC);
-        
+
         for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position);
              zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position) == SUCCESS;
              zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position)) {
@@ -166,11 +173,11 @@ static PHPDBG_COMMAND(back) { /* {{{ */
              }
              zend_print_flat_zval_r(*tmp TSRMLS_CC);
         }
-        
+
         printf("\n");
-        
+
         zval_dtor(&zbacktrace);
-        
+
         return SUCCESS;
     } else {
         printf("Not executing !\n");
@@ -226,18 +233,42 @@ static PHPDBG_COMMAND(break) /* {{{ */
 
                PHPDBG_G(has_file_bp) = 1;
 
-               if (zend_hash_find(&PHPDBG_G(break_files),
+               if (zend_hash_find(&PHPDBG_G(bp_files),
                        new_break.filename, name_len, (void**)&break_files_ptr) == FAILURE) {
                        zend_llist break_files;
 
                        zend_llist_init(&break_files, sizeof(phpdbg_breakfile_t),
                                phpdbg_llist_breakfile_dtor, 0);
 
-                       zend_hash_update(&PHPDBG_G(break_files),
+                       zend_hash_update(&PHPDBG_G(bp_files),
                                new_break.filename, name_len, &break_files, sizeof(zend_llist),
                                (void**)&break_files_ptr);
                }
                zend_llist_add_element(break_files_ptr, &new_break);
+       } else {
+               const char *opline_num_pos = zend_memrchr(expr, '#', expr_len);
+               long opline_num = opline_num_pos ? strtol(opline_num_pos+1, NULL, 0) : 0;
+               phpdbg_breaksymbol_t new_break;
+               zend_llist *break_sym_ptr;
+               size_t name_len = opline_num_pos ? opline_num_pos - expr : strlen(expr);
+
+               new_break.symbol = estrndup(expr, name_len);
+               new_break.opline_num = opline_num;
+
+               PHPDBG_G(has_sym_bp) = 1;
+
+               if (zend_hash_find(&PHPDBG_G(bp_symbols),
+                       new_break.symbol, name_len, (void**)&break_sym_ptr) == FAILURE) {
+                       zend_llist break_syms;
+
+                       zend_llist_init(&break_syms, sizeof(phpdbg_breaksymbol_t),
+                               phpdbg_llist_breaksym_dtor, 0);
+
+                       zend_hash_update(&PHPDBG_G(bp_symbols),
+                               new_break.symbol, name_len, &break_syms, sizeof(zend_llist),
+                               (void**)&break_sym_ptr);
+               }
+               zend_llist_add_element(break_sym_ptr, &new_break);
        }
 
        return SUCCESS;
@@ -316,12 +347,12 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le
        return FAILURE;
 } /* }}} */
 
-int phpdbg_breakpoint(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+int phpdbg_breakpoint_file(zend_op_array *op_array TSRMLS_DC) /* {{{ */
 {
        size_t name_len = strlen(op_array->filename);
        zend_llist *break_list;
 
-       if (zend_hash_find(&PHPDBG_G(break_files), op_array->filename, name_len,
+       if (zend_hash_find(&PHPDBG_G(bp_files), op_array->filename, name_len,
                (void**)&break_list) == SUCCESS) {
                zend_llist_element *le;
 
@@ -338,6 +369,30 @@ int phpdbg_breakpoint(zend_op_array *op_array TSRMLS_DC) /* {{{ */
        return FAILURE;
 } /* }}} */
 
+int phpdbg_breakpoint_symbol(zend_function *fbc TSRMLS_DC)
+{
+       const char *fname;
+       zend_llist *break_list;
+
+       if (fbc->type != ZEND_USER_FUNCTION) {
+               return FAILURE;
+       }
+
+       fname = ((zend_op_array*)fbc)->function_name;
+
+       if (!fname) {
+               fname = "main";
+       }
+
+       if (zend_hash_find(&PHPDBG_G(bp_symbols), fname, strlen(fname),
+               (void**)&break_list) == SUCCESS) {
+               printf("breakpoint reached!\n");
+               return SUCCESS;
+       }
+
+       return FAILURE;
+}
+
 int phpdbg_interactive(int argc, char **argv TSRMLS_DC) /* {{{ */
 {
        char cmd[PHPDBG_MAX_CMD];
@@ -389,7 +444,15 @@ zend_vm_enter:
         printf("[OPLINE: %p]\n", execute_data->opline);
 
         if (PHPDBG_G(has_file_bp)
-                       && phpdbg_breakpoint(execute_data->op_array TSRMLS_CC) == SUCCESS) {
+                       && phpdbg_breakpoint_file(execute_data->op_array TSRMLS_CC) == SUCCESS) {
+                       while (phpdbg_interactive(0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
+                               continue;
+                       }
+               }
+
+               if (PHPDBG_G(has_sym_bp)
+                       && (execute_data->opline->opcode == ZEND_DO_FCALL || execute_data->opline->opcode == ZEND_DO_FCALL_BY_NAME)
+                       && phpdbg_breakpoint_symbol(execute_data->function_state.function TSRMLS_CC) == SUCCESS) {
                        while (phpdbg_interactive(0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
                                continue;
                        }
index 8a4dfad675fd6d47087514002d45575e48a51f93..0f938e0051eb2701edea6d222ff5b2a35f983705 100644 (file)
@@ -57,6 +57,7 @@ typedef struct _phpdbg_breakfile_t {
  */
 typedef struct _phpdbg_breaksymbol_t {
        const char *symbol;
+       long opline_num;
 } phpdbg_breaksymbol_t;
 
 /**
index cbb2641e4faa7e9f48fcb5ca62fc2af77df5adbb..0a10de16a93ebf1e545e73dab9fbb29a9c1eb1db 100644 (file)
--- a/test.php
+++ b/test.php
@@ -1,6 +1,8 @@
 <?php
-echo "Hello World\n";
-if (isset($greeting)) {
-    echo $greeting;
+function test() {
+       echo "Hello World\n";
+}
+if (!isset($greeting)) {
+    echo test();
 }
 ?>