diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg_frame.c')
-rw-r--r-- | sapi/phpdbg/phpdbg_frame.c | 121 |
1 files changed, 113 insertions, 8 deletions
diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index f64d18b4bb..85f3341e17 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -23,15 +23,95 @@ #include "phpdbg_utils.h" #include "phpdbg_frame.h" #include "phpdbg_list.h" +#include "zend_smart_str.h" ZEND_EXTERN_MODULE_GLOBALS(phpdbg) +static inline void phpdbg_append_individual_arg(smart_str *s, uint32_t i, zend_function *func, zval *arg) { + const zend_arg_info *arginfo = func->common.arg_info; + char *arg_name = NULL; + + if (i) { + smart_str_appends(s, ", "); + } + if (i < func->common.num_args) { + if (arginfo) { + if (func->type == ZEND_INTERNAL_FUNCTION) { + arg_name = (char *) ((zend_internal_arg_info *) &arginfo[i])->name; + } else { + arg_name = ZSTR_VAL(arginfo[i].name); + } + } + smart_str_appends(s, arg_name ? arg_name : "?"); + smart_str_appendc(s, '='); + } + { + char *arg_print = phpdbg_short_zval_print(arg, 40); + smart_str_appends(s, arg_print); + efree(arg_print); + } +} + +zend_string *phpdbg_compile_stackframe(zend_execute_data *ex) { + smart_str s = {0}; + zend_op_array *op_array = &ex->func->op_array; + uint32_t i = 0, first_extra_arg = op_array->num_args, num_args = ZEND_CALL_NUM_ARGS(ex); + zval *p = ZEND_CALL_ARG(ex, 1); + + if (op_array->scope) { + smart_str_append(&s, op_array->scope->name); + smart_str_appends(&s, "::"); + } + smart_str_append(&s, op_array->function_name); + smart_str_appendc(&s, '('); + if (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg) { + while (i < first_extra_arg) { + phpdbg_append_individual_arg(&s, i, ex->func, p); + p++; + i++; + } + p = ZEND_CALL_VAR_NUM(ex, op_array->last_var + op_array->T); + } + while (i < num_args) { + phpdbg_append_individual_arg(&s, i, ex->func, p); + p++; + i++; + } + smart_str_appendc(&s, ')'); + + if (ex->func->type == ZEND_USER_FUNCTION) { + smart_str_appends(&s, " at "); + smart_str_append(&s, op_array->filename); + smart_str_appendc(&s, ':'); + smart_str_append_unsigned(&s, ex->opline->lineno); + } else { + smart_str_appends(&s, " [internal function]"); + } + + return s.s; +} + +void phpdbg_print_cur_frame_info() { + const char *file_chr = zend_get_executed_filename(); + zend_string *file = zend_string_init(file_chr, strlen(file_chr), 0); + + phpdbg_list_file(file, 3, zend_get_executed_lineno() - 1, zend_get_executed_lineno()); + efree(file); +} + void phpdbg_restore_frame(void) /* {{{ */ { if (PHPDBG_FRAME(num) == 0) { return; } + if (PHPDBG_FRAME(generator)) { + if (PHPDBG_FRAME(generator)->execute_data->call) { + PHPDBG_FRAME(generator)->frozen_call_stack = zend_generator_freeze_call_stack(PHPDBG_FRAME(generator)->execute_data); + } + PHPDBG_FRAME(generator) = NULL; + } + PHPDBG_FRAME(num) = 0; /* move things back */ @@ -40,7 +120,7 @@ void phpdbg_restore_frame(void) /* {{{ */ void phpdbg_switch_frame(int frame) /* {{{ */ { - zend_execute_data *execute_data = PHPDBG_FRAME(num)?PHPDBG_FRAME(execute_data):EG(current_execute_data); + zend_execute_data *execute_data = PHPDBG_FRAME(num) ? PHPDBG_FRAME(execute_data) : EG(current_execute_data); int i = 0; if (PHPDBG_FRAME(num) == frame) { @@ -78,14 +158,15 @@ void phpdbg_switch_frame(int frame) /* {{{ */ EG(current_execute_data) = execute_data; } - phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); + phpdbg_try_access { + zend_string *s = phpdbg_compile_stackframe(EG(current_execute_data)); + phpdbg_notice("frame", "id=\"%d\" frameinfo=\"%.*s\"", "Switched to frame #%d: %.*s", frame, (int) ZSTR_LEN(s), ZSTR_VAL(s)); + zend_string_release(s); + } phpdbg_catch_access { + phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); + } phpdbg_end_try_access(); - { - const char *file_chr = zend_get_executed_filename(); - zend_string *file = zend_string_init(file_chr, strlen(file_chr), 0); - phpdbg_list_file(file, 3, zend_get_executed_lineno() - 1, zend_get_executed_lineno()); - efree(file); - } + phpdbg_print_cur_frame_info(); } /* }}} */ static void phpdbg_dump_prototype(zval *tmp) /* {{{ */ @@ -238,3 +319,27 @@ void phpdbg_dump_backtrace(size_t num) /* {{{ */ PHPDBG_OUTPUT_BACKUP_RESTORE(); } /* }}} */ + +void phpdbg_open_generator_frame(zend_generator *gen) { + zend_string *s; + + if (EG(current_execute_data) == gen->execute_data) { + return; + } + + phpdbg_restore_frame(); + + PHPDBG_FRAME(num) = -1; + PHPDBG_FRAME(generator) = gen; + + EG(current_execute_data) = gen->execute_data; + if (gen->frozen_call_stack) { + zend_generator_restore_call_stack(gen); + } + gen->execute_data->prev_execute_data = NULL; + + s = phpdbg_compile_stackframe(EG(current_execute_data)); + phpdbg_notice("frame", "handle=\"%d\" frameinfo=\"%.*s\"", "Switched to generator with handle #%d: %.*s", gen->std.handle, (int) ZSTR_LEN(s), ZSTR_VAL(s)); + zend_string_release(s); + phpdbg_print_cur_frame_info(); +} |