From: krakjoe Date: Mon, 11 Nov 2013 11:54:41 +0000 (+0000) Subject: break on opline X-Git-Tag: php-5.6.0alpha1~110^2~492 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=67dc98732ea2ff0edda1d5d1440a0e1d593aa949;p=php break on opline --- diff --git a/phpdbg.c b/phpdbg.c index bae33aab91..3aa8c03524 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -40,6 +40,7 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ pg->last_params_len = 0; pg->has_file_bp = 0; pg->has_sym_bp = 0; + pg->has_opline_bp = 0; } /* }}} */ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ @@ -66,7 +67,8 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { 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); - + zend_hash_init(&PHPDBG_G(bp_oplines), 8, NULL, NULL, 0); + return SUCCESS; } /* }}} */ @@ -74,7 +76,8 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ { zend_hash_destroy(&PHPDBG_G(bp_files)); zend_hash_destroy(&PHPDBG_G(bp_symbols)); - + zend_hash_destroy(&PHPDBG_G(bp_oplines)); + if (PHPDBG_G(exec)) { efree(PHPDBG_G(exec)); } diff --git a/phpdbg.h b/phpdbg.h index e8c02da70a..8adc69cf4f 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -50,20 +50,22 @@ typedef struct _phpdbg_command_t phpdbg_command_t; ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable bp_files; HashTable bp_symbols; - char *exec; /* file to execute */ - size_t exec_len; /* size of exec */ - zend_op_array *ops; /* op_array */ - zval *retval; /* return value */ - int bp_count; /* breakpoint count */ - int stepping; /* stepping */ - int vmret; /* return from last opcode handler execution */ - zend_bool has_file_bp; /* file-based breakpoint has been set */ - zend_bool has_sym_bp; /* symbol-based breakpoint has been set */ - zend_bool quitting; /* quitting flag */ - int quiet; /* quiet */ - phpdbg_command_t *last; /* last command */ - const char *last_params;/* last expression */ - size_t last_params_len; /* last expression length */ + HashTable bp_oplines; + char *exec; /* file to execute */ + size_t exec_len; /* size of exec */ + zend_op_array *ops; /* op_array */ + zval *retval; /* return value */ + int bp_count; /* breakpoint count */ + int stepping; /* stepping */ + int vmret; /* return from last opcode handler execution */ + zend_bool has_file_bp; /* file-based breakpoint has been set */ + zend_bool has_sym_bp; /* symbol-based breakpoint has been set */ + zend_bool has_opline_bp; /* opline-based breakpoint has been set */ + zend_bool quitting; /* quitting flag */ + int quiet; /* quiet */ + phpdbg_command_t *last; /* last command */ + const char *last_params; /* last expression */ + size_t last_params_len; /* last expression length */ ZEND_END_MODULE_GLOBALS(phpdbg) #endif /* PHPDBG_H */ diff --git a/phpdbg_bp.c b/phpdbg_bp.c index 236c0b4e0e..b8b2d35113 100644 --- a/phpdbg_bp.c +++ b/phpdbg_bp.c @@ -59,7 +59,7 @@ void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{ zend_llist_add_element(break_files_ptr, &new_break); printf( - "Breakpoint #%d added at %s:%d\n", new_break.id, new_break.filename, new_break.line); + "Breakpoint #%d added at %s:%ld\n", new_break.id, new_break.filename, new_break.line); } /* }}} */ void phpdbg_set_breakpoint_symbol(const char *name TSRMLS_DC) /* {{{ */ @@ -83,6 +83,29 @@ void phpdbg_set_breakpoint_symbol(const char *name TSRMLS_DC) /* {{{ */ } } /* }}} */ +void phpdbg_set_breakpoint_opline(const char *name TSRMLS_DC) /* {{{ */ +{ + size_t name_len = strlen(name); + + if (!zend_hash_exists(&PHPDBG_G(bp_oplines), name, name_len)) { + phpdbg_breakline_t new_break; + + PHPDBG_G(has_opline_bp) = 1; + + sscanf( + name, "%x", &new_break.opline); + + new_break.id = PHPDBG_G(bp_count)++; + + zend_hash_update(&PHPDBG_G(bp_oplines), name, + name_len, &new_break, sizeof(phpdbg_breakline_t), NULL); + + printf("Breakpoint #%d added at 0x%x\n", new_break.id, new_break.opline); + } else { + printf("Breakpoint exists at %s\n", name); + } +} /* }}} */ + int phpdbg_find_breakpoint_file(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { size_t name_len = strlen(op_array->filename); @@ -130,3 +153,25 @@ int phpdbg_find_breakpoint_symbol(zend_function *fbc TSRMLS_DC) /* {{{ */ return FAILURE; } /* }}} */ + +int phpdbg_find_breakpoint_opline(void *opline TSRMLS_DC) /* {{{ */ +{ + char *opstring = NULL; + size_t opstring_len; + phpdbg_breakline_t *bp; + + opstring_len = asprintf( + &opstring, "0x%x", (unsigned int) opline); + + if (zend_hash_find(&PHPDBG_G(bp_oplines), opstring, opstring_len, + (void**)&bp) == SUCCESS) { + printf("Breakpoint #%d in 0x%x at %s\n", bp->id, bp->opline, + zend_get_executed_filename(TSRMLS_C)); + free(opstring); + + return SUCCESS; + } + + free(opstring); + return FAILURE; +} /* }}} */ diff --git a/phpdbg_bp.h b/phpdbg_bp.h index 104e9d0c1d..3ab00048d9 100644 --- a/phpdbg_bp.h +++ b/phpdbg_bp.h @@ -37,10 +37,20 @@ typedef struct _phpdbg_breaksymbol_t { int id; } phpdbg_breaksymbol_t; +/** + * Breakpoint opline based representation + */ +typedef struct _phpdbg_breakline_t { + zend_uint opline; + int id; +} phpdbg_breakline_t; + void phpdbg_set_breakpoint_file(const char*, long TSRMLS_DC); void phpdbg_set_breakpoint_symbol(const char* TSRMLS_DC); +void phpdbg_set_breakpoint_opline(const char* TSRMLS_DC); int phpdbg_find_breakpoint_file(zend_op_array* TSRMLS_DC); int phpdbg_find_breakpoint_symbol(zend_function* TSRMLS_DC); +int phpdbg_find_breakpoint_opline(void * TSRMLS_DC); #endif /* PHPDBG_BP_H */ diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 283b66bebd..9ab039e476 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -80,7 +80,7 @@ static PHPDBG_COMMAND(compile) /* {{{ */ { if (PHPDBG_G(exec)) { if (PHPDBG_G(ops)) { - printf("Destroying compiled opcodes\n"); + printf("Destroying previously compiled opcodes\n"); destroy_op_array(PHPDBG_G(ops) TSRMLS_CC); efree(PHPDBG_G(ops)); PHPDBG_G(ops)=NULL; @@ -96,6 +96,8 @@ static PHPDBG_COMMAND(compile) /* {{{ */ static PHPDBG_COMMAND(step) /* {{{ */ { PHPDBG_G(stepping) = atoi(expr); + printf( + "Stepping %s\n", PHPDBG_G(stepping) ? "on" : "off"); return SUCCESS; } /* }}} */ @@ -186,7 +188,10 @@ static PHPDBG_COMMAND(print) /* {{{ */ printf("%s\n", expr); return SUCCESS; } - +#ifdef HAVE_READLINE_H + printf("HAVE READLINE\n"); +#endif + printf("--------------------------------------\n"); printf("Execution Context Information:\n"); printf("Exec\t\t%s\n", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none"); @@ -282,14 +287,18 @@ static PHPDBG_COMMAND(break) /* {{{ */ return FAILURE; } } else { - char name[200]; - size_t name_len = strlen(expr); + if (expr_len > 2 && expr[0] == '0' && expr[1] == 'x') { + phpdbg_set_breakpoint_opline(expr TSRMLS_CC); + } else { + char name[200]; + size_t name_len = strlen(expr); - name_len = MIN(name_len, 200); - memcpy(name, expr, name_len); - name[name_len] = 0; + name_len = MIN(name_len, 200); + memcpy(name, expr, name_len); + name[name_len] = 0; - phpdbg_set_breakpoint_symbol(name TSRMLS_CC); + phpdbg_set_breakpoint_symbol(name TSRMLS_CC); + } } return SUCCESS; @@ -403,7 +412,7 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le while (command && command->name) { if (command->name_len == expr_len && memcmp(cmd, command->name, expr_len) == 0) { - PHPDBG_G(last) = command; + PHPDBG_G(last) = (phpdbg_command_t*) command; PHPDBG_G(last_params) = params; PHPDBG_G(last_params_len) = cmd_len - expr_len; return command->handler(params, cmd_len - expr_len TSRMLS_CC); @@ -503,6 +512,13 @@ zend_vm_enter: } } } + + if (PHPDBG_G(has_opline_bp) + && phpdbg_find_breakpoint_opline(execute_data->opline TSRMLS_CC) == SUCCESS) { + while (phpdbg_interactive(TSRMLS_C) != PHPDBG_NEXT) { + continue; + } + } PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);