42static inline void _phpdbg_break_mapping(
int id,
HashTable *table)
48#define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table)
49#define PHPDBG_BREAK_UNMAPPING(id) \
50 zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id))
52#define PHPDBG_BREAK_INIT(b, t) do {\
53 memset(&b, 0, sizeof(b)); \
54 b.id = PHPDBG_G(bp_count)++; \
60static void phpdbg_file_breaks_dtor(
zval *
data)
68static void phpdbg_class_breaks_dtor(
zval *
data)
77static void phpdbg_opline_class_breaks_dtor(
zval *
data)
83static void phpdbg_opline_breaks_dtor(
zval *
data)
132 if (brake->id ==
id) {
133 char *new_str =
NULL;
135 switch (brake->type) {
142 zend_string_release(filename);
147 "%sbreak %s\n", *str,
153 "%sbreak %s::%s\n", *str,
179 zend_string_release(filename);
184 "%sbreak %s\n", *str,
208 *str, conditional->
param.
addr, conditional->code);
213 "%sbreak at %s if %s\n", *str, conditional->
param.
str, conditional->code);
218 "%sbreak at %s::%s if %s\n", *str,
229 zend_string_release(filename);
251 if ((*str) && !(*str)[0]) {
260 const char *original_path = path;
278 if (original_path[0] ==
'/') {
279 phpdbg_error(
"Cannot stat %s, it does not exist", original_path);
284 path = original_path;
287 }
else if (!(ssb.
sb.st_mode & (S_IFREG|
S_IFLNK))) {
288 phpdbg_error(
"Cannot set breakpoint in %s, it is not a regular file", path);
295 path_str = zend_string_init(path, path_len, 0);
297 if (!(broken = zend_hash_find_ptr(file_breaks, path_str))) {
301 broken = zend_hash_add_mem(file_breaks, path_str, &breaks,
sizeof(
HashTable));
304 if (!zend_hash_index_exists(broken, line_num)) {
306 new_break.filename =
estrndup(path, path_len);
307 new_break.
line = line_num;
340 zend_string_release(path_str);
345 phpdbg_debug(
"file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n",
file, filelen,
ZSTR_VAL(cur),
ZSTR_LEN(cur), filelen >
ZSTR_LEN(cur) ?
file[filelen -
ZSTR_LEN(cur) - 1] :
'?', filelen >
ZSTR_LEN(cur) ? memcmp(
file + filelen -
ZSTR_LEN(cur),
ZSTR_VAL(cur),
ZSTR_LEN(cur)) : 0);
348# define WIN32_PATH_CHECK file[filelen - ZSTR_LEN(cur) - 1] == '\\'
350# define WIN32_PATH_CHECK 0
425 phpdbg_notice(
"Breakpoint #%d added at %s", new_break.id, new_break.symbol);
438 size_t class_len =
strlen(class_name);
440 char *func_lcname, *class_lcname;
442 if (*class_name ==
'\\') {
455 if (!zend_hash_str_exists(class_table, func_lcname, func_len)) {
461 new_break.class_name =
estrndup(class_name, class_len);
466 zend_hash_str_update_mem(class_table, func_lcname, func_len, &new_break,
sizeof(
phpdbg_breakmethod_t));
487 new_break.name =
NULL;
488 new_break.
opline = opline;
506 }
else if (brake->func_name ==
NULL) {
515 opline_break.disabled = 0;
516 opline_break.hits = 0;
517 opline_break.id = brake->id;
519 opline_break.name =
NULL;
520 opline_break.
base = brake;
521 if (op_array->
scope) {
564 brake->
class_name && brake->func_name ?
"::" :
"",
565 brake->func_name ? brake->func_name :
"",
577 if (new_break->func_name ==
NULL) {
578 if (
EG(current_execute_data) ==
NULL) {
623 phpdbg_error(
"%s is not a user defined function, no oplines exist", new_break->func_name);
625 phpdbg_error(
"%s::%s is not a user defined method, no oplines exist", new_break->
class_name, new_break->func_name);
671 if (!(method_table = zend_hash_str_find_ptr(class_table, new_break.func_name, new_break.
func_len))) {
673 method_table = zend_hash_str_update_mem(class_table, new_break.func_name, new_break.
func_len, &method_breaks,
sizeof(
HashTable));
676 if (zend_hash_index_exists(method_table, opline)) {
678 efree((
char*)new_break.func_name);
723 if (zend_hash_index_exists(func_table, opline)) {
725 efree((
char*)new_break.func_name);
745 new_break.func_name =
NULL;
769 if (zend_hash_index_exists(file_table, opline)) {
829 uint32_t cops =
CG(compiler_options);
833 switch (param->
type) {
844 phpdbg_error(
"Invalid parameter type for conditional breakpoint");
855 param, &new_break.
param);
874 cops =
CG(compiler_options);
878 new_break.code =
estrndup(expr, expr_len);
882 "return ",
sizeof(
"return ")-1, expr, expr_len,
";",
sizeof(
";")-1);
884 zend_string_release(bp_code);
889 phpdbg_notice(
"Conditional breakpoint #%d added %s/%p", brake->id, brake->code, brake->
ops);
894 phpdbg_error(
"Failed to compile code for expression %s", expr);
895 efree((
char*)new_break.code);
899 CG(compiler_options) = cops;
908 phpdbg_create_conditional_break(
909 &new_break,
NULL, expr, expr_len, expr_hash);
922 condition = param->
next;
926 phpdbg_create_conditional_break(&new_break, param, condition->
str, condition->
len,
hash);
928 phpdbg_notice(
"Conditional break %s exists at the specified location", condition->
str);
948 if (
EG(current_execute_data) && (brake = zend_hash_index_find_ptr(breaks,
EG(current_execute_data)->opline->lineno))) {
967 return phpdbg_find_breakpoint_method(
ops);
970 if (
ops->function_name) {
976 zend_string_release(fname);
987 zend_string *class_lcname = zend_string_tolower(
ops->scope->name);
992 brake = zend_hash_find_ptr(class_table,
lcname);
994 zend_string_release(
lcname);
997 zend_string_release(class_lcname);
1027 switch (param->
type) {
1037 const char *str =
NULL;
1040 str =
ops->function_name ?
ZSTR_VAL(
ops->function_name) :
"main";
1044 return param->type == STR_PARAM || execute_data->opline - ops->opcodes == param->num;
1054 if (lengths[0] == lengths[1]) {
1072 if (lengths[0] == lengths[1] && memcmp(param->
method.
class,
ops->scope->name, lengths[0]) ==
SUCCESS) {
1076 if (lengths[0] == lengths[1] && memcmp(param->
method.
name,
ops->function_name, lengths[0]) ==
SUCCESS) {
1102 const zend_op *orig_opline =
EG(current_execute_data)->opline;
1104 zval *orig_retval =
EG(current_execute_data)->return_value;
1116 EG(no_extensions) = 1;
1128 EG(no_extensions) = 1;
1129 EG(current_execute_data)->opline = orig_opline;
1130 EG(current_execute_data)->func = orig_func;
1131 EG(current_execute_data)->return_value = orig_retval;
1153 (base = phpdbg_find_conditional_breakpoint(
execute_data))) {
1165 if ((base = phpdbg_find_breakpoint_symbol(
execute_data->func))) {
1183 if (base->disabled) {
1198 int type = brake->type;
1200 size_t name_len = 0L;
1205 if (zend_hash_num_elements(table) == 1) {
1215 if (zend_hash_num_elements(table) == 1) {
1287 switch (brake->type) {
1400 brake->disabled = 0;
1409 brake->disabled = 1;
1437 if (brake->id ==
id) {
1456 brake->id, brake->symbol,
1471 brake->id, brake->class_name, brake->
func_name,
1487 brake->id, brake->filename, brake->
line,
1501 brake->id, brake->filename, brake->
line,
1514 switch (brake->type) {
1540 brake->id, brake->
opline,
1569 phpdbg_out(
"Function opline Breakpoints:\n");
1575 brake->id, brake->func_name, brake->
opline_num,
1607 brake->id, brake->
param.
str, brake->code,
1613 brake->id, brake->param.str, brake->param.num, brake->code,
1619 brake->id, brake->param.method.class, brake->param.method.name, brake->code,
1625 brake->id, brake->param.method.class, brake->param.method.name, brake->param.num, brake->code,
1631 brake->id, brake->param.file.name, brake->param.file.line, brake->code,
1637 brake->id, brake->param.addr, brake->code,
1642 phpdbg_error(
"Invalid parameter type for conditional breakpoint");
1647 brake->id, brake->code,
1660 brake->id, brake->name,
file(string $filename, int $flags=0, $context=null)
fputs($stream, string $data, ?int $length=null)
const php_stream_filter_ops * ops
hash(string $algo, string $data, bool $binary=false, array $options=[])
#define php_stream_stat_path(path, ssb)
struct _php_stream_statbuf php_stream_statbuf
PHPAPI zend_string * php_addcslashes_str(const char *str, size_t len, const char *what, size_t what_len)
HashTable bp[PHPDBG_BREAK_TABLES]
#define PHPDBG_HAS_SYM_BP
#define PHPDBG_HAS_OPLINE_BP
#define PHPDBG_HAS_FUNCTION_OPLINE_BP
#define PHPDBG_HAS_FILE_OPLINE_BP
#define PHPDBG_HAS_METHOD_BP
#define PHPDBG_HAS_COND_BP
#define PHPDBG_HAS_METHOD_OPLINE_BP
#define PHPDBG_IN_COND_BP
#define PHPDBG_HAS_PENDING_FILE_BP
#define PHPDBG_IS_BP_ENABLED
#define PHPDBG_HAS_OPCODE_BP
#define PHPDBG_HAS_FILE_BP
#define PHPDBG_BREAK_INIT(b, t)
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakpoint(zend_execute_data *execute_data)
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey)
PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param)
PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline)
PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array)
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline)
#define PHPDBG_BREAK_UNMAPPING(id)
PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type)
PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num)
PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break)
PHPDBG_API void phpdbg_clear_breakpoints(void)
PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, bool output)
PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len)
PHPDBG_API void phpdbg_disable_breakpoints(void)
PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, zend_ulong line_num)
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle)
PHPDBG_API void phpdbg_reset_breakpoints(void)
PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake)
PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file)
PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline)
PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len)
PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline)
PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id)
PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id)
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase(zend_ulong id)
PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str)
PHPDBG_API void phpdbg_enable_breakpoints(void)
PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len)
PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline)
PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array)
#define PHPDBG_BREAK_MAPPING(id, table)
PHPDBG_API HashTable * phpdbg_resolve_pending_file_break_ex(const char *file, uint32_t filelen, zend_string *cur, HashTable *fileht)
PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name)
#define PHPDBG_BREAK_FUNCTION_OPLINE
#define PHPDBG_BREAK_COND
#define PHPDBG_BREAK_FILE_OPLINE
#define PHPDBG_BREAK_OPLINE
#define PHPDBG_BREAK_FILE_PENDING
struct _phpdbg_breakopline_t phpdbg_breakopline_t
#define PHPDBG_BREAK_METHOD
#define PHPDBG_BREAK_OPCODE
#define PHPDBG_BREAK_METHOD_OPLINE
struct _phpdbg_breakmethod_t phpdbg_breakmethod_t
struct _phpdbg_breakop_t phpdbg_breakop_t
struct _phpdbg_breakline_t phpdbg_breakline_t
struct _zend_op * phpdbg_opline_ptr_t
#define PHPDBG_BREAK_FILE
struct _phpdbg_breakbase_t phpdbg_breakbase_t
struct _phpdbg_breakcond_t phpdbg_breakcond_t
struct _phpdbg_breakfile_t phpdbg_breakfile_t
struct _phpdbg_breaksymbol_t phpdbg_breaksymbol_t
PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t *src, phpdbg_param_t *dest)
PHPDBG_API char * phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer)
PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param)
struct _phpdbg_param phpdbg_param_t
#define phpdbg_error(strfmt,...)
#define phpdbg_out(fmt,...)
#define phpdbg_asprintf(buf,...)
#define phpdbg_notice(strfmt,...)
#define phpdbg_debug(strfmt,...)
#define phpdbg_writeln(strfmt,...)
phpdbg_breakopline_t * base
struct _phpdbg_param::@330020305320302230147242007301032363271275050165 file
struct _phpdbg_param::@004226021353141374347100337026301377067143131166 method
zend_string * function_name
#define ZEND_EXTERN_MODULE_GLOBALS(module_name)
ZEND_API zend_array * zend_rebuild_symbol_table(void)
#define estrndup(s, length)
ZEND_API zend_op_array *(* zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position)
#define ZEND_USER_CODE(type)
#define ZEND_COMPILE_DEFAULT_FOR_EVAL
#define ZEND_USER_FUNCTION
struct _zend_op_array zend_op_array
@ ZEND_COMPILE_POSITION_AFTER_OPEN_TAG
#define ZEND_ACC_VARIADIC
ZEND_API uint32_t zend_get_executed_lineno(void)
ZEND_API const char * zend_get_executed_filename(void)
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
union _zend_function zend_function
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr)
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
#define ZEND_HASH_FOREACH_PTR(ht, _ptr)
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
#define zend_hash_get_current_data_ptr(ht)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr)
struct _zend_string zend_string
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
struct _zend_class_entry zend_class_entry
ZEND_API zend_ulong ZEND_FASTCALL zend_hash_func(const char *str, size_t len)
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define Z_ARRVAL_P(zval_p)
struct _zend_array HashTable
struct _zend_execute_data zend_execute_data
#define VCWD_REALPATH(path, real_path)
function(EX_VAR(opline->result.var))
ZEND_API const char *ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode)