]> granicus.if.org Git - php/commitdiff
First non-working test of segfault handlers
authorBob Weinand <bobwei9@hotmail.com>
Wed, 11 Dec 2013 20:27:03 +0000 (21:27 +0100)
committerBob Weinand <bobwei9@hotmail.com>
Wed, 11 Dec 2013 20:27:03 +0000 (21:27 +0100)
config.m4
config.w32
phpdbg.c
phpdbg.h
phpdbg_prompt.c
phpdbg_prompt.h

index 274e6409d04e488f7e39e3a2f6492b6ae3bcf2fe..3016a2075df4c904ea47b508ef5d4e1deeaeae46 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -18,7 +18,7 @@ if test "$PHP_PHPDBG" != "no"; then
   fi
 
   PHP_PHPDBG_CFLAGS="-D_GNU_SOURCE"
-  PHP_PHPDBG_FILES="phpdbg.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_set.c phpdbg_frame.c"
+  PHP_PHPDBG_FILES="phpdbg.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c"
 
   PHP_SUBST(PHP_PHPDBG_CFLAGS)
   PHP_SUBST(PHP_PHPDBG_FILES)
index 29031507b31a7763c53c80a899b8a4153920d13c..d97873ec85d3ddfcd5f78c094351db05cf361ac8 100644 (file)
@@ -1,7 +1,7 @@
 ARG_ENABLE('phpdbg', 'Build phpdbg', 'yes');
 ARG_ENABLE('phpdbgs', 'Build phpdbg shared', 'no');
 
-PHPDBG_SOURCES='phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_set.c phpdbg_frame.c';
+PHPDBG_SOURCES='phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c';
 PHPDBG_DLL='php' + PHP_VERSION + 'phpdbg.dll';
 PHPDBG_EXE='phpdbg.exe';
 
index 7a5cd48e439fb88206ddc860f31be0538dfddc65..d72133b2186421f30afeffa979dfef01ad58f4ba 100644 (file)
--- a/phpdbg.c
+++ b/phpdbg.c
@@ -765,6 +765,26 @@ int phpdbg_open_sockets(char *address, int port[2], int (*listen)[2], int (*sock
 } /* }}} */
 #endif
 
+void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) {
+       int is_handled = FAILURE;
+       TSRMLS_FETCH();
+
+       switch (sig) {
+               case SIGBUS:
+               case SIGSEGV:
+                       is_handled = phpdbg_watchpoint_segfault_handler(info, context TSRMLS_CC);
+                       if (is_handled == FAILURE) {
+#ifdef ZEND_SIGNALS
+                               zend_sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL TSRMLS_CC);
+#else
+                               sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL);
+#endif
+                       }
+                       break;
+       }
+
+}
+
 int main(int argc, char **argv) /* {{{ */
 {
        sapi_module_struct *phpdbg = &phpdbg_sapi_module;
@@ -802,6 +822,10 @@ int main(int argc, char **argv) /* {{{ */
        void ***tsrm_ls;
 #endif
 
+       struct sigaction signal_struct;
+       signal_struct.sa_sigaction = phpdbg_signal_handler;
+       signal_struct.sa_flags = SA_SIGINFO | SA_NODEFER;
+
 #ifndef _WIN32
        address = strdup("127.0.0.1");
        socket[0] = -1;
@@ -825,7 +849,9 @@ int main(int argc, char **argv) /* {{{ */
        tsrm_startup(1, 1, 0, NULL);
 
        tsrm_ls = ts_resource(0);
-#endif
+#endif 
+
+       phpdbg_setup_watchpoints();
 
 phpdbg_main:
        if (!cleaning) {
@@ -1061,17 +1087,28 @@ phpdbg_main:
        if (phpdbg->startup(phpdbg) == SUCCESS) {
                
                zend_activate(TSRMLS_C);
-               
+
+#ifdef ZEND_SIGNALS
+               zend_try {
+                       zend_signal_activate(TSRMLS_C);
+               } zend_end_try();
+#endif
+
+#ifdef ZEND_SIGNALS
+               zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try();
+               zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try();
+#else
+               sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal));
+               sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal));
+#endif
+
                /* do not install sigint handlers for remote consoles */
                /* sending SIGINT then provides a decent way of shutting down the server */
 #ifdef ZEND_SIGNALS
 # ifndef _WIN32
                if (listen[0] < 0) {
 # endif
-                       zend_try {
-                               zend_signal_activate(TSRMLS_C);
-                               zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC);
-                       } zend_end_try();
+                       zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try();
 # ifndef _WIN32
                }
 # endif
