return SUCCESS;
} /* }}} */
+PHPDBG_HELP(finish) /* {{{ */
+{
+ phpdbg_help_header();
+ phpdbg_writeln("While stepping through execution, or after a breakpoint, use the finish command to step back into the vm and continue until the current function has returned");
+ phpdbg_help_footer();
+ return SUCCESS;
+} /* }}} */
+
PHPDBG_HELP(compile) /* {{{ */
{
phpdbg_help_header();
phpdbg_notice("Commands");
{
const phpdbg_command_t *print_command = phpdbg_print_commands;
-
+
phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
while (print_command && print_command->name) {
if (print_command->alias) {
phpdbg_notice("Commands");
{
const phpdbg_command_t *break_command = phpdbg_break_commands;
-
+
phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
while (break_command && break_command->name) {
if (break_command->alias) {
} /* }}} */
PHPDBG_HELP(clean) /* {{{ */
-{
+{
phpdbg_help_header();
phpdbg_writeln("While debugging you may experience errors because of attempts to redeclare classes, constants or functions");
phpdbg_writeln("Cleaning the environment cleans these tables, so that files can be recompiled without exiting phpdbg");
phpdbg_notice("Commands");
{
const phpdbg_command_t *list_command = phpdbg_list_commands;
-
+
phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
while (list_command && list_command->name) {
if (list_command->alias) {
static PHPDBG_COMMAND(run);
static PHPDBG_COMMAND(eval);
static PHPDBG_COMMAND(until);
+static PHPDBG_COMMAND(finish);
static PHPDBG_COMMAND(print);
static PHPDBG_COMMAND(break);
static PHPDBG_COMMAND(back);
/* {{{ command declarations */
static const phpdbg_command_t phpdbg_prompt_commands[] = {
- PHPDBG_COMMAND_EX_D(exec, "set execution context", 'e'),
+ PHPDBG_COMMAND_EX_D(exec, "set execution context", 'e'),
PHPDBG_COMMAND_EX_D(compile, "attempt to pre-compile execution context", 'c'),
- PHPDBG_COMMAND_EX_D(step, "step through execution", 's'),
- 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_COMMANDS_D(print, "print something", 'p', phpdbg_print_commands),
- PHPDBG_COMMANDS_D(break, "set breakpoint", 'b', phpdbg_break_commands),
- PHPDBG_COMMAND_EX_D(back, "show trace", 't'),
- PHPDBG_COMMANDS_D(list, "lists some code", 'l', phpdbg_list_commands),
- PHPDBG_COMMAND_EX_D(clean, "clean the execution environment", 'X'),
- PHPDBG_COMMAND_EX_D(clear, "clear breakpoints", 'C'),
- PHPDBG_COMMANDS_D(help, "show help menu", 'h', phpdbg_help_commands),
- PHPDBG_COMMAND_EX_D(quiet, "silence some output", 'Q'),
- PHPDBG_COMMAND_EX_D(aliases, "show alias list", 'a'),
- PHPDBG_COMMAND_EX_D(oplog, "sets oplog output", 'O'),
- PHPDBG_COMMAND_EX_D(quit, "exit phpdbg", 'q'),
+ PHPDBG_COMMAND_EX_D(step, "step through execution", 's'),
+ 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(finish, "continue until reaches next line", 'f'),
+ PHPDBG_COMMANDS_D(print, "print something", 'p', phpdbg_print_commands),
+ PHPDBG_COMMANDS_D(break, "set breakpoint", 'b', phpdbg_break_commands),
+ PHPDBG_COMMAND_EX_D(back, "show trace", 't'),
+ PHPDBG_COMMANDS_D(list, "lists some code", 'l', phpdbg_list_commands),
+ PHPDBG_COMMAND_EX_D(clean, "clean the execution environment", 'X'),
+ PHPDBG_COMMAND_EX_D(clear, "clear breakpoints", 'C'),
+ PHPDBG_COMMANDS_D(help, "show help menu", 'h', phpdbg_help_commands),
+ PHPDBG_COMMAND_EX_D(quiet, "silence some output", 'Q'),
+ PHPDBG_COMMAND_EX_D(aliases, "show alias list", 'a'),
+ PHPDBG_COMMAND_EX_D(oplog, "sets oplog output", 'O'),
+ PHPDBG_COMMAND_EX_D(quit, "exit phpdbg", 'q'),
{NULL, 0, 0}
}; /* }}} */
return PHPDBG_UNTIL;
} /* }}} */
+static PHPDBG_COMMAND(finish) /* {{{ */
+{
+ return PHPDBG_FINISH;
+} /* }}} */
+
static PHPDBG_COMMAND(run) /* {{{ */
{
if (EG(in_execution)) {
}
break;
+ case PHPDBG_FINISH:
case PHPDBG_UNTIL:
case PHPDBG_NEXT: {
if (!EG(in_execution)) {
int last_step = 0;
uint last_lineno;
const char *last_file;
+ const zend_execute_data *last_exec = NULL, *last_prev_exec;
#if PHP_VERSION_ID < 50500
if (EG(exception)) {
\
do {\
switch (last_step = phpdbg_interactive(TSRMLS_C)) {\
+ case PHPDBG_FINISH:\
case PHPDBG_UNTIL:\
case PHPDBG_NEXT:{\
goto next;\
/* skip possible breakpoints */
goto next;
}
-
if (last_step == PHPDBG_UNTIL
&& last_file == execute_data->op_array->filename
&& last_lineno == execute_data->opline->lineno) {
/* skip possible breakpoints */
goto next;
}
+ if (last_step == PHPDBG_FINISH) {
+ if (!(execute_data->prev_execute_data == last_exec
+ && execute_data == last_prev_exec)) {
+ /* skip possible breakpoints */
+ goto next;
+ }
+ last_exec = NULL;
+ last_prev_exec = NULL;
+ }
/* not while in conditionals */
phpdbg_print_opline(
last_lineno = execute_data->opline->lineno;
last_file = execute_data->op_array->filename;
+ if (last_step == PHPDBG_FINISH && last_exec == NULL) {
+ last_exec = execute_data;
+ last_prev_exec = execute_data->prev_execute_data;
+ }
+
PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);
if (PHPDBG_G(vmret) > 0) {