Skip to content
Permalink
Browse files

Merged pull request #538

  • Loading branch information
derickr committed Jan 13, 2020
2 parents e5d641a + 0e1c9de commit a410c7847f6c8d5a15aad7dbaa55f256054b1f94
Showing with 837 additions and 691 deletions.
  1. +1 −1 run-xdebug-tests.php
  2. +1 −5 src/base/base.c
  3. +26 −1 src/base/stack.c
  4. +1 −0 src/base/stack.h
  5. +0 −25 src/coverage/code_coverage.c
  6. +0 −2 src/coverage/code_coverage_private.h
  7. +175 −16 src/debugger/debugger.c
  8. +9 −0 src/debugger/debugger.h
  9. +17 −0 src/debugger/debugger_private.h
  10. +67 −157 src/debugger/handler_dbgp.c
  11. +3 −5 src/debugger/handler_dbgp.h
  12. +2 −9 src/debugger/handlers.h
  13. +0 −1 src/lib/private.h
  14. +29 −24 tests/debugger/bug00842-php7-001.phpt
  15. +19 −14 tests/debugger/bug00842-php7-004.phpt
  16. +23 −18 tests/debugger/bug01335.phpt
  17. +26 −18 tests/debugger/bug01388-01.phpt
  18. +14 −12 tests/debugger/bug01388-02-php70.phpt
  19. +15 −10 tests/debugger/bug01388-02-php74.phpt
  20. +18 −16 tests/debugger/bug01388-03-php70.phpt
  21. +20 −15 tests/debugger/bug01388-03-php74.phpt
  22. +13 −8 tests/debugger/bug01388-04.phpt
  23. +13 −8 tests/debugger/bug01388-05.phpt
  24. +13 −8 tests/debugger/bug01388-06.phpt
  25. +26 −21 tests/debugger/bug01388-07.phpt
  26. +5 −13 tests/debugger/bug01388-08-php70.phpt
  27. +4 −4 tests/debugger/bug01388-08-php74.phpt
  28. +18 −16 tests/debugger/bug01388-09.phpt
  29. +21 −22 tests/debugger/bug01388-10-php70.phpt
  30. +21 −19 tests/debugger/bug01388-10-php74.phpt
  31. +9 −15 tests/debugger/bug01388-11-php70.phpt
  32. +8 −11 tests/debugger/bug01388-11-php74.phpt
  33. +14 −9 tests/debugger/bug01388-12.phpt
  34. +14 −12 tests/debugger/bug01388-13-php70.phpt
  35. +15 −10 tests/debugger/bug01388-13-php74.phpt
  36. +17 −15 tests/debugger/bug01388-14.phpt
  37. +29 −33 tests/debugger/bug01388-15.phpt
  38. +20 −24 tests/debugger/bug01388-16.phpt
  39. +14 −12 tests/debugger/bug01388-17.phpt
  40. +15 −10 tests/debugger/bug01388-18.phpt
  41. +26 −21 tests/debugger/bug01388-19.phpt
  42. +13 −8 tests/debugger/bug01388-20.phpt
  43. +29 −32 tests/debugger/bug01388-21.phpt
  44. +13 −11 tests/debugger/bug01660.phpt
  45. +1 −0 tests/debugger/remote_log1.phpt
@@ -323,7 +323,7 @@ function write_information()
'session' => array('session.auto_start=0'),
'tidy' => array('tidy.clean_output=0'),
'zlib' => array('zlib.output_compression=Off'),
'xdebug' => array('xdebug.default_enable=0','xdebug.remote_enable=0'),
'xdebug' => array('xdebug.default_enable=0','xdebug.remote_enable=0','xdebug.remote_log_level=20'),
'mbstring' => array('mbstring.func_overload=0'),
);
@@ -148,6 +148,7 @@ static zend_op_array *xdebug_compile_file(zend_file_handle *file_handle, int typ

if (op_array) {
xdebug_coverage_compile_file(op_array);
xdebug_debugger_compile_file(op_array);
}
return op_array;
}
@@ -198,11 +199,6 @@ static void function_stack_entry_dtor(void *dummy, void *elem)
e->profile.call_list = NULL;
}

if (e->executable_lines_cache) {
xdebug_set_free(e->executable_lines_cache);
e->executable_lines_cache = NULL;
}

xdfree(e);
}
}
@@ -912,6 +912,32 @@ void xdebug_func_dtor(xdebug_func *elem)
xdfree(elem);
}