index 7d2b5b5e0c905a0803caa5b3e0d05f8db42738d9..906b894f263a42b7d1d1abefba3ad5f51cbb5400 100644 (file)
--- a/phpdbg.h
+++ b/phpdbg.h
@@ -38,6 +38,7 @@
 #include "zend_globals.h"
 #include "zend_ini_scanner.h"
 #include "zend_stream.h"
+#include "zend_signal.h"
 #include "SAPI.h"
 #include <fcntl.h>
 #include <sys/types.h>
@@ -67,6 +68,7 @@
 
 #include "phpdbg_cmd.h"
 #include "phpdbg_utils.h"
+#include "phpdbg_watch.h"
 
 #ifdef ZTS
 # define PHPDBG_G(v) TSRMG(phpdbg_globals_id, zend_phpdbg_globals *, v)
 #define PHPDBG_IO_FDS                  3 /* }}} */
 
 /* {{{ structs */
+typedef union _phpdbg_btree phpdbg_btree;
+union _phpdbg_btree {
+       phpdbg_btree *branches[2];
+       phpdbg_watchpoint_t *watchpoint;
+};
+
 ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
        HashTable bp[PHPDBG_BREAK_TABLES];           /* break points */
        HashTable registered;                        /* registered */
        HashTable seek;                              /* seek oplines */
        phpdbg_frame_t frame;                        /* frame */
 
+       struct sigaction old_sigsegv_signal;         /* segv signal handler */
+
+       phpdbg_btree *watchpoint_tree;               /* tree with watchpoints */
+       HashTable watchpoints;                       /* watchpoints */
+
        char *exec;                                  /* file to execute */
        size_t exec_len;                             /* size of exec */
        zend_op_array *ops;                          /* op_array */
index c42b8d1efb1bdd8fda6c9e9fa082ffcf0881037e..07b9f1400eebb77c50d8f7a5cc24e299a88648f6 100644 (file)
@@ -63,6 +63,7 @@ const phpdbg_command_t phpdbg_prompt_commands[] = {
        PHPDBG_COMMAND_D(source,  "execute a phpdbginit",                     '.', NULL, 1),
        PHPDBG_COMMAND_D(shell,   "shell a command",                          '-', NULL, 1),
        PHPDBG_COMMAND_D(quit,    "exit phpdbg",                              'q', NULL, 0),
+       PHPDBG_COMMAND_D(watch,   "set watchpoint",                           'w', NULL, 0),
        PHPDBG_END_COMMAND
 }; /* }}} */
 
@@ -1012,6 +1013,19 @@ PHPDBG_COMMAND(list) /* {{{ */
        return SUCCESS;
 } /* }}} */
 
+PHPDBG_COMMAND(watch) /* {{{ */
+{
+       switch (param->type) {
+               case STR_PARAM:
+                       phpdbg_create_var_watchpoint(param->str, param->len TSRMLS_CC);
+                       break;
+
+               phpdbg_default_switch_case();
+       }
+
+       return SUCCESS;
+} /* }}} */
+
 int phpdbg_interactive(TSRMLS_D) /* {{{ */
 {
        int ret = SUCCESS;
index 0bb2cc957f8818a6ef560124162d0a8784fd65ed..523fa6ad3cc700dfd8835812deb52dbf268e533c 100644 (file)
@@ -52,7 +52,8 @@ PHPDBG_COMMAND(shell);
 PHPDBG_COMMAND(set);
 PHPDBG_COMMAND(source);
 PHPDBG_COMMAND(register);
-PHPDBG_COMMAND(quit); /* }}} */
+PHPDBG_COMMAND(quit);
+PHPDBG_COMMAND(watch); /* }}} */
 
 /* {{{ prompt commands */
 extern const phpdbg_command_t phpdbg_prompt_commands[]; /* }}} */