From 8c22352e885986096f0293bddf57feddbdeac335 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 14 Apr 2014 15:45:15 +0200 Subject: [PATCH] Added $this and superglobals support for watchpoints --- phpdbg.c | 2 ++ phpdbg_watch.c | 43 ++++++++++++++++++++++++++++++++----------- phpdbg_watch.h | 4 ++-- test.php | 8 +++++++- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/phpdbg.c b/phpdbg.c index 213906a977..7a90b8d86b 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -1192,6 +1192,8 @@ phpdbg_main: SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]); } SG(request_info).argv[i] = exec ? estrndup(exec, exec_len) : estrdup(""); + + php_hash_environment(TSRMLS_C); } /* do not install sigint handlers for remote consoles */ diff --git a/phpdbg_watch.c b/phpdbg_watch.c index d7da10e7aa..b0edcefb23 100644 --- a/phpdbg_watch.c +++ b/phpdbg_watch.c @@ -138,6 +138,13 @@ static int phpdbg_create_array_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) return SUCCESS; } +static char *phpdbg_get_property_key(char *key) { + if (*key != 0) { + return key; + } + return strchr(key + 1, 0) + 1; +} + static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { HashTable *ht; @@ -183,7 +190,7 @@ static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_ } new_watch->str = NULL; - new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%.*s%s", (int)watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"[":"->", (int)new_watch->name_in_parent_len, new_watch->name_in_parent, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"]":""); + new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%s%s", (int)watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"[":"->", phpdbg_get_property_key(new_watch->name_in_parent), Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"]":""); phpdbg_create_zval_watchpoint(*zv, new_watch); phpdbg_create_recursive_watchpoint(new_watch TSRMLS_CC); @@ -229,7 +236,7 @@ static int phpdbg_delete_watchpoint_recursive(phpdbg_watchpoint_t *watch, zend_b zend_hash_get_current_key_zval_ex(ht, &key, &position); str = NULL; if (Z_TYPE(key) == IS_STRING) { - str_len = asprintf(&str, "%.*s%s%.*s%s", (int)watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", Z_STRLEN(key), Z_STRVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); + str_len = asprintf(&str, "%.*s%s%s%s", (int)watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", phpdbg_get_property_key(Z_STRVAL(key)), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); } else { str_len = asprintf(&str, "%.*s%s%li%s", (int)watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", Z_LVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); } @@ -280,7 +287,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, size_t 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), zend_bool silent TSRMLS_DC) { int ret = FAILURE; zend_bool new_index = 1; char *last_index; @@ -332,7 +339,7 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par zend_hash_get_current_key_zval_ex(parent, key, &position); convert_to_string(key); watch->str = malloc(i + Z_STRLEN_P(key) + 2); - watch->str_len = sprintf(watch->str, "%.*s%.*s%s", (int)i, input, Z_STRLEN_P(key), Z_STRVAL_P(key), input[len - 1] == ']'?"]":""); + watch->str_len = sprintf(watch->str, "%.*s%s%s", (int)i, input, phpdbg_get_property_key(Z_STRVAL_P(key)), input[len - 1] == ']'?"]":""); efree(key); watch->name_in_parent = zend_strndup(last_index, index_len); watch->name_in_parent_len = index_len; @@ -341,9 +348,9 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par ret = callback(watch TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; } else if (Z_TYPE_PP(zv) == IS_OBJECT) { - phpdbg_watchpoint_parse_input(input, len, Z_OBJPROP_PP(zv), i, callback TSRMLS_CC); + phpdbg_watchpoint_parse_input(input, len, Z_OBJPROP_PP(zv), i, callback, silent TSRMLS_CC); } else if (Z_TYPE_PP(zv) == IS_ARRAY) { - phpdbg_watchpoint_parse_input(input, len, Z_ARRVAL_PP(zv), i, callback TSRMLS_CC); + phpdbg_watchpoint_parse_input(input, len, Z_ARRVAL_PP(zv), i, callback, silent TSRMLS_CC); } else { /* Ignore silently */ } @@ -353,7 +360,9 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par char last_chr = last_index[index_len]; last_index[index_len] = 0; if (zend_symtable_find(parent, last_index, index_len + 1, (void **)&zv) == FAILURE) { - phpdbg_error("%.*s is undefined", (int)i, input); + if (!silent) { + phpdbg_error("%.*s is undefined", (int)i, input); + } return FAILURE; } last_index[index_len] = last_chr; @@ -386,6 +395,18 @@ static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *par return FAILURE; } +static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) { + if (EG(This) && len >= 5 && !memcmp("$this", input, 5)) { + zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL); + } + + if (zend_is_auto_global(input, len TSRMLS_CC)) { + phpdbg_watchpoint_parse_input(input, len, &EG(symbol_table), 0, callback, 1 TSRMLS_CC); + } + + return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, callback, 0 TSRMLS_CC); +} + PHPDBG_WATCH(delete) /* {{{ */ { switch (param->type) { @@ -411,7 +432,7 @@ PHPDBG_WATCH(recursive) /* {{{ */ switch (param->type) { case STR_PARAM: - if (phpdbg_watchpoint_parse_input(param->str, param->len, EG(active_symbol_table), 0, phpdbg_create_recursive_watchpoint TSRMLS_CC) != FAILURE) { + if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_recursive_watchpoint TSRMLS_CC) != FAILURE) { phpdbg_notice("Set recursive watchpoint on %.*s", (int)param->len, param->str); } break; @@ -430,7 +451,7 @@ PHPDBG_WATCH(array) /* {{{ */ switch (param->type) { case STR_PARAM: - if (phpdbg_watchpoint_parse_input(param->str, param->len, EG(active_symbol_table), 0, phpdbg_create_array_watchpoint TSRMLS_CC) != FAILURE) { + if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_array_watchpoint TSRMLS_CC) != FAILURE) { phpdbg_notice("Set array watchpoint on %.*s", (int)param->len, param->str); } break; @@ -469,7 +490,7 @@ int phpdbg_create_var_watchpoint(char *input, size_t len TSRMLS_DC) { return FAILURE; } - return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, phpdbg_create_watchpoint TSRMLS_CC); + return phpdbg_watchpoint_parse_symtables(input, len, phpdbg_create_watchpoint TSRMLS_CC); } int phpdbg_delete_var_watchpoint(char *input, size_t len TSRMLS_DC) { @@ -477,7 +498,7 @@ int phpdbg_delete_var_watchpoint(char *input, size_t len TSRMLS_DC) { return FAILURE; } - return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, phpdbg_delete_watchpoint TSRMLS_CC); + return phpdbg_watchpoint_parse_symtables(input, len, phpdbg_delete_watchpoint TSRMLS_CC); } #ifdef _WIN32 diff --git a/phpdbg_watch.h b/phpdbg_watch.h index 7c3a160034..d00bcff77e 100644 --- a/phpdbg_watch.h +++ b/phpdbg_watch.h @@ -56,8 +56,8 @@ typedef enum { } phpdbg_watchtype; -#define PHPDBG_WATCH_SIMPLE 0 -#define PHPDBG_WATCH_RECURSIVE 1 +#define PHPDBG_WATCH_SIMPLE 0x0 +#define PHPDBG_WATCH_RECURSIVE 0x1 typedef struct _phpdbg_watchpoint_t phpdbg_watchpoint_t; diff --git a/test.php b/test.php index e28b8dab98..a18851ca4a 100644 --- a/test.php +++ b/test.php @@ -70,7 +70,13 @@ array_walk($array, function (&$item) { $item -= 1; }); -$obj = (object)["a" => 2, "b" => 5, "c" => 7]; +class testClass { + public $a = 2; + protected $b = [1, 3]; + private $c = 7; +} + +$obj = new testClass; $test = $obj->a; -- 2.40.0