From: David Soria Parra Date: Sat, 24 Apr 2010 13:32:30 +0000 (+0000) Subject: Add DTrace probes X-Git-Tag: php-5.4.0alpha1~191^2~1666 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=08b9fdc8a3bf29e27431b7907b5ea4973e9c7042;p=php Add DTrace probes --- diff --git a/NEWS b/NEWS index f829f3110d..12fe6f7ae9 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ - Added an optimization which saves memory and emalloc/efree calls for empty HashTables (Stas, Dmitry) +- Added DTrace support. (David Soria Parra) - Added Tokyo Cabinet abstract DB support to ext/dba. (Michael Maclean) - Added Jenkins's one-at-a-time hash support to ext/hash. (Martin Jansen) - Added FNV-1 hash support to ext/hash. (Michael Maclean) diff --git a/Zend/zend.c b/Zend/zend.c index 698992a6e6..da6946fbf0 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -29,6 +29,7 @@ #include "zend_builtin_functions.h" #include "zend_ini.h" #include "zend_vm.h" +#include "zend_dtrace.h" #ifdef ZTS # define GLOBAL_FUNCTION_TABLE global_function_table @@ -636,10 +637,17 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS zend_getenv = utility_functions->getenv_function; zend_resolve_path = utility_functions->resolve_path_function; +#if HAVE_DTRACE +/* build with dtrace support */ + zend_compile_file = dtrace_compile_file; + zend_execute = dtrace_execute; + zend_execute_internal = dtrace_execute_internal; +#else zend_compile_file = compile_file; - zend_compile_string = compile_string; zend_execute = execute; zend_execute_internal = NULL; +#endif /* HAVE_SYS_SDT_H */ + zend_compile_string = compile_string; zend_throw_exception_hook = NULL; zend_init_opcodes_handlers(); @@ -971,6 +979,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ uint error_lineno; zval *orig_user_error_handler; zend_bool in_compilation; + char dtrace_error_buffer[1024]; zend_class_entry *saved_class_entry; TSRMLS_FETCH(); @@ -1016,6 +1025,15 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ va_start(args, format); +#ifdef HAVE_DTRACE + if(DTRACE_ERROR_ENABLED()) { + char *dtrace_error_buffer; + zend_vspprintf(&dtrace_error_buffer, 0, format, args); + DTRACE_ERROR(dtrace_error_buffer, error_filename, error_lineno); + efree(dtrace_error_buffer); + } +#endif /* HAVE_DTRACE */ + /* if we don't have a user defined error handler */ if (!EG(user_error_handler) || !(EG(user_error_handler_error_reporting) & type) diff --git a/Zend/zend_dtrace.c b/Zend/zend_dtrace.c new file mode 100644 index 0000000000..5b2d0d2dfe --- /dev/null +++ b/Zend/zend_dtrace.c @@ -0,0 +1,108 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: David Soria Parra | + +----------------------------------------------------------------------+ +*/ + +/* $Id: $ */ + +#include "zend.h" +#include "zend_API.h" +#include "zend_dtrace.h" + +#ifdef HAVE_DTRACE +/* PHP DTrace probes {{{ */ +static inline char *dtrace_get_executed_filename(TSRMLS_D) +{ + if (EG(current_execute_data) && EG(current_execute_data)->op_array) { + return EG(current_execute_data)->op_array->filename; + } else { + return zend_get_executed_filename(TSRMLS_C); + } +} + +ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) +{ + zend_op_array *res; + DTRACE_COMPILE_FILE_ENTRY(file_handle->opened_path, file_handle->filename); + res = compile_file(file_handle, type TSRMLS_CC); + DTRACE_COMPILE_FILE_RETURN(file_handle->opened_path, file_handle->filename); + + return res; +} + +/* We wrap the execute function to have fire the execute-entry/return and function-entry/return probes */ +ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC) +{ + int lineno; + char *scope, *filename, *funcname, *classname; + scope = filename = funcname = classname = NULL; + + /* we need filename and lineno for both execute and function probes */ + if (DTRACE_EXECUTE_ENTRY_ENABLED() || DTRACE_EXECUTE_RETURN_ENABLED() + || DTRACE_FUNCTION_ENTRY_ENABLED() || DTRACE_FUNCTION_RETURN_ENABLED()) { + filename = dtrace_get_executed_filename(TSRMLS_C); + lineno = zend_get_executed_lineno(TSRMLS_C); + } + + if (DTRACE_FUNCTION_ENTRY_ENABLED() || DTRACE_FUNCTION_RETURN_ENABLED()) { + filename = dtrace_get_executed_filename(TSRMLS_C); + classname = get_active_class_name(&scope TSRMLS_CC); + funcname = get_active_function_name(TSRMLS_C); + lineno = zend_get_executed_lineno(TSRMLS_C); + } + + if (DTRACE_EXECUTE_ENTRY_ENABLED()) { + DTRACE_EXECUTE_ENTRY(filename, lineno); + } + + if (DTRACE_FUNCTION_ENTRY_ENABLED() && funcname != NULL) { + DTRACE_FUNCTION_ENTRY(funcname, filename, lineno, classname, scope); + } + + execute(op_array TSRMLS_CC); + + if (DTRACE_FUNCTION_RETURN_ENABLED() && funcname != NULL) { + DTRACE_FUNCTION_RETURN(funcname, filename, lineno, classname, scope); + } + + if (DTRACE_EXECUTE_RETURN_ENABLED()) { + DTRACE_EXECUTE_RETURN(filename, lineno); + } +} + +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) +{ + int lineno; + char *filename; + if (DTRACE_EXECUTE_ENTRY_ENABLED() || DTRACE_EXECUTE_RETURN_ENABLED()) { + filename = dtrace_get_executed_filename(TSRMLS_C); + lineno = zend_get_executed_lineno(TSRMLS_C); + } + + if (DTRACE_EXECUTE_ENTRY_ENABLED()) { + DTRACE_EXECUTE_ENTRY(filename, lineno); + } + + execute_internal(execute_data_ptr, return_value_used TSRMLS_CC); + + if (DTRACE_EXECUTE_RETURN_ENABLED()) { + DTRACE_EXECUTE_RETURN(filename, lineno); + } +} + +/* }}} */ +#endif /* HAVE_DTRACE */ + diff --git a/Zend/zend_dtrace.d b/Zend/zend_dtrace.d new file mode 100644 index 0000000000..609663f4b1 --- /dev/null +++ b/Zend/zend_dtrace.d @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: David Soria Parra | + +----------------------------------------------------------------------+ +*/ + +/* $Id: $ */ + +provider php { + probe exception__caught(char *classname); + probe exception__thrown(char* classname); + probe request__startup(char* request_file, char* request_uri, char* request_method); + probe request__shutdown(char* request_file, char* request_uri, char* request_method); + probe compile__file__entry(char * compile_file, char *compile_file_translated); + probe compile__file__return(char *compile_file, char *compile_file_translated); + 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); +}; + +/*#pragma D attributes Private/Private/Unknown provider php module +#pragma D attributes Private/Private/Unknown provider php function +#pragma D attributes Evolving/Evolving/Common provider php provider */ diff --git a/Zend/zend_dtrace.h b/Zend/zend_dtrace.h new file mode 100644 index 0000000000..65d19ef346 --- /dev/null +++ b/Zend/zend_dtrace.h @@ -0,0 +1,48 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: David Soria Parra | + +----------------------------------------------------------------------+ +*/ + +/* $Id: $ */ + +#ifndef _ZEND_DTRACE_H +#define _ZEND_DTRACE_H + +#ifndef ZEND_WIN32 +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_DTRACE +ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); +ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC); +ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); + +ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); +ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC); +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +#include + +#endif /* HAVE_DTRACE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ZEND_DTRACE_H */ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 6d2460aef2..40c7b1cfd0 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -27,6 +27,7 @@ #include "zend_interfaces.h" #include "zend_exceptions.h" #include "zend_vm.h" +#include "zend_dtrace.h" zend_class_entry *default_exception_ce; zend_class_entry *error_exception_ce; @@ -82,6 +83,14 @@ void zend_exception_restore(TSRMLS_D) /* {{{ */ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ { +#ifdef HAVE_DTRACE + if (DTRACE_EXCEPTION_THROWN_ENABLED()) { + char *classname; + int name_len; + zend_get_object_classname(exception, &classname, &name_len); + DTRACE_EXCEPTION_THROWN(classname); + } + if (exception != NULL) { zval *previous = EG(exception); zend_exception_set_previous(exception, EG(exception) TSRMLS_CC); @@ -93,6 +102,7 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ if (!EG(current_execute_data)) { zend_error(E_ERROR, "Exception thrown without a stack frame"); } +#endif /* HAVE_DTRACE */ if (zend_throw_exception_hook) { zend_throw_exception_hook(exception TSRMLS_CC); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0c84b1e5ca..d573bdc5c6 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -36,6 +36,7 @@ #include "zend_interfaces.h" #include "zend_closures.h" #include "zend_vm.h" +#include "zend_dtrace.h" /* Virtual current working directory support */ #include "tsrm_virtual_cwd.h" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2bcc0af272..1c83bd92ae 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2849,6 +2849,13 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV) } catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); ce = Z_OBJCE_P(EG(exception)); + +#ifdef HAVE_DTRACE + if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { + DTRACE_EXCEPTION_CAUGHT(ce->name); + } +#endif /* HAVE_DTRACE */ + if (ce != catch_ce) { if (!instanceof_function(ce, catch_ce TSRMLS_CC)) { if (opline->result.num) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ed9263aeaf..ecb943a422 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4830,6 +4830,13 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A } catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); ce = Z_OBJCE_P(EG(exception)); + +#ifdef HAVE_DTRACE + if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { + DTRACE_EXCEPTION_CAUGHT(ce->name); + } +#endif /* HAVE_DTRACE */ + if (ce != catch_ce) { if (!instanceof_function(ce, catch_ce TSRMLS_CC)) { if (opline->result.num) { diff --git a/acinclude.m4 b/acinclude.m4 index 92996b1fa2..4063d3c65a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -2877,3 +2877,58 @@ main() fi ]) +dnl +dnl Generate dtrace targets +dnl +AC_DEFUN([PHP_GENERATE_DTRACE],[ + old_IFS=[$]IFS + IFS=. + set $ac_src + IFS=$old_IFS + build_target=$2 + PHP_GLOBAL_OBJS="[$]PHP_GLOBAL_OBJS $1.o" + for src in $PHP_DTRACE_OBJS; do + case [$]build_target in + program|static) + obj="$obj `dirname $src`/`basename $src | sed 's,\.lo$,.o,'` " ;; + *) + obj="$obj `dirname $src`/.libs/`basename $src | sed 's,\.lo$,.o,'` " ;; + esac + done + + cat >>Makefile.objects<