Permalink
Browse files

Use smarter, half-expanded args in backtrace

  • Loading branch information...
1 parent 8600b47 commit c05a1cf1166782602833ff02fe830e50fe5794c9 @bwoebi bwoebi committed Nov 1, 2014
Showing with 174 additions and 4 deletions.
  1. +22 −2 phpdbg_frame.c
  2. +151 −2 phpdbg_utils.c
  3. +1 −0 phpdbg_utils.h
View
@@ -111,9 +111,13 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
zval **funcname, **class, **type, **args, **argstmp;
char is_class;
int has_args = FAILURE;
+ int name_len;
+ zval **file = NULL;
zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), (void **) &funcname);
+ zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **) &file);
+
if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "object", sizeof("object"), (void **) &class)) == FAILURE) {
is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"), (void **)&class);
} else {
@@ -137,7 +141,7 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
phpdbg_xml(" />");
}
- phpdbg_out("%s%s%s(",
+ name_len = phpdbg_out("%s%s%s(",
is_class == FAILURE?"":Z_STRVAL_PP(class),
is_class == FAILURE?"":Z_STRVAL_PP(type),
Z_STRVAL_PP(funcname)
@@ -148,8 +152,14 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
const zend_function *func = NULL;
const zend_arg_info *arginfo = NULL;
int j = 0, m;
+ int termwidth = phpdbg_get_terminal_width(TSRMLS_C);
+ int arglen;
zend_bool is_variadic = 0;
+ if (termwidth < 120) {
+ termwidth = 120;
+ }
+
phpdbg_try_access {
/* assuming no autoloader call is necessary, class should have been loaded if it's in backtrace ... */
if ((func = phpdbg_get_function(Z_STRVAL_PP(funcname), is_class == FAILURE ? NULL : Z_STRVAL_PP(class) TSRMLS_CC))) {
@@ -159,6 +169,13 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
m = func ? func->common.num_args : 0;
+ if (m) {
+ arglen = (termwidth - name_len - 20 - (file ? Z_STRLEN_PP(file) : 0)) / m - 10;
+ if (arglen < 20) {
+ arglen = 20;
+ }
+ }
+
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator);
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args), (void **) &argstmp, &iterator) == SUCCESS) {
if (j) {
@@ -177,7 +194,10 @@ static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
}
++j;
- zend_print_flat_zval_r(*argstmp TSRMLS_CC);
+ phpdbg_xml_var_dump(argstmp TSRMLS_CC);
+/* zend_print_flat_zval_r(*argstmp TSRMLS_CC);*/
+ phpdbg_print_flat_zval_r(argstmp, arglen TSRMLS_CC);
+
zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator);
phpdbg_xml("</arg>");
View
@@ -587,7 +587,7 @@ PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) {
break;
case IS_STRING:
phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_PP(zv), Z_STRLEN_PP(zv), Z_STRVAL_PP(zv));
- break;
+ break;
case IS_ARRAY:
myht = Z_ARRVAL_PP(zv);
if (++myht->nApplyCount > 1) {
@@ -632,11 +632,160 @@ PHPDBG_API void phpdbg_xml_var_dump(zval **zv TSRMLS_DC) {
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");
+ phpdbg_xml("<resource refstatus=\"%s\" id=\"%ld\" type=\"%s\" />", COMMON, Z_LVAL_PP(zv), type_name ? type_name : "unknown");
+ break;
+ }
+ default:
+ break;
+ }
+ } phpdbg_end_try_access();
+}
+
+static int phpdbg_print_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+ int *len = va_arg(args, int *);
+ zend_bool *first = va_arg(args, zend_bool *);
+
+ if (*first) {
+ *first = 0;
+ } else {
+ *len -= phpdbg_out(", ");
+ }
+
+ if (*len < 0) {
+ phpdbg_out("...");
+ return ZEND_HASH_APPLY_STOP;
+ }
+
+ phpdbg_try_access {
+ if (hash_key->nKeyLength == 0) { /* numeric key */
+ *len -= phpdbg_out("%ld => ", hash_key->h);
+ } else { /* string key */
+ *len -= phpdbg_out("\"%.*s\" => ", hash_key->nKeyLength - 1, hash_key->arKey);
+ }
+ } phpdbg_catch_access {
+ *len -= phpdbg_out("???");
+ return 0;
+ } phpdbg_end_try_access();
+
+ *len = phpdbg_print_flat_zval_r(zv, *len TSRMLS_CC);
+
+ return 0;
+}
+
+static int phpdbg_print_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) {
+ int *len = va_arg(args, int *);
+ zend_bool *first = va_arg(args, zend_bool *);
+
+ if (*first) {
+ *first = 0;
+ } else {
+ *len -= phpdbg_out(", ");
+ }
+
+ if (*len < 0) {
+ phpdbg_out("...");
+ return ZEND_HASH_APPLY_STOP;
+ }
+
+ phpdbg_try_access {
+ if (hash_key->nKeyLength == 0) { /* numeric key */
+ *len -= phpdbg_out("%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 && class_name[0] != '*') {
+ *len -= phpdbg_out("\"%s:%s\" => ", class_name, prop_name);
+ } else {
+ *len -= phpdbg_out("\"%s\" => ", prop_name);
+ }
+ }
+ } phpdbg_catch_access {
+ *len -= phpdbg_out("???");
+ return 0;
+ } phpdbg_end_try_access();
+
+
+ *len = phpdbg_print_flat_zval_r(zv, *len TSRMLS_CC);
+
+ return 0;
+}
+
+#define COMMON (Z_ISREF_PP(zv) ? "&" : "")
+
+PHPDBG_API int phpdbg_print_flat_zval_r(zval **zv, int len 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;
+ zend_bool first = 1;
+
+ phpdbg_try_access {
+ switch (Z_TYPE_PP(zv)) {
+ case IS_BOOL:
+ len -= phpdbg_out("%sbool(%s)", COMMON, Z_LVAL_PP(zv) ? "true" : "false");
+ break;
+ case IS_NULL:
+ len -= phpdbg_out("%snull", COMMON);
+ break;
+ case IS_LONG:
+ len -= phpdbg_out("%sint(%ld)", COMMON, Z_LVAL_PP(zv));
+ break;
+ case IS_DOUBLE:
+ len -= phpdbg_out("%sfloat(%.*G)", COMMON, (int) EG(precision), Z_DVAL_PP(zv));
+ break;
+ case IS_STRING:
+ len -= phpdbg_out("%sstring(%d) \"%.*s%s\"", COMMON, Z_STRLEN_PP(zv), Z_STRLEN_PP(zv) > len + 3 ? len < 3 ? 3 : len : Z_STRLEN_PP(zv), Z_STRVAL_PP(zv), Z_STRLEN_PP(zv) > len + 3 ? "..." : "");
+ break;
+ case IS_ARRAY:
+ myht = Z_ARRVAL_PP(zv);
+ if (++myht->nApplyCount > 1) {
+ len -= phpdbg_out("** RECURSION **");
+ --myht->nApplyCount;
+ break;
+ }
+ len -= phpdbg_out("%sarray(%d) [", COMMON, zend_hash_num_elements(myht));
+ element_dump_func = phpdbg_print_array_element_dump;
+ is_temp = 0;
+ goto head_done;
+ case IS_OBJECT:
+ myht = Z_OBJDEBUG_PP(zv, is_temp);
+ if (myht && ++myht->nApplyCount > 1) {
+ len -= phpdbg_out("** 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);
+ len -= phpdbg_out("%s%s#%u (%d) [", COMMON, class_name, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+ efree((char*)class_name);
+ } else {
+ len -= phpdbg_out("%s(Unknown class#%u (%d) [", COMMON, Z_OBJ_HANDLE_PP(zv), myht ? zend_hash_num_elements(myht) : 0);
+ }
+ element_dump_func = phpdbg_print_object_property_dump;
+head_done:
+ if (myht) {
+ zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) element_dump_func, 2, &len, &first);
+ --myht->nApplyCount;
+ if (is_temp) {
+ zend_hash_destroy(myht);
+ efree(myht);
+ }
+ }
+ len -= phpdbg_out("]");
+ break;
+ case IS_RESOURCE: {
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(zv) TSRMLS_CC);
+ len -= phpdbg_out("%sresource(#%ld) \"%s\"", COMMON, Z_LVAL_PP(zv), type_name ? type_name : "unknown");
break;
}
default:
break;
}
} phpdbg_end_try_access();
+
+ return len;
}
+
View
@@ -111,6 +111,7 @@ PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent,
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);
+PHPDBG_API int phpdbg_print_flat_zval_r(zval **zv, int len TSRMLS_DC);
#ifdef ZTS
#define PHPDBG_OUTPUT_BACKUP_DEFINES() \

0 comments on commit c05a1cf

Please sign in to comment.