new_break.name = NULL;
new_break.opline = opline;
new_break.id = PHPDBG_G(bp_count)++;
+ new_break.type = 0; /* no special type */
zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline,
&new_break, sizeof(phpdbg_breakline_t), NULL);
if (op_array->last < brake->opline) {
if (brake->class_name == NULL) {
phpdbg_error("There are only %d oplines in function %s (breaking at opline %d impossible)", op_array->last, brake->func_name, brake->opline);
+ } else if (brake->func_name == NULL) {
+ phpdbg_error("There are only %d oplines in file %s (breaking at opline %d impossible)", op_array->last, brake->class_name, brake->opline);
} else {
phpdbg_error("There are only %d oplines in method %s::%s (breaking at opline %d impossible)", op_array->last, brake->class_name, brake->func_name, brake->opline);
}
opline_break.id = brake->id;
opline_break.opline = (zend_ulong)(op_array->opcodes + brake->opline);
opline_break.name = NULL;
+ if (op_array->scope) {
+ opline_break.type = PHPDBG_BREAK_METHOD_OPLINE;
+ } else if (op_array->function_name) {
+ opline_break.type = PHPDBG_BREAK_FUNCTION_OPLINE;
+ } else {
+ opline_break.type = PHPDBG_BREAK_FILE_OPLINE;
+ }
PHPDBG_G(flags) |= PHPDBG_HAS_OPLINE_BP;
HashTable *func_table = EG(function_table);
zend_function *func;
+ if (new_break->func_name == NULL) {
+ /* no idea yet ...; currently only settable before including of file */
+ return FAILURE;
+ }
+
if (new_break->class_name != NULL) {
zend_class_entry **ce;
if (zend_hash_find(EG(class_table), new_break->class_name, new_break->class_len + 1, (void **)&ce) == FAILURE) {
}
if (zend_hash_find(func_table, new_break->func_name, new_break->func_len + 1, (void **)&func) == FAILURE) {
- if (new_break->class_name != NULL) {
+ if (new_break->class_name != NULL && new_break->func_name != NULL) {
phpdbg_error("Method %s doesn't exist in class %s", new_break->func_name, new_break->class_name);
}
return FAILURE;
zend_hash_index_update(func_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
}
+PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, int opline TSRMLS_DC) /* {{{ */
+{
+ phpdbg_breakopline_t new_break;
+ HashTable file_breaks, *file_table;
+
+ new_break.func_len = 0;
+ new_break.func_name = NULL;
+ new_break.class_len = strlen(file);
+ new_break.class_name = estrndup(file, new_break.class_len);
+ new_break.opline = opline;
+ new_break.id = PHPDBG_G(bp_count)++;
+
+ switch (phpdbg_resolve_opline_break(&new_break TSRMLS_CC)) {
+ case FAILURE:
+ phpdbg_notice("Pending breakpoint #%d at %s:%d", new_break.id, new_break.class_name, new_break.opline);
+ break;
+
+ case SUCCESS:
+ phpdbg_notice("Breakpoint #%d added at %s:%d", new_break.id, new_break.class_name, new_break.opline);
+ break;
+
+ case 2:
+ return;
+ }
+
+ if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, (void **)&file_table) == FAILURE) {
+ zend_hash_init(&file_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0);
+ zend_hash_update(
+ &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE],
+ new_break.class_name,
+ new_break.class_len,
+ (void **)&file_breaks, sizeof(HashTable), (void **)&file_table);
+ }
+
+ if (zend_hash_index_exists(file_table, opline)) {
+ phpdbg_notice("Breakpoint already exists for %s:%d", new_break.class_name, opline);
+ efree(new_break.class_name);
+ PHPDBG_G(bp_count)--;
+ return;
+ }
+
+ PHPDBG_G(flags) |= PHPDBG_HAS_FUNCTION_OPLINE_BP;
+
+ zend_hash_index_update(file_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
+}
+
PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len TSRMLS_DC) /* {{{ */
{
phpdbg_breakop_t new_break;
PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */
{
+ if (PHPDBG_G(flags) & PHPDBG_HAS_METHOD_OPLINE_BP) {
+ HashPosition position[3];
+ phpdbg_breakopline_t *brake;
+ HashTable *class_table, *method_table;
+
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], (void**) &class_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0])) {
+ for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]);
+ zend_hash_get_current_data_ex(class_table, (void**) &method_table, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(class_table, &position[1])) {
+ for (zend_hash_internal_pointer_reset_ex(method_table, &position[2]);
+ zend_hash_get_current_data_ex(method_table, (void**) &brake, &position[2]) == SUCCESS;
+ zend_hash_move_forward_ex(method_table, &position[2])) {
+ if (brake->id == num) {
+ zend_hash_index_del(method_table, brake->opline);
+ }
+ }
+ }
+ }
+ }
+
+ if (PHPDBG_G(flags) & PHPDBG_HAS_FUNCTION_OPLINE_BP) {
+ HashPosition position[2];
+ phpdbg_breakopline_t *brake;
+ HashTable *function_table;
+
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], (void**) &function_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0])) {
+ for (zend_hash_internal_pointer_reset_ex(function_table, &position[1]);
+ zend_hash_get_current_data_ex(function_table, (void**) &brake, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(function_table, &position[1])) {
+ if (brake->id == num) {
+ zend_hash_index_del(function_table, brake->opline);
+ }
+ }
+ }
+ }
+
+ if (PHPDBG_G(flags) & PHPDBG_HAS_FILE_OPLINE_BP) {
+ HashPosition position[2];
+ phpdbg_breakopline_t *brake;
+ HashTable *file_table;
+
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], (void**) &file_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0])) {
+ for (zend_hash_internal_pointer_reset_ex(file_table, &position[1]);
+ zend_hash_get_current_data_ex(file_table, (void**) &brake, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(file_table, &position[1])) {
+ if (brake->id == num) {
+ zend_hash_index_del(file_table, brake->opline);
+ }
+ }
+ }
+ }
+
+ 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);
+ return;
+ }
+ }
+ }
+
if (PHPDBG_G(flags) & PHPDBG_HAS_SYM_BP) {
HashPosition position;
phpdbg_breaksymbol_t *brake;
}
}
- 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);
- 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_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)) {
- phpdbg_writeln("#%d\t\t%#lx", brake->id, brake->opline);
+ switch (brake->type) {
+ case PHPDBG_BREAK_METHOD_OPLINE:
+ case PHPDBG_BREAK_FUNCTION_OPLINE:
+ case PHPDBG_BREAK_FILE_OPLINE:
+ phpdbg_writeln("#%d\t\t%#lx\t\t(%s breakpoint)", brake->id, brake->opline,
+ brake->type == PHPDBG_BREAK_METHOD_OPLINE?"method":
+ brake->type == PHPDBG_BREAK_FUNCTION_OPLINE?"function":
+ brake->type == PHPDBG_BREAK_FILE_OPLINE?"file":
+ "--- error ---"
+ );
+ break;
+
+ default:
+ phpdbg_writeln("#%d\t\t%#lx", brake->id, brake->opline);
+ break;
+ }
+ }
+ } break;
+
+ case PHPDBG_BREAK_METHOD_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_METHOD_OPLINE_BP)) {
+ HashPosition position[3];
+ HashTable *class_table, *method_table;
+ char *class_name = NULL, *method_name = NULL;
+ zend_uint class_len = 0, method_len = 0;
+ zend_ulong class_idx = 0L, method_idx = 0L;
+
+ phpdbg_writeln(SEPARATE);
+ phpdbg_writeln("Method opline Breakpoints:");
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], (void**) &class_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0])) {
+
+ if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE],
+ &class_name, &class_len, &class_idx, 0, &position[0]) == HASH_KEY_IS_STRING) {
+
+ for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]);
+ zend_hash_get_current_data_ex(class_table, (void**) &method_table, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(class_table, &position[1])) {
+
+ if (zend_hash_get_current_key_ex(class_table,
+ &method_name, &method_len, &method_idx, 0, &position[0]) == HASH_KEY_IS_STRING) {
+
+ phpdbg_breakopline_t *brake;
+
+ for (zend_hash_internal_pointer_reset_ex(method_table, &position[2]);
+ zend_hash_get_current_data_ex(method_table, (void**)&brake, &position[2]) == SUCCESS;
+ zend_hash_move_forward_ex(method_table, &position[2])) {
+ phpdbg_writeln("#%d\t\t%s::%s opline %d", brake->id, brake->class_name, brake->func_name, brake->opline);
+ }
+ }
+ }
+ }
+
+ }
+ } break;
+
+ case PHPDBG_BREAK_FUNCTION_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FUNCTION_OPLINE_BP)) {
+ HashPosition position[2];
+ HashTable *function_table;
+ char *function_name = NULL;
+ zend_uint function_len = 0;
+ zend_ulong function_idx = 0L;
+
+ phpdbg_writeln(SEPARATE);
+ phpdbg_writeln("Function opline Breakpoints:");
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], (void**) &function_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0])) {
+
+ if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE],
+ &function_name, &function_len, &function_idx, 0, &position[0]) == HASH_KEY_IS_STRING) {
+
+ phpdbg_breakopline_t *brake;
+
+ for (zend_hash_internal_pointer_reset_ex(function_table, &position[1]);
+ zend_hash_get_current_data_ex(function_table, (void**)&brake, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(function_table, &position[1])) {
+ phpdbg_writeln("#%d\t\t%s opline %d", brake->id, brake->func_name, brake->opline);
+ }
+ }
+
+ }
+ } break;
+
+ case PHPDBG_BREAK_FILE_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_OPLINE_BP)) {
+ HashPosition position[2];
+ HashTable *file_table;
+ char *file_name = NULL;
+ zend_uint file_len = 0;
+ zend_ulong file_idx = 0L;
+
+ phpdbg_writeln(SEPARATE);
+ phpdbg_writeln("File opline Breakpoints:");
+ for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0]);
+ zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], (void**) &file_table, &position[0]) == SUCCESS;
+ zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0])) {
+
+ if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE],
+ &file_name, &file_len, &file_idx, 0, &position[0]) == HASH_KEY_IS_STRING) {
+
+ phpdbg_breakopline_t *brake;
+
+ for (zend_hash_internal_pointer_reset_ex(file_table, &position[1]);
+ zend_hash_get_current_data_ex(file_table, (void**)&brake, &position[1]) == SUCCESS;
+ zend_hash_move_forward_ex(file_table, &position[1])) {
+ phpdbg_writeln("#%d\t\t%s opline %d", brake->id, brake->class_name, brake->opline);
+ }
+ }
+
}
} break;
} break;
}
} /* }}} */
-