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)
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");
}
#endif
#include "phpdbg_cmd.h"
-#include "phpdbg_frame.h"
#ifdef ZTS
# define PHPDBG_G(v) TSRMG(phpdbg_globals_id, zend_phpdbg_globals *, v)
/* {{{ 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
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) /* }}} */
};
/* }}} */
+/* {{{ 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:
+++ /dev/null
-/*
- +----------------------------------------------------------------------+
- | 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 <felipe@php.net> |
- | Authors: Joe Watkins <joe.watkins@live.co.uk> |
- | Authors: Bob Weinand <bwoebi@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-#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);
-}
+++ /dev/null
-/*
- +----------------------------------------------------------------------+
- | 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 <felipe@php.net> |
- | Authors: Joe Watkins <joe.watkins@live.co.uk> |
- | Authors: Bob Weinand <bwoebi@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-#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 */
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");
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);
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();
phpdbg_writeln("Note: upon failure to open a new oplog, the last oplog is held open");
phpdbg_help_footer();
return SUCCESS;
-} /* }}} */
+}
PHPDBG_HELP(register) /* {{{ */
{
PHPDBG_HELP(clear);
PHPDBG_HELP(info);
PHPDBG_HELP(back);
+PHPDBG_HELP(frame);
PHPDBG_HELP(quiet);
PHPDBG_HELP(list);
PHPDBG_HELP(oplog);
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),
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),
+----------------------------------------------------------------------+
| Authors: Felipe Pena <felipe@php.net> |
| Authors: Joe Watkins <joe.watkins@live.co.uk> |
+ | Authors: Bob Weinand <bwoebi@php.net> |
+----------------------------------------------------------------------+
*/
#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[] = {
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),
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();
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);
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;
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;