#include "phpdbg.h"
#include "phpdbg_prompt.h"
+#include "phpdbg_bp.h"
ZEND_DECLARE_MODULE_GLOBALS(phpdbg);
return SUCCESS;
} /* }}} */
-static void php_phpdbg_destroy_break(void *brake) /* {{{ */
+static void php_phpdbg_destroy_bp_file(void *brake) /* {{{ */
{
zend_llist_destroy((zend_llist*)brake);
} /* }}} */
+static void php_phpdbg_destroy_bp_symbol(void *brake) /* {{{ */
+{
+ efree(((phpdbg_breaksymbol_t*)brake)->symbol);
+} /* }}} */
+
static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */
{
- zend_hash_init(&PHPDBG_G(bp_files), 8, NULL, php_phpdbg_destroy_break, 0);
- zend_hash_init(&PHPDBG_G(bp_symbols), 8, NULL, php_phpdbg_destroy_break, 0);
+ zend_hash_init(&PHPDBG_G(bp_files), 8, NULL, php_phpdbg_destroy_bp_file, 0);
+ zend_hash_init(&PHPDBG_G(bp_symbols), 8, NULL, php_phpdbg_destroy_bp_symbol, 0);
return SUCCESS;
} /* }}} */
efree((char*)bp->filename);
} /* }}} */
-static void phpdbg_llist_breaksym_dtor(void *data) /* {{{ */
-{
- phpdbg_breaksymbol_t *bp = (phpdbg_breaksymbol_t*) data;
-
- efree((char*)bp->symbol);
-} /* }}} */
-
void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */
{
phpdbg_breakfile_t new_break;
zend_llist_add_element(break_files_ptr, &new_break);
} /* }}} */
-void phpdbg_set_breakpoint_symbol(const char *name, long opline_num TSRMLS_DC) /* {{{ */
+void phpdbg_set_breakpoint_symbol(const char *name TSRMLS_DC) /* {{{ */
{
- phpdbg_breaksymbol_t new_break;
- zend_llist *break_sym_ptr;
size_t name_len = strlen(name);
- new_break.symbol = estrndup(name, name_len + 1);
- new_break.opline_num = opline_num;
-
- PHPDBG_G(has_sym_bp) = 1;
+ if (!zend_hash_exists(&PHPDBG_G(bp_symbols), name, name_len)) {
+ phpdbg_breaksymbol_t new_break;
- if (zend_hash_find(&PHPDBG_G(bp_symbols),
- new_break.symbol, name_len, (void**)&break_sym_ptr) == FAILURE) {
- zend_llist break_syms;
+ PHPDBG_G(has_sym_bp) = 1;
- zend_llist_init(&break_syms, sizeof(phpdbg_breaksymbol_t),
- phpdbg_llist_breaksym_dtor, 0);
+ new_break.symbol = estrndup(name, name_len + 1);
+ new_break.id = PHPDBG_G(bp_count)++;
- zend_hash_update(&PHPDBG_G(bp_symbols),
- new_break.symbol, name_len, &break_syms, sizeof(zend_llist),
- (void**)&break_sym_ptr);
+ zend_hash_update(&PHPDBG_G(bp_symbols), new_break.symbol,
+ name_len, &new_break, sizeof(phpdbg_breaksymbol_t), NULL);
}
-
- new_break.id = PHPDBG_G(bp_count)++;
- zend_llist_add_element(break_sym_ptr, &new_break);
} /* }}} */
int phpdbg_find_breakpoint_file(zend_op_array *op_array TSRMLS_DC) /* {{{ */
int phpdbg_find_breakpoint_symbol(zend_function *fbc TSRMLS_DC) /* {{{ */
{
const char *fname;
- zend_llist *break_list;
+ phpdbg_breaksymbol_t *bp;
if (fbc->type != ZEND_USER_FUNCTION) {
return FAILURE;
if (!fname) {
fname = "main";
}
-
+
if (zend_hash_find(&PHPDBG_G(bp_symbols), fname, strlen(fname),
- (void**)&break_list) == SUCCESS) {
- printf("breakpoint reached!\n");
+ (void**)&bp) == SUCCESS) {
+ printf("Breakpoint #%d in %s() at %s\n", bp->id, bp->symbol,
+ zend_get_executed_filename(TSRMLS_C));
return SUCCESS;
}
*/
typedef struct _phpdbg_breaksymbol_t {
const char *symbol;
- long opline_num;
int id;
} phpdbg_breaksymbol_t;
void phpdbg_set_breakpoint_file(const char*, long TSRMLS_DC);
-void phpdbg_set_breakpoint_symbol(const char*, long TSRMLS_DC);
+void phpdbg_set_breakpoint_symbol(const char* TSRMLS_DC);
int phpdbg_find_breakpoint_file(zend_op_array* TSRMLS_DC);
int phpdbg_find_breakpoint_symbol(zend_function* TSRMLS_DC);
} else {
printf("Cannot compile while in execution\n");
}
-
+
return FAILURE;
} /* }}} */
phpdbg_set_breakpoint_file(resolved_name, line_num TSRMLS_CC);
} else {
char name[200];
- const char *opnum_pos = zend_memrchr(expr, '#', expr_len);
- long opline_num = opnum_pos ? strtol(opnum_pos+1, NULL, 0) : 0;
- size_t name_len = opnum_pos ? opnum_pos - expr : strlen(expr);
+ size_t name_len = strlen(expr);
+ name_len = MIN(name_len, 200);
memcpy(name, expr, name_len);
name[name_len] = 0;
- phpdbg_set_breakpoint_symbol(name, opline_num TSRMLS_CC);
+ phpdbg_set_breakpoint_symbol(name TSRMLS_CC);
}
return SUCCESS;
}
break;
- case PHPDBG_NEXT:
+ case PHPDBG_NEXT:
return PHPDBG_NEXT;
}
}
#endif
- if (PHPDBG_G(has_file_bp)
+ if (PHPDBG_G(has_file_bp)
&& phpdbg_find_breakpoint_file(execute_data->op_array TSRMLS_CC) == SUCCESS) {
while (phpdbg_interactive(0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
continue;
if (PHPDBG_G(has_sym_bp)) {
zend_execute_data *previous = execute_data->prev_execute_data;
- if (previous && (previous != execute_data)) {
- if (previous->opline) {
- if (previous->opline->opcode == ZEND_DO_FCALL || previous->opline->opcode == ZEND_DO_FCALL_BY_NAME) {
- if (phpdbg_find_breakpoint_symbol(previous->function_state.function TSRMLS_CC) == SUCCESS) {
- while (phpdbg_interactive(0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
- continue;
- }
- }
- }
- }
- }
+ if (previous && previous != execute_data && previous->opline) {
+ if (previous->opline->opcode == ZEND_DO_FCALL
+ || previous->opline->opcode == ZEND_DO_FCALL_BY_NAME) {
+ if (phpdbg_find_breakpoint_symbol(
+ previous->function_state.function TSRMLS_CC) == SUCCESS) {
+ while (phpdbg_interactive(0, NULL TSRMLS_CC) != PHPDBG_NEXT) {
+ continue;
+ }
+ }
+ }
+ }
}
-
+
PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);
-
+
phpdbg_print_opline(
execute_data TSRMLS_CC);