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) /* {{{ */
{
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;
} /* }}} */
{
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));
}
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 */
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) /* {{{ */
}
} /* }}} */
+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);
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;
+} /* }}} */
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 */
{
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;
static PHPDBG_COMMAND(step) /* {{{ */
{
PHPDBG_G(stepping) = atoi(expr);
+ printf(
+ "Stepping %s\n", PHPDBG_G(stepping) ? "on" : "off");
return SUCCESS;
} /* }}} */
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");
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;
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);
}
}
}
+
+ 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);