Skip to content

Commit

Permalink
Merged pull request #834
Browse files Browse the repository at this point in the history
  • Loading branch information
derickr committed May 6, 2022
2 parents 35fe16f + 46e800e commit bca92fd
Show file tree
Hide file tree
Showing 16 changed files with 493 additions and 29 deletions.
14 changes: 10 additions & 4 deletions src/base/base.c
Expand Up @@ -769,7 +769,7 @@ static void xdebug_execute_ex(zend_execute_data *execute_data)
}

/* Check for entry breakpoints */
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL);
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL, NULL);
}

if (XDEBUG_MODE_IS(XDEBUG_MODE_PROFILING)) {
Expand All @@ -795,8 +795,14 @@ static void xdebug_execute_ex(zend_execute_data *execute_data)
}

if (XDEBUG_MODE_IS(XDEBUG_MODE_STEP_DEBUG)) {
zval *return_value = NULL;

if (execute_data->return_value && !(op_array->fn_flags & ZEND_ACC_GENERATOR)) {
return_value = execute_data->return_value;
}

/* Check for return breakpoints */
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN);
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN, return_value);
}

fse->symbol_table = NULL;
Expand Down Expand Up @@ -877,7 +883,7 @@ static void xdebug_execute_internal(zend_execute_data *current_execute_data, zva

if (XDEBUG_MODE_IS(XDEBUG_MODE_STEP_DEBUG)) {
/* Check for entry breakpoints */
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL);
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL, NULL);
}

/* Check for SOAP */
Expand Down Expand Up @@ -919,7 +925,7 @@ static void xdebug_execute_internal(zend_execute_data *current_execute_data, zva

if (XDEBUG_MODE_IS(XDEBUG_MODE_STEP_DEBUG)) {
/* Check for return breakpoints */
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN);
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN, return_value);
}

if (XG_BASE(stack)) {
Expand Down
37 changes: 25 additions & 12 deletions src/debugger/debugger.c
Expand Up @@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
| Copyright (c) 2002-2021 Derick Rethans |
| Copyright (c) 2002-2022 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.01 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
Expand All @@ -20,6 +20,7 @@
#include "zend_exceptions.h"

#include "debugger_private.h"
#include "lib/log.h"
#include "lib/var.h"

extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
Expand Down Expand Up @@ -243,7 +244,7 @@ void xdebug_debugger_statement_call(zend_string *filename, int lineno)
XG_DBG(context).do_break = 0;
XG_DBG(context).pending_breakpoint = NULL;

if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_BREAK, NULL, 0, NULL, brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_BREAK, NULL, 0, NULL, brk_info, NULL)) {
xdebug_mark_debug_connection_not_active();
return;
}
Expand All @@ -269,7 +270,7 @@ void xdebug_debugger_statement_call(zend_string *filename, int lineno)
) {
XG_DBG(context).do_finish = 0;

if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL, NULL)) {
xdebug_mark_debug_connection_not_active();
return;
}
Expand All @@ -280,7 +281,7 @@ void xdebug_debugger_statement_call(zend_string *filename, int lineno)
if (XG_DBG(context).do_next && XG_DBG(context).next_level >= level) {
XG_DBG(context).do_next = 0;

if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL, NULL)) {
xdebug_mark_debug_connection_not_active();
return;
}
Expand All @@ -291,7 +292,7 @@ void xdebug_debugger_statement_call(zend_string *filename, int lineno)
if (XG_DBG(context).do_step) {
XG_DBG(context).do_step = 0;

if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_STEP, NULL, 0, NULL, NULL, NULL)) {
xdebug_mark_debug_connection_not_active();
return;
}
Expand Down Expand Up @@ -323,7 +324,7 @@ void xdebug_debugger_statement_call(zend_string *filename, int lineno)
}
}
if (break_ok && xdebug_handle_hit_value(extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_BREAK, NULL, 0, NULL, extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), filename, lineno, XDEBUG_BREAK, NULL, 0, NULL, extra_brk_info, NULL)) {
xdebug_mark_debug_connection_not_active();
break;
}
Expand Down Expand Up @@ -380,7 +381,8 @@ void xdebug_debugger_throw_exception_hook(zval *exception, zval *file, zval *lin
(char*) STR_NAME_VAL(exception_ce->name),
code_str ? code_str : ((code && Z_TYPE_P(code) == IS_STRING) ? Z_STRVAL_P(code) : NULL),
message ? Z_STRVAL_P(message) : "",
extra_brk_info
extra_brk_info,
NULL
)
) {
xdebug_mark_debug_connection_not_active();
Expand Down Expand Up @@ -412,7 +414,7 @@ void xdebug_debugger_error_cb(zend_string *error_filename, int error_lineno, int
if (xdebug_handle_hit_value(extra_brk_info)) {
char *type_str = xdebug_sprintf("%ld", type);

if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), error_filename, error_lineno, XDEBUG_BREAK, error_type_str, type_str, buffer, extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), error_filename, error_lineno, XDEBUG_BREAK, error_type_str, type_str, buffer, extra_brk_info, NULL)) {
xdebug_mark_debug_connection_not_active();
}

