summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.frag4
-rw-r--r--config.w329
-rw-r--r--phpdbg.c49
-rw-r--r--phpdbg.h17
-rw-r--r--phpdbg_btree.c5
-rw-r--r--phpdbg_watch.c40
-rw-r--r--phpdbg_watch.h23
-rw-r--r--phpdbg_win.c81
-rw-r--r--phpdbg_win.h39
9 files changed, 213 insertions, 54 deletions
diff --git a/Makefile.frag b/Makefile.frag
index 5be6d5b00f..4aebfb40f3 100644
--- a/Makefile.frag
+++ b/Makefile.frag
@@ -23,6 +23,4 @@ test-phpdbg:
@echo "Running phpdbg tests ..."
@$(top_builddir)/sapi/cli/php sapi/phpdbg/tests/run-tests.php --phpdbg sapi/phpdbg/phpdbg
-.PHONY: clean-phpdbg test-phpdbg
-
-
+.PHONY: clean-phpdbg test-phpdbg \ No newline at end of file
diff --git a/config.w32 b/config.w32
index 5813e7f156..7501847726 100644
--- a/config.w32
+++ b/config.w32
@@ -1,19 +1,18 @@
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_watch.c phpdbg_btree.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_win.c phpdbg_btree.c';
PHPDBG_DLL='php' + PHP_VERSION + 'phpdbg.dll';
PHPDBG_EXE='phpdbg.exe';
if (PHP_PHPDBG == "yes") {
- /* build phpdbg binary */
SAPI('phpdbg', PHPDBG_SOURCES, PHPDBG_EXE);
ADD_FLAG("LIBS_PHPDBG", "ws2_32.lib user32.lib");
+ DEFINE("CFLAGS", configure_subst.item("CFLAGS") + " /EHa");
}
if (PHP_PHPDBGS == "yes") {
SAPI('phpdbgs', PHPDBG_SOURCES, PHPDBG_DLL, '/D PHP_PHPDBG_EXPORTS /I win32');
ADD_FLAG("LIBS_PHPDBGS", "ws2_32.lib user32.lib");
-}
-
-
+ DEFINE("CFLAGS", configure_subst.item("CFLAGS") + " /EHa");
+} \ No newline at end of file
diff --git a/phpdbg.c b/phpdbg.c
index b522b6cf39..af3b75c95e 100644
--- a/phpdbg.c
+++ b/phpdbg.c
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-#ifndef ZEND_SIGNALS
+#if !defined(ZEND_SIGNALS) || defined(_WIN32)
# include <signal.h>
#endif
#include "phpdbg.h"
@@ -30,14 +30,6 @@
#include "phpdbg_set.h"
#include "zend_alloc.h"
-/* the beginning (= the important part) of the _zend_mm_heap struct defined in Zend/zend_alloc.c */
-struct _zend_mm_heap {
- int use_zend_alloc;
- void *(*_malloc)(size_t);
- void (*_free)(void*);
- void *(*_realloc)(void*, size_t);
-};
-
/* {{{ remote console headers */
#ifndef _WIN32
# include <sys/socket.h>
@@ -818,7 +810,6 @@ int phpdbg_open_sockets(char *address, int port[2], int (*listen)[2], int (*sock
return SUCCESS;
} /* }}} */
-#endif
void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) {
int is_handled = FAILURE;
@@ -839,6 +830,7 @@ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) {
}
}
+#endif
int main(int argc, char **argv) /* {{{ */
{
@@ -877,11 +869,11 @@ int main(int argc, char **argv) /* {{{ */
void ***tsrm_ls;
#endif
+#ifndef _WIN32
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;
socket[1] = -1;
@@ -1154,51 +1146,52 @@ phpdbg_main:
phpdbg->ini_entries = ini_entries;
if (phpdbg->startup(phpdbg) == SUCCESS) {
-
+#ifdef _WIN32
+ EXCEPTION_POINTERS *xp;
+ __try {
+#endif
zend_mm_heap *mm_heap = zend_mm_set_heap(NULL TSRMLS_CC);
if (!mm_heap->use_zend_alloc) {
free(mm_heap);
mm_heap = zend_mm_startup();
}
PHPDBG_G(original_free_function) = mm_heap->_free;
+#ifdef _WIN32
+ phpdbg_win_set_mm_heap(mm_heap);
+#else
mm_heap->_free = phpdbg_watch_efree;
+#endif
zend_mm_set_heap(mm_heap TSRMLS_CC);
zend_activate(TSRMLS_C);
-#ifdef ZEND_SIGNALS
+#if defined(ZEND_SIGNALS) && !defined(_WIN32)
zend_try {
zend_signal_activate(TSRMLS_C);
} zend_end_try();
#endif
-#ifdef ZEND_SIGNALS
+#if defined(ZEND_SIGNALS) && !defined(_WIN32)
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
+#elif !defined(_WIN32)
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 defined(ZEND_SIGNALS) && !defined(_WIN32)
if (listen[0] < 0) {
-# endif
zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try();
-# ifndef _WIN32
}
-# endif
-#else
-# ifndef _WIN32
+#elif !defined(_WIN32)
if (listen[0] < 0) {
-# endif
+#endif
signal(SIGINT, phpdbg_sigint_handler);
#ifndef _WIN32
}
#endif
-#endif
PG(modules_activated) = 0;
@@ -1284,7 +1277,10 @@ phpdbg_main:
}
}
+/* #ifndef for making compiler shutting up */
+#ifndef _WIN32
phpdbg_interact:
+#endif
/* phpdbg main() */
do {
zend_try {
@@ -1377,6 +1373,11 @@ phpdbg_out:
} zend_end_try();
sapi_shutdown();
+#ifdef _WIN32
+ } __except(phpdbg_exception_handler_win32(xp = GetExceptionInformation())) {
+ // if !EXCEPTION_CONTINUE_EXECUTION
+ }
+ #endif
}
if (cleaning || remote) {
diff --git a/phpdbg.h b/phpdbg.h
index 4c2f2231ae..3c4c88b23e 100644
--- a/phpdbg.h
+++ b/phpdbg.h
@@ -39,7 +39,9 @@
#include "zend_globals.h"
#include "zend_ini_scanner.h"
#include "zend_stream.h"
-#include "zend_signal.h"
+#ifndef _WIN32
+# include "zend_signal.h"
+#endif
#include "SAPI.h"
#include <fcntl.h>
#include <sys/types.h>
@@ -169,8 +171,10 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
HashTable seek; /* seek oplines */
phpdbg_frame_t frame; /* frame */
+#ifndef _WIN32
struct sigaction old_sigsegv_signal; /* segv signal handler */
-
+#endif
+
phpdbg_btree watchpoint_tree; /* tree with watchpoints */
HashTable watchpoints; /* watchpoints */
zend_llist watchlist_mem; /* triggered watchpoints */
@@ -196,4 +200,13 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
zend_ulong flags; /* phpdbg flags */
ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */
+/* the beginning (= the important part) of the _zend_mm_heap struct defined in Zend/zend_alloc.c
+ Needed for realizing watchpoints */
+struct _zend_mm_heap {
+ int use_zend_alloc;
+ void *(*_malloc)(size_t);
+ void (*_free)(void *);
+ void *(*_realloc)(void *, size_t);
+};
+
#endif /* PHPDBG_H */
diff --git a/phpdbg_btree.c b/phpdbg_btree.c
index f3b6306a2a..f606135488 100644
--- a/phpdbg_btree.c
+++ b/phpdbg_btree.c
@@ -24,6 +24,11 @@
#define CHOOSE_BRANCH(n) \
branch = branch->branches[!!(n)];
+#ifdef _Win32
+# define emalloc malloc
+# define efree free
+#endif
+
/* depth in bits */
void phpdbg_btree_init(phpdbg_btree *tree, zend_ulong depth) {
tree->depth = depth;
diff --git a/phpdbg_watch.c b/phpdbg_watch.c
index f89b3277ad..0580592513 100644
--- a/phpdbg_watch.c
+++ b/phpdbg_watch.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
+ | Copyright (c) 1997-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,12 +23,13 @@
#include "phpdbg_btree.h"
#include "phpdbg_watch.h"
#include "phpdbg_utils.h"
-#include <unistd.h>
-#include <sys/mman.h>
+#ifndef _WIN32
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
-long phpdbg_pagesize;
typedef struct {
void *page;
@@ -40,13 +41,6 @@ typedef struct {
#define MEMDUMP_SIZE(size) (sizeof(phpdbg_watch_memdump) - sizeof(void *) + (size))
-static zend_always_inline void *phpdbg_get_page_boundary(void *addr) {
- return (void *)((size_t)addr & ~(phpdbg_pagesize - 1));
-}
-
-static zend_always_inline size_t phpdbg_get_total_page_size(void *addr, size_t size) {
- return (size_t)phpdbg_get_page_boundary(addr + size - 1) - (size_t)phpdbg_get_page_boundary(addr) + phpdbg_pagesize;
-}
static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) {
phpdbg_watchpoint_t *watch;
@@ -285,7 +279,7 @@ static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) {
return ret;
}
-static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, int i, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) {
+static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, size_t i, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) {
int ret = FAILURE;
zend_bool new_index = 1;
char *last_index;
@@ -456,13 +450,23 @@ int phpdbg_delete_var_watchpoint(char *input, size_t len TSRMLS_DC) {
return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, phpdbg_delete_watchpoint TSRMLS_CC);
}
+#ifdef _WIN32
+int phpdbg_watchpoint_segfault_handler(void *addr TSRMLS_DC) {
+#else
int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) {
+#endif
void *page;
phpdbg_watch_memdump *dump;
phpdbg_watchpoint_t *watch;
size_t size;
- watch = phpdbg_check_for_watchpoint(info->si_addr TSRMLS_CC);
+ watch = phpdbg_check_for_watchpoint(
+#ifdef _WIN32
+ addr
+#else
+ info->si_addr
+#endif
+ TSRMLS_CC);
if (watch == NULL) {
return FAILURE;
@@ -506,12 +510,12 @@ static void phpdbg_watch_dtor(void *pDest) {
static void phpdbg_watch_mem_dtor(void *llist_data) {
phpdbg_watch_memdump *dump = *(phpdbg_watch_memdump **)llist_data;
- free(*(void **)llist_data);
-
/* Disble writing again */
if (dump->reenable_writing) {
- mprotect(dump->page, dump->size, PROT_NONE | PROT_READ);
+ mprotect(dump->page, dump->size, PROT_READ);
}
+
+ free(*(void **)llist_data);
}
void phpdbg_setup_watchpoints(TSRMLS_D) {
@@ -668,10 +672,10 @@ void phpdbg_watch_efree(void *ptr) {
if (result) {
phpdbg_watchpoint_t *watch = result->ptr;
- if (watch->addr.ptr + watch->size > ptr) {
+ if ((size_t)watch->addr.ptr + watch->size > (size_t)ptr) {
zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len);
}
}
PHPDBG_G(original_free_function)(ptr);
-}
+} \ No newline at end of file
diff --git a/phpdbg_watch.h b/phpdbg_watch.h
index 1aa3ad75b0..71402ae803 100644
--- a/phpdbg_watch.h
+++ b/phpdbg_watch.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
+ | Copyright (c) 1997-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -24,6 +24,10 @@
#include "TSRM.h"
#include "phpdbg_cmd.h"
+#ifdef _WIN32
+# include "phpdbg_win.h"
+#endif
+
#define PHPDBG_WATCH(name) PHPDBG_COMMAND(watch_##name)
/**
@@ -76,7 +80,11 @@ struct _phpdbg_watchpoint_t {
void phpdbg_setup_watchpoints(TSRMLS_D);
+#ifndef _WIN32
int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC);
+#else
+int phpdbg_watchpoint_segfault_handler(void *addr TSRMLS_DC);
+#endif
void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch);
void phpdbg_create_zval_watchpoint(zval *zv, phpdbg_watchpoint_t *watch);
@@ -90,4 +98,15 @@ void phpdbg_list_watchpoints(TSRMLS_D);
void phpdbg_watch_efree(void *ptr);
-#endif
+
+long phpdbg_pagesize;
+
+static zend_always_inline void *phpdbg_get_page_boundary(void *addr) {
+ return (void *)((size_t)addr & ~(phpdbg_pagesize - 1));
+}
+
+static zend_always_inline size_t phpdbg_get_total_page_size(void *addr, size_t size) {
+ return (size_t)phpdbg_get_page_boundary((void *)((size_t)addr + size - 1)) - (size_t)phpdbg_get_page_boundary(addr) + phpdbg_pagesize;
+}
+
+#endif \ No newline at end of file
diff --git a/phpdbg_win.c b/phpdbg_win.c
new file mode 100644
index 0000000000..29f80449fa
--- /dev/null
+++ b/phpdbg_win.c
@@ -0,0 +1,81 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Felipe Pena <felipe@php.net> |
+ | Authors: Joe Watkins <joe.watkins@live.co.uk> |
+ | Authors: Bob Weinand <bwoebi@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "zend.h"
+#include "phpdbg.h"
+
+phpdbg_btree phpdbg_memory_tree;
+
+int mprotect(void *addr, size_t size, int protection) {
+ int var;
+ //printf("Set protection of %p to %s\n", addr, protection == (PROT_READ | PROT_WRITE) ? "rw": "r-");
+ return (int)VirtualProtect(addr, size, protection == (PROT_READ | PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, &var);
+}
+
+size_t virtual_size(void *ptr) {
+ return (size_t)phpdbg_btree_find(&phpdbg_memory_tree, (zend_ulong)ptr)->ptr;
+}
+
+void *virtual_malloc(size_t size) {
+ size_t real_size = phpdbg_get_total_page_size(NULL, size);
+ void *addr = VirtualAlloc(NULL, real_size, MEM_COMMIT, PAGE_READWRITE);
+ phpdbg_btree_insert(&phpdbg_memory_tree, (zend_ulong)addr, (void *)real_size);
+ return addr;
+}
+
+void virtual_free(void *ptr) {
+ phpdbg_watch_efree(ptr);
+ VirtualFree(ptr, virtual_size(ptr), MEM_RELEASE);
+ phpdbg_btree_delete(&phpdbg_memory_tree, (zend_ulong)ptr);
+}
+
+void *virtual_realloc(void *ptr, size_t size) {
+ void *ret;
+ size_t original_size = virtual_size(ptr);
+
+ if (original_size >= size) {
+ return ptr;
+ }
+
+ ret = virtual_malloc(size);
+ memcpy(ret, ptr, original_size);
+ virtual_free(ptr);
+ return ret;
+}
+
+void phpdbg_win_set_mm_heap(zend_mm_heap *heap) {
+ phpdbg_btree_init(&phpdbg_memory_tree, sizeof(void *) * 8);
+ heap->_free = virtual_free;
+ heap->_realloc = virtual_realloc;
+ heap->_malloc = virtual_malloc;
+}
+
+int phpdbg_exception_handler_win32(EXCEPTION_POINTERS *xp) {
+ EXCEPTION_RECORD *xr = xp->ExceptionRecord;
+ CONTEXT *xc = xp->ContextRecord;
+ if(xr->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+ TSRMLS_FETCH();
+ //printf("Watchpoint hit at: %p\n", xr->ExceptionInformation[1]);
+ if (phpdbg_watchpoint_segfault_handler((void *)xr->ExceptionInformation[1] TSRMLS_CC) == SUCCESS) {
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+} \ No newline at end of file
diff --git a/phpdbg_win.h b/phpdbg_win.h
new file mode 100644
index 0000000000..da97c797b1
--- /dev/null
+++ b/phpdbg_win.h
@@ -0,0 +1,39 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Felipe Pena <felipe@php.net> |
+ | Authors: Joe Watkins <joe.watkins@live.co.uk> |
+ | Authors: Bob Weinand <bwoebi@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef PHPDBG_WIN_H
+#define PHPDBG_WIN_H
+
+#include "winbase.h"
+#include "windows.h"
+#include "excpt.h"
+
+#define PROT_READ 1
+#define PROT_WRITE 2
+
+int mprotect(void *addr, size_t size, int protection);
+
+void phpdbg_win_set_mm_heap(zend_mm_heap *heap);
+
+int phpdbg_exception_handler_win32(EXCEPTION_POINTERS *xp);
+
+int __stdcall phpdbg_watch_set_segv_handler_asm();
+
+#endif \ No newline at end of file