Browse Source

break on opline

pull/550/head
krakjoe 12 years ago
parent
commit
67dc98732e
  1. 7
      phpdbg.c
  2. 30
      phpdbg.h
  3. 47
      phpdbg_bp.c
  4. 10
      phpdbg_bp.h
  5. 34
      phpdbg_prompt.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

@ -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

@ -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

@ -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 */

34
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);

Loading…
Cancel
Save