mirror of
https://github.com/php/php-src.git
synced 2026-03-30 04:02:19 +02:00
break on opline
This commit is contained in:
7
phpdbg.c
7
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));
|
||||
}
|
||||
|
||||
30
phpdbg.h
30
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 */
|
||||
|
||||
47
phpdbg_bp.c
47
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;
|
||||
} /* }}} */
|
||||
|
||||
10
phpdbg_bp.h
10
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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user