From e662fd9eb0008110d82e6c7a0527f2caefb27859 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 19:06:31 +0000 Subject: [PATCH] merge frame/trace commands from bwoebi tidy up add help for frame command fix help made incorrect by additions --- config.m4 | 2 +- config.w32 | 2 +- phpdbg.h | 5 +-- phpdbg_cmd.h | 8 ++++ phpdbg_frame.c | 101 ------------------------------------------------ phpdbg_frame.h | 36 ----------------- phpdbg_help.c | 21 ++++++++-- phpdbg_help.h | 4 +- phpdbg_prompt.c | 91 +++++++++++++++++++++++++++++++++++++++---- 9 files changed, 117 insertions(+), 153 deletions(-) delete mode 100644 phpdbg_frame.c delete mode 100644 phpdbg_frame.h diff --git a/config.m4 b/config.m4 index d8bcce5a31..ee80daa25c 100644 --- a/config.m4 +++ b/config.m4 @@ -18,7 +18,7 @@ if test "$PHP_PHPDBG" != "no"; then fi PHP_PHPDBG_CFLAGS="-I$abc_srcdir" - PHP_PHPDBG_FILES="phpdbg.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_frame.c" + PHP_PHPDBG_FILES="phpdbg.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c" PHP_SUBST(PHP_PHPDBG_CFLAGS) PHP_SUBST(PHP_PHPDBG_FILES) diff --git a/config.w32 b/config.w32 index 1356ced609..eee355da5e 100644 --- a/config.w32 +++ b/config.w32 @@ -1,7 +1,7 @@ ARG_ENABLE('phpdbg', 'Build phpdbg', 'yes'); if (PHP_PHPDBG == "yes") { - SAPI('phpdbg', 'phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_frame.c', 'phpdbg.exe'); + SAPI('phpdbg', 'phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c', 'phpdbg.exe'); ADD_FLAG("LIBS_PHPDBG", "ws2_32.lib user32.lib"); } diff --git a/phpdbg.h b/phpdbg.h index 3e25965e91..39918ca126 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -54,7 +54,6 @@ #endif #include "phpdbg_cmd.h" -#include "phpdbg_frame.h" #ifdef ZTS # define PHPDBG_G(v) TSRMG(phpdbg_globals_id, zend_phpdbg_globals *, v) @@ -111,7 +110,7 @@ /* {{{ strings */ #define PHPDBG_ISSUES "http://github.com/krakjoe/phpdbg/issues" -#define PHPDBG_VERSION "0.0.2-dev" /* }}} */ +#define PHPDBG_VERSION "0.1.0-dev" /* }}} */ /* {{{ output descriptors */ #define PHPDBG_STDIN 0 @@ -133,7 +132,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable seek; /* seek oplines */ zend_ulong flags; /* phpdbg flags */ HashTable registered; /* registered */ - phpdbg_frame frame; /* frame */ + phpdbg_frame_t frame; /* frame */ FILE *io[3]; /* stdin/stdout/stderr */ ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */ diff --git a/phpdbg_cmd.h b/phpdbg_cmd.h index e9c52a7292..f9dd3cd953 100644 --- a/phpdbg_cmd.h +++ b/phpdbg_cmd.h @@ -80,8 +80,16 @@ struct _phpdbg_command_t { }; /* }}} */ +/* {{{ misc */ #define PHPDBG_STRL(s) s, sizeof(s)-1 #define PHPDBG_MAX_CMD 500 +#define PHPDBG_FRAME(v) (PHPDBG_G(frame).v) +#define PHPDBG_EX(v) (EG(current_execute_data)->v) + +typedef struct { + long num; + zend_execute_data *execute_data; +} phpdbg_frame_t; /* }}} */ /* * Workflow: diff --git a/phpdbg_frame.c b/phpdbg_frame.c deleted file mode 100644 index 536debfe01..0000000000 --- a/phpdbg_frame.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Felipe Pena | - | Authors: Joe Watkins | - | Authors: Bob Weinand | - +----------------------------------------------------------------------+ -*/ - -#include "phpdbg.h" -#include "phpdbg_frame.h" -#include "phpdbg_list.h" -#include "phpdbg_utils.h" - -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); - -#define PHPDBG_FRAME(v) (PHPDBG_G(frame).v) -#define PHPDBG_EX(v) (EG(current_execute_data)->v) - -void switch_to_frame(int frame TSRMLS_DC) { - zend_execute_data *execute_data = PHPDBG_FRAME(num)?PHPDBG_FRAME(execute_data):EG(current_execute_data); - int i = 0; - - if (PHPDBG_FRAME(num) == frame) { - phpdbg_notice("Already in frame #%d", frame); - return; - } - - while (execute_data) { - if (i++ == frame) { - break; - } - - do { - execute_data = execute_data->prev_execute_data; - } while (execute_data && execute_data->opline == NULL); - } - - if (execute_data == NULL) { - phpdbg_error("No frame #%d", frame); - return; - } - - restore_frame(TSRMLS_C); - - if (frame > 0) { - PHPDBG_FRAME(num) = frame; - - /* backup things and jump back */ - PHPDBG_FRAME(execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - PHPDBG_FRAME(execute_data)->original_return_value = EG(return_value_ptr_ptr); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); - } - - phpdbg_notice("Switched to frame #%d", frame); - phpdbg_list_file( - zend_get_executed_filename(TSRMLS_C), - 3, - zend_get_executed_lineno(TSRMLS_C)-1, - zend_get_executed_lineno(TSRMLS_C) - TSRMLS_CC - ); -} - -void restore_frame(TSRMLS_D) { - if (PHPDBG_FRAME(num) == 0) { - return; - } - - PHPDBG_FRAME(num) = 0; - - /* move things back */ - EG(current_execute_data) = PHPDBG_FRAME(execute_data); - - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); -} diff --git a/phpdbg_frame.h b/phpdbg_frame.h deleted file mode 100644 index 49cdbcfe70..0000000000 --- a/phpdbg_frame.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Felipe Pena | - | Authors: Joe Watkins | - | Authors: Bob Weinand | - +----------------------------------------------------------------------+ -*/ - -#ifndef PHPDBG_FRAME_H -#define PHPDBG_FRAME_H - -#include "php.h" - -typedef struct { - long num; - - zend_execute_data *execute_data; -} phpdbg_frame; - -void switch_to_frame(int frame TSRMLS_DC); - -void restore_frame(TSRMLS_D); - -#endif /* PHPDBG_FRAME_H */ diff --git a/phpdbg_help.c b/phpdbg_help.c index 9ee044182e..c82a48497d 100644 --- a/phpdbg_help.c +++ b/phpdbg_help.c @@ -88,7 +88,7 @@ PHPDBG_HELP(finish) /* {{{ */ phpdbg_writeln(EMPTY); phpdbg_notice("Examples"); phpdbg_writeln("\t%sfinish", PROMPT); - phpdbg_writeln("\t%sf", PROMPT); + phpdbg_writeln("\t%sF", PROMPT); phpdbg_writeln("\tWill cause control to be passed back to the vm, continuing execution"); phpdbg_writeln(EMPTY); phpdbg_writeln("Note: this allows all breakpoints that would otherwise break execution in the current scope to be skipped"); @@ -329,7 +329,7 @@ PHPDBG_HELP(quiet) /* {{{ */ PHPDBG_HELP(back) /* {{{ */ { phpdbg_help_header(); - phpdbg_writeln("The backtrace is gathered with the default debug backtrace functionality"); + phpdbg_writeln("The backtrace is built with the default debug backtrace functionality"); phpdbg_writeln(EMPTY); phpdbg_notice("Examples"); phpdbg_writeln("\t%sback 5", PROMPT); @@ -341,6 +341,21 @@ PHPDBG_HELP(back) /* {{{ */ return SUCCESS; } /* }}} */ +PHPDBG_HELP(frame) /* {{{ */ +{ + phpdbg_help_header(); + phpdbg_writeln("When viewing a backtrace, it is sometimes useful to jump to a frame in that trace"); + phpdbg_writeln(EMPTY); + phpdbg_notice("Examples"); + phpdbg_writeln("\t%sframe 2", PROMPT); + phpdbg_writeln("\t%sf 2", PROMPT); + phpdbg_writeln("\tWill go to frame 2, temporarily affecting scope and allowing access to the variables in that frame"); + phpdbg_writeln(EMPTY); + phpdbg_writeln("Note: the current frame is restored when execution continues"); + phpdbg_help_footer(); + return SUCCESS; +} /* }}} */ + PHPDBG_HELP(list) /* {{{ */ { phpdbg_help_header(); @@ -407,7 +422,7 @@ PHPDBG_HELP(oplog) /* {{{ */ phpdbg_writeln("Note: upon failure to open a new oplog, the last oplog is held open"); phpdbg_help_footer(); return SUCCESS; -} /* }}} */ +} PHPDBG_HELP(register) /* {{{ */ { diff --git a/phpdbg_help.h b/phpdbg_help.h index ec520c5af3..c453c506bf 100644 --- a/phpdbg_help.h +++ b/phpdbg_help.h @@ -44,6 +44,7 @@ PHPDBG_HELP(clean); PHPDBG_HELP(clear); PHPDBG_HELP(info); PHPDBG_HELP(back); +PHPDBG_HELP(frame); PHPDBG_HELP(quiet); PHPDBG_HELP(list); PHPDBG_HELP(oplog); @@ -61,7 +62,7 @@ static const phpdbg_command_t phpdbg_help_commands[] = { PHPDBG_COMMAND_D_EX(run, "execute inside the phpdbg vm", 'r', help_run, NULL, 0), PHPDBG_COMMAND_D_EX(eval, "access to eval() allows affecting the environment", 'E', help_eval, NULL, 0), PHPDBG_COMMAND_D_EX(until, "continue until the current line is executed", 'u', help_until, NULL, 0), - PHPDBG_COMMAND_D_EX(finish, "continue until the current function has returned", 'f', help_finish, NULL, 0), + PHPDBG_COMMAND_D_EX(finish, "continue until the current function has returned", 'F', help_finish, NULL, 0), PHPDBG_COMMAND_D_EX(leave, "continue until the current function is returning", 'L', help_leave, NULL, 0), PHPDBG_COMMAND_D_EX(print, "print context information or instructions", 'p', help_print, NULL, 0), PHPDBG_COMMAND_D_EX(break, "breakpoints allow execution interruption", 'b', help_break, NULL, 0), @@ -69,6 +70,7 @@ static const phpdbg_command_t phpdbg_help_commands[] = { PHPDBG_COMMAND_D_EX(clear, "reset breakpoints to execute without interruption", 'c', help_clear, NULL, 0), PHPDBG_COMMAND_D_EX(info, "quick access to useful information on the console", 'i', help_info, NULL, 0), PHPDBG_COMMAND_D_EX(back, "show debug backtrace information during execution", 't', help_back, NULL, 0), + PHPDBG_COMMAND_D_EX(frame, "switch to a frame in the current stack for inspection", 'f', help_frame, NULL, 0), PHPDBG_COMMAND_D_EX(quiet, "be quiet during execution", 'Q', help_quiet, NULL, 0), PHPDBG_COMMAND_D_EX(list, "list code gives you quick access to code", 'l', help_list, NULL, 0), PHPDBG_COMMAND_D_EX(oplog, "keep clutter off the screen by logging oplines", 'O', help_oplog, NULL, 0), diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index d73a13ab67..6b20284a2e 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -14,6 +14,7 @@ +----------------------------------------------------------------------+ | Authors: Felipe Pena | | Authors: Joe Watkins | + | Authors: Bob Weinand | +----------------------------------------------------------------------+ */ @@ -32,7 +33,6 @@ #include "phpdbg_utils.h" #include "phpdbg_prompt.h" #include "phpdbg_cmd.h" -#include "phpdbg_frame.h" /* {{{ command declarations */ const phpdbg_command_t phpdbg_prompt_commands[] = { @@ -45,10 +45,10 @@ const phpdbg_command_t phpdbg_prompt_commands[] = { PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0), PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0), PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0), - PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, 1), PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, 2), PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, 1), PHPDBG_COMMAND_D(back, "show trace", 't', NULL, 0), + PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, 1), PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, 2), PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, 1), PHPDBG_COMMAND_D(clean, "clean the execution environment", 'X', NULL, 0), @@ -372,15 +372,87 @@ PHPDBG_COMMAND(leave) /* {{{ */ return PHPDBG_LEAVE; } /* }}} */ +static inline void phpdbg_restore_frame(TSRMLS_D) { /* {{{ */ + if (PHPDBG_FRAME(num) == 0) { + return; + } + + PHPDBG_FRAME(num) = 0; + + /* move things back */ + EG(current_execute_data) = PHPDBG_FRAME(execute_data); + + EG(opline_ptr) = &PHPDBG_EX(opline); + EG(active_op_array) = PHPDBG_EX(op_array); + EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); + EG(active_symbol_table) = PHPDBG_EX(symbol_table); + EG(This) = PHPDBG_EX(current_this); + EG(scope) = PHPDBG_EX(current_scope); + EG(called_scope) = PHPDBG_EX(current_called_scope); +} /* }}} */ + +static inline void phpdbg_switch_frame(int frame TSRMLS_DC) { /* {{{ */ + zend_execute_data *execute_data = PHPDBG_FRAME(num)?PHPDBG_FRAME(execute_data):EG(current_execute_data); + int i = 0; + + if (PHPDBG_FRAME(num) == frame) { + phpdbg_notice("Already in frame #%d", frame); + return; + } + + while (execute_data) { + if (i++ == frame) { + break; + } + + do { + execute_data = execute_data->prev_execute_data; + } while (execute_data && execute_data->opline == NULL); + } + + if (execute_data == NULL) { + phpdbg_error("No frame #%d", frame); + return; + } + + phpdbg_restore_frame(TSRMLS_C); + + if (frame > 0) { + PHPDBG_FRAME(num) = frame; + + /* backup things and jump back */ + PHPDBG_FRAME(execute_data) = EG(current_execute_data); + EG(current_execute_data) = execute_data; + + EG(opline_ptr) = &PHPDBG_EX(opline); + EG(active_op_array) = PHPDBG_EX(op_array); + PHPDBG_FRAME(execute_data)->original_return_value = EG(return_value_ptr_ptr); + EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); + EG(active_symbol_table) = PHPDBG_EX(symbol_table); + EG(This) = PHPDBG_EX(current_this); + EG(scope) = PHPDBG_EX(current_scope); + EG(called_scope) = PHPDBG_EX(current_called_scope); + } + + phpdbg_notice("Switched to frame #%d", frame); + phpdbg_list_file( + zend_get_executed_filename(TSRMLS_C), + 3, + zend_get_executed_lineno(TSRMLS_C)-1, + zend_get_executed_lineno(TSRMLS_C) + TSRMLS_CC + ); +} /* }}} */ + PHPDBG_COMMAND(frame) /* {{{ */ { switch (param->type) { case NUMERIC_PARAM: - switch_to_frame(param->num TSRMLS_CC); + phpdbg_switch_frame(param->num TSRMLS_CC); break; case EMPTY_PARAM: - phpdbg_writeln("Currently at frame %d:", PHPDBG_G(frame).num); + phpdbg_notice("Currently at frame %d:", PHPDBG_G(frame).num); break; phpdbg_default_switch_case(); @@ -567,7 +639,9 @@ PHPDBG_COMMAND(back) /* {{{ */ zend_hash_find(Z_ARRVAL_PP(tmp), "line", sizeof("line"), (void **)&line); zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); if (zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position) == FAILURE) { - phpdbg_write("frame #%d {main} at %s:%d", i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); + phpdbg_write( + "frame #%d {main} at %s:%d", + i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); break; } zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), (void **)&funcname); @@ -583,7 +657,10 @@ PHPDBG_COMMAND(back) /* {{{ */ funcsize = Z_STRLEN_PP(funcname) + (is_class == FAILURE?0:Z_STRLEN_PP(type) + Z_STRLEN_PP(class)) + 1; func = emalloc(funcsize + 2); - phpdbg_write("frame #%d: %s%s%s(", i++, Z_STRVAL_PP(funcname), is_class == FAILURE?"":Z_STRVAL_PP(type), is_class == FAILURE?"":Z_STRVAL_PP(class)); + phpdbg_write( + "frame #%d: %s%s%s(", + i++, Z_STRVAL_PP(funcname), + is_class == FAILURE?"":Z_STRVAL_PP(type), is_class == FAILURE?"":Z_STRVAL_PP(class)); if (zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"), (void **)&args) == SUCCESS) { HashPosition iterator; @@ -1081,7 +1158,7 @@ out: phpdbg_destroy_input(&input TSRMLS_CC); if (EG(in_execution)) { - restore_frame(TSRMLS_C); + phpdbg_restore_frame(TSRMLS_C); } PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE; -- 2.40.0