mirror of
https://github.com/php/php-src.git
synced 2026-03-31 04:32:19 +02:00
Finished working for today, continuing tomorrow (not working)
This commit is contained in:
2
phpdbg.c
2
phpdbg.c
@@ -153,7 +153,7 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */
|
||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0);
|
||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], 8, NULL, NULL, 0);
|
||||
|
||||
|
||||
zend_hash_init(&PHPDBG_G(seek), 8, NULL, NULL, 0);
|
||||
zend_hash_init(&PHPDBG_G(registered), 8, NULL, php_phpdbg_destroy_registered, 0);
|
||||
|
||||
|
||||
1
phpdbg.h
1
phpdbg.h
@@ -177,6 +177,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
|
||||
|
||||
phpdbg_btree *watchpoint_tree; /* tree with watchpoints */
|
||||
HashTable watchpoints; /* watchpoints */
|
||||
zend_llist watchlist_mem; /* triggered watchpoints */
|
||||
|
||||
char *exec; /* file to execute */
|
||||
size_t exec_len; /* size of exec */
|
||||
|
||||
@@ -1291,6 +1291,13 @@ zend_vm_enter:
|
||||
phpdbg_print_opline_ex(
|
||||
execute_data, &vars, 0 TSRMLS_CC);
|
||||
|
||||
/* check if some watchpoint was hit */
|
||||
{
|
||||
if (phpdbg_print_changed_zvals(TSRMLS_C) == SUCCESS) {
|
||||
DO_INTERACTIVE();
|
||||
}
|
||||
}
|
||||
|
||||
/* search for breakpoints */
|
||||
{
|
||||
phpdbg_breakbase_t *brake;
|
||||
|
||||
150
phpdbg_watch.c
150
phpdbg_watch.c
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 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"
|
||||
#include "phpdbg_watch.h"
|
||||
@@ -8,7 +28,20 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
|
||||
|
||||
long phpdbg_pagesize;
|
||||
|
||||
void phpdbg_setup_watchpoints() {
|
||||
typedef struct {
|
||||
void *page;
|
||||
size_t size;
|
||||
/* data must be last element */
|
||||
void *data;
|
||||
} phpdbg_watch_memdump;
|
||||
|
||||
#define MEMDUMP_SIZE(size) (sizeof(phpdbg_watch_memdump) - sizeof(void *) + (size))
|
||||
|
||||
void phpdbg_watch_mem_dtor(void *llist_data) {
|
||||
efree(llist_data);
|
||||
}
|
||||
|
||||
void phpdbg_setup_watchpoints(TSRMLS_D) {
|
||||
#ifdef _SC_PAGE_SIZE
|
||||
phpdbg_pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
@@ -18,32 +51,124 @@ void phpdbg_setup_watchpoints() {
|
||||
#ifdef _SC_NUTC_OS_PAGESIZE
|
||||
phpdbg_pagesize = sysconf(_SC_NUTC_OS_PAGESIZE);
|
||||
#endif
|
||||
|
||||
zend_llist_init(&PHPDBG_G(watchlist_mem), 0, phpdbg_watch_mem_dtor, 0);
|
||||
}
|
||||
|
||||
int phpdbg_check_for_watchpoint(void *addr) {
|
||||
return FAILURE;
|
||||
void *phpdbg_get_page_boundary(void *addr) {
|
||||
return (void *)((unsigned long)addr & ~(phpdbg_pagesize - 1));
|
||||
}
|
||||
|
||||
size_t phpdbg_get_total_page_size(size_t size) {
|
||||
return ((size - 1) & ~(phpdbg_pagesize - 1)) | phpdbg_pagesize;
|
||||
}
|
||||
|
||||
phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr) {
|
||||
phpdbg_watchpoint_t *watch;
|
||||
|
||||
/* find nearest watchpoint */
|
||||
|
||||
/* check if that watchpoint includes addr */
|
||||
if (((char *)watch->addr.ptr) + watch->size > (char *)addr) {
|
||||
/* failure */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return watch;
|
||||
}
|
||||
|
||||
int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) {
|
||||
printf("Text");
|
||||
return FAILURE;
|
||||
void *addr;
|
||||
void *page;
|
||||
phpdbg_watch_memdump *dump;
|
||||
phpdbg_watchpoint_t *watch;
|
||||
size_t size;
|
||||
|
||||
addr = info->si_addr;
|
||||
|
||||
watch = phpdbg_check_for_watchpoint(addr);
|
||||
|
||||
if (watch == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
page = phpdbg_get_page_boundary(addr);
|
||||
size = phpdbg_get_total_page_size(watch->size);
|
||||
|
||||
/* re-enable writing */
|
||||
mprotect(page, size, PROT_NONE | PROT_READ | PROT_WRITE);
|
||||
|
||||
dump = emalloc(MEMDUMP_SIZE(size));
|
||||
|
||||
memcpy(&dump->data, page, size);
|
||||
|
||||
zend_llist_add_element(&PHPDBG_G(watchlist_mem), dump);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void phpdbg_create_addr_watchpoint(void *addr, size_t size) {
|
||||
int phpdbg_print_changed_zval(void *llist_data) {
|
||||
phpdbg_watch_memdump *dump = llist_data;
|
||||
phpdbg_watchpoint_t *watch;
|
||||
phpdbg_btree *tree = PHPDBG_G(watchpoint_tree);
|
||||
void *oldPtr;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* fetch all changes between dump->page and dump->page + dump->size */
|
||||
watch = tree->watchpoint;
|
||||
oldPtr = (char *)dump->data + ((size_t)watch->addr.ptr - (size_t)dump->page);
|
||||
if (memcmp(oldPtr, watch->addr.ptr, watch->size) == SUCCESS) {
|
||||
phpdbg_notice("Breaking on watchpoint %s", watch->str);
|
||||
switch (watch->type) {
|
||||
case WATCH_ON_ZVAL:
|
||||
phpdbg_write("Old value: ");
|
||||
zend_print_flat_zval_r((zval *)oldPtr TSRMLS_CC);
|
||||
phpdbg_write("New value: ");
|
||||
zend_print_flat_zval_r(watch->addr.zv TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int phpdbg_print_changed_zvals(TSRMLS_D) {
|
||||
if (zend_llist_count(&PHPDBG_G(watchlist_mem)) == 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_llist_apply_with_del(&PHPDBG_G(watchlist_mem), phpdbg_print_changed_zval);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch) {
|
||||
int m;
|
||||
|
||||
/* pagesize is assumed to be in the range of 2^x */
|
||||
m= mprotect((void *)((unsigned long)addr & ~(phpdbg_pagesize - 1)), ((size - 1) & ~(phpdbg_pagesize - 1)) | phpdbg_pagesize, PROT_NONE | PROT_READ);
|
||||
watch->addr.ptr = addr;
|
||||
watch->size = size;
|
||||
watch->type = WATCH_ON_PTR;
|
||||
|
||||
printf("\n!!!!!\n%d\n!!!!!\n", m);
|
||||
/* pagesize is assumed to be in the range of 2^x */
|
||||
m = mprotect(phpdbg_get_page_boundary(addr), phpdbg_get_total_page_size(size), PROT_NONE | PROT_READ);
|
||||
|
||||
if (m == FAILURE) {
|
||||
phpdbg_error("Unable to set watchpoint (mprotect() failed)");
|
||||
zend_bailout();
|
||||
}
|
||||
}
|
||||
|
||||
void phpdbg_create_zval_watchpoint(zval *zv) {
|
||||
phpdbg_create_addr_watchpoint(zv, sizeof(zval));
|
||||
void phpdbg_create_zval_watchpoint(zval *zv, phpdbg_watchpoint_t *watch) {
|
||||
phpdbg_create_addr_watchpoint(zv, sizeof(zval), watch);
|
||||
watch->type = WATCH_ON_ZVAL;
|
||||
}
|
||||
|
||||
int phpdbg_create_var_watchpoint(char *name, size_t len TSRMLS_DC) {
|
||||
zval *zv;
|
||||
phpdbg_watchpoint_t watch;
|
||||
|
||||
|
||||
if (!EG(active_op_array)) {
|
||||
phpdbg_error("No active op array!");
|
||||
@@ -61,7 +186,8 @@ int phpdbg_create_var_watchpoint(char *name, size_t len TSRMLS_DC) {
|
||||
|
||||
/* Lookup current symbol table */
|
||||
if (zend_hash_find(EG(current_execute_data)->symbol_table, name, len + 1, (void **)&zv) == SUCCESS) {
|
||||
phpdbg_create_zval_watchpoint(zv);
|
||||
phpdbg_create_zval_watchpoint(zv, &watch);
|
||||
zend_hash_add(&PHPDBG_G(watchpoints), name, len, &watch, sizeof(phpdbg_watchpoint_t), NULL);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 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_WATCH_H
|
||||
#define PHPDBG_WATCH_H
|
||||
|
||||
@@ -30,14 +50,16 @@ struct _phpdbg_watchpoint_t {
|
||||
HashTable *ht;
|
||||
void *ptr;
|
||||
} addr;
|
||||
int size;
|
||||
size_t size;
|
||||
phpdbg_watchtype type;
|
||||
};
|
||||
|
||||
void phpdbg_setup_watchpoints();
|
||||
void phpdbg_setup_watchpoints(TSRMLS_D);
|
||||
|
||||
int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC);
|
||||
|
||||
int phpdbg_create_var_watchpoint(char *name, size_t len TSRMLS_DC);
|
||||
|
||||
int phpdbg_print_changed_zvals(TSRMLS_D);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user