summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/phpdbg_watch.h
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2016-07-11 23:28:14 +0200
committerBob Weinand <bobwei9@hotmail.com>2016-07-11 23:58:20 +0200
commitb00376884e00aa04614dd650e119aad653c1f16b (patch)
tree9531526edb549ef5eae6ada0d6a6969dfe085e46 /sapi/phpdbg/phpdbg_watch.h
parent1223f7f91b63d37c1282c05c0fab5a16bc83bbf1 (diff)
downloadphp-git-b00376884e00aa04614dd650e119aad653c1f16b.tar.gz
Rewrite watchpoints to be much more stable
This mainly involves a separate abstraction layer for elements (e.g. $a->b) and watchpoints (on pointer of the Bucket for example). Also better comparison handling (value backup vs. page dumps). It is not yet finished (there are sometimes false positives announced and names not yet perfect), but the functionality is working and not crashing as far as I have tested. Future scope is also relative watchpoints, e.g. "w $this->val expression()" which does not have the symbol tables as basis, but the value (in this example: return value of expression()) as basis.
Diffstat (limited to 'sapi/phpdbg/phpdbg_watch.h')
-rw-r--r--sapi/phpdbg/phpdbg_watch.h66
1 files changed, 48 insertions, 18 deletions
diff --git a/sapi/phpdbg/phpdbg_watch.h b/sapi/phpdbg/phpdbg_watch.h
index 82c925e011..4f19e5c4d6 100644
--- a/sapi/phpdbg/phpdbg_watch.h
+++ b/sapi/phpdbg/phpdbg_watch.h
@@ -45,6 +45,9 @@ typedef enum {
WATCH_ON_ZVAL,
WATCH_ON_HASHTABLE,
WATCH_ON_REFCOUNTED,
+ WATCH_ON_STR,
+ WATCH_ON_HASHDATA,
+ WATCH_ON_BUCKET,
} phpdbg_watchtype;
@@ -54,41 +57,68 @@ typedef enum {
#define PHPDBG_WATCH_OBJECT 0x08
#define PHPDBG_WATCH_NORMAL (PHPDBG_WATCH_SIMPLE | PHPDBG_WATCH_RECURSIVE)
#define PHPDBG_WATCH_IMPLICIT 0x10
+#define PHPDBG_WATCH_RECURSIVE_ROOT 0x20
-#define PHPDBG_DESTRUCTED_ZVAL 0x80
+typedef struct _phpdbg_watch_collision phpdbg_watch_collision;
-typedef struct _phpdbg_watchpoint_t phpdbg_watchpoint_t;
-
-struct _phpdbg_watchpoint_t {
+typedef struct _phpdbg_watchpoint_t {
union {
zval *zv;
zend_refcounted *ref;
+ Bucket *bucket;
void *ptr;
} addr;
size_t size;
phpdbg_watchtype type;
- char flags;
- unsigned int implicit_ht_count;
- phpdbg_watchpoint_t *parent;
- phpdbg_watchpoint_t *reference;
- HashTable *parent_container;
- zend_string *name_in_parent;
- zend_string *str;
+ zend_refcounted *ref; /* key to fetch the collision on parents */
+ HashTable elements;
+ phpdbg_watch_collision *coll; /* only present on *children* */
+ union {
+ zval zv;
+ Bucket bucket;
+ zend_refcounted ref;
+ HashTable ht;
+ zend_string *str;
+ } backup;
+} phpdbg_watchpoint_t;
+
+struct _phpdbg_watch_collision {
+ phpdbg_watchpoint_t ref;
+ phpdbg_watchpoint_t reference;
+ HashTable parents;
};
-typedef struct {
+typedef struct _phpdbg_watch_element {
+ uint32_t id;
phpdbg_watchpoint_t *watch;
- unsigned int refs;
- HashTable watches;
- HashTable implicit_watches;
-} phpdbg_watch_collision;
+ char flags;
+ struct _phpdbg_watch_element *child; /* always set for implicit watches */
+ struct _phpdbg_watch_element *parent;
+ HashTable child_container; /* children of this watch element for recursive array elements */
+ HashTable *parent_container; /* container of the value */
+ zend_string *name_in_parent;
+ zend_string *str;
+ union {
+ zval zv;
+ zend_refcounted ref;
+ HashTable ht;
+ } backup; /* backup for when watchpoint gets dissociated */
+} phpdbg_watch_element;
typedef struct {
- dtor_func_t dtor;
- HashTable watches;
+ /* to watch rehashes (yes, this is not *perfect*, but good enough for everything in PHP...) */
+ phpdbg_watchpoint_t hash_watch; /* must be first element */
+ Bucket *last;
+ zend_string *last_str;
+ zend_ulong last_idx;
+
+ HashTable *ht;
+ size_t data_size;
+ HashTable watches; /* contains phpdbg_watch_element */
} phpdbg_watch_ht_info;
void phpdbg_setup_watchpoints(void);
+void phpdbg_destroy_watchpoints(void);
#ifndef _WIN32
int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context);