Expand All @@ -422,7 +424,7 @@ void xdebug_debugger_error_cb(zend_string *error_filename, int error_lineno, int
}
}

static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type, zval *return_value)
{
char *tmp_name = NULL;
size_t tmp_len = 0;
Expand Down Expand Up @@ -467,7 +469,7 @@ static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
if (!extra_brk_info->disabled && (extra_brk_info->function_break_type == breakpoint_type)) {
if (xdebug_handle_hit_value(extra_brk_info)) {
if (fse->user_defined == XDEBUG_BUILT_IN || (breakpoint_type == XDEBUG_BREAKPOINT_TYPE_RETURN)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), fse->filename, fse->lineno, XDEBUG_BREAK, NULL, 0, NULL, extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), fse->filename, fse->lineno, XDEBUG_BREAK, NULL, 0, NULL, extra_brk_info, return_value)) {
xdfree(tmp_name);
return 0;
}
Expand All @@ -480,13 +482,24 @@ static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
}
xdfree(tmp_name);

if (
(XG_DBG(context).breakpoint_include_return_value) &&
(breakpoint_type == XDEBUG_BREAKPOINT_TYPE_RETURN) &&
(XG_DBG(context).do_step || XG_DBG(context).do_finish) &&
return_value
) {
if (!XG_DBG(context).handler->remote_breakpoint(&(XG_DBG(context)), XG_BASE(stack), fse->filename, fse->lineno, XDEBUG_BREAK, NULL, 0, NULL, extra_brk_info, return_value)) {
return 0;
}
}

return 1;
}