void xdebug_build_fname_from_oparray(xdebug_func *tmp, zend_op_array *opa)
{
int closure = 0;

memset(tmp, 0, sizeof(xdebug_func));

if (opa->function_name) {
if (xdebug_function_name_is_closure(STR_NAME_VAL(opa->function_name))) {
tmp->function = xdebug_wrap_closure_location_around_function_name(opa, STR_NAME_VAL(opa->function_name));
closure = 1;
} else {
tmp->function = xdstrdup(STR_NAME_VAL(opa->function_name));
}
} else {
tmp->function = xdstrdup("{main}");
tmp->type = XFUNC_MAIN;
}

if (opa->scope && !closure) {
tmp->type = XFUNC_MEMBER;
tmp->class = xdstrdup(STR_NAME_VAL(opa->scope->name));
} else {
tmp->type = XFUNC_NORMAL;
}
}

void xdebug_build_fname(xdebug_func *tmp, zend_execute_data *edata)
{
memset(tmp, 0, sizeof(xdebug_func));
@@ -1073,7 +1099,6 @@ function_stack_entry *xdebug_add_stack_frame(zend_execute_data *zdata, zend_op_a
tmp->is_variadic = 0;
tmp->filtered_tracing = 0;
tmp->filtered_code_coverage = 0;
tmp->executable_lines_cache = NULL;

XG_BASE(function_count)++;
tmp->function_nr = XG_BASE(function_count);
@@ -28,6 +28,7 @@ char* xdebug_wrap_closure_location_around_function_name(zend_op_array *opa, char
void xdebug_func_dtor_by_ref(xdebug_func *elem); /* TODO: Remove this API */
void xdebug_func_dtor(xdebug_func *elem);
void xdebug_build_fname(xdebug_func *tmp, zend_execute_data *edata);
void xdebug_build_fname_from_oparray(xdebug_func *tmp, zend_op_array *opa);
function_stack_entry *xdebug_add_stack_frame(zend_execute_data *zdata, zend_op_array *op_array, int type);
void xdebug_append_error_head(xdebug_str *str, int html, const char *error_type_str);
void xdebug_append_error_description(xdebug_str *str, int html, const char *error_type_str, const char *buffer, const char *error_filename, const int error_lineno);
@@ -438,31 +438,6 @@ static void xdebug_analyse_oparray(zend_op_array *opa, xdebug_set *set, xdebug_b
}
}

void xdebug_build_fname_from_oparray(xdebug_func *tmp, zend_op_array *opa)
{
int closure = 0;

memset(tmp, 0, sizeof(xdebug_func));

if (opa->function_name) {
if (xdebug_function_name_is_closure(STR_NAME_VAL(opa->function_name))) {
tmp->function = xdebug_wrap_closure_location_around_function_name(opa, STR_NAME_VAL(opa->function_name));
closure = 1;
} else {
tmp->function = xdstrdup(STR_NAME_VAL(opa->function_name));
}
} else {
tmp->function = xdstrdup("{main}");
}

if (opa->scope && !closure) {
tmp->type = XFUNC_MEMBER;
tmp->class = xdstrdup(STR_NAME_VAL(opa->scope->name));
} else {
tmp->type = XFUNC_NORMAL;
}
}

static void prefill_from_oparray(char *filename, zend_op_array *op_array)
{
unsigned int i;
@@ -45,8 +45,6 @@ typedef struct xdebug_coverage_function {

xdebug_coverage_file *xdebug_coverage_file_ctor(char *filename);

void xdebug_build_fname_from_oparray(xdebug_func *tmp, zend_op_array *opa);

xdebug_coverage_function *xdebug_coverage_function_ctor(char *function_name);
void xdebug_coverage_function_dtor(void *data);
void xdebug_code_coverage_start_of_function(zend_op_array *op_array, char *function_name);
@@ -22,12 +22,15 @@
#include "zend_exceptions.h"

#include "debugger_private.h"
#include "base/stack.h"

extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);

static size_t (*xdebug_orig_ub_write)(const char *string, size_t len);
static size_t xdebug_ub_write(const char *string, size_t length);

static void xdebug_line_list_dtor(xdebug_lines_list *line_list);

PHP_INI_MH(OnUpdateDebugMode)
{
if (!new_value) {
@@ -123,14 +126,6 @@ void xdebug_debugger_set_program_name(zend_string *filename)
}
}

void xdebug_debugger_register_eval(function_stack_entry *fse)
{
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(context).handler->register_eval_id) {
XG_DBG(context).handler->register_eval_id(&(XG_DBG(context)), fse);
}
}


/* Remote debugger helper functions */
static int xdebug_handle_hit_value(xdebug_brk_info *brk_info)
{
@@ -312,11 +307,11 @@ void xdebug_debugger_throw_exception_hook(zend_class_entry * exception_ce, zval
ce_ptr = ce_ptr->parent;
} while (!exception_breakpoint_found && ce_ptr);
}

#if 0
if (XG_DBG(context).resolved_breakpoints && exception_breakpoint_found) {
XG_DBG(context).handler->resolve_breakpoints(&(XG_DBG(context)), XDEBUG_BREAKPOINT_TYPE_EXCEPTION, extra_brk_info);
XG_DBG(context).handler->resolve_breakpoints(&(XG_DBG(context)), extra_brk_info);
}

#endif
if (exception_breakpoint_found && xdebug_handle_hit_value(extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(
&(XG_DBG(context)), XG_BASE(stack),
@@ -370,11 +365,6 @@ static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
char *tmp_name = NULL;
size_t tmp_len = 0;

/* When we first enter a user defined function, we need to resolve breakpoints for this function */
if (XG_DBG(context).resolved_breakpoints && breakpoint_type == XDEBUG_BREAKPOINT_TYPE_CALL && fse->user_defined == XDEBUG_USER_DEFINED) {
XG_DBG(context).handler->resolve_breakpoints(&(XG_DBG(context)), XDEBUG_BREAKPOINT_TYPE_LINE|XDEBUG_BREAKPOINT_TYPE_CONDITIONAL|XDEBUG_BREAKPOINT_TYPE_CALL|XDEBUG_BREAKPOINT_TYPE_RETURN, fse);
}

/* Function breakpoints */
if (fse->function.type == XFUNC_NORMAL) {
if (xdebug_hash_find(XG_DBG(context).function_breakpoints, fse->function.function, strlen(fse->function.function), (void *) &extra_brk_info)) {
@@ -539,7 +529,9 @@ void xdebug_debugger_rinit(void)
}

xdebug_mark_debug_connection_not_active();

XG_DBG(breakpoints_allowed) = 1;
XG_DBG(breakable_lines_map) = xdebug_hash_alloc(2048, (xdebug_hash_dtor_t) xdebug_line_list_dtor);
XG_DBG(remote_log_file) = NULL;

/* Initialize some debugger context properties */
@@ -571,8 +563,175 @@ void xdebug_debugger_post_deactivate(void)
xdfree(XG_DBG(context).list.last_file);
XG_DBG(context).list.last_file = NULL;
}

xdebug_hash_destroy(XG_DBG(breakable_lines_map));
}

xdebug_set *xdebug_debugger_get_breakable_lines_from_oparray(zend_op_array *opa)
{
int i;
xdebug_set *tmp;

tmp = xdebug_set_create(opa->line_end);

for (i = 0; i < opa->last; i++ ) {
if (opa->opcodes[i].opcode == ZEND_EXT_STMT ) {
xdebug_set_add(tmp, opa->opcodes[i].lineno);
}
}

return tmp;
}


/* {{{ function/lines map collection helpers */
static void xdebug_function_lines_map_dtor(xdebug_function_lines_map_item *lines_map)
{
xdebug_set_free(lines_map->lines_breakable);
xdfree(lines_map);
}

static void xdebug_line_list_dtor(xdebug_lines_list *line_list)
{
size_t i;

for (i = 0; i < line_list->count; i++) {
xdebug_function_lines_map_dtor(line_list->functions[i]);
}
xdfree(line_list->functions);
xdfree(line_list);
}

static xdebug_lines_list *get_file_function_line_list(zend_string *filename)
{
xdebug_lines_list *lines_list;

if (xdebug_hash_find(XG_DBG(breakable_lines_map), ZSTR_VAL(filename), ZSTR_LEN(filename), (void *) &lines_list)) {
return lines_list;
}

lines_list = xdmalloc(sizeof(xdebug_lines_list));
lines_list->count = 0;
lines_list->size = 0;
lines_list->functions = NULL;

xdebug_hash_add(XG_DBG(breakable_lines_map), ZSTR_VAL(filename), ZSTR_LEN(filename), (void *) lines_list);

return lines_list;
}

static void add_function_to_lines_list(xdebug_lines_list *lines_list, zend_op_array *opa)
{
xdebug_function_lines_map_item *map_item = xdmalloc(sizeof(xdebug_function_lines_map_item));

map_item->line_start = opa->line_start;
map_item->line_end = opa->line_end;
map_item->line_span = opa->line_end - opa->line_start;
map_item->lines_breakable = xdebug_debugger_get_breakable_lines_from_oparray(opa);

if (lines_list->count >= lines_list->size) {
lines_list->size = lines_list->size == 0 ? 16 : lines_list->size * 2;
lines_list->functions = xdrealloc(lines_list->functions, sizeof(xdebug_function_lines_map_item *) * lines_list->size);
}
lines_list->functions[lines_list->count] = map_item;
lines_list->count++;
}
/* }}} */

static void resolve_breakpoints_for_function(xdebug_lines_list *lines_list, zend_op_array *opa)
{
if (!ZEND_USER_CODE(opa->type)) {
return;
}

add_function_to_lines_list(lines_list, opa);
}

static void resolve_breakpoints_for_class(xdebug_lines_list *file_function_lines_list, zend_class_entry *ce)
{
zend_op_array *function_op_array;

ZEND_HASH_FOREACH_PTR(&ce->function_table, function_op_array) {
resolve_breakpoints_for_function(file_function_lines_list, function_op_array);
} ZEND_HASH_FOREACH_END();
}

void xdebug_debugger_compile_file(zend_op_array *op_array)
{
zend_op_array *function_op_array;
zend_class_entry *class_entry;
xdebug_lines_list *file_function_lines_list;

if (!XINI_DBG(remote_enable)) {
return;
}

file_function_lines_list = get_file_function_line_list(op_array->filename);

ZEND_HASH_REVERSE_FOREACH_PTR(CG(function_table), function_op_array) {
if (_idx == XG_DBG(function_count)) {
break;
}
resolve_breakpoints_for_function(file_function_lines_list, function_op_array);
} ZEND_HASH_FOREACH_END();
XG_DBG(function_count) = CG(function_table)->nNumUsed;

ZEND_HASH_REVERSE_FOREACH_PTR(CG(class_table), class_entry) {
if (_idx == XG_DBG(class_count)) {
break;
}
resolve_breakpoints_for_class(file_function_lines_list, class_entry);
} ZEND_HASH_FOREACH_END();
XG_DBG(class_count) = CG(class_table)->nNumUsed;

add_function_to_lines_list(file_function_lines_list, op_array);

if (!xdebug_is_debug_connection_active_for_current_pid()) {
return;
}

XG_DBG(context).handler->resolve_breakpoints(
&(XG_DBG(context)),
op_array->filename
);
}

static void resolve_breakpoints_for_eval(int eval_id, zend_op_array *opa)
{
xdebug_lines_list *lines_list;
char *eval_filename = xdebug_sprintf("dbgp://%d", eval_id);
zend_string *eval_string = zend_string_init(eval_filename, strlen(eval_filename), 0);

lines_list = get_file_function_line_list(eval_string);
add_function_to_lines_list(lines_list, opa);

resolve_breakpoints_for_function(lines_list, opa);

if (!xdebug_is_debug_connection_active_for_current_pid()) {
zend_string_release(eval_string);
xdfree(eval_filename);
return;
}

XG_DBG(context).handler->resolve_breakpoints(
&(XG_DBG(context)),
eval_string
);

zend_string_release(eval_string);
xdfree(eval_filename);
}

void xdebug_debugger_register_eval(function_stack_entry *fse)
{
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(context).handler->register_eval_id) {
int eval_id = XG_DBG(context).handler->register_eval_id(&(XG_DBG(context)), fse);

resolve_breakpoints_for_eval(eval_id, fse->op_array);
}
}


PHP_FUNCTION(xdebug_break)
{
/* Start JIT if requested and not yet enabled */
@@ -37,6 +37,11 @@ typedef struct _xdebug_debugger_globals_t {
char *ide_key; /* As Xdebug uses it, from environment, USER, USERNAME or empty */
FILE *remote_log_file; /* File handler for protocol log */

/* breakpoint resolving */
size_t function_count;
size_t class_count;
xdebug_hash *breakable_lines_map;

/* output redirection */
int stdout_mode;
} xdebug_debugger_globals_t;
@@ -66,6 +71,8 @@ int xdebug_debugger_bailout_if_no_exec_requested(void);
void xdebug_debugger_set_program_name(zend_string *filename);
void xdebug_debugger_register_eval(function_stack_entry *fse);

xdebug_set *xdebug_debugger_get_breakable_lines_from_oparray(zend_op_array *opa);

void xdebug_debugger_statement_call(char *file, int file_len, int lineno);
void xdebug_debugger_throw_exception_hook(zend_class_entry * exception_ce, zval *file, zval *line, zval *code, char *code_str, zval *message);
void xdebug_debugger_error_cb(const char *error_filename, int error_lineno, int type, char *error_type_str, char *buffer);
@@ -78,6 +85,8 @@ void xdebug_debugger_minfo(void);
void xdebug_debugger_rinit(void);
void xdebug_debugger_post_deactivate(void);

void xdebug_debugger_compile_file(zend_op_array *op_array);

PHP_FUNCTION(xdebug_break);


0 comments on commit a410c78

Please sign in to comment.
You can’t perform that action at this time.