mirror of
https://github.com/php/php-src.git
synced 2025-08-19 17:04:47 +02:00
add list class and method commands
update help text to be more specific
This commit is contained in:
parent
f03b6b4433
commit
80b82cd538
4 changed files with 159 additions and 65 deletions
|
@ -114,21 +114,22 @@ PHPDBG_HELP(break) /* {{{ */
|
||||||
phpdbg_writeln("Setting a breakpoint stops execution at a specific stage");
|
phpdbg_writeln("Setting a breakpoint stops execution at a specific stage");
|
||||||
phpdbg_writeln(EMPTY);
|
phpdbg_writeln(EMPTY);
|
||||||
phpdbg_writeln("Examples:");
|
phpdbg_writeln("Examples:");
|
||||||
phpdbg_writeln("\t%sbreak test.php:1", PROMPT);
|
phpdbg_writeln("\t%sbreak [file] test.php:1", PROMPT);
|
||||||
phpdbg_writeln("Will break execution on line 1 of test.php");
|
phpdbg_writeln("Will break execution on line 1 of test.php");
|
||||||
phpdbg_writeln("\t%sbreak my_function", PROMPT);
|
phpdbg_writeln("\t%sbreak [func] my_function", PROMPT);
|
||||||
phpdbg_writeln("Will break execution on entry to my_function");
|
phpdbg_writeln("Will break execution on entry to my_function");
|
||||||
phpdbg_writeln("\t%sbreak \\my\\class::method", PROMPT);
|
phpdbg_writeln("\t%sbreak [method] \\my\\class::method", PROMPT);
|
||||||
phpdbg_writeln("Will break execution on entry to \\my\\class::method");
|
phpdbg_writeln("Will break execution on entry to \\my\\class::method");
|
||||||
phpdbg_writeln("\t%sbreak 0x7ff68f570e08", PROMPT);
|
phpdbg_writeln("\t%sbreak [address] 0x7ff68f570e08", PROMPT);
|
||||||
phpdbg_writeln("Will break at the opline with the address provided (addresses are shown during execution)");
|
phpdbg_writeln("Will break at the opline with the address provided (addresses are shown during execution)");
|
||||||
phpdbg_writeln("\t%sbreak 200", PROMPT);
|
phpdbg_writeln("\t%sbreak [lineno] 200", PROMPT);
|
||||||
phpdbg_writeln("Will break at line 200 of the currently executing file");
|
phpdbg_writeln("Will break at line 200 of the currently executing file");
|
||||||
phpdbg_writeln("\t%sbreak on ($expression == true)", PROMPT);
|
phpdbg_writeln("\t%sbreak on ($expression == true)", PROMPT);
|
||||||
phpdbg_writeln("Will break when the condition evaluates to true");
|
phpdbg_writeln("Will break when the condition evaluates to true");
|
||||||
phpdbg_writeln(EMPTY);
|
phpdbg_writeln(EMPTY);
|
||||||
phpdbg_writeln("It is important to note, an address is only valid for the current compiled representation of the script");
|
phpdbg_writeln("It is important to note, an address is only valid for the current compiled representation of the script");
|
||||||
phpdbg_writeln("If you have to clean the environment and recompile then your opline break points will be invalid");
|
phpdbg_writeln("If you have to clean the environment and recompile then your opline break points will be invalid");
|
||||||
|
phpdbg_writeln("The parameters enclosed by [] are usually optional, but help avoid ambigious commands");
|
||||||
phpdbg_writeln(EMPTY);
|
phpdbg_writeln(EMPTY);
|
||||||
phpdbg_writeln("Conditional breaks are costly, use them sparingly !!");
|
phpdbg_writeln("Conditional breaks are costly, use them sparingly !!");
|
||||||
|
|
||||||
|
@ -176,17 +177,22 @@ PHPDBG_HELP(back) /* {{{ */
|
||||||
|
|
||||||
PHPDBG_HELP(list) /* {{{ */
|
PHPDBG_HELP(list) /* {{{ */
|
||||||
{
|
{
|
||||||
phpdbg_writeln("The list command displays N line from current context file");
|
phpdbg_writeln("The list command displays source code for the given argument");
|
||||||
phpdbg_writeln(EMPTY);
|
phpdbg_writeln(EMPTY);
|
||||||
phpdbg_writeln("Examples:");
|
phpdbg_writeln("Examples:");
|
||||||
phpdbg_writeln("\t%slist 2", PROMPT);
|
phpdbg_writeln("\t%slist [lines] 2", PROMPT);
|
||||||
phpdbg_writeln("Will print next 2 lines from the current file");
|
phpdbg_writeln("Will print next 2 lines from the current file");
|
||||||
phpdbg_writeln("\t%slist func", PROMPT);
|
phpdbg_writeln("\t%slist [func] my_function", PROMPT);
|
||||||
phpdbg_writeln("Will print the source of the global function \"func\"");
|
phpdbg_writeln("Will print the source of the global function \"my_function\"");
|
||||||
phpdbg_writeln("\t%slist .mine", PROMPT);
|
phpdbg_writeln("\t%slist [func] .mine", PROMPT);
|
||||||
phpdbg_writeln("Will print the source of the class method \"mine\"");
|
phpdbg_writeln("Will print the source of the method \"mine\" from the currently active scope");
|
||||||
|
phpdbg_writeln("\t%slist [method] my::method", PROMPT);
|
||||||
|
phpdbg_writeln("Will print the source of \"my::method\"");
|
||||||
|
phpdbg_writeln("\t%slist [class] myClass", PROMPT);
|
||||||
|
phpdbg_writeln("Will print the source of \"myClass\"");
|
||||||
phpdbg_writeln(EMPTY);
|
phpdbg_writeln(EMPTY);
|
||||||
phpdbg_writeln("Note: before listing functions you must have a populated function table, try compile !!");
|
phpdbg_writeln("Note: before listing functions you must have a populated function table, try compile !!");
|
||||||
|
phpdbg_writeln("The parameters enclosed by [] are usually optional, but help avoid ambigious commands");
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
|
|
|
@ -31,13 +31,13 @@
|
||||||
|
|
||||||
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
|
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
|
||||||
|
|
||||||
static inline void i_phpdbg_list_func(const char *str TSRMLS_DC)
|
static inline void i_phpdbg_list_func(const char *str, size_t len TSRMLS_DC)
|
||||||
{
|
{
|
||||||
HashTable *func_table = EG(function_table);
|
HashTable *func_table = EG(function_table);
|
||||||
zend_function* fbc;
|
zend_function* fbc;
|
||||||
const char *func_name = str;
|
char *func_name = str;
|
||||||
size_t func_name_len = strlen(str);
|
size_t func_name_len = len;
|
||||||
|
|
||||||
/* search active scope if begins with period */
|
/* search active scope if begins with period */
|
||||||
if (func_name[0] == '.') {
|
if (func_name[0] == '.') {
|
||||||
if (EG(scope)) {
|
if (EG(scope)) {
|
||||||
|
@ -55,13 +55,18 @@ static inline void i_phpdbg_list_func(const char *str TSRMLS_DC)
|
||||||
} else {
|
} else {
|
||||||
func_table = EG(function_table);
|
func_table = EG(function_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* use lowercase names, case insensitive */
|
||||||
|
func_name = zend_str_tolower_dup(func_name, func_name_len);
|
||||||
|
|
||||||
if (zend_hash_find(func_table, func_name, func_name_len+1,
|
if (zend_hash_find(func_table, func_name, func_name_len+1,
|
||||||
(void**)&fbc) == SUCCESS) {
|
(void**)&fbc) == SUCCESS) {
|
||||||
phpdbg_list_function(fbc TSRMLS_CC);
|
phpdbg_list_function(fbc TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
phpdbg_error("Function %s not found", func_name);
|
phpdbg_error("Function %s not found", func_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efree(func_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
PHPDBG_LIST(lines) /* {{{ */
|
PHPDBG_LIST(lines) /* {{{ */
|
||||||
|
@ -87,7 +92,66 @@ PHPDBG_LIST(func) /* {{{ */
|
||||||
{
|
{
|
||||||
if (param->type == STR_PARAM) {
|
if (param->type == STR_PARAM) {
|
||||||
i_phpdbg_list_func(
|
i_phpdbg_list_func(
|
||||||
param->str TSRMLS_CC);
|
param->str, param->len TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
phpdbg_error(
|
||||||
|
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
} /* }}} */
|
||||||
|
|
||||||
|
PHPDBG_LIST(method) /* {{{ */
|
||||||
|
{
|
||||||
|
if (param->type == METHOD_PARAM) {
|
||||||
|
zend_class_entry **ce;
|
||||||
|
|
||||||
|
if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) {
|
||||||
|
zend_function *function;
|
||||||
|
char *lcname = zend_str_tolower_dup(
|
||||||
|
param->method.name, strlen(param->method.name));
|
||||||
|
|
||||||
|
if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**) &function) == SUCCESS) {
|
||||||
|
phpdbg_list_function(
|
||||||
|
function TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
phpdbg_error("Could not find ::%s in %s", param->method.name, param->method.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
efree(lcname);
|
||||||
|
} else {
|
||||||
|
phpdbg_error("Could not find the class %s", param->method.class);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phpdbg_error(
|
||||||
|
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
} /* }}} */
|
||||||
|
|
||||||
|
PHPDBG_LIST(class) /* {{{ */
|
||||||
|
{
|
||||||
|
if (param->type == STR_PARAM) {
|
||||||
|
zend_class_entry **ce;
|
||||||
|
|
||||||
|
if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) {
|
||||||
|
if ((*ce)->type == ZEND_USER_CLASS) {
|
||||||
|
if ((*ce)->info.user.filename) {
|
||||||
|
phpdbg_list_file(
|
||||||
|
(*ce)->info.user.filename,
|
||||||
|
(*ce)->info.user.line_end - (*ce)->info.user.line_start + 1,
|
||||||
|
(*ce)->info.user.line_start TSRMLS_CC
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
phpdbg_error("The source of the requested class (%s) cannot be found", (*ce)->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phpdbg_error("The class requested (%s) is not user defined", (*ce)->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phpdbg_error("The requested class (%s) could not be found", param->str);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
phpdbg_error(
|
phpdbg_error(
|
||||||
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
||||||
|
@ -113,9 +177,13 @@ void phpdbg_list_dispatch(phpdbg_param_t *param TSRMLS_DC) /* {{{ */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STR_PARAM: {
|
case STR_PARAM: {
|
||||||
i_phpdbg_list_func(param->str TSRMLS_CC);
|
i_phpdbg_list_func(param->str, param->len TSRMLS_CC);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case METHOD_PARAM:
|
||||||
|
phpdbg_do_list_method(param TSRMLS_CC);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
phpdbg_error(
|
phpdbg_error(
|
||||||
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
"Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC));
|
||||||
|
@ -209,6 +277,8 @@ void phpdbg_list_function(const zend_function *fbc TSRMLS_DC) /* {{{ */
|
||||||
const zend_op_array *ops;
|
const zend_op_array *ops;
|
||||||
|
|
||||||
if (fbc->type != ZEND_USER_FUNCTION) {
|
if (fbc->type != ZEND_USER_FUNCTION) {
|
||||||
|
phpdbg_error(
|
||||||
|
"The function requested (%s) is not user defined", fbc->common.function_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
int phpdbg_do_list_##name(phpdbg_param_t *param TSRMLS_DC)
|
int phpdbg_do_list_##name(phpdbg_param_t *param TSRMLS_DC)
|
||||||
|
|
||||||
PHPDBG_LIST(lines);
|
PHPDBG_LIST(lines);
|
||||||
|
PHPDBG_LIST(class);
|
||||||
|
PHPDBG_LIST(method);
|
||||||
PHPDBG_LIST(func);
|
PHPDBG_LIST(func);
|
||||||
|
|
||||||
void phpdbg_list_function(const zend_function* TSRMLS_DC);
|
void phpdbg_list_function(const zend_function* TSRMLS_DC);
|
||||||
|
@ -42,8 +44,10 @@ void phpdbg_list_file(const char*, long, long TSRMLS_DC);
|
||||||
void phpdbg_list_dispatch(phpdbg_param_t *param TSRMLS_DC);
|
void phpdbg_list_dispatch(phpdbg_param_t *param TSRMLS_DC);
|
||||||
|
|
||||||
static const phpdbg_command_t phpdbg_list_commands[] = {
|
static const phpdbg_command_t phpdbg_list_commands[] = {
|
||||||
PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'),
|
PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'),
|
||||||
PHPDBG_LIST_EX_D(func, "lists the specified function", 'f'),
|
PHPDBG_LIST_EX_D(class, "lists the specified class", 'c'),
|
||||||
|
PHPDBG_LIST_EX_D(method, "lists the specified method", 'm'),
|
||||||
|
PHPDBG_LIST_EX_D(func, "lists the specified function", 'f'),
|
||||||
{NULL, 0, 0}
|
{NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
104
phpdbg_prompt.c
104
phpdbg_prompt.c
|
@ -413,53 +413,57 @@ static PHPDBG_COMMAND(back) /* {{{ */
|
||||||
|
|
||||||
static PHPDBG_COMMAND(print) /* {{{ */
|
static PHPDBG_COMMAND(print) /* {{{ */
|
||||||
{
|
{
|
||||||
if (param->type == STR_PARAM) {
|
if (param->type == EMPTY_PARAM) {
|
||||||
if (phpdbg_do_cmd(phpdbg_print_commands, param->str, param->len TSRMLS_CC) == FAILURE) {
|
phpdbg_writeln(SEPARATE);
|
||||||
phpdbg_error("Failed to find print command %s", param->str);
|
phpdbg_notice("Execution Context Information");
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
phpdbg_writeln(SEPARATE);
|
|
||||||
phpdbg_notice("Execution Context Information");
|
|
||||||
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
||||||
phpdbg_writeln("Readline\tyes");
|
phpdbg_writeln("Readline\tyes");
|
||||||
#else
|
#else
|
||||||
phpdbg_writeln("Readline\tno");
|
phpdbg_writeln("Readline\tno");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
|
phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
|
||||||
phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no");
|
phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no");
|
||||||
phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off");
|
phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off");
|
||||||
phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off");
|
phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off");
|
||||||
phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off");
|
phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off");
|
||||||
|
|
||||||
if (PHPDBG_G(ops)) {
|
if (PHPDBG_G(ops)) {
|
||||||
phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last);
|
phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last);
|
||||||
|
|
||||||
if (PHPDBG_G(ops)->last_var) {
|
if (PHPDBG_G(ops)->last_var) {
|
||||||
phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1);
|
phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1);
|
||||||
} else {
|
} else {
|
||||||
phpdbg_writeln("Variables\tNone");
|
phpdbg_writeln("Variables\tNone");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no");
|
phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no");
|
||||||
if (EG(in_execution)) {
|
if (EG(in_execution)) {
|
||||||
phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret));
|
phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret));
|
||||||
}
|
}
|
||||||
phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table)));
|
phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table)));
|
||||||
phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table)));
|
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("Constants\t%d", zend_hash_num_elements(EG(zend_constants)));
|
||||||
phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files)));
|
phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files)));
|
||||||
|
|
||||||
phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC);
|
phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC);
|
||||||
phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC);
|
phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC);
|
||||||
phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC);
|
phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC);
|
||||||
phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC);
|
phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC);
|
||||||
phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC);
|
phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC);
|
||||||
|
|
||||||
phpdbg_writeln(SEPARATE);
|
phpdbg_writeln(SEPARATE);
|
||||||
|
} else {
|
||||||
|
if (param->type == STR_PARAM) {
|
||||||
|
if (phpdbg_do_cmd(phpdbg_print_commands, param->str, param->len TSRMLS_CC) == FAILURE) {
|
||||||
|
phpdbg_error("Failed to find print command %s", param->str);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phpdbg_error("You must use a specific printer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
@ -957,12 +961,22 @@ zend_vm_enter:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DO_INTERACTIVE() do {\
|
#define DO_INTERACTIVE() do {\
|
||||||
switch (last_step = phpdbg_interactive(TSRMLS_C)) {\
|
phpdbg_list_file(\
|
||||||
case PHPDBG_UNTIL:\
|
zend_get_executed_filename(TSRMLS_C), \
|
||||||
case PHPDBG_NEXT:\
|
2, \
|
||||||
goto next;\
|
zend_get_executed_lineno(TSRMLS_C) \
|
||||||
}\
|
TSRMLS_CC\
|
||||||
} while(!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING))
|
);\
|
||||||
|
\
|
||||||
|
do {\
|
||||||
|
switch (last_step = phpdbg_interactive(TSRMLS_C)) {\
|
||||||
|
case PHPDBG_UNTIL:\
|
||||||
|
case PHPDBG_NEXT:{\
|
||||||
|
goto next;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
} while(!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING));\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
/* allow conditional breakpoints to access the vm uninterrupted */
|
/* allow conditional breakpoints to access the vm uninterrupted */
|
||||||
if (PHPDBG_G(flags) & PHPDBG_IN_COND_BP) {
|
if (PHPDBG_G(flags) & PHPDBG_IN_COND_BP) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue