diff --git a/Zend/zend_dtrace.c b/Zend/zend_dtrace.c index dfc43a85139b2..af4824cb8d8a5 100644 --- a/Zend/zend_dtrace.c +++ b/Zend/zend_dtrace.c @@ -55,8 +55,8 @@ ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int t ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data) { int lineno; - const char *scope, *filename, *funcname, *classname; - scope = filename = funcname = classname = NULL; + const char *scope, *filename, *funcname, *classname, *prev_funcname, *prev_classname; + scope = filename = funcname = classname = prev_funcname = prev_classname = NULL; /* we need filename and lineno for both execute and function probes */ if (DTRACE_EXECUTE_ENTRY_ENABLED() || DTRACE_EXECUTE_RETURN_ENABLED() @@ -68,6 +68,8 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data) if (DTRACE_FUNCTION_ENTRY_ENABLED() || DTRACE_FUNCTION_RETURN_ENABLED()) { classname = get_active_class_name(&scope); funcname = get_active_function_name(); + prev_funcname = get_prev_active_function_name(); + prev_classname = get_prev_active_class_name(NULL); } if (DTRACE_EXECUTE_ENTRY_ENABLED()) { @@ -75,13 +77,13 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data) } if (DTRACE_FUNCTION_ENTRY_ENABLED() && funcname != NULL) { - DTRACE_FUNCTION_ENTRY((char *)funcname, (char *)filename, lineno, (char *)classname, (char *)scope); + DTRACE_FUNCTION_ENTRY((char *)funcname, (char *)filename, lineno, (char *)classname, (char *)scope, (char *)prev_funcname, (char *)prev_classname); } execute_ex(execute_data); if (DTRACE_FUNCTION_RETURN_ENABLED() && funcname != NULL) { - DTRACE_FUNCTION_RETURN((char *)funcname, (char *)filename, lineno, (char *)classname, (char *)scope); + DTRACE_FUNCTION_RETURN((char *)funcname, (char *)filename, lineno, (char *)classname, (char *)scope, (char *)prev_funcname, (char *)prev_classname); } if (DTRACE_EXECUTE_RETURN_ENABLED()) { diff --git a/Zend/zend_dtrace.d b/Zend/zend_dtrace.d index 6920d0e3602a2..155c5808d7d1f 100644 --- a/Zend/zend_dtrace.d +++ b/Zend/zend_dtrace.d @@ -26,8 +26,8 @@ provider php { probe error(char *errormsg, char *request_file, int lineno); probe execute__entry(char* request_file, int lineno); probe execute__return(char* request_file, int lineno); - probe function__entry(char* function_name, char* request_file, int lineno, char* classname, char* scope); - probe function__return(char* function_name, char* request_file, int lineno, char* classname, char* scope); + probe function__entry(char* function_name, char* request_file, int lineno, char* classname, char* scope, char* prev_function_name, char* prev_classname); + probe function__return(char* function_name, char* request_file, int lineno, char* classname, char* scope, char* prev_function_name, char* prev_classname); }; /*#pragma D attributes Private/Private/Unknown provider php module diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index cee0441eb57ad..2106c6fd4a7da 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -377,7 +377,9 @@ ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named /* services */ ZEND_API const char *get_active_class_name(const char **space); +ZEND_API const char *get_prev_active_class_name(const char **space); ZEND_API const char *get_active_function_name(void); +ZEND_API const char *get_prev_active_function_name(void); ZEND_API const char *get_active_function_arg_name(uint32_t arg_num); ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num); ZEND_API zend_string *get_active_function_or_method_name(void); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 17c3caae21432..7b56073aa11f6 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -489,6 +489,43 @@ void shutdown_executor(void) /* {{{ */ } /* }}} */ +/* return class name and "::" or "". */ +ZEND_API const char *get_prev_active_class_name(const char **space) /* {{{ */ +{ + zend_function *func; + + if (!zend_is_executing()) { + if (space) { + *space = ""; + } + return ""; + } + + zend_execute_data *prev = EG(current_execute_data)->prev_execute_data; + if(!prev) { + return NULL; + } + func = prev->func; + switch (func->type) { + case ZEND_USER_FUNCTION: + case ZEND_INTERNAL_FUNCTION: + { + zend_class_entry *ce = func->common.scope; + + if (space) { + *space = ce ? "::" : ""; + } + return ce ? ZSTR_VAL(ce->name) : ""; + } + default: + if (space) { + *space = ""; + } + return ""; + } +} +/* }}} */ + /* return class name and "::" or "". */ ZEND_API const char *get_active_class_name(const char **space) /* {{{ */ { @@ -553,6 +590,40 @@ ZEND_API const char *get_active_function_name(void) /* {{{ */ } /* }}} */ +ZEND_API const char *get_prev_active_function_name(void) /* {{{ */ +{ + zend_function *func; + + if (!zend_is_executing()) { + return NULL; + } + + zend_execute_data *prev = EG(current_execute_data)->prev_execute_data; + if(!prev) { + return NULL; + } + func = prev->func; + switch (func->type) { + case ZEND_USER_FUNCTION: { + zend_string *function_name = func->common.function_name; + + if (function_name) { + return ZSTR_VAL(function_name); + } else { + return "main"; + } + } + break; + case ZEND_INTERNAL_FUNCTION: + return ZSTR_VAL(func->common.function_name); + break; + default: + return NULL; + } +} +/* }}} */ + + ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */ { ZEND_ASSERT(zend_is_executing());