Skip to content
Permalink
Browse files

debugger: Make functions and structures self-contained

  • Loading branch information...
derickr committed Nov 7, 2019
1 parent 4d0f565 commit 04a4f680c4d8760ca046d63136cd07ecb966a884
@@ -81,7 +81,7 @@ if test "$PHP_XDEBUG" != "no"; then
XDEBUG_LIB_SOURCES="src/lib/usefulstuff.c src/lib/compat.c src/lib/hash.c src/lib/llist.c src/lib/private.c src/lib/set.c src/lib/str.c src/lib/var.c src/lib/xml.c"

XDEBUG_COVERAGE_SOURCES="src/coverage/branch_info.c src/coverage/code_coverage.c"
XDEBUG_DEBUGGER_SOURCES="src/debugger/com.c src/debugger/handler_dbgp.c src/debugger/handlers.c"
XDEBUG_DEBUGGER_SOURCES="src/debugger/com.c src/debugger/debugger.c src/debugger/handler_dbgp.c src/debugger/handlers.c"
XDEBUG_GCSTATS_SOURCES="src/gcstats/gc_stats.c"
XDEBUG_PROFILER_SOURCES="src/profiler/profiler.c"
XDEBUG_TRACING_SOURCES="src/tracing/trace_computerized.c src/tracing/trace_html.c src/tracing/trace_textual.c src/tracing/tracing.c"
@@ -7,7 +7,7 @@ if (PHP_XDEBUG != 'no') {
var XDEBUG_LIB_SOURCES="usefulstuff.c compat.c hash.c llist.c private.c set.c str.c var.c xml.c"

var XDEBUG_COVERAGE_SOURCES="branch_info.c code_coverage.c"
var XDEBUG_DEBUGGER_SOURCES="com.c handler_dbgp.c handlers.c"
var XDEBUG_DEBUGGER_SOURCES="com.c debugger.c handler_dbgp.c handlers.c"
var XDEBUG_GCSTATS_SOURCES="gc_stats.c"
var XDEBUG_PROFILER_SOURCES="profiler.c"
var XDEBUG_TRACING_SOURCES="trace_computerized.c trace_html.c trace_textual.c tracing.c"
@@ -138,6 +138,9 @@ Thu, Jul 25, 2019 - xdebug 2.8.0beta1
<dir name="debugger">
<file name="com.c" role="src" />
<file name="com.h" role="src" />
<file name="debugger.c" role="src" />
<file name="debugger.h" role="src" />
<file name="debugger_private.h" role="src" />
<file name="handlers.c" role="src" />
<file name="handlers.h" role="src" />
<file name="handler_dbgp.c" role="src" />
@@ -31,7 +31,7 @@

#include "coverage/branch_info.h"
#include "coverage/code_coverage.h"
#include "debugger/handlers.h"
#include "debugger/debugger.h"
#include "gcstats/gc_stats.h"
#include "profiler/profiler.h"
#include "lib/compat.h"
@@ -228,47 +228,6 @@ struct xdebug_base_info {
} settings;
};

struct xdebug_stepdbg_info {
int status;
int reason;
const char *lastcmd;
char *lasttransid;

zend_bool remote_connection_enabled;
zend_ulong remote_connection_pid;
zend_bool breakpoints_allowed;
xdebug_con context;
unsigned int breakpoint_count;
unsigned int no_exec;
char *ide_key; /* As Xdebug uses it, from environment, USER, USERNAME or empty */
FILE *remote_log_file; /* File handler for protocol log */

HashTable *active_symbol_table;
zend_execute_data *active_execute_data;
zval *This;
function_stack_entry *active_fse;

/* output redirection */
int stdout_mode;

struct {
zend_bool remote_enable; /* 0 */
zend_long remote_port; /* 9000 */
char *remote_host; /* localhost */
long remote_mode; /* XDEBUG_NONE, XDEBUG_JIT, XDEBUG_REQ */
char *remote_handler; /* php3, gdb, dbgp */
zend_bool remote_autostart; /* Disables the requirement for XDEBUG_SESSION_START */
zend_bool remote_connect_back; /* connect back to the HTTP requestor */
char *remote_log; /* Filename to log protocol communication to */
zend_long remote_log_level; /* Log level XDEBUG_LOG_{ERR,WARN,INFO,DEBUG} */
zend_long remote_cookie_expire_time; /* Expire time for the remote-session cookie */
char *remote_addr_header; /* User configured header to check for forwarded IP address */
zend_long remote_connect_timeout; /* Timeout in MS for remote connections */

char *ide_key_setting; /* Set through php.ini and friends */
} settings;
};

