summaryrefslogtreecommitdiff
path: root/phpdbg_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'phpdbg_utils.c')
-rw-r--r--phpdbg_utils.c138
1 files changed, 138 insertions, 0 deletions
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();
+}