]> granicus.if.org Git - php/commitdiff
Initial support for built-in backtracing.
authorAndi Gutmans <andi@php.net>
Thu, 2 May 2002 17:20:48 +0000 (17:20 +0000)
committerAndi Gutmans <andi@php.net>
Thu, 2 May 2002 17:20:48 +0000 (17:20 +0000)
There are still a few problems such as includes and calling other functions
from internal functions which aren't seen (will have to think if and how to
fix this).
Also the main scripts filename isn't available. Need to think about that.

Zend/zend.h
Zend/zend_builtin_functions.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_globals.h

index e4f5f90b263d292d87ee0218aa0e86f48ed80590..360c8fd2956a7146c69fde021dd3f9b9b3dff88c 100644 (file)
@@ -297,7 +297,6 @@ struct _zend_class_entry {
 };
 
 
-
 typedef struct _zend_utility_functions {
        void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
        int (*printf_function)(const char *format, ...);
index dc398e73de25e33175e6307795949590ccd9e0af..0f30efb30e64c6bc87843b57482e31969fa0a6f3 100644 (file)
@@ -65,6 +65,7 @@ static ZEND_FUNCTION(get_loaded_extensions);
 static ZEND_FUNCTION(extension_loaded);
 static ZEND_FUNCTION(get_extension_funcs);
 static ZEND_FUNCTION(get_defined_constants);
+static ZEND_FUNCTION(debug_backtrace);
 #if ZEND_DEBUG
 static ZEND_FUNCTION(zend_test_func);
 #endif
@@ -116,6 +117,7 @@ static zend_function_entry builtin_functions[] = {
        ZEND_FE(extension_loaded,                       NULL)
        ZEND_FE(get_extension_funcs,            NULL)
        ZEND_FE(get_defined_constants,          NULL)
+       ZEND_FE(debug_backtrace, NULL)
 #if ZEND_DEBUG
        ZEND_FE(zend_test_func,         NULL)
 #endif
@@ -1180,6 +1182,33 @@ ZEND_FUNCTION(get_defined_constants)
 }
 
 
+/* {{{ proto void debug_backtrace(void)
+   Prints out a backtrace */
+ZEND_FUNCTION(debug_backtrace)
+{
+       zend_execute_data *ptr;
+       int lineno;
+
+
+       ptr = EG(current_execute_data);
+       lineno = ptr->opline->lineno;
+
+       ptr = ptr->prev_execute_data;
+
+       while (ptr) {
+               if (ptr->object) {
+                       printf("%s::", Z_OBJCE(*ptr->object)->name);
+               }
+               printf("%s() [%s:%d]\n", ptr->function_state.function->common.function_name, ptr->function_state.function->op_array.filename, lineno);
+               lineno = ptr->opline->lineno;
+               ptr = ptr->prev_execute_data;
+       }
+
+       printf("main() [...:%d]\n", lineno);
+       RETURN_TRUE;
+}
+
+
 /* {{{ proto bool extension_loaded(string extension_name)
    Returns true if the named extension is loaded */
 ZEND_FUNCTION(extension_loaded)
index 4c8e850f809dd49fe03a3f4ee4ba24be11da58e6..d5a0b8a11fa3190d517903b8ffc0b9a0ce337577 100644 (file)
@@ -181,6 +181,19 @@ typedef struct _zend_file_handle {
        zend_bool free_filename;
 } zend_file_handle;
 
+union _temp_variable;
+
+typedef struct _zend_execute_data {
+       struct _zend_op *opline;
+       zend_function_state function_state;
+       zend_function *fbc; /* Function Being Called */
+       zend_function *fbc_constructor;
+       zval *object;
+       union _temp_variable *Ts;
+       zend_bool original_in_execution;
+       zend_class_entry *calling_scope;
+       struct _zend_execute_data *prev_execute_data;
+} zend_execute_data;
 
 
 #define IS_CONST       (1<<0)
index 400ad892b32042d5eb4b972232b3b40aefe7d488..bd3c35c3ae2fe8ea0fe90a55f23826cee9bc807c 100644 (file)
@@ -1127,23 +1127,9 @@ static int zend_check_symbol(zval **pz TSRMLS_DC)
 #define RETURN_FROM_EXECUTE_LOOP(execute_data)                                                         \
        free_alloca(EX(Ts));                                                                                                    \
        EG(in_execution) = EX(original_in_execution);                                                   \
+       EG(current_execute_data) = EX(prev_execute_data);                                               \
        return;
 
-typedef struct _object_info {
-       zval *ptr;
-} object_info;
-
-typedef struct _zend_execute_data {
-       zend_op *opline;
-       zend_function_state function_state;
-       zend_function *fbc; /* Function Being Called */
-       zend_function *fbc_constructor;
-       object_info object;
-       temp_variable *Ts;
-       zend_bool original_in_execution;
-       zend_class_entry *calling_scope;
-} zend_execute_data;
-
 #define EX(element) execute_data.element
 
 ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
@@ -1152,9 +1138,11 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
 
        /* Initialize execute_data */
        EX(fbc) = NULL;
-       EX(object).ptr = NULL;
+       EX(object) = NULL;
        EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable)*op_array->T);