struct xdebug_trace_info {
xdebug_trace_handler_t *trace_handler;
void *trace_context;
@@ -284,17 +243,27 @@ struct xdebug_trace_info {
} settings;
};

struct xdebug_library_info
{
zend_execute_data *active_execute_data;
function_stack_entry *active_fse;
HashTable *active_symbol_table;
zval *This;
};

ZEND_BEGIN_MODULE_GLOBALS(xdebug)
struct xdebug_base_info base;
struct xdebug_stepdbg_info stepdbg;
struct xdebug_library_info library;
struct xdebug_trace_info trace;
struct {
xdebug_coverage_globals_t coverage;
xdebug_debugger_globals_t debugger;
xdebug_gc_stats_globals_t gc_stats;
xdebug_profiler_globals_t profiler;
} globals;
struct {
xdebug_coverage_settings_t coverage;
xdebug_debugger_settings_t debugger;
xdebug_gc_stats_settings_t gc_stats;
xdebug_profiler_settings_t profiler;
} settings;
@@ -307,11 +276,10 @@ ZEND_END_MODULE_GLOBALS(xdebug)
#endif

#define XG_BASE(v) (XG(base.v))
#define XG_DBG(v) (XG(stepdbg.v))
#define XG_LIB(v ) (XG(library.v))
#define XG_TRACE(v) (XG(trace.v))

#define XINI_BASE(v) (XG(base.settings.v))
#define XINI_DBG(v) (XG(stepdbg.settings.v))
#define XINI_TRACE(v) (XG(trace.settings.v))

/* Needed for code coverage as Zend doesn't always add EXT_STMT when expected */
@@ -27,7 +27,6 @@
#include "filter.h"
#include "monitor.h"
#include "stack.h"
#include "debugger/com.h"
#include "gcstats/gc_stats.h"
#include "profiler/profiler.h"

@@ -73,7 +72,6 @@ static void xdebug_throw_exception_hook(zval *exception TSRMLS_DC)
zval *code, *message, *file, *line;
zval *xdebug_message_trace, *previous_exception;
zend_class_entry *default_ce, *exception_ce;
xdebug_brk_info *extra_brk_info;
char *code_str = NULL;
char *exception_trace;
xdebug_str tmp_str = XDEBUG_STR_INITIALIZER;
@@ -138,44 +136,7 @@ static void xdebug_throw_exception_hook(zval *exception TSRMLS_DC)
}
}

/* Start JIT if requested and not yet enabled */
xdebug_do_jit(TSRMLS_C);

if (xdebug_is_debug_connection_active_for_current_pid()) {
int exception_breakpoint_found = 0;

/* Check if we have a wild card exception breakpoint */
if (xdebug_hash_find(XG_DBG(context).exception_breakpoints, "*", 1, (void *) &extra_brk_info)) {
exception_breakpoint_found = 1;
} else {
/* Check if we have a breakpoint on this exception or its parent classes */
zend_class_entry *ce_ptr = exception_ce;

/* Check if we have a breakpoint on this exception or its parent classes */
do {
if (xdebug_hash_find(XG_DBG(context).exception_breakpoints, (char *) STR_NAME_VAL(ce_ptr->name), STR_NAME_LEN(ce_ptr->name), (void *) &extra_brk_info)) {
exception_breakpoint_found = 1;
}
ce_ptr = ce_ptr->parent;
} while (!exception_breakpoint_found && ce_ptr);
}

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);
}

if (exception_breakpoint_found && xdebug_handle_hit_value(extra_brk_info)) {
if (!XG_DBG(context).handler->remote_breakpoint(
&(XG_DBG(context)), XG_BASE(stack),
Z_STRVAL_P(file), Z_LVAL_P(line), XDEBUG_BREAK,
(char*) STR_NAME_VAL(exception_ce->name),
code_str ? code_str : ((code && Z_TYPE_P(code) == IS_STRING) ? Z_STRVAL_P(code) : NULL),
Z_STRVAL_P(message))
) {
xdebug_mark_debug_connection_not_active();
}
}
}
xdebug_debugger_throw_exception_hook(exception_ce, file, line, code, code_str, message);

