diff --git a/config.m4 b/config.m4 index 4d4d95159..7c7ec07a1 100644 --- a/config.m4 +++ b/config.m4 @@ -26,7 +26,7 @@ dnl Check for new current_execute_data field in zend_executor_globals CPPFLAGS=$old_CPPFLAGS - PHP_NEW_EXTENSION(xdebug, xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_var.c xdebug_xml.c usefulstuff.c, $ext_shared,,,,yes) + PHP_NEW_EXTENSION(xdebug, xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_trace_textual.c xdebug_trace_computerized.c xdebug_trace_html.c xdebug_var.c xdebug_xml.c usefulstuff.c, $ext_shared,,,,yes) PHP_SUBST(XDEBUG_SHARED_LIBADD) PHP_ADD_MAKEFILE_FRAGMENT fi diff --git a/config.w32 b/config.w32 index 4b8f8eea2..4dfe1b680 100644 --- a/config.w32 +++ b/config.w32 @@ -4,6 +4,6 @@ ARG_WITH("xdebug", "Xdebug support", "no"); if (PHP_XDEBUG == "yes") { - EXTENSION("xdebug", "xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_var.c xdebug_xml.c usefulstuff.c"); + EXTENSION("xdebug", "xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_trace_textual.c xdebug_trace_computerized.c xdebug_trace_html.c xdebug_var.c xdebug_xml.c usefulstuff.c"); AC_DEFINE("HAVE_XDEBUG", 1, "Xdebug support"); } diff --git a/package.xml b/package.xml index 3a52f87b1..19fce00eb 100644 --- a/package.xml +++ b/package.xml @@ -177,6 +177,12 @@ Tue, May 08, 2012 - xdebug 2.2.0 + + + + + + diff --git a/php_xdebug.h b/php_xdebug.h index ba5c2d96a..efe8770ca 100644 --- a/php_xdebug.h +++ b/php_xdebug.h @@ -176,7 +176,9 @@ ZEND_BEGIN_MODULE_GLOBALS(xdebug) void (*orig_var_dump_func)(INTERNAL_FUNCTION_PARAMETERS); void (*orig_set_time_limit_func)(INTERNAL_FUNCTION_PARAMETERS); - FILE *trace_file; + xdebug_trace_handler_t *trace_handler; + void *trace_context; + zend_bool do_trace; zend_bool auto_trace; zend_bool trace_enable_trigger; @@ -184,7 +186,7 @@ ZEND_BEGIN_MODULE_GLOBALS(xdebug) char *trace_output_name; long trace_options; long trace_format; - char *tracefile_name; + //char *tracefile_name; char *last_exception_trace; char *last_eval_statement; diff --git a/tests/bug00538-2.phpt b/tests/bug00538-2.phpt index 03b729cc3..063e2aa3f 100644 --- a/tests/bug00538-2.phpt +++ b/tests/bug00538-2.phpt @@ -48,7 +48,7 @@ array(2) { ["params"]=> array(3) { ["param1"]=> - string(%d) "'%sxdebug'" + string(%d) "'%s'" ["param2"]=> string(16) "'candena\\a\\nb'" ["param3"]=> diff --git a/tests/stacktrace_variadic_html_0.phpt b/tests/stacktrace_variadic_html_0.phpt index 16b224c12..57c0e7844 100644 --- a/tests/stacktrace_variadic_html_0.phpt +++ b/tests/stacktrace_variadic_html_0.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_0.php:0 -2%f%dfoo( )../stacktrace_variadic_html_0.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_0.php:0 +2%f%dfoo( ).../stacktrace_variadic_html_0.php:7 3%f%dtrigger_error -( )../stacktrace_variadic_html_0.php:4 +( ).../stacktrace_variadic_html_0.php:4
- - + + +( )
( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_0.php:0
2%f%dfoo( )../stacktrace_variadic_html_0.php:8
1%f%d{main}( ).../stacktrace_variadic_html_0.php:0
2%f%dfoo( ).../stacktrace_variadic_html_0.php:8
3%f%dtrigger_error -( )../stacktrace_variadic_html_0.php:4
.../stacktrace_variadic_html_0.php:4

- - + + +( )
( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_0.php:0
2%f%dfoo( )../stacktrace_variadic_html_0.php:9
1%f%d{main}( ).../stacktrace_variadic_html_0.php:0
2%f%dfoo( ).../stacktrace_variadic_html_0.php:9
3%f%dtrigger_error -( )../stacktrace_variadic_html_0.php:4
.../stacktrace_variadic_html_0.php:4
diff --git a/tests/stacktrace_variadic_html_1.phpt b/tests/stacktrace_variadic_html_1.phpt index 03096fcdf..0df64bafa 100644 --- a/tests/stacktrace_variadic_html_1.phpt +++ b/tests/stacktrace_variadic_html_1.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_1.php:0 -2%f%dfoo( long, ??? )../stacktrace_variadic_html_1.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_1.php:0 +2%f%dfoo( long, ??? ).../stacktrace_variadic_html_1.php:7 3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_1.php:4 +( string(6) ).../stacktrace_variadic_html_1.php:4
- - + + +( string(6) )
( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_1.php:0
2%f%dfoo( long, ...variadic(bool) )../stacktrace_variadic_html_1.php:8
1%f%d{main}( ).../stacktrace_variadic_html_1.php:0
2%f%dfoo( long, ...variadic(bool) ).../stacktrace_variadic_html_1.php:8
3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_1.php:4
.../stacktrace_variadic_html_1.php:4

- - + + +( string(6) )
( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_1.php:0
2%f%dfoo( string(3), ...variadic(string(3), double) )../stacktrace_variadic_html_1.php:9
1%f%d{main}( ).../stacktrace_variadic_html_1.php:0
2%f%dfoo( string(3), ...variadic(string(3), double) ).../stacktrace_variadic_html_1.php:9
3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_1.php:4
.../stacktrace_variadic_html_1.php:4
diff --git a/tests/stacktrace_variadic_html_2.phpt b/tests/stacktrace_variadic_html_2.phpt index bcf1c3b60..9c71c2929 100644 --- a/tests/stacktrace_variadic_html_2.phpt +++ b/tests/stacktrace_variadic_html_2.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_2.php:0 -2%f%dfoo( long, ??? )../stacktrace_variadic_html_2.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_2.php:0 +2%f%dfoo( long, ??? ).../stacktrace_variadic_html_2.php:7 3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_2.php:4 +( string(6) ).../stacktrace_variadic_html_2.php:4
- - + + +( string(6) )
( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_2.php:0
2%f%dfoo( long, ...variadic(bool) )../stacktrace_variadic_html_2.php:8
1%f%d{main}( ).../stacktrace_variadic_html_2.php:0
2%f%dfoo( long, ...variadic(bool) ).../stacktrace_variadic_html_2.php:8
3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_2.php:4
.../stacktrace_variadic_html_2.php:4

- - + + +( string(6) )
( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_2.php:0
2%f%dfoo( string(3), ...variadic(string(3), double) )../stacktrace_variadic_html_2.php:9
1%f%d{main}( ).../stacktrace_variadic_html_2.php:0
2%f%dfoo( string(3), ...variadic(string(3), double) ).../stacktrace_variadic_html_2.php:9
3%f%dtrigger_error -( string(6) )../stacktrace_variadic_html_2.php:4
.../stacktrace_variadic_html_2.php:4
diff --git a/tests/stacktrace_variadic_html_3.phpt b/tests/stacktrace_variadic_html_3.phpt index b5de17813..9590ab661 100644 --- a/tests/stacktrace_variadic_html_3.phpt +++ b/tests/stacktrace_variadic_html_3.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_3.php:0 -2%f%dfoo( 42, ??? )../stacktrace_variadic_html_3.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_3.php:0 +2%f%dfoo( 42, ??? ).../stacktrace_variadic_html_3.php:7 3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_3.php:4 +( 'notice' ).../stacktrace_variadic_html_3.php:4
- - + + +( 'notice' )
( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_3.php:0
2%f%dfoo( 1, ...variadic(FALSE) )../stacktrace_variadic_html_3.php:8
1%f%d{main}( ).../stacktrace_variadic_html_3.php:0
2%f%dfoo( 1, ...variadic(FALSE) ).../stacktrace_variadic_html_3.php:8
3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_3.php:4
.../stacktrace_variadic_html_3.php:4

- - + + +( 'notice' )
( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_3.php:0
2%f%dfoo( 'foo', ...variadic('bar', 3.1415) )../stacktrace_variadic_html_3.php:9
1%f%d{main}( ).../stacktrace_variadic_html_3.php:0
2%f%dfoo( 'foo', ...variadic('bar', 3.1415) ).../stacktrace_variadic_html_3.php:9
3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_3.php:4
.../stacktrace_variadic_html_3.php:4
diff --git a/tests/stacktrace_variadic_html_4.phpt b/tests/stacktrace_variadic_html_4.phpt index afd09c964..d057ea896 100644 --- a/tests/stacktrace_variadic_html_4.phpt +++ b/tests/stacktrace_variadic_html_4.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_4.php:0 -2%f%dfoo( $a = 42, $b = ??? )../stacktrace_variadic_html_4.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_4.php:0 +2%f%dfoo( $a = 42, $b = ??? ).../stacktrace_variadic_html_4.php:7 3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_4.php:4 +( 'notice' ).../stacktrace_variadic_html_4.php:4
- - + + +( 'notice' )
( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_4.php:0
2%f%dfoo( $a = 1, ...$b = variadic(FALSE) )../stacktrace_variadic_html_4.php:8
1%f%d{main}( ).../stacktrace_variadic_html_4.php:0
2%f%dfoo( $a = 1, ...$b = variadic(FALSE) ).../stacktrace_variadic_html_4.php:8
3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_4.php:4
.../stacktrace_variadic_html_4.php:4

- - + + +( 'notice' )
( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_4.php:0
2%f%dfoo( $a = 'foo', ...$b = variadic('bar', 3.1415) )../stacktrace_variadic_html_4.php:9
1%f%d{main}( ).../stacktrace_variadic_html_4.php:0
2%f%dfoo( $a = 'foo', ...$b = variadic('bar', 3.1415) ).../stacktrace_variadic_html_4.php:9
3%f%dtrigger_error -( 'notice' )../stacktrace_variadic_html_4.php:4
.../stacktrace_variadic_html_4.php:4
diff --git a/tests/stacktrace_variadic_html_5.phpt b/tests/stacktrace_variadic_html_5.phpt index 333a955e2..88475de4e 100644 --- a/tests/stacktrace_variadic_html_5.phpt +++ b/tests/stacktrace_variadic_html_5.phpt @@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 ); ( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4 Call Stack #TimeMemoryFunctionLocation -1%f%d{main}( )../stacktrace_variadic_html_5.php:0 -2%f%dfoo( aTo0Mjs=, ??? )../stacktrace_variadic_html_5.php:7 +1%f%d{main}( ).../stacktrace_variadic_html_5.php:0 +2%f%dfoo( aTo0Mjs=, ??? ).../stacktrace_variadic_html_5.php:7 3%f%dtrigger_error -( czo2OiJub3RpY2UiOw== )../stacktrace_variadic_html_5.php:4 +( czo2OiJub3RpY2UiOw== ).../stacktrace_variadic_html_5.php:4
- - + + +( czo2OiJub3RpY2UiOw== )
( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_5.php:0
2%f%dfoo( aToxOw==, ...variadic(YjowOw==) )../stacktrace_variadic_html_5.php:8
1%f%d{main}( ).../stacktrace_variadic_html_5.php:0
2%f%dfoo( aToxOw==, ...variadic(YjowOw==) ).../stacktrace_variadic_html_5.php:8
3%f%dtrigger_error -( czo2OiJub3RpY2UiOw== )../stacktrace_variadic_html_5.php:4
.../stacktrace_variadic_html_5.php:4

- - + + +( czo2OiJub3RpY2UiOw== )
( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4
Call Stack
#TimeMemoryFunctionLocation
1%f%d{main}( )../stacktrace_variadic_html_5.php:0
2%f%dfoo( czozOiJmb28iOw==, ...variadic(czozOiJiYXIiOw==, ZDozLjE0MTUwMDAwMDAwMDAwMDI7) )../stacktrace_variadic_html_5.php:9
1%f%d{main}( ).../stacktrace_variadic_html_5.php:0
2%f%dfoo( czozOiJmb28iOw==, ...variadic(czozOiJiYXIiOw==, ZDozLjE0MTUwMDAwMDAwMDAwMDI7) ).../stacktrace_variadic_html_5.php:9
3%f%dtrigger_error -( czo2OiJub3RpY2UiOw== )../stacktrace_variadic_html_5.php:4
.../stacktrace_variadic_html_5.php:4
diff --git a/tests/xdebug_get_function_stack_variadic.phpt b/tests/xdebug_get_function_stack_variadic.phpt index 7b850eb48..2691a3d0c 100644 --- a/tests/xdebug_get_function_stack_variadic.phpt +++ b/tests/xdebug_get_function_stack_variadic.phpt @@ -34,7 +34,7 @@ array(4) { 'function' => string(3) "foo" 'file' => - string(80) "%sxdebug_get_function_stack_variadic.php" + string(%d) "%sxdebug_get_function_stack_variadic.php" 'line' => int(8) 'params' => @@ -49,7 +49,7 @@ array(4) { 'function' => string(3) "foo" 'file' => - string(80) "%sxdebug_get_function_stack_variadic.php" + string(%d) "%sxdebug_get_function_stack_variadic.php" 'line' => int(9) 'params' => @@ -67,7 +67,7 @@ array(4) { 'function' => string(3) "foo" 'file' => - string(80) "%sxdebug_get_function_stack_variadic.php" + string(%d) "%sxdebug_get_function_stack_variadic.php" 'line' => int(10) 'params' => diff --git a/xdebug.c b/xdebug.c index 8cce2905b..13f44c7c4 100644 --- a/xdebug.c +++ b/xdebug.c @@ -313,7 +313,8 @@ static void php_xdebug_init_globals (zend_xdebug_globals *xg TSRMLS_DC) xg->stack = NULL; xg->level = 0; xg->do_trace = 0; - xg->trace_file = NULL; + xg->trace_handler = NULL; + xg->trace_context = NULL; xg->coverage_enable = 0; xg->previous_filename = ""; xg->previous_file = NULL; @@ -330,6 +331,8 @@ static void php_xdebug_init_globals (zend_xdebug_globals *xg TSRMLS_DC) xg->output_is_tty = OUTPUT_NOT_CHECKED; xg->stdout_mode = 0; xg->in_at = 0; + xg->active_execute_data = NULL; + xg->active_op_array = NULL; xdebug_llist_init(&xg->server, xdebug_superglobals_dump_dtor); xdebug_llist_init(&xg->get, xdebug_superglobals_dump_dtor); @@ -470,7 +473,7 @@ static int xdebug_silence_handler(ZEND_OPCODE_HANDLER_ARGS) zend_op *cur_opcode = *EG(opline_ptr); if (XG(do_code_coverage)) { - xdebug_print_opcode_info('S', execute_data, cur_opcode); + xdebug_print_opcode_info('S', execute_data, cur_opcode TSRMLS_CC); } if (XG(do_scream)) { execute_data->opline++; @@ -490,7 +493,7 @@ static int xdebug_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS) if (XG(do_code_coverage)) { zend_op *cur_opcode = *EG(opline_ptr); - xdebug_print_opcode_info('I', execute_data, cur_opcode); + xdebug_print_opcode_info('I', execute_data, cur_opcode TSRMLS_CC); } #if PHP_VERSION_ID >= 50399 if (opline->extended_value == ZEND_EVAL) { @@ -709,6 +712,11 @@ PHP_MINIT_FUNCTION(xdebug) for (i = 0; i < 256; i++) { if (zend_get_user_opcode_handler(i) == NULL) { +#if ZTS + if (i == ZEND_HANDLE_EXCEPTION) { + continue; + } +#endif zend_set_user_opcode_handler(i, xdebug_check_branch_entry_handler); } } @@ -870,8 +878,8 @@ PHP_RINIT_FUNCTION(xdebug) XG(do_code_coverage) = 0; XG(code_coverage) = xdebug_hash_alloc(32, xdebug_coverage_file_dtor); XG(stack) = xdebug_llist_alloc(xdebug_stack_element_dtor); - XG(trace_file) = NULL; - XG(tracefile_name) = NULL; + XG(trace_handler) = NULL; + XG(trace_context) = NULL; XG(profile_file) = NULL; XG(profile_filename) = NULL; XG(prev_memory) = 0; @@ -997,7 +1005,7 @@ ZEND_MODULE_POST_ZEND_DEACTIVATE_D(xdebug) xdebug_llist_destroy(XG(stack), NULL); XG(stack) = NULL; - if (XG(do_trace) && XG(trace_file)) { + if (XG(do_trace) && XG(trace_context)) { xdebug_stop_trace(TSRMLS_C); } @@ -1294,7 +1302,7 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC) zval **dummy; function_stack_entry *fse, *xfse; char *magic_cookie = NULL; - int do_return = (XG(do_trace) && XG(trace_file)); + int do_return = (XG(do_trace) && XG(trace_context)); int function_nr = 0; xdebug_llist_element *le; int clear = 0; @@ -1426,7 +1434,9 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC) } function_nr = XG(function_count); - xdebug_trace_function_begin(fse, function_nr TSRMLS_CC); + if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_entry)) { + XG(trace_handler)->function_entry(XG(trace_context), fse, function_nr TSRMLS_CC); + } fse->symbol_table = EG(active_symbol_table); #if PHP_VERSION_ID < 50500 @@ -1493,25 +1503,23 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC) if (XG(profiler_enabled)) { xdebug_profiler_function_user_end(fse, op_array TSRMLS_CC); } - - xdebug_trace_function_end(fse, function_nr TSRMLS_CC); + + if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_exit)) { + XG(trace_handler)->function_exit(XG(trace_context), fse, function_nr TSRMLS_CC); + } /* Store return value in the trace file */ - if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_file)) { + if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_context)) { if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - char *t; #if PHP_VERSION_ID >= 50500 if (op_array->fn_flags & ZEND_ACC_GENERATOR) { - t = xdebug_return_trace_stack_generator_retval(fse, (zend_generator *) EG(return_value_ptr_ptr) TSRMLS_CC); + XG(trace_handler)->generator_return_value(XG(trace_context), fse, function_nr, (zend_generator*) EG(return_value_ptr_ptr) TSRMLS_CC); } else { - t = xdebug_return_trace_stack_retval(fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC); + XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC); } #else - t = xdebug_return_trace_stack_retval(fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC); + XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC); #endif - fprintf(XG(trace_file), "%s", t); - fflush(XG(trace_file)); - xdfree(t); } } if (clear && *EG(return_value_ptr_ptr)) { @@ -1559,7 +1567,7 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze zend_execute_data *edata = EG(current_execute_data); function_stack_entry *fse; zend_op *cur_opcode; - int do_return = (XG(do_trace) && XG(trace_file)); + int do_return = (XG(do_trace) && XG(trace_context)); int function_nr = 0; int restore_error_handler_situation = 0; @@ -1574,7 +1582,9 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze fse->function.internal = 1; function_nr = XG(function_count); - xdebug_trace_function_begin(fse, function_nr TSRMLS_CC); + if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_entry)) { + XG(trace_handler)->function_entry(XG(trace_context), fse, function_nr TSRMLS_CC); + } /* Check for entry breakpoints */ if (XG(remote_enabled) && XG(breakpoints_allowed)) { @@ -1616,18 +1626,17 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze zend_error_cb = tmp_error_cb; } - xdebug_trace_function_end(fse, function_nr TSRMLS_CC); + if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_exit)) { + XG(trace_handler)->function_exit(XG(trace_context), fse, function_nr TSRMLS_CC); + } /* Store return value in the trace file */ - if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_file) && EG(opline_ptr)) { + if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_context) && EG(opline_ptr) && current_execute_data->opline) { cur_opcode = *EG(opline_ptr); if (cur_opcode) { zval *ret = xdebug_zval_ptr(cur_opcode->XDEBUG_TYPE(result), &(cur_opcode->result), current_execute_data TSRMLS_CC); if (ret) { - char* t = xdebug_return_trace_stack_retval(fse, function_nr, ret TSRMLS_CC); - fprintf(XG(trace_file), "%s", t); - fflush(XG(trace_file)); - xdfree(t); + XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, ret TSRMLS_CC); } } } diff --git a/xdebug.ini b/xdebug.ini index 05d923121..c00edf69e 100644 --- a/xdebug.ini +++ b/xdebug.ini @@ -8,9 +8,9 @@ ; When this setting is set to on, the tracing of function calls will be enabled ; just before the script is run. This makes it possible to trace code in the ; auto_prepend_file [1]. -; +; ; [1] http://www.php.net/manual/en/configuration.directives.php#ini.auto-prepend-file -; +; ; ;xdebug.auto_trace = 0 @@ -24,17 +24,17 @@ ; If this setting is 1, Xdebug will color var_dumps and stack traces output when ; in CLI mode and when the output is a tty. On Windows, the ANSICON [1] tool ; needs to be installed. -; +; ; [1] http://adoxa.110mb.com/ansicon/ -; +; ; If the setting is 2, then Xdebug will always color var_dumps and stack trace, ; no matter whether it's connected to a tty or whether ANSICON is installed. In ; this case, you might end up seeing escape codes. -; +; ; See this article [1] for some more information. -; +; ; [1] http://drck.me/clicolor-9cr -; +; ; ;xdebug.cli_color = 0 @@ -47,7 +47,7 @@ ; ; This setting, defaulting to 0, controls whether Xdebug should add variable ; assignments to function traces. -; +; ; ;xdebug.collect_assignments = 0 @@ -59,7 +59,7 @@ ; This setting, defaulting to 1, controls whether Xdebug should write the ; filename used in include(), include_once(), require() or require_once() to the ; trace files. -; +; ; ;xdebug.collect_includes = 1 @@ -71,7 +71,7 @@ ; This setting, defaulting to 0, controls whether Xdebug should collect the ; parameters passed to functions when a function call is recorded in either the ; function trace or the stack trace. -; +; ; The setting defaults to 0 because for very large scripts it may use huge ; amounts of memory and therefore make it impossible for the huge script to run. ; You can most safely turn this setting on, but you can expect some problems in @@ -80,12 +80,12 @@ ; as it will never store this information in memory. Instead it will only be ; written to disk. This means that you need to have a look at the disk usage ; though. -; +; ; This setting can have four different values. For each of the values a ; different amount of information is shown. Below you will see what information ; each of the values provides. See also the introduction of the feature Stack ; Traces for a few screenshots. -; +; ; ===== ======================================================================== ; Value Argument Information Shown ; ===== ======================================================================== @@ -100,11 +100,15 @@ ; xdebug.var_display_max_depth. ; ----- ------------------------------------------------------------------------ ; 4 Full variable contents and variable name. +; ----- ------------------------------------------------------------------------ +; 5 PHP serialized variable contents, without the name. +; +; (New in Xdebug 2.3) ; ===== ======================================================================== -; +; ; 1 in the CLI version of PHP it will not have the tool tip, nor in output ; files. -; +; ; ;xdebug.collect_params = 0 @@ -115,7 +119,10 @@ ; ; This setting, defaulting to 0, controls whether Xdebug should write the return ; value of function calls to the trace files. -; +; +; For computerized trace files (xdebug.trace_format=1) this only works from +; Xdebug 2.3 onwards. +; ; ;xdebug.collect_return = 0 @@ -129,21 +136,21 @@ ; engineer PHP's opcode arrays. This setting will not record which values the ; different variables have, for that use xdebug.collect_params. This setting ; needs to be enabled only if you wish to use xdebug_get_declared_vars(). -; +; ; ;xdebug.collect_vars = 0 ; ----------------------------------------------------------------------------- ; xdebug.coverage_enable ; -; Only in Xdebug versions > 2.2 +; Only in Xdebug versions >= 2.2 ; ; Type: boolean, Default value: 1 ; ; If this setting is set to 0, then Xdebug will not set-up internal structures ; to allow code coverage. This speeds up Xdebug quite a bit, but of course, Code ; Coverage Analysis won't work. -; +; ; ;xdebug.coverage_enable = 1 @@ -156,7 +163,7 @@ ; event. You can disable showing stacktraces from your code with ; xdebug_disable(). As this is one of the basic functions of Xdebug, it is ; advisable to leave this setting set to 1. -; +; ; ;xdebug.default_enable = 1 @@ -165,15 +172,20 @@ ; ; Type: string, Default value: Empty ; -; * = COOKIE, FILES, GET, POST, REQUEST, SERVER, SESSION. These seven settings -; control which data from the superglobals is shown when an error situation -; occurs. Each php.ini setting can consist of a comma seperated list of -; variables from this superglobal to dump, but make sure you do not add spaces -; in this setting. In order to dump the REMOTE_ADDR and the REQUEST_METHOD when -; an error occurs, add this setting: -; +; * can be any of COOKIE, FILES, GET, POST, REQUEST, SERVER, SESSION. These +; seven settings control which data from the superglobals is shown when an error +; situation occurs. +; +; Each of those php.ini setting can consist of a comma seperated list of +; variables from this superglobal to dump, or ``*`` for all of them. Make sure +; you do not add spaces in this setting. +; +; In order to dump the REMOTE_ADDR and the REQUEST_METHOD when an error occurs, +; and all GET parameters, add these settings: +; ; xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD -; +; xdebug.dump.GET = * +; ; ;xdebug.dump.* = Empty @@ -183,8 +195,8 @@ ; Type: boolean, Default value: 1 ; ; Controls whether the values of the superglobals as defined by the -; xdebug.dump.* settings whould be shown or not. -; +; xdebug.dump.* settings should be shown or not. +; ; ;xdebug.dump_globals = 1 @@ -195,7 +207,7 @@ ; ; Controls whether the values of the superglobals should be dumped on all error ; situations (set to 0) or only on the first (set to 1). -; +; ; ;xdebug.dump_once = 1 @@ -206,7 +218,7 @@ ; ; If you want to dump undefined values from the superglobals you should set this ; setting to 1, otherwise leave it set to 0. -; +; ; ;xdebug.dump_undefined = 0 @@ -221,7 +233,7 @@ ; this option as PHP's generated oparrays will increase with about a third of ; the size slowing down your scripts. This setting can not be set in your ; scripts with ini_set(), but only in php.ini. -; +; ; ;xdebug.extended_info = 1 @@ -237,11 +249,11 @@ ; link-protocol that makes it possible to go directly to a line and file by ; clicking on the filenames that Xdebug shows in stack traces. An example format ; might look like: -; +; ; myide://%f@%l -; +; ; The possible format specifiers are: -; +; ; ========= =============== ; Specifier Meaning ; ========= =============== @@ -249,96 +261,160 @@ ; --------- --------------- ; %l the line number ; ========= =============== -; +; ; For various IDEs/OSses there are some instructions listed on how to make this ; work: -; +; ; ---------------- ; Firefox on Linux ; ---------------- -; +; ; - Open -; +; ; about:config -; +; ; - Add a new boolean setting "network.protocol-handler.expose.xdebug" -; +; ; - Add the following into a shell script -; +; ; ``~/bin/ff-xdebug.sh``: -; +; ; #! /bin/sh -; +; ; f=`echo $1 | cut -d @ -f 1 | sed 's/xdebug:\/\///'` ; l=`echo $1 | cut -d @ -f 2` -; +; ; Add to that one of (depending whether you have komodo or gvim): -; +; ; - komodo $f -l $l -; +; ; - gvim --remote-tab +$l $f -; +; ; - Make the script executable with -; +; ; chmod +x ~/bin/ff-xdebug.sh -; +; ; - Set the xdebug.file_link_format setting to -; +; ; xdebug://%f@%l -; +; ; -------------------- ; Windows and netbeans ; -------------------- -; +; ; - Create the file -; +; ; ``netbeans.bat`` and save it in your path ( ``C:\Windows`` will work): -; -; @echo off -; setlocal enableextensions enabledelayedexpansion +; +; @echo off +; setlocal enableextensions enabledelayedexpansion ; set NETBEANS=%1 ; set FILE=%~2 ; %NETBEANS% --nosplash --console suppress --open "%FILE:~19%" ; nircmd win activate process netbeans.exe -; +; ; **Note:** Remove the last line if you don't have ``nircmd``. -; +; ; - Save the following code as -; +; ; ``netbeans_protocol.reg``: -; +; ; Windows Registry Editor Version 5.00 -; +; ; [HKEY_CLASSES_ROOT\netbeans] ; "URL Protocol"="" ; @="URL:Netbeans Protocol" -; +; ; [HKEY_CLASSES_ROOT\netbeans\DefaultIcon] ; @="\"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe,1\"" -; +; ; [HKEY_CLASSES_ROOT\netbeans\shell] -; +; ; [HKEY_CLASSES_ROOT\netbeans\shell\open] -; +; ; [HKEY_CLASSES_ROOT\netbeans\shell\open\command] ; @="\"C:\\Windows\\netbeans.bat\" \"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe\" \"%1\"" -; +; ; **Note:** Make sure to change the path to Netbeans (twice), as well as the ; ``netbeans.bat`` batch file if you saved it somewhere else than ; ``C:\Windows\``. -; +; ; - Double click on the -; +; ; ``netbeans_protocol.reg`` file to import it into the registry. -; +; ; - Set the xdebug.file_link_format setting to -; +; ; xdebug.file_link_format = ; "netbeans://open/?f=%f:%l" -; +; ; ;xdebug.file_link_format = +; ----------------------------------------------------------------------------- +; xdebug.force_display_errors +; +; Only in Xdebug versions 2.3 +; +; Type: int, Default value: 0 +; +; If this setting is set to ``1`` then errors will **always** be displayed, no +; matter what the setting of PHP's display_errors [1] is. +; +; [1] http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors +; +; +;xdebug.force_display_errors = 0 + +; ----------------------------------------------------------------------------- +; xdebug.force_error_reporting +; +; Only in Xdebug versions 2.3 +; +; Type: int, Default value: 0 +; +; This setting is a bitmask, like error_reporting [1]. This bitmask will be +; logically ORed with the bitmask represented by error_reporting [2] to dermine +; which errors should be displayed. This setting can only be made in php.ini and +; allows you to force certain errors from being shown no matter what an +; application does with ini_set() [3]. +; +; [1] http://php.net/manual/en/errorfunc.configuration.php#ini.error-reporting +; [2] http://php.net/manual/en/errorfunc.configuration.php#ini.error-reporting +; [3] http://php.net/manual/en/function.ini-set.php +; +; +;xdebug.force_error_reporting = 0 + +; ----------------------------------------------------------------------------- +; xdebug.halt_level +; +; Only in Xdebug versions 2.3 +; +; Type: int, Default value: 0 +; +; This setting allows you to configure a mask that determines whether, and +; which, notices and/or warnings get converted to errors. You can configure +; notices and warnings that are generated by PHP, and notices and warnings that +; you generate yourself (by means of trigger_error()). For example, to convert +; the warning of strlen() (without arguments) to an error, you would do: +; +; ini_set('xdebug.halt_level', E_WARNING); +; echo "Hi!\n"; +; +; Which will then result in the showing of the error message, and the abortion +; of the script. ``echo "Hi!\n";`` will not be executed. +; +; The setting is a bit mask, so to convert all notices and warnings into errors +; for all applications, you can set this in php.ini: +; +; xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE +; +; The bitmask only supports the four level that are mentioned above. +; +; +;xdebug.halt_level = 0 + ; ----------------------------------------------------------------------------- ; xdebug.idekey ; @@ -350,7 +426,7 @@ ; to the first environment variable that is found. If none could be found the ; setting has as default ''. If this setting is set, it always overrides the ; environment variables. -; +; ; ;xdebug.idekey = *complex* @@ -364,7 +440,7 @@ ; This is the base url for the links from the function traces and error message ; to the manual pages of the function from the message. It is advisable to set ; this setting to use the closest mirror. -; +; ; ;xdebug.manual_url = http://www.php.net @@ -376,7 +452,7 @@ ; Controls the protection mechanism for infinite recursion protection. The value ; of this setting is the maximum level of nested functions that are allowed ; before the script will be aborted. -; +; ; ;xdebug.max_nesting_level = 100 @@ -391,7 +467,12 @@ ; displaying variables when the html_errors php.ini setting is set to 1. In case ; you do not want that, you can set this setting to 0, but check first if it's ; not smarter to turn off html_errors. -; +; +; You can also use ``2`` as value for this setting. Besides formatting the +; var_dump() output nicely, it will also add filename and line number to the +; output. The xdebug.file_link_format setting is also respected. *(New in Xdebug +; 2.3)* +; ; ;xdebug.overload_var_dump = 1 @@ -404,7 +485,7 @@ ; new request would map to the same file (depnding on the ; xdebug.profiler_output_name setting. Instead the file will be appended to with ; the new profile. -; +; ; ;xdebug.profiler_append = 0 @@ -418,7 +499,7 @@ ; can not be set in your script with ini_set(). If you want to selectively ; enable the profiler, please set xdebug.profiler_enable_trigger to 1 ; **instead** of using this setting. -; +; ; ;xdebug.profiler_enable = 0 @@ -432,7 +513,7 @@ ; name XDEBUG_PROFILE. This will then write the profiler data to defined ; directory. In order to prevent the profiler to generate profile files for each ; request, you need to set xdebug.profiler_enable to 0. -; +; ; ;xdebug.profiler_enable_trigger = 0 @@ -444,7 +525,7 @@ ; The directory where the profiler output will be written to, make sure that the ; user who the PHP will be running as has write permissions to that directory. ; This setting can not be set in your script with ini_set(). -; +; ; ;xdebug.profiler_output_dir = /tmp @@ -457,9 +538,9 @@ ; The setting specifies the format with format specifiers, very similar to ; sprintf() and strftime(). There are several format specifiers that can be used ; to format the file name. -; +; ; See the xdebug.trace_output_name documentation for the supported specifiers. -; +; ; ;xdebug.profiler_output_name = cachegrind.out.%p @@ -472,7 +553,7 @@ ; debugging (see Remote Debugging). When this setting is set to 1, Xdebug will ; always attempt to start a remote debugging session and try to connect to a ; client, even if the GET/POST/COOKIE variable was not present. -; +; ; ;xdebug.remote_autostart = 0 @@ -489,7 +570,7 @@ ; note that there is **no** filter available, and anybody who can connect to the ; webserver will then be able to start a debugging session, even if their ; address does not match xdebug.remote_host. -; +; ; ;xdebug.remote_connect_back = 0 @@ -502,7 +583,7 @@ ; ; This setting can be used to increase (or decrease) the time that the remote ; debugging session stays alive via the session cookie. -; +; ; ;xdebug.remote_cookie_expire_time = 3600 @@ -515,7 +596,7 @@ ; is listening on the host and port as set with the settings xdebug.remote_host ; and xdebug.remote_port. If a connection can not be established the script will ; just continue as if this setting was 0. -; +; ; ;xdebug.remote_enable = 0 @@ -526,14 +607,13 @@ ; ; Can be either 'php3' which selects the old PHP 3 style debugger [1] output, ; 'gdb' which enables the GDB like debugger interface or 'dbgp' - the debugger -; protocol [2]. The DBGp protocol is more widely supported by clients. See more -; information in the introduction for Remote Debugging. -; +; protocol [2]. The DBGp protocol is the only supported protocol. +; ; [1] http://www.php.net/manual/en/debugger.php ; [2] http://xdebug.org/docs-dbgp.php -; +; ; **Note**: Xdebug 2.1 and later only support 'dbgp' as protocol. -; +; ; ;xdebug.remote_handler = dbgp @@ -545,7 +625,7 @@ ; Selects the host where the debug client is running, you can either use a host ; name or an IP address. This setting is ignored if xdebug.remote_connect_back ; is enabled. -; +; ; ;xdebug.remote_host = localhost @@ -558,13 +638,13 @@ ; debugger communications are logged. The file is always opened in append-mode, ; and will therefore not be overwritten by default. There is no concurrency ; protection available. The format of the file looks something like: -; +; ; Log opened at 2007-05-27 14:28:15 ; -> path_info.paths[i]); + xdebug_path_info_dump(branch_info->path_info.paths[i] TSRMLS_CC); } } diff --git a/xdebug_branch_info.h b/xdebug_branch_info.h index f1e8d77d8..8d794d670 100644 --- a/xdebug_branch_info.h +++ b/xdebug_branch_info.h @@ -74,8 +74,8 @@ void xdebug_path_add(xdebug_path *path, unsigned int nr); xdebug_path *xdebug_path_new(xdebug_path *old_path); void xdebug_path_info_dump(xdebug_path *path TSRMLS_DC); void xdebug_path_free(xdebug_path *path); -void xdebug_path_info_add_path_for_level(xdebug_path_info *path_info, xdebug_path *path, unsigned int level); -xdebug_path *xdebug_path_info_get_path_for_level(xdebug_path_info *path_info, unsigned int level); +void xdebug_path_info_add_path_for_level(xdebug_path_info *path_info, xdebug_path *path, unsigned int level TSRMLS_DC); +xdebug_path *xdebug_path_info_get_path_for_level(xdebug_path_info *path_info, unsigned int level TSRMLS_DC); void xdebug_create_key_for_path(xdebug_path *path, xdebug_str *str); void xdebug_branch_info_mark_reached(char *filename, char *function_name, zend_op_array *op_array, long opcode_nr TSRMLS_DC); diff --git a/xdebug_code_coverage.c b/xdebug_code_coverage.c index 974b9ed0b..d07a3c1d6 100644 --- a/xdebug_code_coverage.c +++ b/xdebug_code_coverage.c @@ -82,7 +82,7 @@ void xdebug_coverage_function_dtor(void *data) xdfree(function); } -void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode) +void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode TSRMLS_DC) { zend_op_array *op_array = execute_data->op_array; char *file = (char *) op_array->filename; @@ -109,7 +109,7 @@ int xdebug_check_branch_entry_handler(ZEND_OPCODE_HANDLER_ARGS) zend_op *cur_opcode; cur_opcode = *EG(opline_ptr); - xdebug_print_opcode_info('G', execute_data, cur_opcode); + xdebug_print_opcode_info('G', execute_data, cur_opcode TSRMLS_CC); } return ZEND_USER_OPCODE_DISPATCH; } @@ -135,7 +135,7 @@ int xdebug_common_override_handler(ZEND_OPCODE_HANDLER_ARGS) file = (char *)op_array->filename; - xdebug_print_opcode_info('C', execute_data, cur_opcode); + xdebug_print_opcode_info('C', execute_data, cur_opcode TSRMLS_CC); xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC); } return ZEND_USER_OPCODE_DISPATCH; @@ -292,7 +292,6 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN zend_op *cur_opcode, *next_opcode; char *full_varname; zval *val = NULL; - char *t; int is_var; function_stack_entry *fse; @@ -302,13 +301,13 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN lineno = cur_opcode->lineno; if (XG(do_code_coverage)) { - xdebug_print_opcode_info('=', execute_data, cur_opcode); + xdebug_print_opcode_info('=', execute_data, cur_opcode TSRMLS_CC); if (do_cc) { xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC); } } - if (XG(do_trace) && XG(trace_file) && XG(collect_assignments)) { + if (XG(do_trace) && XG(trace_context) && XG(collect_assignments)) { full_varname = xdebug_find_var_name(execute_data TSRMLS_CC); if (cur_opcode->opcode >= ZEND_PRE_INC && cur_opcode->opcode <= ZEND_POST_DEC) { @@ -344,11 +343,10 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN } fse = XDEBUG_LLIST_VALP(XDEBUG_LLIST_TAIL(XG(stack))); - t = xdebug_return_trace_assignment(fse, full_varname, val, op, file, lineno TSRMLS_CC); + if (XG(do_trace) && XG(trace_context) && XG(collect_assignments) && XG(trace_handler)->assignment) { + XG(trace_handler)->assignment(XG(trace_context), fse, full_varname, val, op, file, lineno TSRMLS_CC); + } xdfree(full_varname); - fprintf(XG(trace_file), "%s", t); - fflush(XG(trace_file)); - xdfree(t); } return ZEND_USER_OPCODE_DISPATCH; } @@ -794,7 +792,7 @@ void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC) xdebug_path *path = xdebug_path_new(NULL); xdebug_prefill_code_coverage(op_array TSRMLS_CC); - xdebug_path_info_add_path_for_level(&(XG(paths_stack)), path, XG(level)); + xdebug_path_info_add_path_for_level(&(XG(paths_stack)), path, XG(level) TSRMLS_CC); if (XG(branches).size == 0 || XG(level) > XG(branches).size) { XG(branches).size += 32; @@ -807,7 +805,7 @@ void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC) void xdebug_code_coverage_end_of_function(zend_op_array *op_array TSRMLS_DC) { xdebug_str str = { 0, 0, NULL }; - xdebug_path *path = xdebug_path_info_get_path_for_level(&(XG(paths_stack)), XG(level)); + xdebug_path *path = xdebug_path_info_get_path_for_level(&(XG(paths_stack)), XG(level) TSRMLS_CC); char *file = (char *) op_array->filename; xdebug_func func_info; char *function_name; @@ -988,13 +986,14 @@ static void add_cc_function(void *ret, xdebug_hash_element *e) xdebug_coverage_function *function = (xdebug_coverage_function*) e->ptr; zval *retval = (zval*) ret; zval *function_info; + TSRMLS_FETCH(); MAKE_STD_ZVAL(function_info); array_init(function_info); if (function->branch_info) { - add_branches(function_info, function->branch_info); - add_paths(function_info, function->branch_info); + add_branches(function_info, function->branch_info TSRMLS_CC); + add_paths(function_info, function->branch_info TSRMLS_CC); } add_assoc_zval_ex(retval, function->name, strlen(function->name) + 1, function_info); diff --git a/xdebug_code_coverage.h b/xdebug_code_coverage.h index 2fe387da4..d8aaf5cbd 100644 --- a/xdebug_code_coverage.h +++ b/xdebug_code_coverage.h @@ -56,7 +56,7 @@ void xdebug_coverage_file_dtor(void *data); xdebug_coverage_function *xdebug_coverage_function_ctor(char *function_name); void xdebug_coverage_function_dtor(void *data); -void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode); +void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode TSRMLS_DC); void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC); void xdebug_code_coverage_end_of_function(zend_op_array *op_array TSRMLS_DC); diff --git a/xdebug_compat.c b/xdebug_compat.c index 24928b120..51f42ee69 100644 --- a/xdebug_compat.c +++ b/xdebug_compat.c @@ -72,6 +72,10 @@ void *php_zend_memrchr(const void *s, int c, size_t n) zval *xdebug_zval_ptr(int op_type, XDEBUG_ZNODE *node, zend_execute_data *zdata TSRMLS_DC) { + if (!zdata->opline) { + return NULL; + } + switch (op_type & 0x0F) { case IS_CONST: #if PHP_VERSION_ID >= 50399 diff --git a/xdebug_private.h b/xdebug_private.h index 5aeabbc46..88500dda4 100644 --- a/xdebug_private.h +++ b/xdebug_private.h @@ -206,6 +206,23 @@ function_stack_entry *xdebug_get_stack_head(TSRMLS_D); function_stack_entry *xdebug_get_stack_frame(int nr TSRMLS_DC); function_stack_entry *xdebug_get_stack_tail(TSRMLS_D); +typedef struct +{ + void *(*init)(char *fname, long options TSRMLS_DC); + void (*deinit)(void *ctxt TSRMLS_DC); + void (*write_header)(void *ctxt TSRMLS_DC); + void (*write_footer)(void *ctxt TSRMLS_DC); + char *(*get_filename)(void *ctxt TSRMLS_DC); + void (*function_entry)(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC); + void (*function_exit)(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC); + void (*return_value)(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC); +#if PHP_VERSION_ID >= 50500 + void (*generator_return_value)(void *ctxt, function_stack_entry *fse, int function_nr, zend_generator *generator TSRMLS_DC); +#endif + void (*assignment)(void *ctxt, function_stack_entry *fse, char *full_varname, zval *value, char *op, char *file, int lineno TSRMLS_DC); +} xdebug_trace_handler_t; + + xdebug_hash* xdebug_used_var_hash_from_llist(xdebug_llist *list); void xdebug_init_debugger(TSRMLS_D); diff --git a/xdebug_stack.c b/xdebug_stack.c index 0d37f75f6..efbeb9f75 100644 --- a/xdebug_stack.c +++ b/xdebug_stack.c @@ -959,7 +959,7 @@ static void xdebug_build_fname(xdebug_func *tmp, zend_execute_data *edata TSRMLS fname = "whoops"; } - lineno = find_line_number_for_current_execute_point(edata TSRMLS_DC); + lineno = find_line_number_for_current_execute_point(edata TSRMLS_CC); tmp->function = xdebug_sprintf( "%s:{%s:%d}", diff --git a/xdebug_trace_computerized.c b/xdebug_trace_computerized.c new file mode 100644 index 000000000..4dc98417b --- /dev/null +++ b/xdebug_trace_computerized.c @@ -0,0 +1,251 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#include "xdebug_trace_computerized.h" +#include "xdebug_var.h" +#include "ext/standard/php_string.h" + +extern ZEND_DECLARE_MODULE_GLOBALS(xdebug); + +void *xdebug_trace_computerized_init(char *fname, long options TSRMLS_DC) +{ + xdebug_trace_computerized_context *tmp_computerized_context; + char *used_fname; + + tmp_computerized_context = xdmalloc(sizeof(xdebug_trace_computerized_context)); + tmp_computerized_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC); + tmp_computerized_context->trace_filename = used_fname; + + return tmp_computerized_context; +} + +void xdebug_trace_computerized_deinit(void *ctxt TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + + fclose(context->trace_file); + context->trace_file = NULL; + xdfree(context->trace_filename); + + xdfree(context); +} + +void xdebug_trace_computerized_write_header(void *ctxt TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + char *str_time; + + fprintf(context->trace_file, "Version: %s\n", XDEBUG_VERSION); + fprintf(context->trace_file, "File format: 4\n"); + + str_time = xdebug_get_time(); + fprintf(context->trace_file, "TRACE START [%s]\n", str_time); + fflush(context->trace_file); + xdfree(str_time); +} + +void xdebug_trace_computerized_write_footer(void *ctxt TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + char *str_time; + double u_time; + char *tmp; + + u_time = xdebug_get_utime(); + tmp = xdebug_sprintf("\t\t\t%f\t", u_time - XG(start_time)); + fprintf(context->trace_file, "%s", tmp); + xdfree(tmp); +#if HAVE_PHP_MEMORY_USAGE + fprintf(context->trace_file, "%lu", XG_MEMORY_USAGE()); +#else + fprintf(context->trace_file, ""); +#endif + fprintf(context->trace_file, "\n"); + str_time = xdebug_get_time(); + + fprintf(context->trace_file, "TRACE END [%s]\n\n", str_time); + fflush(context->trace_file); + xdfree(str_time); +} + +char *xdebug_trace_computerized_get_filename(void *ctxt TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + + return context->trace_filename; +} + +static char *render_variable(zval *var, int type TSRMLS_DC) +{ + char *tmp_value = NULL; + + switch (XG(collect_params)) { + case 1: /* synopsis */ + case 2: + tmp_value = xdebug_get_zval_synopsis(var, 0, NULL); + break; + case 3: /* full */ + case 4: /* full (with var) */ + default: + tmp_value = xdebug_get_zval_value(var, 0, NULL); + break; + case 5: /* serialized */ + tmp_value = xdebug_get_zval_value_serialized(var, 0, NULL TSRMLS_CC); + break; + } + + return tmp_value; +} + + +void xdebug_trace_computerized_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + char *tmp_name; + xdebug_str str = {0, 0, NULL}; + + xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1); + xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1); + + tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC); + + xdebug_str_add(&str, "0\t", 0); + xdebug_str_add(&str, xdebug_sprintf("%f\t", fse->time - XG(start_time)), 1); +#if HAVE_PHP_MEMORY_USAGE + xdebug_str_add(&str, xdebug_sprintf("%lu\t", fse->memory), 1); +#else + xdebug_str_add(&str, "\t", 0); +#endif + xdebug_str_add(&str, xdebug_sprintf("%s\t", tmp_name), 1); + xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->user_defined == XDEBUG_EXTERNAL ? 1 : 0), 1); + xdfree(tmp_name); + + if (fse->include_filename) { + if (fse->function.type == XFUNC_EVAL) { + int tmp_len; + + char *escaped; + escaped = php_addcslashes(fse->include_filename, strlen(fse->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC); + xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1); + efree(escaped); + } else { + xdebug_str_add(&str, fse->include_filename, 0); + } + } + + /* Filename and Lineno (9, 10) */ + xdebug_str_add(&str, xdebug_sprintf("\t%s\t%d", fse->filename, fse->lineno), 1); + + + if (XG(collect_params) > 0) { + unsigned int j = 0; /* Counter */ + + /* Nr of arguments (11) */ + xdebug_str_add(&str, xdebug_sprintf("\t%d", fse->varc), 1); + + /* Arguments (12-...) */ + for (j = 0; j < fse->varc; j++) { + char *tmp_value; + + xdebug_str_addl(&str, "\t", 1, 0); + + if (fse->var[j].is_variadic) { + xdebug_str_addl(&str, "...\t", 4, 0); + } + + if (fse->var[j].name && XG(collect_params) == 4) { + xdebug_str_add(&str, xdebug_sprintf("$%s = ", fse->var[j].name), 1); + } + + tmp_value = render_variable(fse->var[j].addr, XG(collect_params) TSRMLS_CC); + + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } else { + xdebug_str_add(&str, "???", 0); + } + } + } + + /* Trailing \n */ + xdebug_str_add(&str, "\n", 0); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + xdfree(str.d); +} + +void xdebug_trace_computerized_function_exit(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + xdebug_str str = {0, 0, NULL}; + + xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1); + xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1); + + xdebug_str_add(&str, "1\t", 0); + xdebug_str_add(&str, xdebug_sprintf("%f\t", xdebug_get_utime() - XG(start_time)), 1); +#if HAVE_PHP_MEMORY_USAGE + xdebug_str_add(&str, xdebug_sprintf("%lu\n", XG_MEMORY_USAGE()), 1); +#else + xdebug_str_add(&str, "\n", 0); +#endif + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + xdfree(str.d); +} + +void xdebug_trace_computerized_function_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC) +{ + xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt; + xdebug_str str = {0, 0, NULL}; + char *tmp_value = NULL; + + xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1); + xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1); + xdebug_str_add(&str, "R\t\t\t", 0); + + tmp_value = render_variable(return_value, XG(collect_params) TSRMLS_CC); + + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } else { + xdebug_str_add(&str, "???", 0); + } + xdebug_str_addl(&str, "\n", 2, 0); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + xdfree(str.d); +} + +xdebug_trace_handler_t xdebug_trace_handler_computerized = +{ + xdebug_trace_computerized_init, + xdebug_trace_computerized_deinit, + xdebug_trace_computerized_write_header, + xdebug_trace_computerized_write_footer, + xdebug_trace_computerized_get_filename, + xdebug_trace_computerized_function_entry, + xdebug_trace_computerized_function_exit, + xdebug_trace_computerized_function_return_value, +#if PHP_VERSION_ID >= 50500 + NULL /* xdebug_trace_computerized_generator_return_value */, +#endif + NULL /* xdebug_trace_computerized_assignment */ +}; diff --git a/xdebug_trace_computerized.h b/xdebug_trace_computerized.h new file mode 100644 index 000000000..b5ef2d534 --- /dev/null +++ b/xdebug_trace_computerized.h @@ -0,0 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#ifndef XDEBUG_TRACE_COMPUTERIZED_H +#define XDEBUG_TRACE_COMPUTERIZED_H + +#include "xdebug_tracing.h" + +typedef struct _xdebug_trace_computerized_context +{ + FILE *trace_file; + char *trace_filename; +} xdebug_trace_computerized_context; + +extern xdebug_trace_handler_t xdebug_trace_handler_computerized; +#endif diff --git a/xdebug_trace_html.c b/xdebug_trace_html.c new file mode 100644 index 000000000..c3465c54c --- /dev/null +++ b/xdebug_trace_html.c @@ -0,0 +1,136 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#include "xdebug_trace_html.h" +#include "xdebug_var.h" + +extern ZEND_DECLARE_MODULE_GLOBALS(xdebug); + +void *xdebug_trace_html_init(char *fname, long options TSRMLS_DC) +{ + xdebug_trace_html_context *tmp_html_context; + char *used_fname; + + tmp_html_context = xdmalloc(sizeof(xdebug_trace_html_context)); + tmp_html_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC); + tmp_html_context->trace_filename = used_fname; + + return tmp_html_context; +} + +void xdebug_trace_html_deinit(void *ctxt TSRMLS_DC) +{ + xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt; + + fclose(context->trace_file); + context->trace_file = NULL; + xdfree(context->trace_filename); + + xdfree(context); +} + +void xdebug_trace_html_write_header(void *ctxt TSRMLS_DC) +{ + xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt; + + fprintf(context->trace_file, "\n"); + fprintf(context->trace_file, "\t"); +#if HAVE_PHP_MEMORY_USAGE + fprintf(context->trace_file, ""); +#endif + fprintf(context->trace_file, "\n"); + fflush(context->trace_file); +} + +void xdebug_trace_html_write_footer(void *ctxt TSRMLS_DC) +{ + xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt; + + fprintf(context->trace_file, "
#TimeMemFunctionLocation
\n"); + fflush(context->trace_file); +} + +char *xdebug_trace_html_get_filename(void *ctxt TSRMLS_DC) +{ + xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt; + + return context->trace_filename; +} + +void xdebug_trace_html_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC) +{ + xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt; + char *tmp_name; + unsigned int j; + xdebug_str str = {0, 0, NULL}; + + xdebug_str_add(&str, "\t", 0); + xdebug_str_add(&str, xdebug_sprintf("%d", function_nr), 1); + xdebug_str_add(&str, xdebug_sprintf("%0.6f", fse->time - XG(start_time)), 1); +#if HAVE_PHP_MEMORY_USAGE + xdebug_str_add(&str, xdebug_sprintf("%lu", fse->memory), 1); +#endif + xdebug_str_add(&str, "", 0); + for (j = 0; j < fse->level - 1; j++) { + xdebug_str_add(&str, "   ", 0); + } + xdebug_str_add(&str, "->", 0); + + tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC); + xdebug_str_add(&str, xdebug_sprintf("%s(", tmp_name), 1); + xdfree(tmp_name); + + if (fse->include_filename) { + if (fse->function.type == XFUNC_EVAL) { + char *joined; + xdebug_arg *parts = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg)); + + xdebug_arg_init(parts); + xdebug_explode("\n", fse->include_filename, parts, 99999); + joined = xdebug_join("
", parts, 0, 99999); + xdebug_arg_dtor(parts); + + xdebug_str_add(&str, xdebug_sprintf("'%s'", joined), 1); + xdfree(joined); + } else { + xdebug_str_add(&str, fse->include_filename, 0); + } + } + + xdebug_str_add(&str, xdebug_sprintf(")%s:%d", fse->filename, fse->lineno), 1); + xdebug_str_add(&str, "\n", 0); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + xdfree(str.d); +} + +xdebug_trace_handler_t xdebug_trace_handler_html = +{ + xdebug_trace_html_init, + xdebug_trace_html_deinit, + xdebug_trace_html_write_header, + xdebug_trace_html_write_footer, + xdebug_trace_html_get_filename, + xdebug_trace_html_function_entry, + NULL /* xdebug_trace_html_function_exit */, + NULL /* xdebug_trace_html_function_return_value */, +#if PHP_VERSION_ID >= 50500 + NULL /* xdebug_trace_html_generator_return_value */, +#endif + NULL /* xdebug_trace_html_assignment */ +}; diff --git a/xdebug_trace_html.h b/xdebug_trace_html.h new file mode 100644 index 000000000..52d506bcd --- /dev/null +++ b/xdebug_trace_html.h @@ -0,0 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#ifndef XDEBUG_TRACE_HTML_H +#define XDEBUG_TRACE_HTML_H + +#include "xdebug_tracing.h" + +typedef struct _xdebug_trace_html_context +{ + FILE *trace_file; + char *trace_filename; +} xdebug_trace_html_context; + +extern xdebug_trace_handler_t xdebug_trace_handler_html; +#endif diff --git a/xdebug_trace_textual.c b/xdebug_trace_textual.c new file mode 100644 index 000000000..b46ef81bb --- /dev/null +++ b/xdebug_trace_textual.c @@ -0,0 +1,311 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#include "xdebug_tracing.h" +#include "xdebug_trace_textual.h" +#include "xdebug_var.h" +#include "ext/standard/php_string.h" + +extern ZEND_DECLARE_MODULE_GLOBALS(xdebug); + +void *xdebug_trace_textual_init(char *fname, long options TSRMLS_DC) +{ + xdebug_trace_textual_context *tmp_textual_context; + char *used_fname; + + tmp_textual_context = xdmalloc(sizeof(xdebug_trace_textual_context)); + tmp_textual_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC); + tmp_textual_context->trace_filename = used_fname; + + return tmp_textual_context; +} + +void xdebug_trace_textual_deinit(void *ctxt TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + + fclose(context->trace_file); + context->trace_file = NULL; + xdfree(context->trace_filename); + + xdfree(context); +} + +void xdebug_trace_textual_write_header(void *ctxt TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + char *str_time; + + str_time = xdebug_get_time(); + fprintf(context->trace_file, "TRACE START [%s]\n", str_time); + fflush(context->trace_file); + xdfree(str_time); +} + +void xdebug_trace_textual_write_footer(void *ctxt TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + char *str_time; + double u_time; + char *tmp; + + u_time = xdebug_get_utime(); + tmp = xdebug_sprintf("%10.4f ", u_time - XG(start_time)); + fprintf(context->trace_file, "%s", tmp); + xdfree(tmp); +#if HAVE_PHP_MEMORY_USAGE + fprintf(context->trace_file, "%10zu", XG_MEMORY_USAGE()); +#else + fprintf(context->trace_file, "%10u", 0); +#endif + fprintf(context->trace_file, "\n"); + str_time = xdebug_get_time(); + fprintf(context->trace_file, "TRACE END [%s]\n\n", str_time); + fflush(context->trace_file); + xdfree(str_time); +} + +char *xdebug_trace_textual_get_filename(void *ctxt TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + + return context->trace_filename; +} + +void xdebug_trace_textual_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + int c = 0; /* Comma flag */ + unsigned int j = 0; /* Counter */ + char *tmp_name; + xdebug_str str = {0, 0, NULL}; + + tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC); + + xdebug_str_add(&str, xdebug_sprintf("%10.4f ", fse->time - XG(start_time)), 1); + xdebug_str_add(&str, xdebug_sprintf("%10lu ", fse->memory), 1); + if (XG(show_mem_delta)) { + xdebug_str_add(&str, xdebug_sprintf("%+8ld ", fse->memory - fse->prev_memory), 1); + } + for (j = 0; j < fse->level; j++) { + xdebug_str_addl(&str, " ", 2, 0); + } + xdebug_str_add(&str, xdebug_sprintf("-> %s(", tmp_name), 1); + + xdfree(tmp_name); + + /* Printing vars */ + if (XG(collect_params) > 0) { + int variadic_opened = 0; + int variadic_count = 0; + + for (j = 0; j < fse->varc; j++) { + char *tmp_value; + + if (c) { + xdebug_str_addl(&str, ", ", 2, 0); + } else { + c = 1; + } + + if (fse->var[j].is_variadic && fse->var[j].addr) { + xdebug_str_add(&str, "...", 0); + variadic_opened = 1; + } + + if (fse->var[j].name && XG(collect_params) == 4) { + xdebug_str_add(&str, xdebug_sprintf("$%s = ", fse->var[j].name), 1); + } + + if (fse->var[j].is_variadic && fse->var[j].addr) { + xdebug_str_add(&str, "variadic(", 0); + } + + if (variadic_opened && XG(collect_params) != 5) { + xdebug_str_add(&str, xdebug_sprintf("%d => ", variadic_count++), 1); + } + + switch (XG(collect_params)) { + case 1: /* synopsis */ + case 2: + tmp_value = xdebug_get_zval_synopsis(fse->var[j].addr, 0, NULL); + break; + case 3: /* full */ + case 4: /* full (with var) */ + default: + tmp_value = xdebug_get_zval_value(fse->var[j].addr, 0, NULL); + break; + case 5: /* serialized */ + tmp_value = xdebug_get_zval_value_serialized(fse->var[j].addr, 0, NULL TSRMLS_CC); + break; + } + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } else { + xdebug_str_add(&str, "???", 0); + } + } + + if (variadic_opened) { + xdebug_str_add(&str, ")", 0); + } + } + + if (fse->include_filename) { + if (fse->function.type == XFUNC_EVAL) { + int tmp_len; + + char *escaped; + escaped = php_addcslashes(fse->include_filename, strlen(fse->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC); + xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1); + efree(escaped); + } else { + xdebug_str_add(&str, fse->include_filename, 0); + } + } + + xdebug_str_add(&str, xdebug_sprintf(") %s:%d\n", fse->filename, fse->lineno), 1); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + + xdfree(str.d); +} + +/* Used for normal return values, and generator return values */ +static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *fse TSRMLS_DC) +{ + unsigned int j = 0; /* Counter */ + + xdebug_str_add(str, xdebug_sprintf("%10.4f ", xdebug_get_utime() - XG(start_time)), 1); +#if HAVE_PHP_MEMORY_USAGE + xdebug_str_add(str, xdebug_sprintf("%10lu ", XG_MEMORY_USAGE()), 1); +#endif + + if (XG(show_mem_delta)) { + xdebug_str_addl(str, " ", 8, 0); + } + for (j = 0; j < fse->level; j++) { + xdebug_str_addl(str, " ", 2, 0); + } + xdebug_str_addl(str, " >=> ", 5, 0); +} + + +void xdebug_trace_textual_function_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + xdebug_str str = {0, 0, NULL}; + char *tmp_value; + + xdebug_return_trace_stack_common(&str, fse TSRMLS_CC); + + tmp_value = xdebug_get_zval_value(return_value, 0, NULL); + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } + xdebug_str_addl(&str, "\n", 2, 0); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + + xdfree(str.d); +} + +#if PHP_VERSION_ID >= 50500 +void xdebug_trace_textual_generator_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zend_generator *generator TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + xdebug_str str = {0, 0, NULL}; + char *tmp_value = NULL; + + /* Generator key */ + tmp_value = xdebug_get_zval_value(generator->key, 0, NULL); + if (tmp_value) { + xdebug_return_trace_stack_common(&str, fse TSRMLS_CC); + + xdebug_str_addl(&str, "(", 1, 0); + xdebug_str_add(&str, tmp_value, 1); + xdebug_str_addl(&str, " => ", 4, 0); + + tmp_value = xdebug_get_zval_value(generator->value, 0, NULL); + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } + xdebug_str_addl(&str, ")", 1, 0); + xdebug_str_addl(&str, "\n", 2, 0); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + + xdfree(str.d); + } +} +#endif + +void xdebug_trace_textual_assignment(void *ctxt, function_stack_entry *fse, char *full_varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC) +{ + xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt; + unsigned int j = 0; + xdebug_str str = {0, 0, NULL}; + char *tmp_value; + + xdebug_str_addl(&str, " ", 20, 0); + if (XG(show_mem_delta)) { + xdebug_str_addl(&str, " ", 8, 0); + } + for (j = 0; j <= fse->level; j++) { + xdebug_str_addl(&str, " ", 2, 0); + } + xdebug_str_addl(&str, " => ", 6, 0); + + xdebug_str_add(&str, full_varname, 0); + + if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */ + xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1); + + tmp_value = xdebug_get_zval_value(retval, 0, NULL); + + if (tmp_value) { + xdebug_str_add(&str, tmp_value, 1); + } else { + xdebug_str_addl(&str, "NULL", 4, 0); + } + } + xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1); + + fprintf(context->trace_file, "%s", str.d); + fflush(context->trace_file); + + xdfree(str.d); +} + +xdebug_trace_handler_t xdebug_trace_handler_textual = +{ + xdebug_trace_textual_init, + xdebug_trace_textual_deinit, + xdebug_trace_textual_write_header, + xdebug_trace_textual_write_footer, + xdebug_trace_textual_get_filename, + xdebug_trace_textual_function_entry, + NULL /*xdebug_trace_textual_function_exit */, + xdebug_trace_textual_function_return_value, +#if PHP_VERSION_ID >= 50500 + xdebug_trace_textual_generator_return_value, +#endif + xdebug_trace_textual_assignment +}; diff --git a/xdebug_trace_textual.h b/xdebug_trace_textual.h new file mode 100644 index 000000000..a59234b75 --- /dev/null +++ b/xdebug_trace_textual.h @@ -0,0 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | Xdebug | + +----------------------------------------------------------------------+ + | Copyright (c) 2002-2014 Derick Rethans | + +----------------------------------------------------------------------+ + | This source file is subject to version 1.0 of the Xdebug license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://xdebug.derickrethans.nl/license.php | + | If you did not receive a copy of the Xdebug license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | xdebug@derickrethans.nl so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ + */ +#ifndef XDEBUG_TRACE_TEXTUAL_H +#define XDEBUG_TRACE_TEXTUAL_H + +#include "xdebug_tracing.h" + +typedef struct _xdebug_trace_textual_context +{ + FILE *trace_file; + char *trace_filename; +} xdebug_trace_textual_context; + +extern xdebug_trace_handler_t xdebug_trace_handler_textual; +#endif diff --git a/xdebug_tracing.c b/xdebug_tracing.c index 02c9fc182..0ab4efe15 100644 --- a/xdebug_tracing.c +++ b/xdebug_tracing.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Xdebug | +----------------------------------------------------------------------+ - | Copyright (c) 2002-2013 Derick Rethans | + | Copyright (c) 2002-2014 Derick Rethans | +----------------------------------------------------------------------+ | This source file is subject to version 1.0 of the Xdebug license, | | that is bundled with this package in the file LICENSE, and is | @@ -12,7 +12,7 @@ | to obtain it through the world-wide-web, please send a note to | | xdebug@derickrethans.nl so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Derick Rethans | + | Authors: Derick Rethans | +----------------------------------------------------------------------+ */ #include "php_xdebug.h" @@ -22,449 +22,85 @@ #include "xdebug_var.h" #include "ext/standard/php_string.h" -ZEND_EXTERN_MODULE_GLOBALS(xdebug) - -static char* return_trace_stack_frame_begin(function_stack_entry* i, int fnr TSRMLS_DC); -static char* return_trace_stack_frame_end(function_stack_entry* i, int fnr TSRMLS_DC); - -void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC) -{ - if (XG(do_trace) && XG(trace_file)) { - char *t = return_trace_stack_frame_begin(fse, function_nr TSRMLS_CC); - if (fprintf(XG(trace_file), "%s", t) < 0) { - fclose(XG(trace_file)); - XG(trace_file) = NULL; - } else { - fflush(XG(trace_file)); - } - xdfree(t); - } -} - -void xdebug_trace_function_end(function_stack_entry *fse, int function_nr TSRMLS_DC) -{ - if (XG(do_trace) && XG(trace_file)) { - char *t = return_trace_stack_frame_end(fse, function_nr TSRMLS_CC); - if (fprintf(XG(trace_file), "%s", t) < 0) { - fclose(XG(trace_file)); - XG(trace_file) = NULL; - } else { - fflush(XG(trace_file)); - } - xdfree(t); - } -} - - -char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC) -{ - unsigned int j = 0; - xdebug_str str = {0, 0, NULL}; - char *tmp_value; - - if (XG(trace_format) != 0) { - return xdstrdup(""); - } - - xdebug_str_addl(&str, " ", 20, 0); - if (XG(show_mem_delta)) { - xdebug_str_addl(&str, " ", 8, 0); - } - for (j = 0; j <= i->level; j++) { - xdebug_str_addl(&str, " ", 2, 0); - } - xdebug_str_addl(&str, " => ", 6, 0); - - xdebug_str_add(&str, varname, 0); - - if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */ - xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1); - - tmp_value = xdebug_get_zval_value(retval, 0, NULL); - - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); - } else { - xdebug_str_addl(&str, "NULL", 4, 0); - } - } - xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1); - - return str.d; -} - -static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *i TSRMLS_DC) -{ - unsigned int j = 0; /* Counter */ - - xdebug_str_add(str, xdebug_sprintf("%10.4f ", xdebug_get_utime() - XG(start_time)), 1); -#if HAVE_PHP_MEMORY_USAGE - xdebug_str_add(str, xdebug_sprintf("%10lu ", XG_MEMORY_USAGE()), 1); -#endif +#include "xdebug_tracing.h" +#include "xdebug_trace_textual.h" +#include "xdebug_trace_computerized.h" +#include "xdebug_trace_html.h" - if (XG(show_mem_delta)) { - xdebug_str_addl(str, " ", 8, 0); - } - for (j = 0; j < i->level; j++) { - xdebug_str_addl(str, " ", 2, 0); - } - xdebug_str_addl(str, " >=> ", 5, 0); -} +ZEND_EXTERN_MODULE_GLOBALS(xdebug) -static char* return_trace_stack_retval_normal(function_stack_entry* i, zval* retval TSRMLS_DC) +xdebug_trace_handler_t *xdebug_select_trace_handler(int options TSRMLS_DC) { - xdebug_str str = {0, 0, NULL}; - char *tmp_value; - - xdebug_return_trace_stack_common(&str, i TSRMLS_CC); + xdebug_trace_handler_t *tmp; - tmp_value = xdebug_get_zval_value(retval, 0, NULL); - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); + switch (XG(trace_format)) { + case 0: tmp = &xdebug_trace_handler_textual; break; + case 1: tmp = &xdebug_trace_handler_computerized; break; + case 2: tmp = &xdebug_trace_handler_html; break; } - xdebug_str_addl(&str, "\n", 2, 0); - - return str.d; -} -static char *render_variable(zval *var, int type TSRMLS_DC) -{ - char *tmp_value = NULL; - - switch (XG(collect_params)) { - case 1: /* synopsis */ - case 2: - tmp_value = xdebug_get_zval_synopsis(var, 0, NULL); - break; - case 3: /* full */ - case 4: /* full (with var) */ - default: - tmp_value = xdebug_get_zval_value(var, 0, NULL); - break; - case 5: /* serialized */ - tmp_value = xdebug_get_zval_value_serialized(var, 0, NULL TSRMLS_CC); - break; + if (options & XDEBUG_TRACE_OPTION_COMPUTERIZED) { + tmp = &xdebug_trace_handler_computerized; } - - return tmp_value; -} - -static char* return_trace_stack_retval_computerized(function_stack_entry* i, int fnr, zval* retval TSRMLS_DC) -{ - xdebug_str str = {0, 0, NULL}; - char *tmp_value = NULL; - - xdebug_str_add(&str, xdebug_sprintf("%d\t", i->level), 1); - xdebug_str_add(&str, xdebug_sprintf("%d\t", fnr), 1); - xdebug_str_add(&str, "R\t\t\t", 0); - - tmp_value = render_variable(retval, XG(collect_params) TSRMLS_CC); - - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); - } else { - xdebug_str_add(&str, "???", 0); + if (options & XDEBUG_TRACE_OPTION_HTML) { + tmp = &xdebug_trace_handler_html; } - xdebug_str_addl(&str, "\n", 2, 0); - return str.d; + return tmp; } -char* xdebug_return_trace_stack_retval(function_stack_entry* i, int fnr, zval* retval TSRMLS_DC) +FILE *xdebug_trace_open_file(char *fname, long options, char **used_fname TSRMLS_DC) { - switch (XG(trace_format)) { - case 0: - return return_trace_stack_retval_normal(i, retval TSRMLS_CC); - case 1: - return return_trace_stack_retval_computerized(i, fnr, retval TSRMLS_CC); - default: - return xdstrdup(""); - } -} - -#if PHP_VERSION_ID >= 50500 -char* xdebug_return_trace_stack_generator_retval(function_stack_entry* i, zend_generator* generator TSRMLS_DC) -{ - xdebug_str str = {0, 0, NULL}; - char *tmp_value = NULL; - - if (XG(trace_format) != 0) { - return xdstrdup(""); - } - - /* Generator key */ - tmp_value = xdebug_get_zval_value(generator->key, 0, NULL); - if (tmp_value) { - xdebug_return_trace_stack_common(&str, i TSRMLS_CC); - - xdebug_str_addl(&str, "(", 1, 0); - xdebug_str_add(&str, tmp_value, 1); - xdebug_str_addl(&str, " => ", 4, 0); + FILE *file; + char *filename; - tmp_value = xdebug_get_zval_value(generator->value, 0, NULL); - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); - } - xdebug_str_addl(&str, ")", 1, 0); - xdebug_str_addl(&str, "\n", 2, 0); - return str.d; + if (fname && strlen(fname)) { + filename = xdstrdup(fname); } else { - return xdstrdup(""); - } -} -#endif - -static char* return_trace_stack_frame_begin_normal(function_stack_entry* i TSRMLS_DC) -{ - int c = 0; /* Comma flag */ - unsigned int j = 0; /* Counter */ - char *tmp_name; - xdebug_str str = {0, 0, NULL}; - - tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC); - - xdebug_str_add(&str, xdebug_sprintf("%10.4f ", i->time - XG(start_time)), 1); - xdebug_str_add(&str, xdebug_sprintf("%10lu ", i->memory), 1); - if (XG(show_mem_delta)) { - xdebug_str_add(&str, xdebug_sprintf("%+8ld ", i->memory - i->prev_memory), 1); - } - for (j = 0; j < i->level; j++) { - xdebug_str_addl(&str, " ", 2, 0); - } - xdebug_str_add(&str, xdebug_sprintf("-> %s(", tmp_name), 1); - - xdfree(tmp_name); - - /* Printing vars */ - if (XG(collect_params) > 0) { - int variadic_opened = 0; - int variadic_count = 0; - - for (j = 0; j < i->varc; j++) { - char *tmp_value; - - if (c) { - xdebug_str_addl(&str, ", ", 2, 0); - } else { - c = 1; - } - - if (i->var[j].is_variadic && i->var[j].addr) { - xdebug_str_add(&str, "...", 0); - variadic_opened = 1; - } - - if (i->var[j].name && XG(collect_params) == 4) { - xdebug_str_add(&str, xdebug_sprintf("$%s = ", i->var[j].name), 1); - } - - if (i->var[j].is_variadic && i->var[j].addr) { - xdebug_str_add(&str, "variadic(", 0); - } - - if (variadic_opened && XG(collect_params) != 5) { - xdebug_str_add(&str, xdebug_sprintf("%d => ", variadic_count++), 1); - } - - switch (XG(collect_params)) { - case 1: /* synopsis */ - case 2: - tmp_value = xdebug_get_zval_synopsis(i->var[j].addr, 0, NULL); - break; - case 3: /* full */ - case 4: /* full (with var) */ - default: - tmp_value = xdebug_get_zval_value(i->var[j].addr, 0, NULL); - break; - case 5: /* serialized */ - tmp_value = xdebug_get_zval_value_serialized(i->var[j].addr, 0, NULL TSRMLS_CC); - break; - } - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); - } else { - xdebug_str_add(&str, "???", 0); - } - } - - if (variadic_opened) { - xdebug_str_add(&str, ")", 0); + if (!strlen(XG(trace_output_name)) || + xdebug_format_output_filename(&fname, XG(trace_output_name), NULL) <= 0 + ) { + /* Invalid or empty xdebug.trace_output_name */ + return NULL; } - } - - if (i->include_filename) { - if (i->function.type == XFUNC_EVAL) { - int tmp_len; - - char *escaped; - escaped = php_addcslashes(i->include_filename, strlen(i->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC); - xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1); - efree(escaped); + if (IS_SLASH(XG(trace_output_dir)[strlen(XG(trace_output_dir)) - 1])) { + filename = xdebug_sprintf("%s%s", XG(trace_output_dir), fname); } else { - xdebug_str_add(&str, i->include_filename, 0); + filename = xdebug_sprintf("%s%c%s", XG(trace_output_dir), DEFAULT_SLASH, fname); } + xdfree(fname); } - - xdebug_str_add(&str, xdebug_sprintf(") %s:%d\n", i->filename, i->lineno), 1); - - return str.d; -} - -#define return_trace_stack_frame_begin_computerized(i,f) return_trace_stack_frame_computerized((i), (f), 0 TSRMLS_CC) -#define return_trace_stack_frame_end_computerized(i,f) return_trace_stack_frame_computerized((i), (f), 1 TSRMLS_CC) - -static char* return_trace_stack_frame_computerized(function_stack_entry* i, int fnr, int whence TSRMLS_DC) -{ - char *tmp_name; - xdebug_str str = {0, 0, NULL}; - - xdebug_str_add(&str, xdebug_sprintf("%d\t", i->level), 1); - xdebug_str_add(&str, xdebug_sprintf("%d\t", fnr), 1); - if (whence == 0) { /* start */ - tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC); - - xdebug_str_add(&str, "0\t", 0); - xdebug_str_add(&str, xdebug_sprintf("%f\t", i->time - XG(start_time)), 1); -#if HAVE_PHP_MEMORY_USAGE - xdebug_str_add(&str, xdebug_sprintf("%lu\t", i->memory), 1); -#else - xdebug_str_add(&str, "\t", 0); -#endif - xdebug_str_add(&str, xdebug_sprintf("%s\t", tmp_name), 1); - xdebug_str_add(&str, xdebug_sprintf("%d\t", i->user_defined == XDEBUG_EXTERNAL ? 1 : 0), 1); - xdfree(tmp_name); - - if (i->include_filename) { - if (i->function.type == XFUNC_EVAL) { - int tmp_len; - - char *escaped; - escaped = php_addcslashes(i->include_filename, strlen(i->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC); - xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1); - efree(escaped); - } else { - xdebug_str_add(&str, i->include_filename, 0); - } - } - - /* Filename and Lineno (9, 10) */ - xdebug_str_add(&str, xdebug_sprintf("\t%s\t%d", i->filename, i->lineno), 1); - - - if (XG(collect_params) > 0) { - unsigned int j = 0; /* Counter */ - - /* Nr of arguments (11) */ - xdebug_str_add(&str, xdebug_sprintf("\t%d", i->varc), 1); - - /* Arguments (12-...) */ - for (j = 0; j < i->varc; j++) { - char *tmp_value; - - xdebug_str_addl(&str, "\t", 1, 0); - - if (i->var[j].is_variadic) { - xdebug_str_addl(&str, "...\t", 4, 0); - } - - if (i->var[j].name && XG(collect_params) == 4) { - xdebug_str_add(&str, xdebug_sprintf("$%s = ", i->var[j].name), 1); - } - - tmp_value = render_variable(i->var[j].addr, XG(collect_params) TSRMLS_CC); - - if (tmp_value) { - xdebug_str_add(&str, tmp_value, 1); - } else { - xdebug_str_add(&str, "???", 0); - } - } - } - - /* Trailing \n */ - xdebug_str_add(&str, "\n", 0); - - } else if (whence == 1) { /* end */ - xdebug_str_add(&str, "1\t", 0); - xdebug_str_add(&str, xdebug_sprintf("%f\t", xdebug_get_utime() - XG(start_time)), 1); -#if HAVE_PHP_MEMORY_USAGE - xdebug_str_add(&str, xdebug_sprintf("%lu\n", XG_MEMORY_USAGE()), 1); -#else - xdebug_str_add(&str, "\n", 0); -#endif + if (options & XDEBUG_TRACE_OPTION_APPEND) { + file = xdebug_fopen(filename, "a", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", used_fname); + } else { + file = xdebug_fopen(filename, "w", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", used_fname); } + xdfree(filename); - return str.d; + return file; } -static char* return_trace_stack_frame_begin_html(function_stack_entry* i, int fnr TSRMLS_DC) +char* xdebug_start_trace(char* fname, long options TSRMLS_DC) { - char *tmp_name; - unsigned int j; - xdebug_str str = {0, 0, NULL}; - - xdebug_str_add(&str, "\t", 0); - xdebug_str_add(&str, xdebug_sprintf("%d", fnr), 1); - xdebug_str_add(&str, xdebug_sprintf("%0.6f", i->time - XG(start_time)), 1); -#if HAVE_PHP_MEMORY_USAGE - xdebug_str_add(&str, xdebug_sprintf("%lu", i->memory), 1); -#endif - xdebug_str_add(&str, "", 0); - for (j = 0; j < i->level - 1; j++) { - xdebug_str_add(&str, "   ", 0); - } - xdebug_str_add(&str, "->", 0); - - tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC); - xdebug_str_add(&str, xdebug_sprintf("%s(", tmp_name), 1); - xdfree(tmp_name); - - if (i->include_filename) { - if (i->function.type == XFUNC_EVAL) { - char *joined; - xdebug_arg *parts = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg)); + XG(trace_handler) = xdebug_select_trace_handler(options TSRMLS_CC); + XG(trace_context) = (void*) XG(trace_handler)->init(fname, options TSRMLS_CC); - xdebug_arg_init(parts); - xdebug_explode("\n", i->include_filename, parts, 99999); - joined = xdebug_join("
", parts, 0, 99999); - xdebug_arg_dtor(parts); - - xdebug_str_add(&str, xdebug_sprintf("'%s'", joined), 1); - xdfree(joined); - } else { - xdebug_str_add(&str, i->include_filename, 0); - } + if (XG(trace_context)) { + XG(do_trace) = 1; + XG(trace_handler)->write_header(XG(trace_context) TSRMLS_CC); + return xdstrdup(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC)); } - xdebug_str_add(&str, xdebug_sprintf(")%s:%d", i->filename, i->lineno), 1); - xdebug_str_add(&str, "\n", 0); - - return str.d; -} - - -static char* return_trace_stack_frame_begin(function_stack_entry* i, int fnr TSRMLS_DC) -{ - switch (XG(trace_format)) { - case 0: - return return_trace_stack_frame_begin_normal(i TSRMLS_CC); - case 1: - return return_trace_stack_frame_begin_computerized(i, fnr); - case 2: - return return_trace_stack_frame_begin_html(i, fnr TSRMLS_CC); - default: - return xdstrdup(""); - } + return NULL; } - -static char* return_trace_stack_frame_end(function_stack_entry* i, int fnr TSRMLS_DC) +void xdebug_stop_trace(TSRMLS_D) { - switch (XG(trace_format)) { - case 1: - return return_trace_stack_frame_end_computerized(i, fnr); - default: - return xdstrdup(""); + XG(do_trace) = 0; + if (XG(trace_context)) { + XG(trace_handler)->write_footer(XG(trace_context) TSRMLS_CC); + XG(trace_handler)->deinit(XG(trace_context) TSRMLS_CC); + XG(trace_context) = NULL; } } @@ -497,105 +133,10 @@ PHP_FUNCTION(xdebug_start_trace) } } -char* xdebug_start_trace(char* fname, long options TSRMLS_DC) -{ - char *str_time; - char *filename; - char *tmp_fname = NULL; - - if (fname && strlen(fname)) { - filename = xdstrdup(fname); - } else { - if (!strlen(XG(trace_output_name)) || - xdebug_format_output_filename(&fname, XG(trace_output_name), NULL) <= 0 - ) { - /* Invalid or empty xdebug.trace_output_name */ - return NULL; - } - if (IS_SLASH(XG(trace_output_dir)[strlen(XG(trace_output_dir)) - 1])) { - filename = xdebug_sprintf("%s%s", XG(trace_output_dir), fname); - } else { - filename = xdebug_sprintf("%s%c%s", XG(trace_output_dir), DEFAULT_SLASH, fname); - } - xdfree(fname); - } - if (options & XDEBUG_TRACE_OPTION_APPEND) { - XG(trace_file) = xdebug_fopen(filename, "a", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", (char**) &tmp_fname); - } else { - XG(trace_file) = xdebug_fopen(filename, "w", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", (char**) &tmp_fname); - } - xdfree(filename); - if (options & XDEBUG_TRACE_OPTION_COMPUTERIZED) { - XG(trace_format) = 1; - } - if (options & XDEBUG_TRACE_OPTION_HTML) { - XG(trace_format) = 2; - } - if (XG(trace_file)) { - if (XG(trace_format) == 1) { - fprintf(XG(trace_file), "Version: %s\n", XDEBUG_VERSION); - fprintf(XG(trace_file), "File format: 4\n"); - } - if (XG(trace_format) == 0 || XG(trace_format) == 1) { - str_time = xdebug_get_time(); - fprintf(XG(trace_file), "TRACE START [%s]\n", str_time); - xdfree(str_time); - } - if (XG(trace_format) == 2) { - fprintf(XG(trace_file), "\n"); - fprintf(XG(trace_file), "\t"); -#if HAVE_PHP_MEMORY_USAGE - fprintf(XG(trace_file), ""); -#endif - fprintf(XG(trace_file), "\n"); - } - XG(do_trace) = 1; - XG(tracefile_name) = tmp_fname; - return xdstrdup(XG(tracefile_name)); - } - return NULL; -} - -void xdebug_stop_trace(TSRMLS_D) -{ - char *str_time; - double u_time; - char *tmp; - - XG(do_trace) = 0; - if (XG(trace_file)) { - if (XG(trace_format) == 0 || XG(trace_format) == 1) { - u_time = xdebug_get_utime(); - tmp = xdebug_sprintf(XG(trace_format) == 0 ? "%10.4f " : "\t\t\t%f\t", u_time - XG(start_time)); - fprintf(XG(trace_file), "%s", tmp); - xdfree(tmp); -#if HAVE_PHP_MEMORY_USAGE - fprintf(XG(trace_file), XG(trace_format) == 0 ? "%10zu" : "%lu", XG_MEMORY_USAGE()); -#else - fprintf(XG(trace_file), XG(trace_format) == 0 ? "%10u" : "", 0); -#endif - fprintf(XG(trace_file), "\n"); - str_time = xdebug_get_time(); - fprintf(XG(trace_file), "TRACE END [%s]\n\n", str_time); - xdfree(str_time); - } - if (XG(trace_format) == 2) { - fprintf(XG(trace_file), "
#TimeMemFunctionLocation
\n"); - } - - fclose(XG(trace_file)); - XG(trace_file) = NULL; - } - if (XG(tracefile_name)) { - xdfree(XG(tracefile_name)); - XG(tracefile_name) = NULL; - } -} - PHP_FUNCTION(xdebug_stop_trace) { if (XG(do_trace) == 1) { - RETVAL_STRING(XG(tracefile_name), 1); + RETVAL_STRING(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC), 1); xdebug_stop_trace(TSRMLS_C); } else { RETVAL_FALSE; @@ -605,8 +146,8 @@ PHP_FUNCTION(xdebug_stop_trace) PHP_FUNCTION(xdebug_get_tracefile_name) { - if (XG(tracefile_name)) { - RETURN_STRING(XG(tracefile_name), 1); + if (XG(do_trace) == 1 && XG(trace_handler) && XG(trace_handler)->get_filename) { + RETURN_STRING(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC), 1); } else { RETURN_FALSE; } diff --git a/xdebug_tracing.h b/xdebug_tracing.h index 6b7c68234..6078a12a3 100644 --- a/xdebug_tracing.h +++ b/xdebug_tracing.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Xdebug | +----------------------------------------------------------------------+ - | Copyright (c) 2002-2013 Derick Rethans | + | Copyright (c) 2002-2014 Derick Rethans | +----------------------------------------------------------------------+ | This source file is subject to version 1.0 of the Xdebug license, | | that is bundled with this package in the file LICENSE, and is | @@ -12,18 +12,21 @@ | to obtain it through the world-wide-web, please send a note to | | xdebug@derickrethans.nl so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Derick Rethans | + | Authors: Derick Rethans | +----------------------------------------------------------------------+ */ - #ifndef XDEBUG_TRACING_H #define XDEBUG_TRACING_H +#include "php.h" +#include "php_xdebug.h" + char* xdebug_return_trace_stack_retval(function_stack_entry* i, int fnr, zval* retval TSRMLS_DC); #if PHP_VERSION_ID >= 50500 char* xdebug_return_trace_stack_generator_retval(function_stack_entry* i, zend_generator* generator TSRMLS_DC); #endif char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *file, int fileno TSRMLS_DC); +FILE *xdebug_trace_open_file(char *fname, long options, char **used_fname TSRMLS_DC); void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC); void xdebug_trace_function_end(function_stack_entry *fse, int function_nr TSRMLS_DC);