Back to index

php5  5.3.10
Functions
zend_builtin_functions.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int zend_startup_builtin_functions (TSRMLS_D)
ZEND_API void zend_fetch_debug_backtrace (zval *return_value, int skip_last, int options TSRMLS_DC)

Function Documentation

ZEND_API void zend_fetch_debug_backtrace ( zval *  return_value,
int  skip_last,
int options  TSRMLS_DC 
)

Definition at line 2093 of file zend_builtin_functions.c.

{
       zend_execute_data *ptr, *skip;
       int lineno;
       char *function_name;
       char *filename;
       char *class_name;
       char *include_filename = NULL;
       zval *stack_frame;

       ptr = EG(current_execute_data);

       /* skip "new Exception()" */
       if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
              ptr = ptr->prev_execute_data;
       }

       /* skip debug_backtrace() */
       if (skip_last-- && ptr) {
              ptr = ptr->prev_execute_data;
       }

       array_init(return_value);

       while (ptr) {
              MAKE_STD_ZVAL(stack_frame);
              array_init(stack_frame);

              skip = ptr;
              /* skip internal handler */
              if (!skip->op_array &&
                  skip->prev_execute_data &&
                  skip->prev_execute_data->opline &&
                  skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
                  skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
                  skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
                     skip = skip->prev_execute_data;
              }

              if (skip->op_array) {
                     filename = skip->op_array->filename;
                     lineno = skip->opline->lineno;
                     add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1);
                     add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno);

                     /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
                      * and debug_baktrace() might have been called by the error_handler. in this case we don't 
                      * want to pop anything of the argument-stack */
              } else {
                     zend_execute_data *prev = skip->prev_execute_data;

                     while (prev) {
                            if (prev->function_state.function &&
                                   prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
                                   !(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
                                          (prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
                                   break;
                            }                               
                            if (prev->op_array) {
                                   add_assoc_string_ex(stack_frame, "file", sizeof("file"), prev->op_array->filename, 1);
                                   add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
                                   break;
                            }
                            prev = prev->prev_execute_data;
                     }
                     filename = NULL;
              }

              function_name = ptr->function_state.function->common.function_name;

              if (function_name) {
                     add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);

                     if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
                            if (ptr->function_state.function->common.scope) {
                                   add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
                            } else {
                                   zend_uint class_name_len;
                                   int dup;

                                   dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
                                   add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
                                   
                            }
                            if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
                                   add_assoc_zval_ex(stack_frame, "object", sizeof("object"), ptr->object);
                                   Z_ADDREF_P(ptr->object);
                            }

                            add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
                     } else if (ptr->function_state.function->common.scope) {
                            add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
                            add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
                     }

                     if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 && 
                            ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
                            if (ptr->function_state.arguments) {
                                   add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(ptr->function_state.arguments TSRMLS_CC));
                            }
                     }
              } else {
                     /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
                     zend_bool build_filename_arg = 1;

                     if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
                            /* can happen when calling eval from a custom sapi */
                            function_name = "unknown";
                            build_filename_arg = 0;
                     } else
                     switch (ptr->opline->op2.u.constant.value.lval) {
                            case ZEND_EVAL:
                                   function_name = "eval";
                                   build_filename_arg = 0;
                                   break;
                            case ZEND_INCLUDE:
                                   function_name = "include";
                                   break;
                            case ZEND_REQUIRE:
                                   function_name = "require";
                                   break;
                            case ZEND_INCLUDE_ONCE:
                                   function_name = "include_once";
                                   break;
                            case ZEND_REQUIRE_ONCE:
                                   function_name = "require_once";
                                   break;
                            default:
                                   /* this can actually happen if you use debug_backtrace() in your error_handler and 
                                    * you're in the top-scope */
                                   function_name = "unknown"; 
                                   build_filename_arg = 0;
                                   break;
                     }

                     if (build_filename_arg && include_filename) {
                            zval *arg_array;

                            MAKE_STD_ZVAL(arg_array);
                            array_init(arg_array);

                            /* include_filename always points to the last filename of the last last called-fuction.
                               if we have called include in the frame above - this is the file we have included.
                             */

                            add_next_index_string(arg_array, include_filename, 1);
                            add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array);
                     }

                     add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
              }

              add_next_index_zval(return_value, stack_frame);

              include_filename = filename; 

              ptr = skip->prev_execute_data;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 316 of file zend_builtin_functions.c.

Here is the call graph for this function:

Here is the caller graph for this function: