From: krakjoe Date: Tue, 26 Nov 2013 22:20:52 +0000 (+0000) Subject: many improvements in breakpoints X-Git-Tag: php-5.6.0alpha1~110^2~30^2~76 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3df8e29b0d24d378d168183028aed46c1826a511;p=php many improvements in breakpoints make file breakpoints faster make exports happen in correct order make deletes simpler, set flags correctly fix info vars when no scope is set --- diff --git a/phpdbg.c b/phpdbg.c index f15e023503..bd477e7109 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -84,7 +84,7 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ static void php_phpdbg_destroy_bp_file(void *brake) /* {{{ */ { - zend_llist_destroy((zend_llist*)brake); + zend_hash_destroy((HashTable*)brake); } /* }}} */ static void php_phpdbg_destroy_bp_symbol(void *brake) /* {{{ */ @@ -119,7 +119,7 @@ static void php_phpdbg_destroy_bp_condition(void *data) /* {{{ */ } } /* }}} */ -static void php_phpdbg_destroy_registered(void *data) +static void php_phpdbg_destroy_registered(void *data) /* {{{ */ { TSRMLS_FETCH(); @@ -127,7 +127,7 @@ static void php_phpdbg_destroy_registered(void *data) destroy_zend_function( function TSRMLS_CC); -} +} /* }}} */ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { @@ -137,6 +137,8 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], 8, NULL, NULL, 0); + zend_hash_init(&PHPDBG_G(seek), 8, NULL, NULL, 0); zend_hash_init(&PHPDBG_G(registered), 8, NULL, php_phpdbg_destroy_registered, 0); @@ -151,6 +153,7 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); zend_hash_destroy(&PHPDBG_G(seek)); zend_hash_destroy(&PHPDBG_G(registered)); diff --git a/phpdbg.h b/phpdbg.h index b045d85fe0..1d07ee1cc6 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -79,6 +79,10 @@ #define PHPDBG_FINISH 4 #define PHPDBG_LEAVE 5 +/* + BEGIN: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE +*/ + /* {{{ tables */ #define PHPDBG_BREAK_FILE 0 #define PHPDBG_BREAK_SYM 1 @@ -86,7 +90,8 @@ #define PHPDBG_BREAK_METHOD 3 #define PHPDBG_BREAK_COND 4 #define PHPDBG_BREAK_OPCODE 5 -#define PHPDBG_BREAK_TABLES 6 /* }}} */ +#define PHPDBG_BREAK_MAP 6 +#define PHPDBG_BREAK_TABLES 7 /* }}} */ /* {{{ flags */ #define PHPDBG_HAS_FILE_BP (1<<1) @@ -97,6 +102,10 @@ #define PHPDBG_HAS_OPCODE_BP (1<<6) #define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP) +/* + END: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE +*/ + #define PHPDBG_IN_COND_BP (1<<7) #define PHPDBG_IN_EVAL (1<<8) @@ -148,7 +157,6 @@ 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 */ FILE *oplog; /* opline log */ diff --git a/phpdbg_bp.c b/phpdbg_bp.c index 75d0918401..61c8f74d0a 100644 --- a/phpdbg_bp.c +++ b/phpdbg_bp.c @@ -19,7 +19,6 @@ #include "zend.h" #include "zend_hash.h" -#include "zend_llist.h" #include "phpdbg.h" #include "phpdbg_bp.h" #include "phpdbg_utils.h" @@ -28,14 +27,27 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -static void phpdbg_llist_breakfile_dtor(void *data) /* {{{ */ +/* +* Note: +* A break point must always set the corect id and type +* A set breakpoint function must always map new points +*/ +static inline _phpdbg_break_mapping(int id, HashTable* table TSRMLS_DC) { + zend_hash_index_update( + &PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id), (void**) &table, sizeof(void*), NULL); +} + +#define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table TSRMLS_CC) +#define PHPDBG_BREAK_UNMAPPING(id) \ + zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id)) + +static void phpdbg_file_breaks_dtor(void *data) /* {{{ */ { phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) data; efree((char*)bp->filename); } /* }}} */ - static void phpdbg_class_breaks_dtor(void *data) /* {{{ */ { phpdbg_breakmethod_t *bp = (phpdbg_breakmethod_t*) data; @@ -46,110 +58,63 @@ static void phpdbg_class_breaks_dtor(void *data) /* {{{ */ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ { - HashPosition position; - HashTable *table = NULL; - - if (PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) { - zend_llist *brakes; - - table = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE]; - - for (zend_hash_internal_pointer_reset_ex(table, &position); - zend_hash_get_current_data_ex(table, (void*) &brakes, &position) == SUCCESS; - zend_hash_move_forward_ex(table, &position)) { - - zend_llist_position lposition; - phpdbg_breakfile_t *brake; - int count = zend_llist_count(brakes); - - if ((brake = zend_llist_get_first_ex(brakes, &lposition))) { - phpdbg_notice( - "Exporting file breakpoints in %s (%d)", brake->filename, count); - - do { - fprintf(handle, "break file %s:%lu\n", brake->filename, brake->line); - } while ((brake = zend_llist_get_next_ex(brakes, &lposition))); - } - } - } - - if (PHPDBG_G(flags) & PHPDBG_HAS_SYM_BP) { - phpdbg_breaksymbol_t *brake; - - table = &PHPDBG_G(bp)[PHPDBG_BREAK_SYM]; - - phpdbg_notice("Exporting symbol breakpoints (%d)", zend_hash_num_elements(table)); - - for (zend_hash_internal_pointer_reset_ex(table, &position); - zend_hash_get_current_data_ex(table, (void*) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(table, &position)) { - fprintf( - handle, "break %s\n", brake->symbol); - } - } - - if (PHPDBG_G(flags) & PHPDBG_HAS_METHOD_BP) { - HashTable *class; - phpdbg_breakmethod_t *brake; - HashPosition mposition; - zend_bool noted = 0; - - table = &PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]; - - for (zend_hash_internal_pointer_reset_ex(table, &position); - zend_hash_get_current_data_ex(table, (void**) &class, &position) == SUCCESS; - zend_hash_move_forward_ex(table, &position)) { - noted = 0; - - for (zend_hash_internal_pointer_reset_ex(class, &mposition); - zend_hash_get_current_data_ex(class, (void**) &brake, &mposition) == SUCCESS; - zend_hash_move_forward_ex(class, &mposition)) { - if (!noted) { - phpdbg_notice( - "Exporting method breakpoints in %s (%d)", - brake->class_name, zend_hash_num_elements(class)); - noted = 1; + HashPosition position[2]; + HashTable **table = NULL; + zend_ulong id = 0L; + + if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { + phpdbg_notice( + "Exporting %ld breakpoints", + zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])); + + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0]); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (void**)&table, &position[0]) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0])) { + phpdbg_breakbase_t *brake; + + zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], NULL, NULL, &id, 0, &position[0]); + + for (zend_hash_internal_pointer_reset_ex((*table), &position[1]); + zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex((*table), &position[1])) { + if (brake->id == id) { + switch (brake->type) { + case PHPDBG_BREAK_FILE: { + fprintf(handle, + "break file %s:%lu\n", + ((phpdbg_breakfile_t*)brake)->filename, + ((phpdbg_breakfile_t*)brake)->line); + } break; + + case PHPDBG_BREAK_SYM: { + fprintf(handle, + "break func %s\n", + ((phpdbg_breaksymbol_t*)brake)->symbol); + } break; + + case PHPDBG_BREAK_METHOD: { + fprintf(handle, + "break method %s::%s\n", + ((phpdbg_breakmethod_t*)brake)->class_name, + ((phpdbg_breakmethod_t*)brake)->func_name); + } break; + + case PHPDBG_BREAK_OPCODE: { + fprintf(handle, + "break op %s\n", + ((phpdbg_breakop_t*)brake)->name); + } break; + + case PHPDBG_BREAK_COND: { + fprintf(handle, + "break on %s\n", + Z_STRVAL(((phpdbg_breakcond_t*)brake)->code)); + } break; + } } - - fprintf( - handle, "break %s::%s\n", brake->class_name, brake->func_name); } } } - - if (PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) { - phpdbg_breakop_t *brake; - - table = &PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]; - - phpdbg_notice( - "Exporting opcode breakpoints (%d)", zend_hash_num_elements(table)); - - for (zend_hash_internal_pointer_reset_ex(table, &position); - zend_hash_get_current_data_ex(table, (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(table, &position)) { - - fprintf( - handle, "break op %s\n", brake->name); - } - } - - if (PHPDBG_G(flags) & PHPDBG_HAS_COND_BP) { - phpdbg_breakcond_t *brake; - - table = &PHPDBG_G(bp)[PHPDBG_BREAK_COND]; - - phpdbg_notice( - "Exporting conditional breakpoints (%d)", zend_hash_num_elements(table)); - - for (zend_hash_internal_pointer_reset_ex(table, &position); - zend_hash_get_current_data_ex(table, (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(table, &position)) { - - fprintf( - handle, "break on %s\n", Z_STRVAL(brake->code)); - } - } } /* }}} */ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */ @@ -158,32 +123,40 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML if (VCWD_STAT(path, &sb) != FAILURE) { if (sb.st_mode & (S_IFREG|S_IFLNK)) { + HashTable *broken; phpdbg_breakfile_t new_break; - zend_llist *break_files_ptr; size_t path_len = strlen(path); - new_break.filename = estrndup(path, path_len); - new_break.line = line_num; - - PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - new_break.filename, path_len, (void**)&break_files_ptr) == FAILURE) { - zend_llist break_files; - - zend_llist_init(&break_files, sizeof(phpdbg_breakfile_t), - phpdbg_llist_breakfile_dtor, 0); + path, path_len, (void**)&broken) == FAILURE) { + HashTable breaks; + + zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - new_break.filename, path_len, &break_files, sizeof(zend_llist), - (void**)&break_files_ptr); + path, path_len, &breaks, sizeof(HashTable), + (void**)&broken); } - - new_break.id = PHPDBG_G(bp_count)++; - zend_llist_add_element(break_files_ptr, &new_break); - - phpdbg_notice("Breakpoint #%d added at %s:%ld", - new_break.id, new_break.filename, new_break.line); + + if (!zend_hash_index_exists(broken, line_num)) { + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + new_break.filename = estrndup(path, path_len); + new_break.line = line_num; + new_break.id = PHPDBG_G(bp_count)++; + new_break.type = PHPDBG_BREAK_FILE; + + zend_hash_index_update( + broken, line_num, (void**)&new_break, sizeof(phpdbg_breakfile_t), NULL); + + phpdbg_notice("Breakpoint #%d added at %s:%ld", + new_break.id, new_break.filename, new_break.line); + + PHPDBG_BREAK_MAPPING(new_break.id, broken); + } else { + phpdbg_error("Breakpoint at %s:%ld exists", path, line_num); + } + } else { phpdbg_error("Cannot set breakpoint in %s, it is not a regular file", path); } @@ -201,12 +174,15 @@ PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len T new_break.symbol = estrndup(name, name_len); new_break.id = PHPDBG_G(bp_count)++; - + new_break.type = PHPDBG_BREAK_SYM; + zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], new_break.symbol, name_len, &new_break, sizeof(phpdbg_breaksymbol_t), NULL); phpdbg_notice("Breakpoint #%d added at %s", new_break.id, new_break.symbol); + + PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); } else { phpdbg_notice("Breakpoint exists at %s", name); } @@ -238,12 +214,15 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char* class_name, const char* new_break.func_name = estrndup(func_name, func_len); new_break.func_len = func_len; new_break.id = PHPDBG_G(bp_count)++; - + new_break.type = PHPDBG_BREAK_METHOD; + zend_hash_update(class_table, lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t), NULL); phpdbg_notice("Breakpoint #%d added at %s::%s", new_break.id, class_name, func_name); + + PHPDBG_BREAK_MAPPING(new_break.id, class_table); } else { phpdbg_notice("Breakpoint exists at %s::%s", class_name, func_name); } @@ -261,12 +240,14 @@ PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ new_break.name = NULL; new_break.opline = opline; new_break.id = PHPDBG_G(bp_count)++; - + new_break.type = PHPDBG_BREAK_OPLINE; + zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, &new_break, sizeof(phpdbg_breakline_t), NULL); phpdbg_notice("Breakpoint #%d added at %#lx", new_break.id, new_break.opline); + PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); } else { phpdbg_notice("Breakpoint exists at %#lx", opline); } @@ -286,6 +267,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len T new_break.hash = hash; new_break.name = estrndup(name, name_len); new_break.id = PHPDBG_G(bp_count)++; + new_break.type = PHPDBG_BREAK_OPCODE; zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, &new_break, sizeof(phpdbg_breakop_t), NULL); @@ -293,6 +275,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len T PHPDBG_G(flags) |= PHPDBG_HAS_OPCODE_BP; phpdbg_notice("Breakpoint #%d added at %s", new_break.id, name); + PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); } /* }}} */ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRMLS_DC) /* {{{ */ @@ -304,12 +287,14 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRML new_break.opline = (zend_ulong) opline; new_break.id = PHPDBG_G(bp_count)++; - + new_break.type = PHPDBG_BREAK_OPLINE; + zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t), NULL); phpdbg_notice("Breakpoint #%d added at %#lx", new_break.id, new_break.opline); + PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); } } /* }}} */ @@ -326,6 +311,7 @@ PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_l new_break.hash = hash; new_break.id = PHPDBG_G(bp_count)++; + new_break.type = PHPDBG_BREAK_COND; cops = CG(compiler_options); @@ -353,6 +339,7 @@ PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_l brake->id, Z_STRVAL(brake->code), brake->ops); PHPDBG_G(flags) |= PHPDBG_HAS_COND_BP; + PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_COND]); } else { phpdbg_error( "Failed to compile code for expression %s", expr); @@ -367,23 +354,19 @@ PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_l int phpdbg_find_breakpoint_file(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { + HashTable *breaks; + phpdbg_breakfile_t *brake; size_t name_len = strlen(op_array->filename); - zend_llist *break_list; - zend_llist_element *le; - + if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename, - name_len, (void**)&break_list) == FAILURE) { + name_len, (void**)&breaks) == FAILURE) { return FAILURE; } - for (le = break_list->head; le; le = le->next) { - const phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*)le->data; - - if (bp->line == (*EG(opline_ptr))->lineno) { - phpdbg_notice("Breakpoint #%d at %s:%ld", - bp->id, bp->filename, bp->line); - return SUCCESS; - } + if (zend_hash_index_find(breaks, (*EG(opline_ptr))->lineno, (void**)&brake) == SUCCESS) { + phpdbg_notice("Breakpoint #%d at %s:%ld", + brake->id, brake->filename, brake->line); + return SUCCESS; } return FAILURE; @@ -598,102 +581,75 @@ 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; + HashTable **table; - 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) { + if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], num, (void**)&table) == SUCCESS) { 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); - return; - } - } - } - - 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; - } - } - } - - if (PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) { - HashPosition position; - phpdbg_breakop_t *brake; - - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], &position)) { + phpdbg_breakbase_t *brake; + + for (zend_hash_internal_pointer_reset_ex((*table), &position); + zend_hash_get_current_data_ex((*table), (void**)&brake, &position) == SUCCESS; + zend_hash_move_forward_ex((*table), &position)) { + char *key; + zend_uint klen; + zend_ulong idx; + if (brake->id == num) { - zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], brake->hash); + int type = brake->type; + char *name = NULL; + size_t name_len = 0L; + + switch (type) { + case PHPDBG_BREAK_FILE: + case PHPDBG_BREAK_METHOD: + if (zend_hash_num_elements((*table)) == 1) { + name = estrdup(brake->name); + name_len = strlen(name); + if (zend_hash_num_elements(&PHPDBG_G(bp)[type]) == 1) { + PHPDBG_G(flags) &= ~(1<<(brake->type+1)); + } + } + break; + + default: { + if (zend_hash_num_elements((*table)) == 1) { + PHPDBG_G(flags) &= ~(1<<(brake->type+1)); + } + } + } + + switch (zend_hash_get_current_key_ex( + (*table), &key, &klen, &idx, 0, &position)) { + + case HASH_KEY_IS_STRING: + zend_hash_del((*table), key, klen); + break; + + default: + zend_hash_index_del((*table), idx); + } + + switch (type) { + case PHPDBG_BREAK_FILE: + case PHPDBG_BREAK_METHOD: + if (name) { + zend_hash_del(&PHPDBG_G(bp)[type], name, name_len); + efree(name); + } + break; + } +deleted: + phpdbg_notice("Deleted breakpoint #%ld", num); + PHPDBG_BREAK_UNMAPPING(num); return; - } + } } + + phpdbg_error("Failed to delete breakpoint #%ld", num); + } else { + phpdbg_error("Failed to find breakpoint #%ld", num); } } /* }}} */ @@ -705,7 +661,8 @@ PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); - + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); + PHPDBG_G(flags) &= ~PHPDBG_BP_MASK; PHPDBG_G(bp_count) = 0; @@ -742,7 +699,6 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], &class_name, &class_len, &class_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - phpdbg_breakmethod_t *brake; for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]); @@ -756,23 +712,23 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ } break; case PHPDBG_BREAK_FILE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP)) { - HashPosition position; - zend_llist *points; - + HashPosition position[2]; + HashTable *points; + phpdbg_writeln(SEPARATE); phpdbg_writeln("File Breakpoints:"); - 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)) { - zend_llist_position lposition; + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position[0]); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], (void**) &points, &position[0]) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position[0])) { phpdbg_breakfile_t *brake; - if ((brake = zend_llist_get_first_ex(points, &lposition))) { - do { - phpdbg_writeln("#%d\t\t%s:%lu", brake->id, brake->filename, brake->line); - } while ((brake = zend_llist_get_next_ex(points, &lposition))); + for (zend_hash_internal_pointer_reset_ex(points, &position[1]); + zend_hash_get_current_data_ex(points, (void**)&brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex(points, &position[1])) { + phpdbg_writeln("#%d\t\t%s:%lu", brake->id, brake->filename, brake->line); } } + } break; case PHPDBG_BREAK_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)) { diff --git a/phpdbg_bp.h b/phpdbg_bp.h index eb30e3ee25..84162ecf66 100644 --- a/phpdbg_bp.h +++ b/phpdbg_bp.h @@ -23,60 +23,73 @@ /* {{{ */ typedef struct _zend_op *phpdbg_opline_ptr_t; /* }}} */ +/* {{{ breakpoint base */ +typedef struct _phpdbg_breakbase_t { + int id; + zend_uchar type; + const char *name; +} phpdbg_breakbase_t; /* }}} */ + /** * Breakpoint file-based representation */ typedef struct _phpdbg_breakfile_t { + int id; + zend_uchar type; const char *filename; long line; - int id; } phpdbg_breakfile_t; /** * Breakpoint symbol-based representation */ typedef struct _phpdbg_breaksymbol_t { - const char *symbol; int id; + zend_uchar type; + const char *symbol; } phpdbg_breaksymbol_t; /** * Breakpoint method based representation */ typedef struct _phpdbg_breakmethod_t { + int id; + zend_uchar type; const char *class_name; size_t class_len; const char *func_name; size_t func_len; - int id; } phpdbg_breakmethod_t; /** * Breakpoint opline based representation */ typedef struct _phpdbg_breakline_t { + int id; + zend_uchar type; const char *name; zend_ulong opline; - int id; } phpdbg_breakline_t; /** * Breakpoint opcode based representation */ typedef struct _phpdbg_breakop_t { - zend_ulong hash; - const char *name; int id; + zend_uchar type; + const char *name; + zend_ulong hash; } phpdbg_breakop_t; /** * Breakpoint condition based representation */ typedef struct _phpdbg_breakcond_t { + int id; + zend_uchar type; 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); diff --git a/phpdbg_info.c b/phpdbg_info.c index 727e676778..f44d19211a 100644 --- a/phpdbg_info.c +++ b/phpdbg_info.c @@ -73,6 +73,11 @@ PHPDBG_INFO(vars) /* {{{ */ char *var; zval **data; + if (!EG(active_op_array)) { + phpdbg_error("No active op array!"); + return SUCCESS; + } + if (!EG(active_symbol_table)) { zend_rebuild_symbol_table(TSRMLS_C);