summaryrefslogtreecommitdiff
path: root/Zend/zend_builtin_functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_builtin_functions.c')
-rw-r--r--Zend/zend_builtin_functions.c97
1 files changed, 53 insertions, 44 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index dbe02ded5c..96b339cd67 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -2033,7 +2033,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
ZEND_FUNCTION(debug_print_backtrace)
{
- zend_execute_data *ptr, *skip;
+ zend_execute_data *call, *ptr, *skip;
zend_object *object;
int lineno, frameno = 0;
zend_function *func;
@@ -2055,7 +2055,7 @@ ZEND_FUNCTION(debug_print_backtrace)
ptr = EG(current_execute_data)->prev_execute_data;
/* skip debug_backtrace() */
- object = ptr->object;
+ call = ptr;
ptr = ptr->prev_execute_data;
while (ptr && (limit == 0 || frameno < limit)) {
@@ -2068,7 +2068,8 @@ ZEND_FUNCTION(debug_print_backtrace)
/* skip internal handler */
if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
skip->prev_execute_data &&
- skip->prev_execute_data->opline &&
+ skip->prev_execute_data->func &&
+ ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
@@ -2091,15 +2092,16 @@ ZEND_FUNCTION(debug_print_backtrace)
}
/* $this may be passed into regular internal functions */
+ object = call->object;
if (object &&
- ptr->call &&
- ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
- !ptr->call->func->common.scope) {
+ call &&
+ call->func->type == ZEND_INTERNAL_FUNCTION &&
+ !call->func->common.scope) {
object = NULL;
}
- if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
- func = ptr->call->func;
+ if (call->func) {
+ func = call->func;
function_name = (func->common.scope &&
func->common.scope->trait_aliases) ?
zend_resolve_method_name(
@@ -2109,9 +2111,8 @@ ZEND_FUNCTION(debug_print_backtrace)
(func->common.function_name ?
func->common.function_name->val : NULL);
} else {
- func = ptr->func;
- function_name = func && func->common.function_name ?
- func->common.function_name->val : NULL;
+ func = NULL;
+ function_name = NULL;
}
if (function_name) {
@@ -2132,14 +2133,14 @@ ZEND_FUNCTION(debug_print_backtrace)
}
if (func->type != ZEND_EVAL_CODE) {
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
- debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
+ debug_backtrace_get_args(call, &arg_array 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) {
+ if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
/* can happen when calling eval from a custom sapi */
function_name = "unknown";
build_filename_arg = 0;
@@ -2188,12 +2189,13 @@ ZEND_FUNCTION(debug_print_backtrace)
if (filename) {
zend_printf(") called at [%s:%d]\n", filename, lineno);
} else {
+ zend_execute_data *prev_call = skip;
zend_execute_data *prev = skip->prev_execute_data;
while (prev) {
- if (prev->call &&
- prev->call->func &&
- !ZEND_USER_CODE(prev->call->func->common.type)) {
+ if (prev_call &&
+ prev_call->func &&
+ !ZEND_USER_CODE(prev_call->func->common.type)) {
prev = NULL;
break;
}
@@ -2201,6 +2203,7 @@ ZEND_FUNCTION(debug_print_backtrace)
zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
break;
}
+ prev_call = prev;
prev = prev->prev_execute_data;
}
if (!prev) {
@@ -2208,7 +2211,7 @@ ZEND_FUNCTION(debug_print_backtrace)
}
}
include_filename = filename;
- object = skip->object;
+ call = skip;
ptr = skip->prev_execute_data;
++indent;
}
@@ -2218,8 +2221,8 @@ ZEND_FUNCTION(debug_print_backtrace)
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
{
- zend_execute_data *ptr, *skip;
- zend_object *object = Z_OBJ(EG(This));
+ zend_execute_data *call, *ptr, *skip;
+ zend_object *object;
int lineno, frameno = 0;
zend_function *func;
const char *function_name;
@@ -2228,24 +2231,29 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
const char *include_filename = NULL;
zval stack_frame;
+ call = NULL;
ptr = EG(current_execute_data);
- if (!ptr->opline) {
+ if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
+ call = ptr;
ptr = ptr->prev_execute_data;
}
if (ptr) {
if (skip_last) {
/* skip debug_backtrace() */
- object = ptr->object;
+ call = ptr;
ptr = ptr->prev_execute_data;
} else {
/* skip "new Exception()" */
- if (ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
- object = ptr->object;
+ if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
+ call = ptr;
ptr = ptr->prev_execute_data;
}
}
}
+ if (!call) {
+ call = ptr;
+ }
array_init(return_value);
@@ -2257,7 +2265,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
/* skip internal handler */
if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
skip->prev_execute_data &&
- skip->prev_execute_data->opline &&
+ skip->prev_execute_data->func &&
+ ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
@@ -2281,14 +2290,15 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
* 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_call = skip;
zend_execute_data *prev = skip->prev_execute_data;
while (prev) {
- if (prev->call &&
- prev->call->func &&
- !ZEND_USER_CODE(prev->call->func->common.type) &&
- !(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
- (prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
+ if (prev_call &&
+ prev_call->func &&
+ !ZEND_USER_CODE(prev_call->func->common.type) &&
+ !(prev_call->func->common.type == ZEND_INTERNAL_FUNCTION &&
+ (prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
break;
}
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
@@ -2297,21 +2307,22 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
break;
}
+ prev_call = prev;
prev = prev->prev_execute_data;
}
filename = NULL;
}
/* $this may be passed into regular internal functions */
+ object = call ? call->object : NULL;
if (object &&
- ptr->call &&
- ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
- !ptr->call->func->common.scope) {
+ call->func->type == ZEND_INTERNAL_FUNCTION &&
+ !call->func->common.scope) {
object = NULL;
}
- if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
- func = ptr->call->func;
+ if (call && call->func) {
+ func = call->func;
function_name = (func->common.scope &&
func->common.scope->trait_aliases) ?
zend_resolve_method_name(
@@ -2321,9 +2332,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
(func->common.function_name ?
func->common.function_name->val : NULL);
} else {
- func = ptr->func;
- function_name = func && func->common.function_name ?
- func->common.function_name->val : NULL;
+ func = NULL;
+ function_name = NULL;
}
if (function_name) {
@@ -2352,17 +2362,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
func->type != ZEND_EVAL_CODE) {
- if (ptr->call) {
- zval args;
- debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
- add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
- }
+ zval args;
+
+ debug_backtrace_get_args(call, &args TSRMLS_CC);
+ add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
}
} 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) {
+ if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
/* can happen when calling eval from a custom sapi */
function_name = "unknown";
build_filename_arg = 0;
@@ -2412,7 +2421,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
include_filename = filename;
- object = skip->object;
+ call = skip;
ptr = skip->prev_execute_data;
}
}