From 80b82cd538d0af80fc2bc175c1823d06b0bad165 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Sat, 16 Nov 2013 18:53:12 +0000 Subject: [PATCH] add list class and method commands update help text to be more specific --- phpdbg_help.c | 28 ++++++++----- phpdbg_list.c | 84 ++++++++++++++++++++++++++++++++++---- phpdbg_list.h | 8 +++- phpdbg_prompt.c | 106 +++++++++++++++++++++++++++--------------------- 4 files changed, 160 insertions(+), 66 deletions(-) diff --git a/phpdbg_help.c b/phpdbg_help.c index 651ef8623a..295ada4810 100644 --- a/phpdbg_help.c +++ b/phpdbg_help.c @@ -114,21 +114,22 @@ PHPDBG_HELP(break) /* {{{ */ phpdbg_writeln("Setting a breakpoint stops execution at a specific stage"); phpdbg_writeln(EMPTY); 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("\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("\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("\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("\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("\t%sbreak on ($expression == true)", PROMPT); phpdbg_writeln("Will break when the condition evaluates to true"); 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("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("Conditional breaks are costly, use them sparingly !!"); @@ -176,17 +177,22 @@ PHPDBG_HELP(back) /* {{{ */ 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("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("\t%slist func", PROMPT); - phpdbg_writeln("Will print the source of the global function \"func\""); - phpdbg_writeln("\t%slist .mine", PROMPT); - phpdbg_writeln("Will print the source of the class method \"mine\""); + phpdbg_writeln("\t%slist [func] my_function", PROMPT); + phpdbg_writeln("Will print the source of the global function \"my_function\""); + phpdbg_writeln("\t%slist [func] .mine", PROMPT); + 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("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; } /* }}} */ diff --git a/phpdbg_list.c b/phpdbg_list.c index a4c3d1272d..78ec2fc75a 100644 --- a/phpdbg_list.c +++ b/phpdbg_list.c @@ -31,13 +31,13 @@ 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); zend_function* fbc; - const char *func_name = str; - size_t func_name_len = strlen(str); - + char *func_name = str; + size_t func_name_len = len; + /* search active scope if begins with period */ if (func_name[0] == '.') { if (EG(scope)) { @@ -55,13 +55,18 @@ static inline void i_phpdbg_list_func(const char *str TSRMLS_DC) } else { 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, (void**)&fbc) == SUCCESS) { phpdbg_list_function(fbc TSRMLS_CC); } else { phpdbg_error("Function %s not found", func_name); } + + efree(func_name); } PHPDBG_LIST(lines) /* {{{ */ @@ -87,7 +92,66 @@ PHPDBG_LIST(func) /* {{{ */ { if (param->type == STR_PARAM) { 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 { phpdbg_error( "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; case STR_PARAM: { - i_phpdbg_list_func(param->str TSRMLS_CC); + i_phpdbg_list_func(param->str, param->len TSRMLS_CC); } break; + case METHOD_PARAM: + phpdbg_do_list_method(param TSRMLS_CC); + break; + default: phpdbg_error( "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; if (fbc->type != ZEND_USER_FUNCTION) { + phpdbg_error( + "The function requested (%s) is not user defined", fbc->common.function_name); return; } diff --git a/phpdbg_list.h b/phpdbg_list.h index 8829d7f6cc..53113aab30 100644 --- a/phpdbg_list.h +++ b/phpdbg_list.h @@ -35,6 +35,8 @@ int phpdbg_do_list_##name(phpdbg_param_t *param TSRMLS_DC) PHPDBG_LIST(lines); +PHPDBG_LIST(class); +PHPDBG_LIST(method); PHPDBG_LIST(func); 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); static const phpdbg_command_t phpdbg_list_commands[] = { - PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'), - PHPDBG_LIST_EX_D(func, "lists the specified function", 'f'), + PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'), + 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} }; diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index b0e2ff8b5f..9e6d73f622 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -413,53 +413,57 @@ static PHPDBG_COMMAND(back) /* {{{ */ static PHPDBG_COMMAND(print) /* {{{ */ { - 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 SUCCESS; - } - - phpdbg_writeln(SEPARATE); - phpdbg_notice("Execution Context Information"); + if (param->type == EMPTY_PARAM) { + phpdbg_writeln(SEPARATE); + phpdbg_notice("Execution Context Information"); #ifdef HAVE_LIBREADLINE - phpdbg_writeln("Readline\tyes"); + phpdbg_writeln("Readline\tyes"); #else - phpdbg_writeln("Readline\tno"); + phpdbg_writeln("Readline\tno"); #endif - 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("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("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off"); + 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("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("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off"); - if (PHPDBG_G(ops)) { - phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last); + if (PHPDBG_G(ops)) { + phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last); - if (PHPDBG_G(ops)->last_var) { - phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1); - } else { - phpdbg_writeln("Variables\tNone"); - } - } - - phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no"); - if (EG(in_execution)) { - phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret)); - } - 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("Constants\t%d", zend_hash_num_elements(EG(zend_constants))); - 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_SYM TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC); + if (PHPDBG_G(ops)->last_var) { + phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1); + } else { + phpdbg_writeln("Variables\tNone"); + } + } - phpdbg_writeln(SEPARATE); + phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no"); + if (EG(in_execution)) { + phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret)); + } + 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("Constants\t%d", zend_hash_num_elements(EG(zend_constants))); + 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_SYM TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC); + + 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; } /* }}} */ @@ -957,12 +961,22 @@ zend_vm_enter: #endif #define DO_INTERACTIVE() do {\ - switch (last_step = phpdbg_interactive(TSRMLS_C)) {\ - case PHPDBG_UNTIL:\ - case PHPDBG_NEXT:\ - goto next;\ - }\ -} while(!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) + phpdbg_list_file(\ + zend_get_executed_filename(TSRMLS_C), \ + 2, \ + zend_get_executed_lineno(TSRMLS_C) \ + TSRMLS_CC\ + );\ + \ + 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 */ if (PHPDBG_G(flags) & PHPDBG_IN_COND_BP) { -- 2.50.1