From 2cd489fcbda122861e5b31065a2120777cdb046e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 8 Aug 2024 16:03:58 +0200 Subject: [PATCH 1/2] Support exit() as function --- src/base/base.c | 20 ++++++++++++++++++++ src/coverage/code_coverage.c | 4 ++++ src/profiler/profiler.c | 12 ++++++++++++ src/profiler/profiler.h | 1 + 4 files changed, 37 insertions(+) diff --git a/src/base/base.c b/src/base/base.c index 92cff19b..356b0504 100644 --- a/src/base/base.c +++ b/src/base/base.c @@ -55,6 +55,7 @@ zif_handler orig_error_reporting_func = NULL; zif_handler orig_set_time_limit_func = NULL; zif_handler orig_pcntl_exec_func = NULL; zif_handler orig_pcntl_fork_func = NULL; +zif_handler orig_exit_func = NULL; #if PHP_VERSION_ID >= 80100 void (*xdebug_old_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message); @@ -81,6 +82,7 @@ PHP_FUNCTION(xdebug_set_time_limit); PHP_FUNCTION(xdebug_error_reporting); PHP_FUNCTION(xdebug_pcntl_exec); PHP_FUNCTION(xdebug_pcntl_fork); +PHP_FUNCTION(xdebug_exit); /* {{{ zend_op_array xdebug_compile_file (file_handle, type) @@ -1100,6 +1102,13 @@ static void xdebug_base_overloaded_functions_setup(void) orig_pcntl_fork_func = orig->internal_function.handler; orig->internal_function.handler = zif_xdebug_pcntl_fork; } + + /* Override exit with our own function to be able to write profiling summary */ + orig = zend_hash_str_find_ptr(CG(function_table), "exit", sizeof("exit") - 1); + if (orig) { + orig_exit_func = orig->internal_function.handler; + orig->internal_function.handler = zif_xdebug_exit; + } } static int xdebug_closure_serialize_deny_wrapper(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data) @@ -1603,6 +1612,17 @@ PHP_FUNCTION(xdebug_pcntl_exec) } /* }}} */ +/* {{{ proto void xdebug_exit(void) + Dummy function to stop profiling when we run exit */ +PHP_FUNCTION(xdebug_exit) +{ + orig_exit_func(INTERNAL_FUNCTION_PARAM_PASSTHRU); + + /* We need to stop the profiler and trace files here */ + xdebug_profiler_exit_function_handler(); +} +/* }}} */ + /* {{{ proto int xdebug_pcntl_fork(void) Dummy function to set a new connection when forking a process */ PHP_FUNCTION(xdebug_pcntl_fork) diff --git a/src/coverage/code_coverage.c b/src/coverage/code_coverage.c index a84f2322..fbf9f48d 100644 --- a/src/coverage/code_coverage.c +++ b/src/coverage/code_coverage.c @@ -357,7 +357,9 @@ static int xdebug_find_jumps(zend_op_array *opa, unsigned int position, size_t * } else if ( opcode.opcode == ZEND_GENERATOR_RETURN || +#if PHP_VERSION_ID < 80400 opcode.opcode == ZEND_EXIT || +#endif opcode.opcode == ZEND_THROW || opcode.opcode == ZEND_MATCH_ERROR || opcode.opcode == ZEND_RETURN @@ -448,6 +450,7 @@ static void xdebug_analyse_branch(zend_op_array *opa, unsigned int position, xde break; } +#if PHP_VERSION_ID < 80400 /* See if we have an exit instruction */ if (opa->opcodes[position].opcode == ZEND_EXIT) { /* fprintf(stderr, "X* Return found\n"); */ @@ -457,6 +460,7 @@ static void xdebug_analyse_branch(zend_op_array *opa, unsigned int position, xde } break; } +#endif /* See if we have a return instruction */ if ( opa->opcodes[position].opcode == ZEND_RETURN diff --git a/src/profiler/profiler.c b/src/profiler/profiler.c index 1926e478..31003f97 100644 --- a/src/profiler/profiler.c +++ b/src/profiler/profiler.c @@ -22,6 +22,7 @@ #include "TSRM.h" #include "php_globals.h" #include "Zend/zend_alloc.h" +#include "Zend/zend_exceptions.h" #include "php_xdebug.h" #include "profiler.h" @@ -44,8 +45,10 @@ void xdebug_init_profiler_globals(xdebug_profiler_globals_t *xg) void xdebug_profiler_minit(void) { +#if PHP_VERSION_ID < 80400 /* Overload the "exit" opcode */ xdebug_set_opcode_handler(ZEND_EXIT, xdebug_profiler_exit_handler); +#endif } void xdebug_profiler_mshutdown(void) @@ -82,6 +85,15 @@ void xdebug_profiler_pcntl_exec_handler(void) deinit_if_active(); } +void xdebug_profiler_exit_function_handler(void) +{ + function_stack_entry *fse = XDEBUG_VECTOR_TAIL(XG_BASE(stack)); + + deinit_if_active(); + + xdebug_profiler_free_function_details(fse); +} + int xdebug_profiler_exit_handler(XDEBUG_OPCODE_HANDLER_ARGS) { const zend_op *cur_opcode = execute_data->opline; diff --git a/src/profiler/profiler.h b/src/profiler/profiler.h index 61f6d493..fd979044 100644 --- a/src/profiler/profiler.h +++ b/src/profiler/profiler.h @@ -47,6 +47,7 @@ void xdebug_profiler_rinit(void); void xdebug_profiler_post_deactivate(void); void xdebug_profiler_pcntl_exec_handler(void); +void xdebug_profiler_exit_function_handler(void); void xdebug_profiler_init_if_requested(zend_op_array *op_array); void xdebug_profiler_execute_ex(function_stack_entry *fse, zend_op_array *op_array); -- 2.40.1