From 3a3f3696788c8af3ee19bade368197561fb7df78 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 16 Jan 2011 20:39:22 +0000 Subject: [PATCH] Add options to debug_backtrace functions --- NEWS | 1 + Zend/tests/debug_backtrace_options.phpt | 397 ++++++++++++++++++++++++ Zend/zend.h | 3 + Zend/zend_builtin_functions.c | 26 +- Zend/zend_constants.c | 2 + 5 files changed, 417 insertions(+), 12 deletions(-) create mode 100755 Zend/tests/debug_backtrace_options.phpt diff --git a/NEWS b/NEWS index f6c179d074..34f08317eb 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ - Zend Engine: . Indirect reference to $this fails to resolve if direct $this is never used in method. (Scott) + . Added options to debug backtrace functions. (Stas) . Fixed Bug #53629 (memory leak inside highlight_string()). (Hannes, Ilia) - Core: diff --git a/Zend/tests/debug_backtrace_options.phpt b/Zend/tests/debug_backtrace_options.phpt new file mode 100755 index 0000000000..1b2d7e5485 --- /dev/null +++ b/Zend/tests/debug_backtrace_options.phpt @@ -0,0 +1,397 @@ +--TEST-- +debug_backtrace options +--FILE-- +doCall($dowhat, $how); + } +} +foo::statCall("doit", "debug_print_backtrace"); +foo::statCall("doit", "backtrace_print"); + +?> +--EXPECTF-- +==default +#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +==true +#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +==false +#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +==DEBUG_BACKTRACE_PROVIDE_OBJECT +#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d] +==DEBUG_BACKTRACE_IGNORE_ARGS +#0 doit() called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall() called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall() called at [%sdebug_backtrace_options.php:%d] +==both +#0 doit() called at [%sdebug_backtrace_options.php:%d] +#1 foo->doCall() called at [%sdebug_backtrace_options.php:%d] +#2 foo::statCall() called at [%sdebug_backtrace_options.php:%d] +==default +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => backtrace_print + [args] => Array + ( + ) + + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + [args] => Array + ( + [0] => a + [1] => b + [2] => backtrace_print + ) + + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [object] => foo Object + ( + ) + + [type] => -> + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + +) +==true +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => 17 + [function] => backtrace_print + [args] => Array + ( + [0] => 1 + ) + + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + [args] => Array + ( + [0] => a + [1] => b + [2] => backtrace_print + ) + + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [object] => foo Object + ( + ) + + [type] => -> + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + +) +==false +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => 19 + [function] => backtrace_print + [args] => Array + ( + [0] => + ) + + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + [args] => Array + ( + [0] => a + [1] => b + [2] => backtrace_print + ) + + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [type] => -> + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + +) +==DEBUG_BACKTRACE_PROVIDE_OBJECT +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => 21 + [function] => backtrace_print + [args] => Array + ( + [0] => 1 + ) + + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + [args] => Array + ( + [0] => a + [1] => b + [2] => backtrace_print + ) + + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [object] => foo Object + ( + ) + + [type] => -> + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + [args] => Array + ( + [0] => doit + [1] => backtrace_print + ) + + ) + +) +==DEBUG_BACKTRACE_IGNORE_ARGS +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => 23 + [function] => backtrace_print + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [type] => -> + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + ) + +) +==both +Array +( + [0] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => 25 + [function] => backtrace_print + ) + + [1] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doit + ) + + [2] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => doCall + [class] => foo + [object] => foo Object + ( + ) + + [type] => -> + ) + + [3] => Array + ( + [file] => %sdebug_backtrace_options.php + [line] => %d + [function] => statCall + [class] => foo + [type] => :: + ) + +) diff --git a/Zend/zend.h b/Zend/zend.h index a3fc72c948..4df761a0c9 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -771,6 +771,9 @@ ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC); ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC); ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC); +#define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0) +#define DEBUG_BACKTRACE_IGNORE_ARGS (1<<1) + #endif /* ZEND_H */ /* diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index a657ee22f7..6888b7f662 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -211,7 +211,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0) - ZEND_ARG_INFO(0, provide_object) + ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1) @@ -272,7 +272,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */ ZEND_FE(get_extension_funcs, arginfo_extension_loaded) ZEND_FE(get_defined_constants, arginfo_get_defined_constants) ZEND_FE(debug_backtrace, arginfo_debug_backtrace) - ZEND_FE(debug_print_backtrace, arginfo_zend__void) + ZEND_FE(debug_print_backtrace, arginfo_debug_backtrace) #if ZEND_DEBUG ZEND_FE(zend_test_func, NULL) #ifdef ZTS @@ -1944,7 +1944,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) } } -/* {{{ proto void debug_print_backtrace(void) */ +/* {{{ proto void debug_print_backtrace([int options]) */ ZEND_FUNCTION(debug_print_backtrace) { zend_execute_data *ptr, *skip; @@ -1956,8 +1956,9 @@ ZEND_FUNCTION(debug_print_backtrace) char *include_filename = NULL; zval *arg_array = NULL; int indent = 0; + long options = 0; - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) { return; } @@ -2016,7 +2017,7 @@ ZEND_FUNCTION(debug_print_backtrace) call_type = NULL; } if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { - if (ptr->function_state.arguments) { + if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) { arg_array = debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC); } } @@ -2103,7 +2104,7 @@ ZEND_FUNCTION(debug_print_backtrace) /* }}} */ -ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int provide_object TSRMLS_DC) +ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options TSRMLS_DC) { zend_execute_data *ptr, *skip; int lineno; @@ -2187,7 +2188,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup); } - if (provide_object) { + if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) { add_assoc_zval_ex(stack_frame, "object", sizeof("object"), ptr->object); Z_ADDREF_P(ptr->object); } @@ -2198,7 +2199,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1); } - if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { + if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && + ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) { if (ptr->function_state.arguments) { add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC)); } @@ -2264,17 +2266,17 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int /* }}} */ -/* {{{ proto array debug_backtrace([bool provide_object]) +/* {{{ proto array debug_backtrace([int options]) Return backtrace as array */ ZEND_FUNCTION(debug_backtrace) { - zend_bool provide_object = 1; + long options = DEBUG_BACKTRACE_PROVIDE_OBJECT; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &provide_object) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) { return; } - zend_fetch_debug_backtrace(return_value, 1, provide_object TSRMLS_CC); + zend_fetch_debug_backtrace(return_value, 1, options TSRMLS_CC); } /* }}} */ diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index c85610cc58..82e4a75271 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -113,6 +113,8 @@ void zend_register_standard_constants(TSRMLS_D) REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); /* true/false constants */ { zend_constant c; -- 2.40.0