]> granicus.if.org Git - php/commitdiff
Add DTrace probes
authorDavid Soria Parra <dsp@php.net>
Sat, 24 Apr 2010 13:32:30 +0000 (13:32 +0000)
committerDavid Soria Parra <dsp@php.net>
Sat, 24 Apr 2010 13:32:30 +0000 (13:32 +0000)
13 files changed:
NEWS
Zend/zend.c
Zend/zend_dtrace.c [new file with mode: 0644]
Zend/zend_dtrace.d [new file with mode: 0644]
Zend/zend_dtrace.h [new file with mode: 0644]
Zend/zend_exceptions.c
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
acinclude.m4
configure.in
ext/standard/info.c
main/main.c

diff --git a/NEWS b/NEWS
index f829f3110d3077b02c9c257b467ff35d21cd99fa..12fe6f7ae928eed0697d7304f85408cfd8e9e00e 100644 (file)
--- 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)
index 698992a6e6103b39f769b1e578f635664cb1c025..da6946fbf0d31c4b88f72c0384f20f2e6d712cc7 100644 (file)
@@ -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 (file)
index 0000000..5b2d0d2
--- /dev/null
@@ -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 <david.soriaparra@sun.com>                |
+   +----------------------------------------------------------------------+
+*/
+
+/* $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 (file)
index 0000000..609663f
--- /dev/null
@@ -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 <david.soriaparra@sun.com>                |
+   +----------------------------------------------------------------------+
+*/
+
+/* $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 (file)
index 0000000..65d19ef
--- /dev/null
@@ -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 <david.soriaparra@sun.com>                |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#ifndef        _ZEND_DTRACE_H
+#define        _ZEND_DTRACE_H
+
+#ifndef ZEND_WIN32
+# include <unistd.h>
+#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 <zend_dtrace_gen.h>
+
+#endif /* HAVE_DTRACE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZEND_DTRACE_H */
index 6d2460aef295e005bd25156688b4aeaf1c1a1a36..40c7b1cfd03196cef7063e5dfe660c3eac3c75c0 100644 (file)
@@ -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);
index 0c84b1e5ca2447a543474e871a77a01664776b1b..d573bdc5c61259b4be41de53fd9ae74dfa0a55c9 100644 (file)
@@ -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"
index 2bcc0af2725e8c3320f88a1b5c2a0d877b479549..1c83bd92ae2e016a4c0d3e4a26d83d68166aea73 100644 (file)
@@ -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) {
index ed9263aeafedca0168f0f8779ddaca13015195a7..ecb943a422bd5383ff2956cfcedeeefeefe85f72 100644 (file)
@@ -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) {
index 92996b1fa20ff25af30ff7b127a6786863186d01..4063d3c65abc4f3d5f443d5b6b2dae69fad48653 100644 (file)
@@ -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<<EOF
+$1.o: \$(PHP_DTRACE_OBJS)
+       dtrace -G -o $1.o -s $1 $obj
+EOF
+
+])
+
+dnl
+dnl Link given source files with dtrace
+dnl PHP_ADD_DTRACE(providerdesc, sources, module)
+dnl
+AC_DEFUN([PHP_ADD_DTRACE],[
+   case "$3" in
+    ""[)] unset ac_bdir;;
+    /*[)] ac_bdir=$ac_srcdir;;
+    *[)] extdir=PHP_EXT_DIR($3); ac_bdir="$extdir/";;
+    esac
+  old_IFS=[$]IFS
+  for ac_src in $2; do
+    IFS=.
+    set $ac_src
+    ac_obj=[$]1
+    IFS=$old_IFS
+
+    PHP_DTRACE_OBJS="[$]PHP_DTRACE_OBJS [$]ac_bdir[$]ac_obj.lo"
+  done;
+])
+
+dnl
+dnl Generate platform specific dtrace header
+dnl
+AC_DEFUN([PHP_INIT_DTRACE], [
+  dtrace -h -C -s $1 -o $2
+  $SED -ibak 's,PHP_,DTRACE_,g' $2
+])
+
index d88cf118976614c947385a056bc8471ad1ca0d6f..3a9ff823ad495ed92b2a171dae7c9b5419eba1b8 100644 (file)
@@ -901,6 +901,23 @@ if test "$PHP_IPV6" != "no" && test "$ac_cv_ipv6_support" = yes; then
   AC_DEFINE(HAVE_IPV6, 1, [Whether to enable IPv6 support])
 fi
 
+dnl ## DTRACE CHECHKS
+dnl ## this needs to be done before SAPI configureation
+PHP_ARG_ENABLE(dtrace, whether to enable DTrace support,
+[  --enable-dtrace         Enable DTrace support], no, no)
+
+dnl ## DTRACE CHECHKS
+dnl ## this needs to be done before SAPI configureation
+if test "$PHP_DTRACE" = "yes"; then
+  AC_CHECK_HEADERS([sys/sdt.h],
+    [PHP_ADD_DTRACE([Zend/zend_dtrace.d], [main/main.c, Zend/zend_API.c \
+       Zend/zend_execute.c Zend/zend_exceptions.c \
+       Zend/zend_dtrace.c Zend/zend.c])
+     AC_DEFINE(HAVE_DTRACE, 1, [Whether to enable DTrace support])
+     PHP_INIT_DTRACE([Zend/zend_dtrace.d], [Zend/zend_dtrace_gen.h])],
+    [])
+fi
+
 AC_MSG_CHECKING([how big to make fd sets])
 PHP_ARG_ENABLE(fd-setsize,,
 [  --enable-fd-setsize     Set size of descriptor sets], no, no)
@@ -1227,6 +1244,7 @@ PHP_SUBST(PHP_EXECUTABLE)
 PHP_SUBST(PHP_CLI_TARGET)
 PHP_SUBST(PHP_SAPI_OBJS)
 PHP_SUBST(PHP_CLI_OBJS)
+PHP_SUBST(PHP_DTRACE_OBJS)
 PHP_SUBST(PHP_GLOBAL_OBJS)
 
 PHP_SUBST(PHP_MODULES)
@@ -1417,7 +1435,7 @@ esac
 PHP_ADD_SOURCES(Zend, \
     zend_language_parser.c zend_language_scanner.c \
     zend_ini_parser.c zend_ini_scanner.c \
-    zend_alloc.c zend_compile.c zend_constants.c zend_dynamic_array.c \
+    zend_alloc.c zend_compile.c zend_constants.c zend_dynamic_array.c zend_dtrace.c \
     zend_execute_API.c zend_highlight.c zend_llist.c \
     zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
     zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
@@ -1449,6 +1467,13 @@ PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/scripts/Makefile.frag,$abs_srcdir/scripts,
 PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/Makefile.frag,$abs_srcdir/Zend,Zend)
 PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/Zend/Makefile.frag,$abs_srcdir/Zend,Zend)
 
+if test "$PHP_DTRACE" = "yes"; then
+  case $host_alias in
+    *solaris*)
+      PHP_GENERATE_DTRACE([Zend/zend_dtrace.d],$php_build_target);;
+  esac
+fi
+
 PHP_GEN_BUILD_DIRS
 PHP_GEN_GLOBAL_MAKEFILE
 
index a1e2b1edff548abf835fba9797fcebc41b4be8ad..685dd81b5aab0ac910a701bd23920e43721775ce 100644 (file)
@@ -749,6 +749,12 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
 #else
                php_info_print_table_row(2, "IPv6 Support", "disabled" );
 #endif
+
+#if HAVE_DTRACE
+               php_info_print_table_row(2, "DTrace Support", "enabled" );
+#else
+               php_info_print_table_row(2, "DTrace Support", "disabled" );
+#endif
                {
                        HashTable *url_stream_wrappers_hash;
                        char *stream_protocol, *stream_protocols_buf = NULL;
index ccf618ce80805c681412efcb6e8f63b002fd5ac1..f47bf0b7a2ce72f2e1f8efd7ec091663ae5019ec 100644 (file)
@@ -81,6 +81,7 @@
 #include "zend_indent.h"
 #include "zend_extensions.h"
 #include "zend_ini.h"
+#include "zend_dtrace.h"
 
 #include "php_content_types.h"
 #include "php_ticks.h"
@@ -1379,6 +1380,10 @@ int php_request_startup(TSRMLS_D)
 {
        int retval = SUCCESS;
 
+#ifdef HAVE_DTRACE
+       DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), SAFE_FILENAME(SG(request_info).request_method));
+#endif /* HAVE_DTRACE */
+
 #ifdef PHP_WIN32
        PG(com_initialized) = 0;
 #endif
@@ -1662,6 +1667,10 @@ void php_request_shutdown(void *dummy)
                PG(com_initialized) = 0;
        }
 #endif
+
+#ifdef HAVE_DTRACE
+       DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), SAFE_FILENAME(SG(request_info).request_method));
+#endif /* HAVE_DTRACE */
 }
 /* }}} */