summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2014-10-23 17:19:26 +0200
committerBob Weinand <bobwei9@hotmail.com>2014-10-23 17:19:26 +0200
commitf0254826784df569bfd5ae8aca16a05b04a9aa2e (patch)
treeefa926b84f7c799a2f44aa0da48f76d5c2c557e6
parent28dcdb2d130d63d4aece862d96fa27c440397705 (diff)
downloadphp-git-f0254826784df569bfd5ae8aca16a05b04a9aa2e.tar.gz
Add xml formatted deep dump of return value from ev
-rw-r--r--phpdbg_prompt.c4
-rw-r--r--phpdbg_utils.c138
-rw-r--r--phpdbg_utils.h2
-rw-r--r--xml.md83
4 files changed, 227 insertions, 0 deletions
diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c
index 6c78ec6d13..82444fbf1d 100644
--- a/phpdbg_prompt.c
+++ b/phpdbg_prompt.c
@@ -707,6 +707,10 @@ PHPDBG_COMMAND(ev) /* {{{ */
zend_try {
if (zend_eval_stringl(param->str, param->len,&retval, "eval()'d code" TSRMLS_CC) == SUCCESS) {
phpdbg_xml("<eval %r>");
+ if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
+ zval *zvp = &retval;
+ phpdbg_xml_var_dump(&zvp TSRMLS_CC);
+ }
zend_print_zval_r(&retval, 0 TSRMLS_CC);
phpdbg_xml("</eval>");
phpdbg_out("\n");
diff --git a/phpdbg_utils.c b/phpdbg_utils.c
index fa4b8b0baa..6dfec7d272 100644
--- a/phpdbg_utils.c
+++ b/phpdbg_utils.c
@@ -19,6 +19,7 @@
*/
#include "zend.h"
+
#include "php.h"
#include "phpdbg.h"
#include "phpdbg_opcode.h"
@@ -502,3 +503,140 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable
phpdbg_error("variable", "type=\"invalidinput\"", "Malformed input");
return FAILURE;
}
+
+static int phpdbg_xml_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+ phpdbg_xml("<element");
+
+ phpdbg_try_access {
+ if (hash_key->nKeyLength == 0) { /* numeric key */
+ phpdbg_xml(" name=\"%ld\"", hash_key->h);
+ } else { /* string key */
+ phpdbg_xml(" name=\"%.*s\"", hash_key->arKey, hash_key->nKeyLength - 1);
+ }
+ } phpdbg_catch_access {
+ phpdbg_xml(" severity=\"error\" ></element>");
+ return 0;
+ } phpdbg_end_try_access();
+
+ phpdbg_xml(">");
+
+ phpdbg_xml_var_dump(zv TSRMLS_CC);
+
+ phpdbg_xml("</element>");
+
+ return 0;
+}
+
+static int phpdbg_xml_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+ phpdbg_xml("<property");
+
+ phpdbg_try_access {
+ if (hash_key->nKeyLength == 0) { /* numeric key */
+ phpdbg_xml(" name=\"%ld\"", hash_key->h);
+ } else { /* string key */
+ const char *prop_name, *class_name;
+ int unmangle = zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
+
+ if (class_name && unmangle == SUCCESS) {
+ phpdbg_xml(" name=\"%s\"", prop_name);
+ if (class_name[0] == '*') {
+ phpdbg_xml(" protection=\"protected\"");
+ } else {
+ phpdbg_xml("class=\"%s\" protection=\"private\"", class_name);
+ }
+ } else {
+ phpdbg_xml(" name=\"%.*s\" protection=\"public\"", hash_key->arKey, hash_key->nKeyLength - 1);
+ }
+ }
+ } phpdbg_catch_access {
+ phpdbg_xml(" severity=\"error\" ></property>");
+ return 0;
+ } phpdbg_end_try_access();
+
+ phpdbg_xml(">");
+
+ phpdbg_xml_var_dump(zv TSRMLS_CC);
+
+ phpdbg_xml("</property>");
+
+ return 0;
+}
+
+#define COMMON (Z_ISREF_PP(zv) ? "&" : "")
+
+PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) {
+ HashTable *myht;
+ const char *class_name;
+ zend_uint class_name_len;
+ int (*element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
+ int is_temp;
+
+ phpdbg_try_access {
+ switch (Z_TYPE_PP(zv)) {
+ case IS_BOOL:
+ phpdbg_xml("<bool refstatus=\"%s\" value=\"%s\" />", COMMON, Z_LVAL_PP(zv) ? "true" : "false");
+ break;
+ case IS_NULL:
+ phpdbg_xml("<null refstatus=\"%s\" />", COMMON);
+ break;
+ case IS_LONG:
+ phpdbg_xml("<int refstatus=\"%s\" value=\"%ld\" />", COMMON, Z_LVAL_PP(zv));
+ break;
+ case IS_DOUBLE:
+ php_printf("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_PP(zv));
+ break;
+ case IS_STRING:
+ php_printf("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_PP(zv), Z_STRLEN_PP(zv), Z_STRVAL_PP(zv));
+ break;
+ case IS_ARRAY:
+ myht = Z_ARRVAL_PP(zv);
+ if (++myht->nApplyCount > 1) {
+ phpdbg_xml("<recursion />");
+ --myht->nApplyCount;
+ break;
+ }
+ phpdbg_xml("<array refstatus=\"%s\" num=\"%d\">", COMMON, zend_hash_num_elements(myht));
+ element_dump_func = phpdbg_xml_array_element_dump;
+ is_temp = 0;
+ goto head_done;
+ case IS_OBJECT:
+ myht = Z_OBJDEBUG_PP(zv, is_temp);
+ if (myht && ++myht->nApplyCount > 1) {
+ phpdbg_xml("<recursion />");
+ --myht->nApplyCount;
+ break;
+ }
+
+ if (Z_OBJ_HANDLER(**zv, get_class_name)) {
+ Z_OBJ_HANDLER(**zv, get_class_name)(*zv, &class_name, &class_name_len, 0 TSRMLS_CC);
+ phpdbg_xml("<object refstatus=\"%s\" class=\"%s\" id=\"%d\" num=\"%d\">", COMMON, class_name, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+ efree((char*)class_name);
+ } else {
+ phpdbg_xml("<object refstatus=\"%s\" class=\"\" id=\"%d\" num=\"%d\">", COMMON, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+ }
+ element_dump_func = phpdbg_xml_object_property_dump;
+head_done:
+ if (myht) {
+ zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) element_dump_func, 0);
+ --myht->nApplyCount;
+ if (is_temp) {
+ zend_hash_destroy(myht);
+ efree(myht);
+ }
+ }
+ if (Z_TYPE_PP(zv) == IS_ARRAY) {
+ phpdbg_xml("</array>");
+ } else {
+ phpdbg_xml("</object>");
+ }
+ break;
+ case IS_RESOURCE: {
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(zv) TSRMLS_CC);
+ phpdbg_xml("<resource refstatus=\"%s\" id=\"%ld\" type=\"%ld\" />", COMMON, Z_LVAL_PP(zv), type_name ? type_name : "unknown");
+ break;
+ }
+ default:
+ break;
+ }
+ } phpdbg_end_try_access();
+}
diff --git a/phpdbg_utils.h b/phpdbg_utils.h
index 52338c1836..d657dc79fd 100644
--- a/phpdbg_utils.h
+++ b/phpdbg_utils.h
@@ -110,4 +110,6 @@ typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyn
PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent TSRMLS_DC);
PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg TSRMLS_DC);
+PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC);
+
#endif /* PHPDBG_UTILS_H */
diff --git a/xml.md b/xml.md
index 05734d6be8..9d3b83f826 100644
--- a/xml.md
+++ b/xml.md
@@ -60,6 +60,7 @@ type
- general attribute for most errors, describes the genre of the error
+
General tags
============
@@ -460,6 +461,7 @@ ev
- eval()uates some code
- output wrapped in &lt;eval> tags
+- output is here first a dump of xml tags (see "Variable Dump" section), then a dump wrapped in <stream> tags
sh
--
@@ -633,6 +635,7 @@ dl
- errors may have the module or extension attribute when their name is already known at the point of failure
+
Other tags
==========
@@ -673,3 +676,83 @@ Other tags
- generally emitted when data couldn't be fetched (e.g. by accessing inconsistent data); only used in hard interrupt mode
- it might mean that data couldn't be fetched at all, or that only incomplete data was fetched (e.g. when a fixed number of following attributes are fetched, this tag will mark a stop of fetching if none or not all tags were printed)
+
+
+Variable Dump
+=============
+
+- all except property and element tags have a refstatus attribute, is set to non-empty if it's a reference
+
+object properties
+-----------------
+
+- wrapped in a property tag &lt;property name="" protection="">
+ - name: name of key
+ - protection: one of these three values: public / protected / private
+ - class: only present if protection attribute is set to "private", contains the name of the class to which the property belongs
+- if the property tag contains any serverity="error" attribute, there was some crucial error to read it, just skip it
+
+array elements
+--------------
+- wrapped in an element tag &lt;property name="" protection="">
+ - name: name of key
+- if the element tag contains any serverity="error" attribute, there was some crucial error to read it, jsut skip it
+
+int
+---
+
+- &lt;int refstatus="" value="" />
+ - value is the integer
+
+float
+-----
+
+- &lt;float refstatus="" value="" />
+ - value is the float
+
+bool
+----
+
+- &lt;bool refstatus="" value="" />
+ -value: true or false
+
+string
+------
+
+- &lt;string refstatus="" length="" value="" />
+ - length: length or string
+ - value: the string
+
+null
+----
+
+- &lt;null refstatus="" />
+
+array
+-----
+
+- &lt;array refstatus="" num="">
+ - num: number of elements
+ - contains &lt;element> tags
+
+object
+------
+
+- &lt;object refstatus="" class="" id="" num="">
+ - class: name of the class the object is an instance of (may be empty if unknown)
+ - id: id of the object
+ - num: number of properties
+ - contains &lt;property> tags
+
+resource
+--------
+
+- &lt;resource refstatus="" id="" type="" />
+ - id: resource id
+ - type: type of resource
+
+recursion
+---------
+
+- &lt;recursion />
+- if that tag appears, there's a recursive reference inside the value to be printed