/* Free code_str if necessary */
if (code_str) {
@@ -300,64 +261,6 @@ static void add_used_variables(function_stack_entry *fse, zend_op_array *op_arra
}


static int handle_breakpoints(function_stack_entry *fse, int breakpoint_type)
{
xdebug_brk_info *extra_brk_info = NULL;
char *tmp_name = NULL;
size_t tmp_len = 0;
TSRMLS_FETCH();

/* 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)) {
/* Yup, breakpoint found, we call the handler when it's not
* disabled AND handle_hit_value is happy */
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)) {
return 0;
}
} else {
XG_DBG(context).do_break = 1;
}
}
}
}
}
/* class->function breakpoints */
else if (fse->function.type == XFUNC_MEMBER || fse->function.type == XFUNC_STATIC_MEMBER) {
/* We intentionally do not use xdebug_sprintf because it can create a bottleneck in large
codebases due to setlocale calls. We don't care about the locale here. */
tmp_len = strlen(fse->function.class) + strlen(fse->function.function) + 3;
tmp_name = xdmalloc(tmp_len);
snprintf(tmp_name, tmp_len, "%s::%s", fse->function.class, fse->function.function);

if (xdebug_hash_find(XG_DBG(context).function_breakpoints, tmp_name, tmp_len - 1, (void *) &extra_brk_info)) {
/* Yup, breakpoint found, call handler if the breakpoint is not
* disabled AND handle_hit_value is happy */
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)) {
return 0;
}
} else {
XG_DBG(context).do_break = 1;
}
}
}
}
xdfree(tmp_name);
}
return 1;
}

/* Opcode handler for exit, to be able to clean up the profiler */
int xdebug_exit_handler(zend_execute_data *execute_data)
{
@@ -385,9 +288,7 @@ static void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
EX(opline) = EX(func)->op_array.opcodes;
}

/* We need to do this first before the executable clauses are called */
if (XG_DBG(no_exec) == 1) {
php_printf("DEBUG SESSION ENDED");
if (xdebug_debugger_bailout_if_no_exec_requested()) {
return;
}

@@ -404,9 +305,7 @@ static void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
return;
}

if (!XG_DBG(context).program_name) {
XG_DBG(context).program_name = xdstrdup(STR_NAME_VAL(op_array->filename));
}
xdebug_debugger_set_program_name(op_array->filename);

if (XG_BASE(in_execution)) {
/* Start debugger if this is the first main script, or previously a
@@ -492,16 +391,12 @@ static void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
/* If we're in an eval, we need to create an ID for it. This ID however
* depends on the debugger mechanism in use so we need to call a function
* in the handler for it */
if (fse->function.type == XFUNC_EVAL && 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);
if (fse->function.type == XFUNC_EVAL) {
xdebug_debugger_register_eval(fse);
}

/* Check for entry breakpoints */
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(breakpoints_allowed)) {
if (!handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL)) {
xdebug_mark_debug_connection_not_active();
}
}
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL);

xdebug_profiler_execute_ex(fse, op_array);

@@ -534,11 +429,7 @@ static void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
}

/* Check for return breakpoints */
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(breakpoints_allowed)) {
if (!handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN)) {
xdebug_mark_debug_connection_not_active();
}
}
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN);

fse->symbol_table = NULL;
fse->execute_data = NULL;
@@ -601,11 +492,7 @@ static void xdebug_execute_internal(zend_execute_data *current_execute_data, zva
}

/* Check for entry breakpoints */
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(breakpoints_allowed)) {
if (!handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL)) {
xdebug_mark_debug_connection_not_active();
}
}
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_CALL);

/* Check for SOAP */
if (check_soap_call(fse, current_execute_data)) {
@@ -644,11 +531,7 @@ static void xdebug_execute_internal(zend_execute_data *current_execute_data, zva
}

/* Check for return breakpoints */
if (xdebug_is_debug_connection_active_for_current_pid() && XG_DBG(breakpoints_allowed)) {
if (!handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN)) {
xdebug_mark_debug_connection_not_active();
}
}
xdebug_debugger_handle_breakpoints(fse, XDEBUG_BREAKPOINT_TYPE_RETURN);

if (XG_BASE(stack)) {
xdebug_llist_remove(XG_BASE(stack), XDEBUG_LLIST_TAIL(XG_BASE(stack)), function_stack_entry_dtor);

0 comments on commit 04a4f68

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