diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg_frame.c')
| -rw-r--r-- | sapi/phpdbg/phpdbg_frame.c | 125 | 
1 files changed, 113 insertions, 12 deletions
diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index d6256a84af..85f3341e17 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -23,26 +23,104 @@  #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 */  	EG(current_execute_data) = PHPDBG_FRAME(execute_data); - -	EG(scope) = PHPDBG_EX(func)->op_array.scope;  } /* }}} */  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,18 +156,17 @@ void phpdbg_switch_frame(int frame) /* {{{ */  		/* backup things and jump back */  		PHPDBG_FRAME(execute_data) = EG(current_execute_data);  		EG(current_execute_data) = execute_data; - -		EG(scope) = PHPDBG_EX(func)->op_array.scope;  	} -	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) /* {{{ */ @@ -242,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(); +}  | 