void xdebug_debugger_handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
void xdebug_debugger_handle_breakpoints(function_stack_entry *fse, int breakpoint_type, zval *return_value)
{
if (xdebug_is_debug_connection_active() && XG_DBG(breakpoints_allowed)) {
if (!handle_breakpoints(fse, breakpoint_type)) {
if (!handle_breakpoints(fse, breakpoint_type, return_value)) {
xdebug_mark_debug_connection_not_active();
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/debugger/debugger.h
Expand Up @@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
| Copyright (c) 2002-2020 Derick Rethans |
| Copyright (c) 2002-2022 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.01 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
Expand All @@ -24,6 +24,7 @@ typedef struct _xdebug_debugger_globals_t {
int reason;
const char *lastcmd;
char *lasttransid;
zval *current_return_value;

zend_bool remote_connection_enabled;
zend_ulong remote_connection_pid;
Expand Down Expand Up @@ -62,6 +63,8 @@ PHP_INI_MH(OnUpdateDebugMode);

void xdebug_init_debugger_globals(xdebug_debugger_globals_t *xg);

#define XDEBUG_RETURN_VALUE_VAR_NAME "__RETURN_VALUE"

void xdebug_debugger_reset_ide_key(char *envval);
int xdebug_debugger_bailout_if_no_exec_requested(void);
void xdebug_debugger_set_program_name(zend_string *filename);
Expand All @@ -78,7 +81,7 @@ void xdebug_debugger_throw_exception_hook(zend_object *exception, zval *file, zv
void xdebug_debugger_throw_exception_hook(zval *exception, zval *file, zval *line, zval *code, char *code_str, zval *message);
#endif
void xdebug_debugger_error_cb(zend_string *error_filename, int error_lineno, int type, char *error_type_str, char *buffer);
void xdebug_debugger_handle_breakpoints(function_stack_entry *fse, int breakpoint_type);
void xdebug_debugger_handle_breakpoints(function_stack_entry *fse, int breakpoint_type, zval *return_value);

void xdebug_debugger_zend_startup(void);
void xdebug_debugger_zend_shutdown(void);
Expand Down
53 changes: 50 additions & 3 deletions src/debugger/handler_dbgp.c
Expand Up @@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
| Copyright (c) 2002-2021 Derick Rethans |
| Copyright (c) 2002-2022 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.01 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
Expand Down Expand Up @@ -1314,6 +1314,11 @@ DBGP_FUNC(feature_get)
xdebug_xml_add_attribute(*retval, "supported", "1");
XDEBUG_STR_CASE_END

XDEBUG_STR_CASE("breakpoint_include_return_value")
xdebug_xml_add_text(*retval, xdebug_sprintf("%ld", XG_DBG(context).breakpoint_include_return_value));
xdebug_xml_add_attribute(*retval, "supported", "1");
XDEBUG_STR_CASE_END

XDEBUG_STR_CASE_DEFAULT
xdebug_xml_add_text(*retval, xdstrdup(lookup_cmd(CMD_OPTION_CHAR('n')) ? "1" : "0"));
xdebug_xml_add_attribute(*retval, "supported", lookup_cmd(CMD_OPTION_CHAR('n')) ? "1" : "0");
Expand Down Expand Up @@ -1385,6 +1390,10 @@ DBGP_FUNC(feature_set)
XG_DBG(context).breakpoint_details = strtol(CMD_OPTION_CHAR('v'), NULL, 10);
XDEBUG_STR_CASE_END

XDEBUG_STR_CASE("breakpoint_include_return_value")
XG_DBG(context).breakpoint_include_return_value = strtol(CMD_OPTION_CHAR('v'), NULL, 10);
XDEBUG_STR_CASE_END

XDEBUG_STR_CASE_DEFAULT
RETURN_RESULT(XG_DBG(status), XG_DBG(reason), XDEBUG_ERROR_INVALID_ARGS);
XDEBUG_STR_CASE_DEFAULT_END
Expand Down Expand Up @@ -1535,7 +1544,7 @@ DBGP_FUNC(property_get)
add_var_retval = add_variable_node(*retval, CMD_OPTION_XDEBUG_STR('n'), 1, 0, 0, options);
XG_DBG(context).inhibit_notifications = 0;

if (add_var_retval) {
if (add_var_retval == FAILURE) {
options->max_data = old_max_data;
RETURN_RESULT(XG_DBG(status), XG_DBG(reason), XDEBUG_ERROR_PROPERTY_NON_EXISTENT);
}
Expand Down Expand Up @@ -1837,6 +1846,21 @@ static int attach_context_vars(xdebug_xml_node *node, xdebug_var_export_options
return 0;
}

/* Add return value special one if set and depth = 0 */
if (XG_DBG(context).breakpoint_include_return_value && XG_DBG(current_return_value) && depth == 0) {
xdebug_xml_node *tmp_node;
xdebug_str *name = xdebug_str_create_from_const_char("$"XDEBUG_RETURN_VALUE_VAR_NAME);

tmp_node = xdebug_get_zval_value_xml_node(name, XG_DBG(current_return_value), options);
xdebug_xml_expand_attribute_value(tmp_node, "facet", "virtual");
xdebug_xml_expand_attribute_value(tmp_node, "facet", "return_value");

xdebug_xml_add_child(node, tmp_node);
xdebug_str_free(name);

return 0;
}

/* Here the context_id is 0 */
if ((fse = xdebug_get_stack_frame(depth))) {
function_stack_entry *old_fse = xdebug_get_stack_frame(depth - 1);
Expand Down Expand Up @@ -2456,6 +2480,7 @@ int xdebug_dbgp_init(xdebug_con *context, int mode)
context->inhibit_notifications = 0;
context->resolved_breakpoints = 0;
context->breakpoint_details = 0;
context->breakpoint_include_return_value = 0;

xdebug_mark_debug_connection_active();
xdebug_dbgp_cmdloop(context, XDEBUG_CMDLOOP_BAIL);
Expand Down Expand Up @@ -2639,7 +2664,7 @@ int xdebug_dbgp_break_on_line(xdebug_con *context, xdebug_brk_info *brk, zend_st
return 0;
}

int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info)
int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info, zval *return_value)
{
xdebug_xml_node *response, *error_container;

Expand Down Expand Up @@ -2683,6 +2708,18 @@ int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_strin
}
xdebug_xml_add_child(response, error_container);

if (XG_DBG(context).breakpoint_include_return_value && return_value) {
xdebug_xml_node *return_value_container, *tmp_node;
xdebug_var_export_options *options = (xdebug_var_export_options*) context->options;

return_value_container = xdebug_xml_node_init("xdebug:return_value");
tmp_node = xdebug_get_zval_value_xml_node(NULL, return_value, options);

xdebug_xml_add_child(return_value_container, tmp_node);

xdebug_xml_add_child(response, return_value_container);
}

if (XG_DBG(context).breakpoint_details && brk_info) {
xdebug_xml_node *breakpoint_node = xdebug_xml_node_init("breakpoint");
breakpoint_brk_info_add(breakpoint_node, brk_info);
Expand All @@ -2698,8 +2735,18 @@ int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_strin
XG_DBG(lasttransid) = NULL;
}

XG_DBG(current_return_value) = return_value;
if (XG_DBG(current_return_value)) {
Z_TRY_ADDREF_P(XG_DBG(current_return_value));
}

xdebug_dbgp_cmdloop(context, XDEBUG_CMDLOOP_BAIL);

if (XG_DBG(current_return_value)) {
Z_TRY_DELREF_P(XG_DBG(current_return_value));
}
XG_DBG(current_return_value) = NULL;

return xdebug_is_debug_connection_active();
}

Expand Down
4 changes: 2 additions & 2 deletions src/debugger/handler_dbgp.h
Expand Up @@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
| Copyright (c) 2002-2020 Derick Rethans |
| Copyright (c) 2002-2022 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.01 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
Expand Down Expand Up @@ -99,7 +99,7 @@ int xdebug_dbgp_init(xdebug_con *context, int mode);
int xdebug_dbgp_deinit(xdebug_con *context);
int xdebug_dbgp_error(xdebug_con *context, int type, char *exception_type, char *message, const char *location, const unsigned int line, xdebug_vector *stack);
int xdebug_dbgp_break_on_line(xdebug_con *context, xdebug_brk_info *brk, zend_string *filename, int lineno);
int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info);
int xdebug_dbgp_breakpoint(xdebug_con *context, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info, zval *return_value);
int xdebug_dbgp_resolve_breakpoints(xdebug_con *context, zend_string *filename);
int xdebug_dbgp_stream_output(const char *string, unsigned int length);
int xdebug_dbgp_notification(xdebug_con *context, zend_string *filename, long lineno, int type, char *type_string, char *message);
Expand Down
5 changes: 3 additions & 2 deletions src/debugger/handlers.h
Expand Up @@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
| Copyright (c) 2002-2021 Derick Rethans |
| Copyright (c) 2002-2022 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.01 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
Expand Down Expand Up @@ -89,6 +89,7 @@ struct _xdebug_con {

int resolved_breakpoints;
int breakpoint_details;
int breakpoint_include_return_value;

/* Statistics and diagnostics */
char *connected_hostname;
Expand Down Expand Up @@ -141,7 +142,7 @@ struct _xdebug_remote_handler {

/* Breakpoints */
int (*break_on_line)(xdebug_con *h, xdebug_brk_info *brk, zend_string *filename, int lineno);
int (*remote_breakpoint)(xdebug_con *h, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info);
int (*remote_breakpoint)(xdebug_con *h, xdebug_vector *stack, zend_string *filename, long lineno, int type, char *exception, char *code, const char *message, xdebug_brk_info *brk_info, zval *return_value);
int (*resolve_breakpoints)(xdebug_con *h, zend_string *opa);

/* Output redirection */
Expand Down
3 changes: 2 additions & 1 deletion src/lib/log.c
Expand Up @@ -756,7 +756,8 @@ static void print_step_debug_information(void)
xdebug_info_printf("Extended Properties => %s\n", options->extended_properties ? "Yes" : "No");
xdebug_info_printf("Notifications => %s\n", XG_DBG(context).send_notifications ? "Yes" : "No");
xdebug_info_printf("Resolved Breakpoints => %s\n", XG_DBG(context).resolved_breakpoints ? "Yes" : "No");
xdebug_info_printf("Breakpoint Details => %s\n", XG_DBG(context).breakpoint_details ? "Yes" : "No");
xdebug_info_printf("Breakpoint: Details => %s\n", XG_DBG(context).breakpoint_details ? "Yes" : "No");
xdebug_info_printf("Breakpoint: Include Return Values => %s\n", XG_DBG(context).breakpoint_include_return_value ? "Yes" : "No");
}
}
php_info_print_table_end();
Expand Down
1 change: 1 addition & 0 deletions src/lib/str.h
Expand Up @@ -50,6 +50,7 @@ void xdebug_str_chop(xdebug_str *xs, size_t c);

xdebug_str *xdebug_str_new(void);
xdebug_str *xdebug_str_create_from_char(char *c);
#define xdebug_str_create_from_const_char(c) xdebug_str_create_from_char((char*) (c))
xdebug_str *xdebug_str_create(const char *c, size_t len);
xdebug_str *xdebug_str_copy(xdebug_str *orig);
void xdebug_str_destroy(xdebug_str *s);
Expand Down
9 changes: 9 additions & 0 deletions src/lib/var.c
Expand Up @@ -424,6 +424,15 @@ static void fetch_zval_from_symbol_table(
break;

case XF_ST_ROOT:
/* Check for return value */
if (
XG_DBG(current_return_value) &&
(strncmp(name, XDEBUG_RETURN_VALUE_VAR_NAME, name_length) == 0)
) {
ZVAL_COPY(&tmp_retval, XG_DBG(current_return_value));
goto cleanup;
}

/* Check for compiled vars */
element = prepare_search_key(name, &element_length, "", 0);
if (xdebug_lib_has_active_data() && xdebug_lib_has_active_function()) {
Expand Down

0 comments on commit bca92fd

Please sign in to comment.