diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg_frame.c')
| -rw-r--r-- | sapi/phpdbg/phpdbg_frame.c | 246 | 
1 files changed, 142 insertions, 104 deletions
| diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index f4d2fcc5dc..4f0e5e88b0 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -1,6 +1,6 @@  /*     +----------------------------------------------------------------------+ -   | PHP Version 5                                                        | +   | PHP Version 7                                                        |     +----------------------------------------------------------------------+     | Copyright (c) 1997-2015 The PHP Group                                |     +----------------------------------------------------------------------+ @@ -26,7 +26,7 @@  ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -void phpdbg_restore_frame(TSRMLS_D) /* {{{ */ +void phpdbg_restore_frame(void) /* {{{ */  {  	if (PHPDBG_FRAME(num) == 0) {  		return; @@ -37,41 +37,40 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */  	/* move things back */  	EG(current_execute_data) = PHPDBG_FRAME(execute_data); -	EG(opline_ptr) = &PHPDBG_EX(opline); -	EG(active_op_array) = PHPDBG_EX(op_array); -	EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); -	EG(active_symbol_table) = PHPDBG_EX(symbol_table); -	EG(This) = PHPDBG_EX(current_this); -	EG(scope) = PHPDBG_EX(current_scope); -	EG(called_scope) = PHPDBG_EX(current_called_scope); +	EG(scope) = PHPDBG_EX(func)->op_array.scope;  } /* }}} */ -void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */ +void phpdbg_switch_frame(int frame) /* {{{ */  {  	zend_execute_data *execute_data = PHPDBG_FRAME(num)?PHPDBG_FRAME(execute_data):EG(current_execute_data);  	int i = 0;  	if (PHPDBG_FRAME(num) == frame) { -		phpdbg_notice("Already in frame #%d", frame); +		phpdbg_notice("frame", "id=\"%d\"", "Already in frame #%d", frame);  		return;  	} -	while (execute_data) { -		if (i++ == frame) { -			break; -		} +	phpdbg_try_access { +		while (execute_data) { +			if (i++ == frame) { +				break; +			} -		do { -			execute_data = execute_data->prev_execute_data; -		} while (execute_data && execute_data->opline == NULL); -	} +			do { +				execute_data = execute_data->prev_execute_data; +			} while (execute_data && execute_data->opline == NULL); +		} +	} phpdbg_catch_access { +		phpdbg_error("signalsegv", "", "Couldn't switch frames, invalid data source"); +		return; +	} phpdbg_end_try_access();  	if (execute_data == NULL) { -		phpdbg_error("No frame #%d", frame); +		phpdbg_error("frame", "type=\"maxnum\" id=\"%d\"", "No frame #%d", frame);  		return;  	} -	phpdbg_restore_frame(TSRMLS_C); +	phpdbg_restore_frame();  	if (frame > 0) {  		PHPDBG_FRAME(num) = frame; @@ -80,127 +79,166 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */  		PHPDBG_FRAME(execute_data) = EG(current_execute_data);  		EG(current_execute_data) = execute_data; -		EG(opline_ptr) = &PHPDBG_EX(opline); -		EG(active_op_array) = PHPDBG_EX(op_array); -		PHPDBG_FRAME(execute_data)->original_return_value = EG(return_value_ptr_ptr); -		EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); -		EG(active_symbol_table) = PHPDBG_EX(symbol_table); -		EG(This) = PHPDBG_EX(current_this); -		EG(scope) = PHPDBG_EX(current_scope); -		EG(called_scope) = PHPDBG_EX(current_called_scope); +		EG(scope) = PHPDBG_EX(func)->op_array.scope;  	} -	phpdbg_notice("Switched to frame #%d", frame); -	phpdbg_list_file( -		zend_get_executed_filename(TSRMLS_C), -		3, -		zend_get_executed_lineno(TSRMLS_C)-1, -		zend_get_executed_lineno(TSRMLS_C) -		TSRMLS_CC -	); +	phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); + +	{ +		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); +	}  } /* }}} */ -static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */ +static void phpdbg_dump_prototype(zval *tmp) /* {{{ */  { -	zval **funcname, **class, **type, **args, **argstmp; -	char is_class; +	zval *funcname, *class, class_zv, *type, *args, *argstmp; -	zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), -		(void **)&funcname); +	funcname = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("function")); -	if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp), -		"object", sizeof("object"), (void **)&class)) == FAILURE) { -		is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"), -			(void **)&class); +	if ((class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("object")))) { +		ZVAL_NEW_STR(&class_zv, Z_OBJCE_P(class)->name); +		class = &class_zv;  	} else { -		zend_get_object_classname(*class, (const char **)&Z_STRVAL_PP(class), -			(zend_uint *)&Z_STRLEN_PP(class) TSRMLS_CC); +		class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("class"));  	} -	if (is_class == SUCCESS) { -		zend_hash_find(Z_ARRVAL_PP(tmp), "type", sizeof("type"), (void **)&type); +	if (class) { +		type = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("type"));  	} -	phpdbg_write("%s%s%s(", -		is_class == FAILURE?"":Z_STRVAL_PP(class), -		is_class == FAILURE?"":Z_STRVAL_PP(type), -		Z_STRVAL_PP(funcname) -	); - -	if (zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"), -		(void **)&args) == SUCCESS) { -		HashPosition iterator; -		const zend_function *func = phpdbg_get_function( -			Z_STRVAL_PP(funcname), is_class == FAILURE ? NULL : Z_STRVAL_PP(class) TSRMLS_CC); -		const zend_arg_info *arginfo = func ? func->common.arg_info : NULL; -		int j = 0, m = func ? func->common.num_args : 0; +	args = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("args")); + +	phpdbg_xml(" symbol=\"%s%s%s\"", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); + +	if (args) { +		phpdbg_xml(">"); +	} else { +		phpdbg_xml(" />"); +	} + +	phpdbg_out("%s%s%s(", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); + +	if (args) { +		const zend_function *func = NULL; +		const zend_arg_info *arginfo = NULL;  		zend_bool is_variadic = 0; +		int j = 0, m; + +		phpdbg_try_access { +			/* assuming no autoloader call is necessary, class should have been loaded if it's in backtrace ... */ +			if ((func = phpdbg_get_function(Z_STRVAL_P(funcname), class ? Z_STRVAL_P(class) : NULL))) { +				arginfo = func->common.arg_info; +			} +		} phpdbg_end_try_access(); -		zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator); -		while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args), -			(void **) &argstmp, &iterator) == SUCCESS) { +		m = func ? func->common.num_args : 0; + +		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), argstmp) {  			if (j) { -				phpdbg_write(", "); +				phpdbg_out(", ");  			} +			phpdbg_xml("<arg %r");  			if (m && j < m) { -#if PHP_VERSION_ID >= 50600 -				is_variadic = arginfo[j].is_variadic; -#endif -				phpdbg_write("%s=%s", -					arginfo[j].name, is_variadic ? "[": ""); +				char *arg_name = NULL; + +				if (arginfo) { +					if (func->type == ZEND_INTERNAL_FUNCTION) { +						arg_name = (char *)((zend_internal_arg_info *)&arginfo[j])->name; +					} else { +						arg_name = ZSTR_VAL(arginfo[j].name); +					} +				} + +				if (!is_variadic) { +					is_variadic = arginfo ? arginfo[j].is_variadic : 0; +				} + +				phpdbg_xml(" variadic=\"%s\" name=\"%s\">", is_variadic ? "variadic" : "", arg_name ? arg_name : ""); +				phpdbg_out("%s=%s", arg_name ? arg_name : "?", is_variadic ? "[": ""); + +			} else { +				phpdbg_xml(">");  			}  			++j; -			zend_print_flat_zval_r(*argstmp TSRMLS_CC); -			zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator); -		} +			{ +				char *arg_print = phpdbg_short_zval_print(argstmp, 40); +				php_printf("%s", arg_print); +				efree(arg_print); +			} + +			phpdbg_xml("</arg>"); +		} ZEND_HASH_FOREACH_END(); +  		if (is_variadic) { -			phpdbg_write("]"); +			phpdbg_out("]");  		} +		phpdbg_xml("</frame>");  	} -	phpdbg_write(")"); +	phpdbg_out(")");  } -void phpdbg_dump_backtrace(size_t num TSRMLS_DC) /* {{{ */ +void phpdbg_dump_backtrace(size_t num) /* {{{ */  { -	zval zbacktrace; -	zval **tmp; -	zval **file, **line;  	HashPosition position; +	zval zbacktrace; +	zval *tmp; +	zval startline, startfile; +	const char *startfilename; +	zval *file = &startfile, *line = &startline;  	int i = 0, limit = num; -	int user_defined; + +	PHPDBG_OUTPUT_BACKUP();  	if (limit < 0) { -		phpdbg_error("Invalid backtrace size %d", limit); +		phpdbg_error("backtrace", "type=\"minnum\"", "Invalid backtrace size %d", limit); + +		PHPDBG_OUTPUT_BACKUP_RESTORE(); +		return;  	} -	zend_fetch_debug_backtrace( -		&zbacktrace, 0, 0, limit TSRMLS_CC); +	phpdbg_try_access { +		zend_fetch_debug_backtrace(&zbacktrace, 0, 0, limit); +	} phpdbg_catch_access { +		phpdbg_error("signalsegv", "", "Couldn't fetch backtrace, invalid data source"); +		return; +	} phpdbg_end_try_access(); -	zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); -	zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position); -	while (1) { -		user_defined = zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **)&file); -		zend_hash_find(Z_ARRVAL_PP(tmp), "line", sizeof("line"), (void **)&line); -		zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); +	phpdbg_xml("<backtrace %r>"); -		if (zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), -			(void**)&tmp, &position) == FAILURE) { -			phpdbg_write("frame #%d: {main} at %s:%ld", i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); -			break; -		} +	Z_LVAL(startline) = zend_get_executed_lineno(); +	startfilename = zend_get_executed_filename(); +	Z_STR(startfile) = zend_string_init(startfilename, strlen(startfilename), 0); -		if (user_defined == SUCCESS) { -			phpdbg_write("frame #%d: ", i++); -			phpdbg_dump_prototype(tmp TSRMLS_CC); -			phpdbg_writeln(" at %s:%ld", Z_STRVAL_PP(file), Z_LVAL_PP(line)); +	zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); +	tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position); +	while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) { +		if (file) { /* userland */ +			phpdbg_out("frame #%d: ", i); +			phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"%d\"", i, Z_STRVAL_P(file), Z_LVAL_P(line)); +			phpdbg_dump_prototype(tmp); +			phpdbg_out(" at %s:%ld\n", Z_STRVAL_P(file), Z_LVAL_P(line)); +			i++;  		} else { -			phpdbg_write(" => "); -			phpdbg_dump_prototype(tmp TSRMLS_CC); -			phpdbg_writeln(" (internal function)"); +			phpdbg_out(" => "); +			phpdbg_xml("<frame %r id=\"%d\" internal=\"internal\"", i); +			phpdbg_dump_prototype(tmp); +			phpdbg_out(" (internal function)\n");  		} + +		file = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("file")); +		line = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("line")); +		zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position);  	} -	phpdbg_writeln(EMPTY); +	phpdbg_writeln("frame", "id=\"%d\" symbol=\"{main}\" file=\"%s\" line=\"%d\"", "frame #%d: {main} at %s:%ld", i, Z_STRVAL_P(file), Z_LVAL_P(line)); +	phpdbg_xml("</backtrace>"); +  	zval_dtor(&zbacktrace); +	zend_string_release(Z_STR(startfile)); + +	PHPDBG_OUTPUT_BACKUP_RESTORE();  } /* }}} */ | 