-       EX(original_in_execution)=EG(in_execution);
+       EX(original_in_execution) = EG(in_execution);
+       EX(prev_execute_data) = EG(current_execute_data);
+       EG(current_execute_data) = &execute_data;
 
        EG(in_execution) = 1;
        if (op_array->start_op) {
@@ -1873,29 +1861,29 @@ binary_assign_op_addr_obj:
                                }
                        case ZEND_INIT_CTOR_CALL:
                                {
-                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object));
 
                                        if (EX(opline)->op1.op_type == IS_VAR) {
                                                SELECTIVE_PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr, &EX(opline)->op1);
                                        }
 
                                        /* We are not handling overloaded classes right now */
-                                       EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
-                                       if (!PZVAL_IS_REF(EX(object).ptr)) {
-                                               EX(object).ptr->refcount++; /* For $this pointer */
+                                       EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                                       if (!PZVAL_IS_REF(EX(object))) {
+                                               EX(object)->refcount++; /* For $this pointer */
                                        } else {
                                                zval *this_ptr;
 
                                                ALLOC_ZVAL(this_ptr);
-                                               *this_ptr = *EX(object).ptr;
+                                               *this_ptr = *EX(object);
                                                INIT_PZVAL(this_ptr);
                                                zval_copy_ctor(this_ptr);
-                                               EX(object).ptr = this_ptr;
+                                               EX(object) = this_ptr;
                                        }
 
                                        EX(fbc) = EX(fbc_constructor);
                                        if(EX(fbc)->type == ZEND_USER_FUNCTION) { /* HACK!! */
-                                               EX(calling_scope) = Z_OBJCE_P(EX(object).ptr);
+                                               EX(calling_scope) = Z_OBJCE_P(EX(object));
                                        } else {
                                                EX(calling_scope) = NULL;
                                        }
@@ -1910,7 +1898,7 @@ binary_assign_op_addr_obj:
                                        char *function_name_strval;
                                        int function_name_strlen;
                                        
-                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object));
 
                                        is_const = (EX(opline)->op2.op_type == IS_CONST);
 
@@ -1936,13 +1924,13 @@ binary_assign_op_addr_obj:
                                                if (!EG(This)) {
                                                        zend_error(E_ERROR, "Can't fetch $this as not in object context");
                                                }
-                                               EX(object).ptr = EG(This);
+                                               EX(object) = EG(This);
                                        } else {
-                                               EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                                               EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
                                        }
                                                        
-                                       if (EX(object).ptr && EX(object).ptr->type == IS_OBJECT) {
-                                               EX(fbc) = Z_OBJ_HT_P(EX(object).ptr)->get_method(EX(object).ptr, function_name_strval, function_name_strlen TSRMLS_CC);
+                                       if (EX(object) && EX(object)->type == IS_OBJECT) {
+                                               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
                                        } else {
                                                zend_error(E_ERROR, "Call to a member function on a non-object");
                                        }
@@ -1950,19 +1938,19 @@ binary_assign_op_addr_obj:
                                                zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
                                        }
 
-                                       if (!PZVAL_IS_REF(EX(object).ptr)) {
-                                               EX(object).ptr->refcount++; /* For $this pointer */
+                                       if (!PZVAL_IS_REF(EX(object))) {
+                                               EX(object)->refcount++; /* For $this pointer */
                                        } else {
                                                zval *this_ptr;
                                                ALLOC_ZVAL(this_ptr);
-                                               *this_ptr = *EX(object).ptr;
+                                               *this_ptr = *EX(object);
                                                INIT_PZVAL(this_ptr);
                                                zval_copy_ctor(this_ptr);
-                                               EX(object).ptr = this_ptr;
+                                               EX(object) = this_ptr;
                                        }
 
                                        if(EX(fbc)->type == ZEND_USER_FUNCTION) {
-                                               EX(calling_scope) = Z_OBJCE_P(EX(object).ptr);
+                                               EX(calling_scope) = Z_OBJCE_P(EX(object));
                                        } else {
                                                EX(calling_scope) = NULL;
                                        }
@@ -1984,7 +1972,7 @@ binary_assign_op_addr_obj:
                                        char *function_name_strval;
                                        int function_name_strlen;
 
-                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object));
 
                                        is_const = (EX(opline)->op2.op_type == IS_CONST);
 
@@ -2003,8 +1991,8 @@ binary_assign_op_addr_obj:
                                                function_name_strlen = tmp.value.str.len;
                                        }
                                        
-                                       if ((EX(object).ptr = EG(This))) {
-                                               EX(object).ptr->refcount++;
+                                       if ((EX(object) = EG(This))) {
+                                               EX(object)->refcount++;
                                        }
 
                                        ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
@@ -2033,7 +2021,7 @@ binary_assign_op_addr_obj:
                                        char *function_name_strval;
                                        int function_name_strlen;
 
-                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object));
 
                                        is_const = (EX(opline)->op2.op_type == IS_CONST);
 
