static PHP_MINIT_FUNCTION(phpdbg) {
ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL);
-
+
zend_execute_old = zend_execute_ex;
zend_execute_ex = phpdbg_execute_ex;
-
+
return SUCCESS;
}
static inline void php_phpdbg_destroy_break(void *brake) {
-
+
}
static PHP_RINIT_FUNCTION(phpdbg) {
- zend_hash_init(&PHPDBG_G(breaks), 8, NULL, php_phpdbg_destroy_break, 0);
-
- return SUCCESS;
+ zend_hash_init(&PHPDBG_G(break_files), 8, NULL, php_phpdbg_destroy_break, 0);
+ zend_hash_init(&PHPDBG_G(break_symbols), 8, NULL, php_phpdbg_destroy_break, 0);
+
+ return SUCCESS;
}
static PHP_RSHUTDOWN_FUNCTION(phpdbg) {
- zend_hash_destroy(&PHPDBG_G(breaks));
-
+ zend_hash_destroy(&PHPDBG_G(break_files));
+ zend_hash_destroy(&PHPDBG_G(break_symbols));
+
if (PHPDBG_G(exec)) {
efree(PHPDBG_G(exec));
}
-
+
if (PHPDBG_G(ops)) {
destroy_op_array(PHPDBG_G(ops) TSRMLS_CC);
efree(PHPDBG_G(ops));
#endif
ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
- HashTable breaks;
- char *exec; /* file to execute */
- size_t exec_len; /* size of exec */
- zend_op_array *ops; /* op_array */
- zval *retval; /* return value */
+ HashTable break_files;
+ HashTable break_symbols;
+ char *exec; /* file to execute */
+ size_t exec_len; /* size of exec */
+ zend_op_array *ops; /* op_array */
+ zval *retval; /* return value */
+ zend_bool has_breakpoint; /* breakpoint has been set */
ZEND_END_MODULE_GLOBALS(phpdbg)
#include "phpdbg_prompt.h"
return FAILURE;
}
}
-
+
EG(active_op_array) = PHPDBG_G(ops);
EG(return_value_ptr_ptr) = &PHPDBG_G(retval);
-
+
zend_try {
zend_execute(EG(active_op_array) TSRMLS_CC);
} zend_catch {
printf("Caught excetion in VM\n");
return FAILURE;
} zend_end_try();
-
+
return SUCCESS;
} else {
printf("Nothing to execute !");
return SUCCESS;
} /* }}} */
-static PHPDBG_COMMAND(break) { /* {{{ */
- return SUCCESS;
+static PHPDBG_COMMAND(break) /* {{{ */
+{
+ const char *line_pos = zend_memrchr(expr, ':', expr_len);
+
+ if (line_pos) {
+ long line_num = strtol(line_pos+1, NULL, 0);
+ phpdbg_breakfile_t new_break;
+ zend_llist break_files;
+
+ new_break.filename = estrndup(expr, line_pos - expr);
+ new_break.line = line_num;
+
+ PHPDBG_G(has_breakpoint) = 1;
+
+ if (zend_hash_find(&PHPDBG_G(break_files), new_break.filename, line_pos - expr, &break_files) == FAILURE) {
+ zend_llist_init(&break_files, sizeof(phpdbg_breakfile_t), NULL, 0);
+ }
+ zend_llist_add_element(&break_files, &new_break);
+ }
+
+ return SUCCESS;
} /* }}} */
static PHPDBG_COMMAND(quit) /* {{{ */
return FAILURE;
} /* }}} */
+void phpdbg_breakpoint(zend_op_array *op_array) /* {{{ */
+{
+ printf(">> %s\n", op_array->filename);
+} /* }}} */
+
void phpdbg_interactive(int argc, char **argv TSRMLS_DC) /* {{{ */
{
char cmd[PHPDBG_MAX_CMD];
#endif
printf("[OPLINE: %p]\n", execute_data->opline);
-
+
+ if (PHPDBG_G(has_breakpoint)) {
+ phpdbg_breakpoint(execute_data->op_array);
+ }
+
if ((ret = execute_data->opline->handler(execute_data TSRMLS_CC)) > 0) {
switch (ret) {
case 1:
phpdbg_command_handler_t handler; /* Command handler */
} phpdbg_command_t;
+
+/**
+ * Breakpoint file-based representation
+ */
+typedef struct _phpdbg_breakfile_t {
+ const char *filename;
+ long line;
+} phpdbg_breakfile_t;
+
+/**
+ * Breakpoint symbol-based representation
+ */
+typedef struct _phpdbg_breaksymbol_t {
+ const char *symbol;
+} phpdbg_breaksymbol_t;
+
/**
* Command Executor
*/