From: Bob Weinand Date: Thu, 23 Oct 2014 15:19:26 +0000 (+0200) Subject: Add xml formatted deep dump of return value from ev X-Git-Tag: php-5.6.3RC1~51^2~8 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0254826784df569bfd5ae8aca16a05b04a9aa2e;p=php Add xml formatted deep dump of return value from ev --- 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(""); + 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(""); 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("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\" >"); + return 0; + } phpdbg_end_try_access(); + + phpdbg_xml(">"); + + phpdbg_xml_var_dump(zv TSRMLS_CC); + + phpdbg_xml(""); + + 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("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\" >"); + return 0; + } phpdbg_end_try_access(); + + phpdbg_xml(">"); + + phpdbg_xml_var_dump(zv TSRMLS_CC); + + phpdbg_xml(""); + + 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("", COMMON, Z_LVAL_PP(zv) ? "true" : "false"); + break; + case IS_NULL: + phpdbg_xml("", COMMON); + break; + case IS_LONG: + phpdbg_xml("", COMMON, Z_LVAL_PP(zv)); + break; + case IS_DOUBLE: + php_printf("", COMMON, (int) EG(precision), Z_DVAL_PP(zv)); + break; + case IS_STRING: + php_printf("", 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(""); + --myht->nApplyCount; + break; + } + phpdbg_xml("", 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(""); + --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("", COMMON, class_name, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0); + efree((char*)class_name); + } else { + phpdbg_xml("", 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(""); + } else { + phpdbg_xml(""); + } + break; + case IS_RESOURCE: { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(zv) TSRMLS_CC); + phpdbg_xml("", 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 <eval> tags +- output is here first a dump of xml tags (see "Variable Dump" section), then a dump wrapped in 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 <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 <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 +--- + +- <int refstatus="" value="" /> + - value is the integer + +float +----- + +- <float refstatus="" value="" /> + - value is the float + +bool +---- + +- <bool refstatus="" value="" /> + -value: true or false + +string +------ + +- <string refstatus="" length="" value="" /> + - length: length or string + - value: the string + +null +---- + +- <null refstatus="" /> + +array +----- + +- <array refstatus="" num=""> + - num: number of elements + - contains <element> tags + +object +------ + +- <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 <property> tags + +resource +-------- + +- <resource refstatus="" id="" type="" /> + - id: resource id + - type: type of resource + +recursion +--------- + +- <recursion /> +- if that tag appears, there's a recursive reference inside the value to be printed