@@ -2056,8 +2044,8 @@ binary_assign_op_addr_obj:
                                        do {
                                                if (EG(scope)) {
                                                        if (zend_hash_find(&EG(scope)->function_table, function_name_strval, function_name_strlen+1, (void **) &function) == SUCCESS) {
-                                                               if ((EX(object).ptr = EG(This))) {
-                                                                       EX(object).ptr->refcount++;
+                                                               if ((EX(object) = EG(This))) {
+                                                                       EX(object)->refcount++;
                                                                }
                                                                EX(calling_scope) = EG(scope);
                                                                break;
@@ -2067,7 +2055,7 @@ binary_assign_op_addr_obj:
                                                        zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
                                                }
                                                EX(calling_scope) = function->common.scope;
-                                               EX(object).ptr = NULL;
+                                               EX(object) = NULL;
                                        } while (0);
                                        
                                        if (!is_const) {
@@ -2084,13 +2072,13 @@ binary_assign_op_addr_obj:
                        case ZEND_DO_FCALL: {
                                        zval *fname = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
                                        
-                                       zend_ptr_stack_push(&EG(arg_types_stack), EX(object).ptr);
+                                       zend_ptr_stack_push(&EG(arg_types_stack), EX(object));
 
                                        do {
                                                if (EG(scope)) {
                                                        if (zend_hash_find(&EG(scope)->function_table, fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function) == SUCCESS) {
-                                                               if ((EX(object).ptr = EG(This))) {
-                                                                       EX(object).ptr->refcount++;
+                                                               if ((EX(object) = EG(This))) {
+                                                                       EX(object)->refcount++;
                                                                }
                                                                EX(calling_scope) = EG(scope);
                                                                break;
@@ -2099,7 +2087,7 @@ binary_assign_op_addr_obj:
                                                if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
                                                        zend_error(E_ERROR, "Unknown function:  %s()\n", fname->value.str.val);
                                                }
-                                               EX(object).ptr = NULL;
+                                               EX(object) = NULL;
                                                EX(calling_scope) = EX(function_state).function->common.scope;
                                        } while (0);
 
@@ -2119,14 +2107,14 @@ do_fcall_common:
                                        EG(scope) = EX(calling_scope);
 
                                        current_this = EG(This);
-                                       EG(This) = EX(object).ptr;
+                                       EG(This) = EX(object);
 
                                        EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
 
                                        if (EX(function_state).function->type==ZEND_INTERNAL_FUNCTION) {        
                                                ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
                                                INIT_ZVAL(*(EX(Ts)[EX(opline)->result.u.var].var.ptr));
-                                               ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, return_value_used TSRMLS_CC);
+                                               ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object), return_value_used TSRMLS_CC);
                                                EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref = 0;
                                                EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount = 1;
                                                if (!return_value_used) {
@@ -2176,8 +2164,8 @@ do_fcall_common:
                                                ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
                                                INIT_ZVAL(*(EX(Ts)[EX(opline)->result.u.var].var.ptr));
 
-                                               if(EX(object).ptr) {
-                                                       Z_OBJ_HT_P(EX(object).ptr)->call_method(EX(fbc)->common.function_name, EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, return_value_used TSRMLS_CC);
+                                               if(EX(object)) {
+                                                       Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object), return_value_used TSRMLS_CC);
                                                } else {
                                                        zend_error(E_ERROR, "Cannot call overloaded function for non-object");
                                                }
@@ -2188,9 +2176,9 @@ do_fcall_common:
                                                }
                                        }
                                        if (EX(opline)->opcode == ZEND_DO_FCALL_BY_NAME) {
-                                               zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &EX(object).ptr, &EX(fbc));
+                                               zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &EX(object), &EX(fbc));
                                        } else {
-                                               EX(object).ptr = zend_ptr_stack_pop(&EG(arg_types_stack));
+                                               EX(object) = zend_ptr_stack_pop(&EG(arg_types_stack));
                                        }
                                        EX(function_state).function = (zend_function *) op_array;
                                        EG(function_state_ptr) = &EX(function_state);
index 278745459010cd04def86eaa0df0d03bd799235e..e6ef99b114357ecf7124c0a127d8b987d78525c4 100644 (file)
@@ -174,6 +174,8 @@ void init_executor(TSRMLS_D)
        EG(main_class_ptr) = &CG(main_class);
        CG(main_class).static_members = &EG(symbol_table);
 
+       EG(current_execute_data) = NULL;
+
        EG(This) = NULL;
 }
 
index 7b029b0e316491f5f9d73cd80ba77a7d9be162f2..58b2c4894546c085640f8e8ecf77efe0d38eec13 100644 (file)
@@ -203,6 +203,8 @@ struct _zend_executor_globals {
        zend_objects objects;
        zval *exception;
 
+       struct _zend_execute_data *current_execute_data;
+
        void *reserved[ZEND_MAX_RESERVED_RESOURCES];
 };