|
|
|
@ -363,6 +363,15 @@ PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file) /* {{{ */ |
|
|
|
|
|
|
|
PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len) /* {{{ */ |
|
|
|
{ |
|
|
|
char *lcname; |
|
|
|
|
|
|
|
if (*name == '\\') { |
|
|
|
name++; |
|
|
|
name_len--; |
|
|
|
} |
|
|
|
|
|
|
|
lcname = zend_str_tolower_dup(name, name_len); |
|
|
|
|
|
|
|
if (!zend_hash_str_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { |
|
|
|
phpdbg_breaksymbol_t new_break; |
|
|
|
|
|
|
|
@ -371,7 +380,7 @@ PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len) |
|
|
|
PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_SYM); |
|
|
|
new_break.symbol = estrndup(name, name_len); |
|
|
|
|
|
|
|
zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], new_break.symbol, name_len, &new_break, sizeof(phpdbg_breaksymbol_t)); |
|
|
|
zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], lcname, name_len, &new_break, sizeof(phpdbg_breaksymbol_t)); |
|
|
|
|
|
|
|
phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" function=\"%s\"", "Breakpoint #%d added at %s", new_break.id, new_break.symbol); |
|
|
|
|
|
|
|
@ -379,6 +388,8 @@ PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len) |
|
|
|
} else { |
|
|
|
phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" function=\"%s\"", "Breakpoint exists at %s", name); |
|
|
|
} |
|
|
|
|
|
|
|
efree(lcname); |
|
|
|
} /* }}} */ |
|
|
|
|
|
|
|
PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name) /* {{{ */ |
|
|
|
@ -386,14 +397,22 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char |
|
|
|
HashTable class_breaks, *class_table; |
|
|
|
size_t class_len = strlen(class_name); |
|
|
|
size_t func_len = strlen(func_name); |
|
|
|
char *lcname = zend_str_tolower_dup(func_name, func_len); |
|
|
|
char *func_lcname, *class_lcname; |
|
|
|
|
|
|
|
if (*class_name == '\\') { |
|
|
|
class_name++; |
|
|
|
class_len--; |
|
|
|
} |
|
|
|
|
|
|
|
if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, class_len))) { |
|
|
|
func_lcname = zend_str_tolower_dup(func_name, func_len); |
|
|
|
class_lcname = zend_str_tolower_dup(class_name, class_len); |
|
|
|
|
|
|
|
if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len))) { |
|
|
|
zend_hash_init(&class_breaks, 8, NULL, phpdbg_class_breaks_dtor, 0); |
|
|
|
class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, class_len, &class_breaks, sizeof(HashTable)); |
|
|
|
class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len, &class_breaks, sizeof(HashTable)); |
|
|
|
} |
|
|
|
|
|
|
|
if (!zend_hash_str_exists(class_table, lcname, func_len)) { |
|
|
|
if (!zend_hash_str_exists(class_table, func_lcname, func_len)) { |
|
|
|
phpdbg_breakmethod_t new_break; |
|
|
|
|
|
|
|
PHPDBG_G(flags) |= PHPDBG_HAS_METHOD_BP; |
|
|
|
@ -404,7 +423,7 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char |
|
|
|
new_break.func_name = estrndup(func_name, func_len); |
|
|
|
new_break.func_len = func_len; |
|
|
|
|
|
|
|
zend_hash_str_update_mem(class_table, lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t)); |
|
|
|
zend_hash_str_update_mem(class_table, func_lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t)); |
|
|
|
|
|
|
|
phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" method=\"%s::%s\"", "Breakpoint #%d added at %s::%s", new_break.id, class_name, func_name); |
|
|
|
|
|
|
|
@ -413,7 +432,8 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char |
|
|
|
phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" method=\"%s::%s\"", "Breakpoint exists at %s::%s", class_name, func_name); |
|
|
|
} |
|
|
|
|
|
|
|
efree(lcname); |
|
|
|
efree(func_lcname); |
|
|
|
efree(class_lcname); |
|
|
|
} /* }}} */ |
|
|
|
|
|
|
|
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline) /* {{{ */ |
|
|
|
@ -572,6 +592,8 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break) /* { |
|
|
|
return SUCCESS; |
|
|
|
} /* }}} */ |
|
|
|
|
|
|
|
/* TODO ... method/function oplines need to be normalized (leading backslash, lowercase) and file oplines need to be resolved properly */ |
|
|
|
|
|
|
|
PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline) /* {{{ */ |
|
|
|
{ |
|
|
|
phpdbg_breakopline_t new_break; |
|
|
|
@ -872,8 +894,6 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ |
|
|
|
|
|
|
|
static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *fbc) /* {{{ */ |
|
|
|
{ |
|
|
|
const char *fname; |
|
|
|
size_t flen; |
|
|
|
zend_op_array *ops; |
|
|
|
|
|
|
|
if (fbc->type != ZEND_USER_FUNCTION) { |
|
|
|
@ -888,30 +908,33 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *f |
|
|
|
} |
|
|
|
|
|
|
|
if (ops->function_name) { |
|
|
|
fname = ZSTR_VAL(ops->function_name); |
|
|
|
flen = ZSTR_LEN(ops->function_name); |
|
|
|
phpdbg_breakbase_t *brake; |
|
|
|
zend_string *fname = zend_string_tolower(ops->function_name); |
|
|
|
|
|
|
|
brake = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname); |
|
|
|
|
|
|
|
zend_string_release(fname); |
|
|
|
return brake; |
|
|
|
} else { |
|
|
|
fname = "main"; |
|
|
|
flen = 4; |
|
|
|
return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], ZEND_STRL("main")); |
|
|
|
} |
|
|
|
|
|
|
|
return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname, flen); |
|
|
|
} /* }}} */ |
|
|
|
|
|
|
|
static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *ops) /* {{{ */ |
|
|
|
{ |
|
|
|
HashTable *class_table; |
|
|
|
phpdbg_breakbase_t *brake = NULL; |
|
|
|
zend_string *class_lcname = zend_string_tolower(ops->scope->name); |
|
|
|
|
|
|
|
if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], ops->scope->name))) { |
|
|
|
size_t lcname_len = ZSTR_LEN(ops->function_name); |
|
|
|
char *lcname = zend_str_tolower_dup(ZSTR_VAL(ops->function_name), lcname_len); |
|
|
|
if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname))) { |
|
|
|
zend_string *lcname = zend_string_tolower(ops->function_name); |
|
|
|
|
|
|
|
brake = zend_hash_str_find_ptr(class_table, lcname, lcname_len); |
|
|
|
brake = zend_hash_find_ptr(class_table, lcname); |
|
|
|
|
|
|
|
efree(lcname); |
|
|
|
zend_string_release(lcname); |
|
|
|
} |
|
|
|
|
|
|
|
zend_string_release(class_lcname); |
|
|
|
return brake; |
|
|
|
} /* }}} */ |
|
|
|
|
|
|
|
|