1
0
mirror of https://github.com/php/php-src.git synced 2026-04-27 10:16:41 +02:00
This commit is contained in:
krakjoe
2013-11-16 11:12:22 +00:00
5 changed files with 121 additions and 74 deletions
+13
View File
@@ -0,0 +1,13 @@
ChangeLog for phpdbg
====================
Version 0.0.2 0000-00-00
------------------------
1. Added until/u command
Version 0.0.1 2013-11-15
------------------------
1. Initial features
+8 -2
View File
@@ -49,6 +49,12 @@ PHPDBG_HELP(next) /* {{{ */
return SUCCESS;
} /* }}} */
PHPDBG_HELP(until) /* {{{ */
{
phpdbg_writeln("While stepping through execution, or after a breakpoint, use the until command to step back into the vm and reaches the next source line");
return SUCCESS;
} /* }}} */
PHPDBG_HELP(compile) /* {{{ */
{
phpdbg_writeln("Pre-compilation of the execution context provides the opportunity to inspect the opcodes before they are executed");
@@ -80,7 +86,7 @@ PHPDBG_HELP(print) /* {{{ */
phpdbg_notice("Commands");
{
const phpdbg_command_t *print_command = phpdbg_print_commands;
while (print_command && print_command->name) {
phpdbg_writeln("\t%s\t%s", print_command->name, print_command->tip);
++print_command;
@@ -125,7 +131,7 @@ PHPDBG_HELP(break) /* {{{ */
phpdbg_writeln("If you have to clean the environment and recompile then your opline break points will be invalid");
phpdbg_writeln(EMPTY);
phpdbg_writeln("Conditional breaks are costly, use them sparingly !!");
return SUCCESS;
} /* }}} */
+2
View File
@@ -40,6 +40,7 @@ PHPDBG_HELP(step);
PHPDBG_HELP(next);
PHPDBG_HELP(run);
PHPDBG_HELP(eval);
PHPDBG_HELP(until);
PHPDBG_HELP(print);
PHPDBG_HELP(break);
PHPDBG_HELP(clean);
@@ -59,6 +60,7 @@ static const phpdbg_command_t phpdbg_help_commands[] = {
PHPDBG_HELP_D(next, "continue executing while stepping or after breaking"),
PHPDBG_HELP_D(run, "execution inside the phpdbg vm allows detailed inspection and debugging"),
PHPDBG_HELP_D(eval, "access to eval() allows you to affect the environment during execution"),
PHPDBG_HELP_D(until, "continue until the program reaches a source line different than the current one"),
PHPDBG_HELP_D(print, "printing allows inspection of the execution environment"),
PHPDBG_HELP_D(break, "breakpoints allow execution interruption"),
PHPDBG_HELP_D(clean, "resetting the environment is useful while debugging and recompiling"),
+96 -71
View File
@@ -37,6 +37,7 @@ static PHPDBG_COMMAND(step);
static PHPDBG_COMMAND(next);
static PHPDBG_COMMAND(run);
static PHPDBG_COMMAND(eval);
static PHPDBG_COMMAND(until);
static PHPDBG_COMMAND(print);
static PHPDBG_COMMAND(break);
static PHPDBG_COMMAND(back);
@@ -57,6 +58,7 @@ static const phpdbg_command_t phpdbg_prompt_commands[] = {
PHPDBG_COMMAND_EX_D(next, "continue execution", 'n'),
PHPDBG_COMMAND_EX_D(run, "attempt execution", 'r'),
PHPDBG_COMMAND_EX_D(eval, "evaluate some code", 'E'),
PHPDBG_COMMAND_EX_D(until, "continue until reaches next line", 'u'),
PHPDBG_COMMAND_EX_D(print, "print something", 'p'),
PHPDBG_COMMAND_EX_D(break, "set breakpoint", 'b'),
PHPDBG_COMMAND_EX_D(back, "show trace", 't'),
@@ -79,28 +81,28 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS
if (!init_file && use_default) {
struct stat sb;
if (VCWD_STAT(".phpdbginit", &sb) != -1) {
init_file = ".phpdbginit";
init_file_len = strlen(".phpdbginit");
init_default = 1;
}
}
if (init_file) {
FILE *fp = fopen(init_file, "r");
if (fp) {
int line = 1;
char cmd[PHPDBG_MAX_CMD];
size_t cmd_len = 0L;
char *code = NULL;
size_t code_len = 0L;
zend_bool in_code = 0;
while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) {
cmd_len = strlen(cmd)-1;
while (*cmd && isspace(cmd[cmd_len-1]))
cmd_len--;
@@ -125,12 +127,12 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS
}
}
}
if (in_code) {
if (code == NULL) {
code = malloc(cmd_len);
} else code = realloc(code, code_len + cmd_len);
if (code) {
memcpy(
&code[code_len], cmd, cmd_len);
@@ -138,7 +140,7 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS
}
goto next_line;
}
switch (phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) {
case FAILURE:
phpdbg_error(
@@ -149,17 +151,17 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS
next_line:
line++;
}
if (code) {
free(code);
}
fclose(fp);
} else {
phpdbg_error(
"Failed to open %s for initialization", init_file);
}
if (!init_default) {
free(init_file);
}
@@ -274,6 +276,11 @@ static PHPDBG_COMMAND(next) /* {{{ */
return PHPDBG_NEXT;
} /* }}} */
static PHPDBG_COMMAND(until) /* {{{ */
{
return PHPDBG_UNTIL;
} /* }}} */
static PHPDBG_COMMAND(run) /* {{{ */
{
if (EG(in_execution)) {
@@ -433,7 +440,7 @@ static PHPDBG_COMMAND(print) /* {{{ */
phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC);
phpdbg_writeln(SEPARATE);
return SUCCESS;
@@ -443,7 +450,7 @@ static PHPDBG_COMMAND(break) /* {{{ */
{
phpdbg_param_t param;
int type;
if (expr_len == 0) {
phpdbg_error("No expression found");
return FAILURE;
@@ -473,7 +480,7 @@ static PHPDBG_COMMAND(break) /* {{{ */
default:
break;
}
phpdbg_clear_param(type, &param TSRMLS_CC);
return SUCCESS;
@@ -483,7 +490,7 @@ static PHPDBG_COMMAND(quit) /* {{{ */
{
/* don't allow this to loop, ever ... */
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
zend_bailout();
}
@@ -575,7 +582,7 @@ static PHPDBG_COMMAND(oplog) /* {{{ */
fclose(old);
}
phpdbg_notice("Successfully opened oplog");
return SUCCESS;
}
}
@@ -614,7 +621,7 @@ static PHPDBG_COMMAND(help) /* {{{ */
phpdbg_writeln("\t%s\t%s", help_command->name, help_command->tip);
++help_command;
}
phpdbg_notice("Command Line Options and Flags");
phpdbg_writeln("\tOption\tExample\t\t\tPurpose");
phpdbg_writeln(EMPTY);
@@ -652,16 +659,16 @@ static PHPDBG_COMMAND(list) /* {{{ */
{
phpdbg_param_t param;
int type = 0;
/* allow advanced listers to run */
if (phpdbg_do_cmd(phpdbg_list_commands, (char*)expr, expr_len TSRMLS_CC) == SUCCESS) {
return SUCCESS;
}
phpdbg_list_dispatch(
phpdbg_parse_param(expr, expr_len, &param TSRMLS_CC),
phpdbg_parse_param(expr, expr_len, &param TSRMLS_CC),
&param TSRMLS_CC);
phpdbg_clear_param(type, &param TSRMLS_CC);
return SUCCESS;
@@ -701,6 +708,7 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le
int phpdbg_interactive(TSRMLS_D) /* {{{ */
{
size_t cmd_len;
int cmd_type;
#ifndef HAVE_LIBREADLINE
char cmd[PHPDBG_MAX_CMD];
@@ -732,24 +740,25 @@ int phpdbg_interactive(TSRMLS_D) /* {{{ */
add_history(cmd);
#endif
switch (phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) {
switch (cmd_type = phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) {
case FAILURE:
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
phpdbg_error("Failed to execute %s!", cmd);
}
break;
case PHPDBG_UNTIL:
case PHPDBG_NEXT: {
if (!EG(in_execution)) {
phpdbg_error("Not running");
}
#ifdef HAVE_LIBREADLINE
if (cmd) {
free(cmd);
}
#endif
return PHPDBG_NEXT;
return cmd_type;
}
}
@@ -790,7 +799,7 @@ void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags
/* output line info */
phpdbg_notice("#%lu %p %s %s",
opline->lineno,
opline,
opline,
phpdbg_decode_opcode(opline->opcode),
execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
}
@@ -798,7 +807,7 @@ void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags
if (!ignore_flags && PHPDBG_G(oplog)) {
phpdbg_log_ex(PHPDBG_G(oplog), "#%lu %p %s %s",
opline->lineno,
opline,
opline,
phpdbg_decode_opcode(opline->opcode),
execute_data->op_array->filename ? execute_data->op_array->filename : "unknown");
}
@@ -814,10 +823,10 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */
PHPDBG_G(ops) = NULL;
}
if (full)
if (full)
{
PHPDBG_G(flags) |= PHPDBG_IS_CLEANING;
zend_bailout();
}
} /* }}} */
@@ -878,7 +887,7 @@ static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_ar
EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL;
return execute_data;
#endif
} /* }}} */
@@ -893,6 +902,9 @@ void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */
zend_bool nested = 0;
#endif
zend_bool original_in_execution = EG(in_execution);
int last_step = 0;
uint last_lineno;
const char *last_file;
#if PHP_VERSION_ID < 50500
if (EG(exception)) {
@@ -921,60 +933,73 @@ zend_vm_enter:
#endif
#define DO_INTERACTIVE() do {\
switch (phpdbg_interactive(TSRMLS_C)) {\
switch (last_step = phpdbg_interactive(TSRMLS_C)) {\
case PHPDBG_UNTIL:\
case PHPDBG_NEXT:\
goto next;\
}\
} while(!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING))
/* allow conditional breakpoints to access the vm uninterrupted */
if (!(PHPDBG_G(flags) & PHPDBG_IN_COND_BP)) {
/* allow conditional breakpoints to access the vm uninterrupted */
if (PHPDBG_G(flags) & PHPDBG_IN_COND_BP) {
/* skip possible breakpoints */
goto next;
}
/* not while in conditionals */
phpdbg_print_opline(
execute_data, 0 TSRMLS_CC);
if (last_step == PHPDBG_UNTIL
&& last_file == execute_data->op_array->filename
&& last_lineno == execute_data->opline->lineno) {
/* skip possible breakpoints */
goto next;
}
/* conditions cannot be executed by eval()'d code */
if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)
&& (PHPDBG_G(flags) & PHPDBG_HAS_COND_BP)
&& phpdbg_find_conditional_breakpoint(TSRMLS_C) == SUCCESS) {
DO_INTERACTIVE();
}
/* not while in conditionals */
phpdbg_print_opline(
execute_data, 0 TSRMLS_CC);
if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP)
&& phpdbg_find_breakpoint_file(execute_data->op_array TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
/* conditions cannot be executed by eval()'d code */
if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)
&& (PHPDBG_G(flags) & PHPDBG_HAS_COND_BP)
&& phpdbg_find_conditional_breakpoint(TSRMLS_C) == SUCCESS) {
DO_INTERACTIVE();
}
if ((PHPDBG_G(flags) & (PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_SYM_BP))) {
zend_execute_data *previous = execute_data->prev_execute_data;
if (previous && previous != execute_data && previous->opline) {
/* check we are the beginning of a function entry */
if (execute_data->opline == EG(active_op_array)->opcodes) {
switch (previous->opline->opcode) {
case ZEND_DO_FCALL:
case ZEND_DO_FCALL_BY_NAME:
case ZEND_INIT_STATIC_METHOD_CALL: {
if (phpdbg_find_breakpoint_symbol(previous->function_state.function TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
} break;
}
}
}
}
if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)
&& phpdbg_find_breakpoint_opline(execute_data->opline TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
if ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING)) {
DO_INTERACTIVE();
}
}
if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP)
&& phpdbg_find_breakpoint_file(execute_data->op_array TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
if ((PHPDBG_G(flags) & (PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_SYM_BP))) {
zend_execute_data *previous = execute_data->prev_execute_data;
if (previous && previous != execute_data && previous->opline) {
/* check we are the beginning of a function entry */
if (execute_data->opline == EG(active_op_array)->opcodes) {
switch (previous->opline->opcode) {
case ZEND_DO_FCALL:
case ZEND_DO_FCALL_BY_NAME:
case ZEND_INIT_STATIC_METHOD_CALL: {
if (phpdbg_find_breakpoint_symbol(previous->function_state.function TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
} break;
}
}
}
}
if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)
&& phpdbg_find_breakpoint_opline(execute_data->opline TSRMLS_CC) == SUCCESS) {
DO_INTERACTIVE();
}
if ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING)) {
DO_INTERACTIVE();
}
next:
last_lineno = execute_data->opline->lineno;
last_file = execute_data->op_array->filename;
PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);
if (PHPDBG_G(vmret) > 0) {
+2 -1
View File
@@ -27,7 +27,8 @@
#define PHPDBG_STRL(s) s, sizeof(s)-1
#define PHPDBG_NEXT 2
#define PHPDBG_NEXT 2
#define PHPDBG_UNTIL 3
/**
* Command handler