mirror of
https://github.com/php/php-src.git
synced 2026-03-31 12:42:29 +02:00
Merge branch 'master' of https://github.com/krakjoe/phpdbg
This commit is contained in:
@@ -18,7 +18,7 @@ if test "$PHP_PHPDBG" != "no"; then
|
||||
fi
|
||||
|
||||
PHP_PHPDBG_CFLAGS="-D_GNU_SOURCE"
|
||||
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_set.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 phpdbg_set.c phpdbg_frame.c"
|
||||
|
||||
PHP_SUBST(PHP_PHPDBG_CFLAGS)
|
||||
PHP_SUBST(PHP_PHPDBG_FILES)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
ARG_ENABLE('phpdbg', 'Build phpdbg', 'yes');
|
||||
ARG_ENABLE('phpdbgs', 'Build phpdbg shared', 'no');
|
||||
|
||||
PHPDBG_SOURCES='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_set.c';
|
||||
PHPDBG_SOURCES='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_set.c phpdbg_frame.c';
|
||||
PHPDBG_DLL='php' + PHP_VERSION + 'phpdbg.dll';
|
||||
PHPDBG_EXE='phpdbg.exe';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Author: krakjoe #
|
||||
# Purpose: Daemonize phpdbg automatically on boot #
|
||||
# chkconfig: 2345 07 09 #
|
||||
# description:Starts, stops and restarts phpdbg daemon #
|
||||
# description: Starts, stops and restarts phpdbg daemon #
|
||||
################################################################
|
||||
LOCKFILE=/var/lock/subsys/phpdbg
|
||||
PIDFILE=/var/run/phpdbg.pid
|
||||
@@ -16,7 +16,7 @@ if [ "x${PHPDBG}" == "x" ]; then
|
||||
PHPDBG=$(which phpdbg 2>/dev/null)
|
||||
fi
|
||||
################################################################
|
||||
# Options to pass to phpdbg upon boot #
|
||||
# Options to pass to phpdbg upon boot #
|
||||
################################################################
|
||||
OPTIONS=
|
||||
LOGFILE=/var/log/phpdbg.log
|
||||
|
||||
@@ -171,7 +171,7 @@ PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **point
|
||||
|
||||
case FILE_PARAM:
|
||||
asprintf(pointer,
|
||||
"%s:%u",
|
||||
"%s:%lu",
|
||||
param->file.name,
|
||||
param->file.line);
|
||||
break;
|
||||
|
||||
206
phpdbg_frame.c
Normal file
206
phpdbg_frame.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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 "zend.h"
|
||||
#include "phpdbg.h"
|
||||
#include "phpdbg_utils.h"
|
||||
#include "phpdbg_frame.h"
|
||||
#include "phpdbg_list.h"
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
|
||||
|
||||
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);
|
||||
} /* }}} */
|
||||
|
||||
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
|
||||
);
|
||||
} /* }}} */
|
||||
|
||||
static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **funcname, **class, **type, **args, **argstmp;
|
||||
char is_class;
|
||||
|
||||
zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"),
|
||||
(void **)&funcname);
|
||||
|
||||
if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp),
|
||||
"object", sizeof("object"), (void **)&class)) == FAILURE) {
|
||||
is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"),
|
||||
(void **)&class);
|
||||
} else {
|
||||
zend_get_object_classname(*class, (const char **)&Z_STRVAL_PP(class),
|
||||
(zend_uint *)&Z_STRLEN_PP(class) TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (is_class == SUCCESS) {
|
||||
zend_hash_find(Z_ARRVAL_PP(tmp), "type", sizeof("type"), (void **)&type);
|
||||
}
|
||||
|
||||
phpdbg_write("%s%s%s(",
|
||||
is_class == FAILURE?"":Z_STRVAL_PP(class),
|
||||
is_class == FAILURE?"":Z_STRVAL_PP(type),
|
||||
Z_STRVAL_PP(funcname)
|
||||
);
|
||||
|
||||
if (zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"),
|
||||
(void **)&args) == SUCCESS) {
|
||||
HashPosition iterator;
|
||||
const zend_function *func = phpdbg_get_function(
|
||||
Z_STRVAL_PP(funcname), is_class == FAILURE ? NULL : Z_STRVAL_PP(class) TSRMLS_CC);
|
||||
const zend_arg_info *arginfo = func ? func->common.arg_info : NULL;
|
||||
int j = 0, m = func ? func->common.num_args : 0;
|
||||
zend_bool is_variadic = 0;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator);
|
||||
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args),
|
||||
(void **) &argstmp, &iterator) == SUCCESS) {
|
||||
if (j) {
|
||||
phpdbg_write(", ");
|
||||
}
|
||||
if (m && j < m) {
|
||||
#if PHP_VERSION_ID >= 50600
|
||||
is_variadic = arginfo[j].is_variadic;
|
||||
#endif
|
||||
phpdbg_write("%s=%s",
|
||||
arginfo[j].name, is_variadic ? "[": "");
|
||||
}
|
||||
++j;
|
||||
|
||||
zend_print_flat_zval_r(*argstmp TSRMLS_CC);
|
||||
zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator);
|
||||
}
|
||||
if (is_variadic) {
|
||||
phpdbg_write("]");
|
||||
}
|
||||
}
|
||||
phpdbg_write(")");
|
||||
}
|
||||
|
||||
void phpdbg_dump_backtrace(size_t num TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval zbacktrace;
|
||||
zval **tmp;
|
||||
zval **file, **line;
|
||||
HashPosition position;
|
||||
int i = 1, limit = num;
|
||||
int user_defined;
|
||||
|
||||
if (limit < 0) {
|
||||
phpdbg_error("Invalid backtrace size %d", limit);
|
||||
}
|
||||
|
||||
zend_fetch_debug_backtrace(
|
||||
&zbacktrace, 0, 0, limit TSRMLS_CC);
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position);
|
||||
zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position);
|
||||
while (1) {
|
||||
user_defined = zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **)&file);
|
||||
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 #0: {main} at %s:%ld", Z_STRVAL_PP(file), Z_LVAL_PP(line));
|
||||
break;
|
||||
}
|
||||
|
||||
if (user_defined == SUCCESS) {
|
||||
phpdbg_write("frame #%d: ", i++);
|
||||
phpdbg_dump_prototype(tmp TSRMLS_CC);
|
||||
phpdbg_writeln(" at %s:%ld", Z_STRVAL_PP(file), Z_LVAL_PP(line));
|
||||
} else {
|
||||
phpdbg_write(" => ");
|
||||
phpdbg_dump_prototype(tmp TSRMLS_CC);
|
||||
phpdbg_writeln(" (internal function)");
|
||||
}
|
||||
}
|
||||
|
||||
phpdbg_writeln(EMPTY);
|
||||
zval_dtor(&zbacktrace);
|
||||
} /* }}} */
|
||||
30
phpdbg_frame.h
Normal file
30
phpdbg_frame.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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 "TSRM.h"
|
||||
|
||||
void phpdbg_restore_frame(TSRMLS_D);
|
||||
void phpdbg_switch_frame(int TSRMLS_DC);
|
||||
void phpdbg_dump_backtrace(size_t TSRMLS_DC);
|
||||
|
||||
#endif /* PHPDBG_FRAME_H */
|
||||
161
phpdbg_prompt.c
161
phpdbg_prompt.c
@@ -34,6 +34,7 @@
|
||||
#include "phpdbg_prompt.h"
|
||||
#include "phpdbg_cmd.h"
|
||||
#include "phpdbg_set.h"
|
||||
#include "phpdbg_frame.h"
|
||||
|
||||
/* {{{ command declarations */
|
||||
const phpdbg_command_t phpdbg_prompt_commands[] = {
|
||||
@@ -132,7 +133,8 @@ static inline int phpdbg_call_register(phpdbg_input_t *input TSRMLS_DC) /* {{{ *
|
||||
return FAILURE;
|
||||
} /* }}} */
|
||||
|
||||
void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC) {
|
||||
void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (init_file && VCWD_STAT(init_file, &sb) != -1) {
|
||||
@@ -190,7 +192,7 @@ void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_
|
||||
{
|
||||
phpdbg_input_t *input = phpdbg_read_input(cmd TSRMLS_CC);
|
||||
switch (phpdbg_do_cmd(phpdbg_prompt_commands, input TSRMLS_CC)) {
|
||||
case FAILURE:
|
||||
case FAILURE:
|
||||
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
|
||||
if (phpdbg_call_register(input TSRMLS_CC) == FAILURE) {
|
||||
phpdbg_error("Unrecognized command in %s:%d: %s!", init_file, line, input->string);
|
||||
@@ -244,7 +246,7 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS
|
||||
if (i != -1) {
|
||||
scan_dir[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
asprintf(
|
||||
&init_file, "%s/%s", scan_dir, PHPDBG_INIT_FILENAME);
|
||||
phpdbg_try_file_init(init_file, strlen(init_file), 1 TSRMLS_CC);
|
||||
@@ -471,80 +473,6 @@ 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) {
|
||||
@@ -727,73 +655,10 @@ PHPDBG_COMMAND(back) /* {{{ */
|
||||
|
||||
switch (param->type) {
|
||||
case EMPTY_PARAM:
|
||||
case NUMERIC_PARAM: {
|
||||
zval zbacktrace;
|
||||
zval **tmp, **argstmp;
|
||||
HashPosition position;
|
||||
int i = 0,
|
||||
limit = (param->type == NUMERIC_PARAM) ? param->num : 0;
|
||||
|
||||
zval **file, **line, **funcname, **class, **type, **args;
|
||||
char is_class;
|
||||
|
||||
if (limit < 0) {
|
||||
phpdbg_error("Invalid backtrace size %d", limit);
|
||||
}
|
||||
|
||||
zend_fetch_debug_backtrace(
|
||||
&zbacktrace, 0, 0, limit TSRMLS_CC);
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position);
|
||||
zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position);
|
||||
while (1) {
|
||||
zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **)&file);
|
||||
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:%ld",
|
||||
i, Z_STRVAL_PP(file), Z_LVAL_PP(line));
|
||||
break;
|
||||
}
|
||||
zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), (void **)&funcname);
|
||||
if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "object", sizeof("object"), (void **)&class)) == FAILURE) {
|
||||
is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"), (void **)&class);
|
||||
} else {
|
||||
zend_get_object_classname(*class, (const char **)&Z_STRVAL_PP(class), (zend_uint *)&Z_STRLEN_PP(class) TSRMLS_CC);
|
||||
}
|
||||
if (is_class == SUCCESS) {
|
||||
zend_hash_find(Z_ARRVAL_PP(tmp), "type", sizeof("type"), (void **)&type);
|
||||
}
|
||||
|
||||
phpdbg_write(
|
||||
"frame #%d: %s%s%s(",
|
||||
i++,
|
||||
is_class == FAILURE?"":Z_STRVAL_PP(class),
|
||||
is_class == FAILURE?"":Z_STRVAL_PP(type),
|
||||
Z_STRVAL_PP(funcname)
|
||||
);
|
||||
|
||||
if (zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"), (void **)&args) == SUCCESS) {
|
||||
HashPosition iterator;
|
||||
int j = 0;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator);
|
||||
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args), (void **) &argstmp, &iterator) == SUCCESS) {
|
||||
if (j++) {
|
||||
phpdbg_write(", ");
|
||||
}
|
||||
zend_print_flat_zval_r(*argstmp TSRMLS_CC);
|
||||
zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator);
|
||||
}
|
||||
}
|
||||
|
||||
phpdbg_writeln(") at %s:%ld", Z_STRVAL_PP(file), Z_LVAL_PP(line));
|
||||
}
|
||||
|
||||
phpdbg_writeln(EMPTY);
|
||||
zval_dtor(&zbacktrace);
|
||||
} break;
|
||||
case NUMERIC_PARAM:
|
||||
phpdbg_dump_backtrace(
|
||||
(param->type == NUMERIC_PARAM) ? param->num : 0 TSRMLS_CC);
|
||||
break;
|
||||
|
||||
phpdbg_default_switch_case();
|
||||
}
|
||||
@@ -838,7 +703,7 @@ PHPDBG_COMMAND(print) /* {{{ */
|
||||
phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table)));
|
||||
phpdbg_writeln("Constants\t%d", zend_hash_num_elements(EG(zend_constants)));
|
||||
phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files)));
|
||||
|
||||
|
||||
phpdbg_writeln(SEPARATE);
|
||||
} break;
|
||||
|
||||
@@ -929,7 +794,7 @@ PHPDBG_COMMAND(source) /* {{{ */
|
||||
switch (param->type) {
|
||||
case STR_PARAM: {
|
||||
if (input->argc > 2) {
|
||||
if (phpdbg_argv_is(1, "export")) {
|
||||
if (phpdbg_argv_is(1, "export")) {
|
||||
FILE *h = VCWD_FOPEN(input->argv[2]->string, "w+");
|
||||
if (h) {
|
||||
phpdbg_export_breakpoints(h TSRMLS_CC);
|
||||
@@ -1412,8 +1277,8 @@ zend_vm_enter:
|
||||
/* search for breakpoints */
|
||||
{
|
||||
phpdbg_breakbase_t *brake;
|
||||
|
||||
if ((PHPDBG_G(flags) & PHPDBG_BP_MASK) &&
|
||||
|
||||
if ((PHPDBG_G(flags) & PHPDBG_BP_MASK) &&
|
||||
(brake = phpdbg_find_breakpoint(execute_data TSRMLS_CC))) {
|
||||
phpdbg_hit_breakpoint(
|
||||
brake, 1 TSRMLS_CC);
|
||||
|
||||
@@ -147,6 +147,33 @@ PHPDBG_API const char *phpdbg_current_file(TSRMLS_D) /* {{{ */
|
||||
return file;
|
||||
} /* }}} */
|
||||
|
||||
PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *func = NULL;
|
||||
size_t fname_len = strlen(fname);
|
||||
char *lcname = zend_str_tolower_dup(fname, fname_len);
|
||||
|
||||
if (cname) {
|
||||
zend_class_entry **ce;
|
||||
size_t cname_len = strlen(cname);
|
||||
char *lc_cname = zend_str_tolower_dup(cname, cname_len);
|
||||
int ret = zend_lookup_class(lc_cname, cname_len, &ce TSRMLS_CC);
|
||||
|
||||
efree(lc_cname);
|
||||
|
||||
if (ret == SUCCESS) {
|
||||
zend_hash_find(&(*ce)->function_table, lcname, fname_len+1,
|
||||
(void**)&func);
|
||||
}
|
||||
} else {
|
||||
zend_hash_find(EG(function_table), lcname, fname_len+1,
|
||||
(void**)&func);
|
||||
}
|
||||
|
||||
efree(lcname);
|
||||
return func;
|
||||
} /* }}} */
|
||||
|
||||
PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len) /* {{{ */
|
||||
{
|
||||
const char *p = str;
|
||||
@@ -248,18 +275,18 @@ PHPDBG_API int phpdbg_print(int type TSRMLS_DC, FILE *fp, const char *format, ..
|
||||
|
||||
PHPDBG_API int phpdbg_rlog(FILE *fp, const char *fmt, ...) { /* {{{ */
|
||||
int rc = 0;
|
||||
|
||||
|
||||
va_list args;
|
||||
struct timeval tp;
|
||||
|
||||
|
||||
va_start(args, fmt);
|
||||
if (gettimeofday(&tp, NULL) == SUCCESS) {
|
||||
char friendly[100];
|
||||
char *format = NULL, *buffer = NULL;
|
||||
|
||||
|
||||
strftime(friendly, 100, "%a %b %d %T.%%04d %Y", localtime(&tp.tv_sec));
|
||||
asprintf(
|
||||
&buffer, friendly, tp.tv_usec/1000);
|
||||
&buffer, friendly, tp.tv_usec/1000);
|
||||
asprintf(
|
||||
&format, "[%s]: %s\n", buffer, fmt);
|
||||
rc = vfprintf(
|
||||
@@ -269,7 +296,7 @@ PHPDBG_API int phpdbg_rlog(FILE *fp, const char *fmt, ...) { /* {{{ */
|
||||
free(buffer);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
|
||||
return rc;
|
||||
} /* }}} */
|
||||
|
||||
@@ -330,7 +357,7 @@ PHPDBG_API void phpdbg_set_prompt(const char *prompt TSRMLS_DC) /* {{{ */
|
||||
} /* }}} */
|
||||
|
||||
PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
{
|
||||
/* find cached prompt */
|
||||
if (PHPDBG_G(prompt)[1]) {
|
||||
return PHPDBG_G(prompt)[1];
|
||||
|
||||
@@ -30,6 +30,7 @@ PHPDBG_API int phpdbg_is_class_method(const char*, size_t, char**, char**);
|
||||
PHPDBG_API const char *phpdbg_current_file(TSRMLS_D);
|
||||
PHPDBG_API char *phpdbg_resolve_path(const char* TSRMLS_DC);
|
||||
PHPDBG_API char *phpdbg_trim(const char*, size_t, size_t*);
|
||||
PHPDBG_API const zend_function *phpdbg_get_function(const char*, const char* TSRMLS_DC);
|
||||
|
||||
/**
|
||||
* Error/notice/formatting helpers
|
||||
|
||||
4
test.php
4
test.php
@@ -13,7 +13,7 @@ class phpdbg {
|
||||
}
|
||||
}
|
||||
|
||||
function test($x) {
|
||||
function test($x, $y = 0) {
|
||||
$var = $x + 1;
|
||||
$var += 2;
|
||||
$var <<= 3;
|
||||
@@ -32,7 +32,7 @@ $dbg = new phpdbg();
|
||||
var_dump(
|
||||
$dbg->isGreat("PHP Rocks !!"));
|
||||
|
||||
foreach (test(1) as $gen)
|
||||
foreach (test(1,2) as $gen)
|
||||
continue;
|
||||
|
||||
echo "it works!\n";
|
||||
|
||||
Reference in New Issue
Block a user