diff --git a/Changelog.md b/Changelog.md index 32ecce879f5..ea7900a47ef 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,10 +1,10 @@ ChangeLog for phpdbg ==================== -Version 0.1.1 2013-00-00 +Version 0.2.0 2013-00-00 ------------------------ - +1. Added "break delete " command Version 0.1.0 2013-11-23 ------------------------ diff --git a/phpdbg.h b/phpdbg.h index af13f669964..60a713a98de 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -121,7 +121,7 @@ /* {{{ strings */ #define PHPDBG_ISSUES "http://github.com/krakjoe/phpdbg/issues" -#define PHPDBG_VERSION "0.1.1-dev" /* }}} */ +#define PHPDBG_VERSION "0.2.0-dev" /* }}} */ /* {{{ output descriptors */ #define PHPDBG_STDIN 0 @@ -136,6 +136,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) zend_op_array *ops; /* op_array */ zval *retval; /* return value */ int bp_count; /* breakpoint count */ + int del_bp_num; /* breakpoint to delete */ int vmret; /* return from last opcode handler execution */ phpdbg_command_t *lcmd; /* last command */ phpdbg_param_t lparam; /* last param */ diff --git a/phpdbg_bp.c b/phpdbg_bp.c index bdd2eef3aef..c06afde9363 100644 --- a/phpdbg_bp.c +++ b/phpdbg_bp.c @@ -211,6 +211,7 @@ PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_l ZVAL_STRINGL(&new_break.code, expr, expr_len, 1); + new_break.hash = hash; new_break.id = PHPDBG_G(bp_count)++; cops = CG(compiler_options); @@ -476,6 +477,90 @@ int phpdbg_find_breakpoint(zend_execute_data* execute_data TSRMLS_DC) /* {{{ */ return FAILURE; } /* }}} */ +int phpdbg_delete_breakpoint_from_file_llist(void *brake) { + TSRMLS_FETCH(); + return ((phpdbg_breakfile_t*)brake)->id == PHPDBG_G(del_bp_num); +} + +PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ +{ + if (PHPDBG_G(flags) & PHPDBG_HAS_SYM_BP) { + HashPosition position; + phpdbg_breaksymbol_t *brake; + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], &position); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], (void**) &brake, &position) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], &position)) { + if (brake->id == num) { + zend_hash_del(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], brake->symbol, strlen(brake->symbol)); + return; + } + } + } + + if (PHPDBG_G(flags) & PHPDBG_HAS_METHOD_BP) { + HashPosition position[2]; + phpdbg_breakmethod_t *brake; + HashTable *class_table; + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], &position[0]); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], (void**) &class_table, &position[0]) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], &position[0])) { + for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]); + zend_hash_get_current_data_ex(class_table, (void**) &brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex(class_table, &position[1])) { + if (brake->id == num) { + zend_hash_del(class_table, brake->func_name, brake->func_len); + return; + } + } + } + } + + if (PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) { + HashPosition position; + zend_llist *points; + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], (void**) &points, &position) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position)) { + size_t size = points->size; + PHPDBG_G(del_bp_num) = num; + zend_llist_apply_with_del(points, phpdbg_delete_breakpoint_from_file_llist); + if (size != points->size) { + return; + } + } + } + + if (PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) { + HashPosition position; + phpdbg_breakline_t *brake; + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], &position); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (void**) &brake, &position) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], &position)) { + if (brake->id == num) { + zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], brake->opline); + } + } + } + + if (PHPDBG_G(flags) & PHPDBG_HAS_COND_BP) { + HashPosition position; + phpdbg_breakcond_t *brake; + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], (void**) &brake, &position) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position)) { + if (brake->id == num) { + zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], brake->hash); + return; + } + } + } +} /* }}} */ + PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); diff --git a/phpdbg_bp.h b/phpdbg_bp.h index 92d2a634dbf..e96c6ec44f9 100644 --- a/phpdbg_bp.h +++ b/phpdbg_bp.h @@ -72,9 +72,10 @@ typedef struct _phpdbg_breakop_t { * Breakpoint condition based representation */ typedef struct _phpdbg_breakcond_t { - zval code; - zend_op_array *ops; - int id; + zend_ulong hash; + zval code; + zend_op_array *ops; + int id; } phpdbg_breakcond_t; PHPDBG_API void phpdbg_set_breakpoint_file(const char*, long TSRMLS_DC); @@ -94,6 +95,7 @@ int phpdbg_find_conditional_breakpoint(TSRMLS_D); int phpdbg_find_catch(zend_uchar TSRMLS_DC); int phpdbg_find_breakpoint(zend_execute_data* TSRMLS_DC); +PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC); PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D); PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC); diff --git a/phpdbg_break.c b/phpdbg_break.c index 62404b3d31d..c5d91220ff7 100644 --- a/phpdbg_break.c +++ b/phpdbg_break.c @@ -121,3 +121,16 @@ PHPDBG_BREAK(op) /* {{{ */ return SUCCESS; } /* }}} */ + +PHPDBG_BREAK(del) /* {{{ */ +{ + switch (param->type) { + case NUMERIC_PARAM: { + phpdbg_delete_breakpoint(param->num TSRMLS_CC); + } break; + + phpdbg_default_switch_case(); + } + + return SUCCESS; +} /* }}} */ diff --git a/phpdbg_break.h b/phpdbg_break.h index a4f55f314b2..1d6f594bc8f 100644 --- a/phpdbg_break.h +++ b/phpdbg_break.h @@ -31,10 +31,11 @@ PHPDBG_BREAK(file); PHPDBG_BREAK(method); PHPDBG_BREAK(address); +PHPDBG_BREAK(op); PHPDBG_BREAK(on); PHPDBG_BREAK(lineno); PHPDBG_BREAK(func); -PHPDBG_BREAK(op); +PHPDBG_BREAK(del); /** * Commands @@ -47,6 +48,7 @@ static const phpdbg_command_t phpdbg_break_commands[] = { PHPDBG_COMMAND_D_EX(on, "specify breakpoint by expression", 'o', break_on, NULL, 1), PHPDBG_COMMAND_D_EX(lineno, "specify breakpoint by line of currently executing file", 'l', break_lineno, NULL, 1), PHPDBG_COMMAND_D_EX(func, "specify breakpoint by global function name", 'f', break_func, NULL, 1), + PHPDBG_COMMAND_D_EX(del, "delete breakpoint by identifier number", 'd', break_del, NULL, 1), PHPDBG_END_COMMAND };