mirror of
https://github.com/php/php-src.git
synced 2025-08-19 17:04:47 +02:00
Several fixes and cleanups on opline num support
This commit is contained in:
parent
2e7c695c05
commit
25f2d4eca1
4 changed files with 145 additions and 62 deletions
7
phpdbg.c
7
phpdbg.c
|
@ -135,6 +135,7 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0);
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
||||||
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, NULL, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, NULL, 0);
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0);
|
||||||
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
||||||
|
@ -150,6 +151,9 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
||||||
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
||||||
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]);
|
||||||
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]);
|
||||||
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]);
|
||||||
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
||||||
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]);
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]);
|
||||||
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
||||||
|
@ -241,6 +245,9 @@ static PHP_FUNCTION(phpdbg_clear)
|
||||||
{
|
{
|
||||||
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
||||||
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
||||||
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]);
|
||||||
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]);
|
||||||
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]);
|
||||||
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
||||||
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
||||||
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]);
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]);
|
||||||
|
|
64
phpdbg.h
64
phpdbg.h
|
@ -88,37 +88,41 @@
|
||||||
#define PHPDBG_BREAK_OPCODE 5
|
#define PHPDBG_BREAK_OPCODE 5
|
||||||
#define PHPDBG_BREAK_FUNCTION_OPLINE 6
|
#define PHPDBG_BREAK_FUNCTION_OPLINE 6
|
||||||
#define PHPDBG_BREAK_METHOD_OPLINE 7
|
#define PHPDBG_BREAK_METHOD_OPLINE 7
|
||||||
#define PHPDBG_BREAK_TABLES 8/* }}} */
|
#define PHPDBG_BREAK_FILE_OPLINE 8
|
||||||
|
#define PHPDBG_BREAK_TABLES 9 /* }}} */
|
||||||
|
|
||||||
/* {{{ flags */
|
/* {{{ flags */
|
||||||
#define PHPDBG_HAS_FILE_BP (1<<1)
|
#define PHPDBG_HAS_FILE_BP (1<<1)
|
||||||
#define PHPDBG_HAS_SYM_BP (1<<2)
|
#define PHPDBG_HAS_SYM_BP (1<<2)
|
||||||
#define PHPDBG_HAS_OPLINE_BP (1<<3)
|
#define PHPDBG_HAS_OPLINE_BP (1<<3)
|
||||||
#define PHPDBG_HAS_METHOD_BP (1<<4)
|
#define PHPDBG_HAS_METHOD_BP (1<<4)
|
||||||
#define PHPDBG_HAS_COND_BP (1<<5)
|
#define PHPDBG_HAS_COND_BP (1<<5)
|
||||||
#define PHPDBG_HAS_OPCODE_BP (1<<6)
|
#define PHPDBG_HAS_OPCODE_BP (1<<6)
|
||||||
#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP)
|
#define PHPDBG_HAS_FUNCTION_OPLINE_BP (1<<7)
|
||||||
|
#define PHPDBG_HAS_METHOD_OPLINE_BP (1<<8)
|
||||||
|
#define PHPDBG_HAS_FILE_OPLINE_BP (1<<9)
|
||||||
|
#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP|PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP)
|
||||||
|
|
||||||
#define PHPDBG_IN_COND_BP (1<<7)
|
#define PHPDBG_IN_COND_BP (1<<8)
|
||||||
#define PHPDBG_IN_EVAL (1<<8)
|
#define PHPDBG_IN_EVAL (1<<9)
|
||||||
|
|
||||||
#define PHPDBG_IS_STEPPING (1<<9)
|
#define PHPDBG_IS_STEPPING (1<<10)
|
||||||
#define PHPDBG_IS_QUIET (1<<10)
|
#define PHPDBG_IS_QUIET (1<<11)
|
||||||
#define PHPDBG_IS_QUITTING (1<<11)
|
#define PHPDBG_IS_QUITTING (1<<12)
|
||||||
#define PHPDBG_IS_COLOURED (1<<12)
|
#define PHPDBG_IS_COLOURED (1<<13)
|
||||||
#define PHPDBG_IS_CLEANING (1<<13)
|
#define PHPDBG_IS_CLEANING (1<<14)
|
||||||
|
|
||||||
#define PHPDBG_IN_UNTIL (1<<14)
|
#define PHPDBG_IN_UNTIL (1<<15)
|
||||||
#define PHPDBG_IN_FINISH (1<<15)
|
#define PHPDBG_IN_FINISH (1<<16)
|
||||||
#define PHPDBG_IN_LEAVE (1<<16)
|
#define PHPDBG_IN_LEAVE (1<<17)
|
||||||
#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL|PHPDBG_IN_FINISH|PHPDBG_IN_LEAVE)
|
#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL|PHPDBG_IN_FINISH|PHPDBG_IN_LEAVE)
|
||||||
|
|
||||||
#define PHPDBG_IS_REGISTERED (1<<17)
|
#define PHPDBG_IS_REGISTERED (1<<18)
|
||||||
#define PHPDBG_IS_STEPONEVAL (1<<18)
|
#define PHPDBG_IS_STEPONEVAL (1<<19)
|
||||||
#define PHPDBG_IS_INITIALIZING (1<<19)
|
#define PHPDBG_IS_INITIALIZING (1<<20)
|
||||||
#define PHPDBG_IS_SIGNALED (1<<20)
|
#define PHPDBG_IS_SIGNALED (1<<21)
|
||||||
#define PHPDBG_IS_INTERACTIVE (1<<21)
|
#define PHPDBG_IS_INTERACTIVE (1<<22)
|
||||||
#define PHPDBG_IS_BP_ENABLED (1<<22)
|
#define PHPDBG_IS_BP_ENABLED (1<<23)
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED)
|
# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED)
|
||||||
|
@ -144,8 +148,14 @@
|
||||||
/* {{{ structs */
|
/* {{{ structs */
|
||||||
typedef union _phpdbg_btree phpdbg_btree;
|
typedef union _phpdbg_btree phpdbg_btree;
|
||||||
union _phpdbg_btree {
|
union _phpdbg_btree {
|
||||||
phpdbg_btree *branches[2];
|
phpdbg_btree *branches[2];
|
||||||
zend_op_array *op_array;
|
struct {
|
||||||
|
char *func_name;
|
||||||
|
zend_uint func_len;
|
||||||
|
char *class_name;
|
||||||
|
zend_uint class_len;
|
||||||
|
zend_uint last;
|
||||||
|
} info;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
|
ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
|
||||||
|
|
135
phpdbg_bp.c
135
phpdbg_bp.c
|
@ -53,8 +53,12 @@ static void phpdbg_opline_breaks_dtor(void *data) /* {{{ */
|
||||||
{
|
{
|
||||||
phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) data;
|
phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) data;
|
||||||
|
|
||||||
efree((char*)bp->class_name);
|
if (bp->class_name) {
|
||||||
efree((char*)bp->func_name);
|
efree((char*)bp->class_name);
|
||||||
|
}
|
||||||
|
if (bp->func_name) {
|
||||||
|
efree((char*)bp->func_name);
|
||||||
|
}
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
|
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
|
||||||
|
@ -284,7 +288,21 @@ PHPDBG_API void phpdbg_save_oplines(zend_op_array *op_array TSRMLS_DC) {
|
||||||
} while (i--);
|
} while (i--);
|
||||||
}
|
}
|
||||||
|
|
||||||
(*branch)->op_array = op_array;
|
if (((*branch)->info.func_name = op_array->function_name)) {
|
||||||
|
(*branch)->info.func_len = strlen(op_array->function_name);
|
||||||
|
if (op_array->scope) {
|
||||||
|
(*branch)->info.class_name = op_array->scope->name;
|
||||||
|
(*branch)->info.class_len = op_array->scope->name_length;
|
||||||
|
} else {
|
||||||
|
(*branch)->info.class_name = NULL;
|
||||||
|
(*branch)->info.class_len = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*branch)->info.func_len = 0;
|
||||||
|
(*branch)->info.class_name = op_array->filename;
|
||||||
|
(*branch)->info.class_len = strlen(op_array->filename);
|
||||||
|
}
|
||||||
|
(*branch)->info.last = op_array->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ */
|
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ */
|
||||||
|
@ -300,75 +318,102 @@ PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{
|
||||||
int i = sizeof(void *) * 8 - 1, last_superior_i = -1;
|
int i = sizeof(void *) * 8 - 1, last_superior_i = -1;
|
||||||
phpdbg_btree *branch = PHPDBG_G(opline_btree);
|
phpdbg_btree *branch = PHPDBG_G(opline_btree);
|
||||||
HashTable *insert = &PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE];
|
HashTable *insert = &PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE];
|
||||||
HashTable func_breaks, *func_table;
|
HashTable func_breaks, *func_table = EG(function_table);
|
||||||
|
zend_ulong opcodes = 0;
|
||||||
|
|
||||||
|
/* get highest opcodes root lower than or eqal to opline */
|
||||||
|
#define CHOOSE_BRANCH(n) \
|
||||||
|
opcodes = (opcodes << 1) + !!(n); \
|
||||||
|
branch = branch->branches[!!(n)];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
/* an impossible branch was found if: */
|
||||||
if ((opline >> i) % 2 == 0 && !branch->branches[0]) {
|
if ((opline >> i) % 2 == 0 && !branch->branches[0]) {
|
||||||
|
/* there's no lower branch than opline */
|
||||||
if (last_superior_i == -1) {
|
if (last_superior_i == -1) {
|
||||||
goto error;
|
phpdbg_error("No opline could be found at 0x%lx", opline);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
/* reset state */
|
||||||
branch = PHPDBG_G(opline_btree);
|
branch = PHPDBG_G(opline_btree);
|
||||||
|
opcodes = 0;
|
||||||
i = sizeof(void *) * 8 - 1;
|
i = sizeof(void *) * 8 - 1;
|
||||||
|
/* follow branch according to bits in opline until the last lower branch before the impossible branch */
|
||||||
do {
|
do {
|
||||||
branch = branch->branches[(opline >> i) % 2 == 1 && branch->branches[1]];
|
CHOOSE_BRANCH((opline >> i) % 2 == 1 && branch->branches[1]);
|
||||||
} while (i-- > last_superior_i);
|
} while (--i > last_superior_i);
|
||||||
branch = branch->branches[0];
|
/* use now the lower branch of which we can be sure that it contains only branches lower than opline */
|
||||||
|
CHOOSE_BRANCH(0);
|
||||||
|
/* and choose the highest possible branch in the branch containing only branches lower than opline */
|
||||||
while (i--) {
|
while (i--) {
|
||||||
branch = branch->branches[branch->branches[1] != NULL];
|
CHOOSE_BRANCH(branch->branches[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* follow branch according to bits in opline until having found an impossible branch */
|
||||||
if ((opline >> i) % 2 == 1 && branch->branches[1]) {
|
if ((opline >> i) % 2 == 1 && branch->branches[1]) {
|
||||||
if (branch->branches[0]) {
|
if (branch->branches[0]) {
|
||||||
last_superior_i = i;
|
last_superior_i = i;
|
||||||
}
|
}
|
||||||
branch = branch->branches[1];
|
CHOOSE_BRANCH(1);
|
||||||
} else {
|
} else {
|
||||||
branch = branch->branches[0];
|
CHOOSE_BRANCH(0);
|
||||||
}
|
}
|
||||||
} while (i--);
|
} while (i--);
|
||||||
|
|
||||||
if ((zend_ulong)(branch->op_array->opcodes + branch->op_array->last) <= opline ||
|
/* make sure that opline is an opcode address in the closest zend_op array */
|
||||||
(opline - (zend_ulong)branch->op_array->opcodes) % sizeof(zend_op) > 0) {
|
if (opcodes + branch->info.last * sizeof(zend_op) <= opline ||
|
||||||
error:
|
(opline - opcodes) % sizeof(zend_op) > 0) {
|
||||||
phpdbg_error("No opline could be found at 0x%lx", opline);
|
phpdbg_error("No opline could be found at 0x%lx; the closest opline is at 0x%lx (%s %s%s%s) with size %ld",
|
||||||
|
opline,
|
||||||
|
opcodes,
|
||||||
|
branch->info.func_name?(branch->info.class_name?"method":"function"):"file",
|
||||||
|
branch->info.func_name?branch->info.func_name:"",
|
||||||
|
branch->info.func_name&&branch->info.class_name?"::":"",
|
||||||
|
branch->info.class_name?branch->info.class_name:"",
|
||||||
|
branch->info.last);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
opline_break.opline = (opline - (zend_ulong)branch->op_array) / sizeof(zend_op);
|
opline_break.opline = (opline - opcodes) / sizeof(zend_op);
|
||||||
|
|
||||||
PHPDBG_G(flags) |= PHPDBG_HAS_OPLINE_BP;
|
PHPDBG_G(flags) |= PHPDBG_HAS_OPLINE_BP;
|
||||||
|
|
||||||
new_break.name = NULL;
|
opline_break.func_len = branch->info.func_len;
|
||||||
new_break.opline = opline;
|
opline_break.func_name = branch->info.func_name;
|
||||||
new_break.id = PHPDBG_G(bp_count)++;
|
opline_break.id = PHPDBG_G(bp_count)++;
|
||||||
|
if (branch->info.func_name == NULL) {
|
||||||
|
opline_break.func_len = branch->info.class_len;
|
||||||
|
opline_break.func_name = branch->info.class_name;
|
||||||
|
|
||||||
zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline,
|
insert = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE];
|
||||||
&new_break, sizeof(phpdbg_breakline_t), NULL);
|
PHPDBG_G(flags) |= PHPDBG_HAS_FILE_OPLINE_BP;
|
||||||
|
new_break.type = PHPDBG_BREAK_FILE_OPLINE;
|
||||||
opline_break.func_len = branch->op_array->function_name?strlen(branch->op_array->function_name):0;
|
} else if (branch->info.class_name) {
|
||||||
opline_break.func_name = opline_break.func_len?estrndup(branch->op_array->function_name, opline_break.func_len):"";
|
|
||||||
opline_break.id = new_break.id;
|
|
||||||
if (branch->op_array->scope) {
|
|
||||||
HashTable class_breaks, *class_table;
|
HashTable class_breaks, *class_table;
|
||||||
|
|
||||||
if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE],
|
if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE],
|
||||||
branch->op_array->scope->name,
|
branch->info.class_name,
|
||||||
branch->op_array->scope->name_length,
|
branch->info.class_len,
|
||||||
(void **)&class_table
|
(void **)&class_table
|
||||||
) == FAILURE) {
|
) == FAILURE) {
|
||||||
zend_hash_init(&class_breaks, 8, NULL, phpdbg_opline_class_breaks_dtor, 0);
|
zend_hash_init(&class_breaks, 8, NULL, phpdbg_opline_class_breaks_dtor, 0);
|
||||||
zend_hash_update(
|
zend_hash_update(
|
||||||
&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE],
|
&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE],
|
||||||
branch->op_array->scope->name,
|
branch->info.class_name,
|
||||||
branch->op_array->scope->name_length,
|
branch->info.class_len,
|
||||||
(void **)&class_breaks, sizeof(HashTable), (void **)&class_table);
|
(void **)&class_breaks, sizeof(HashTable), (void **)&class_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
opline_break.class_len = branch->op_array->scope->name_length;
|
opline_break.class_len = branch->info.class_len;
|
||||||
opline_break.class_name = estrndup(branch->op_array->scope->name, opline_break.class_len);
|
opline_break.class_name = branch->info.class_name;
|
||||||
|
|
||||||
insert = class_table;
|
insert = class_table;
|
||||||
|
PHPDBG_G(flags) |= PHPDBG_HAS_METHOD_OPLINE_BP;
|
||||||
|
new_break.type = PHPDBG_BREAK_METHOD_OPLINE;
|
||||||
|
} else {
|
||||||
|
PHPDBG_G(flags) |= PHPDBG_HAS_FUNCTION_OPLINE_BP;
|
||||||
|
new_break.type = PHPDBG_BREAK_FUNCTION_OPLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zend_hash_find(insert, opline_break.func_name, opline_break.func_len, (void **)&func_table) == FAILURE) {
|
if (zend_hash_find(insert, opline_break.func_name, opline_break.func_len, (void **)&func_table) == FAILURE) {
|
||||||
|
@ -380,10 +425,24 @@ error:
|
||||||
(void **)&func_breaks, sizeof(HashTable), (void **)&func_table);
|
(void **)&func_breaks, sizeof(HashTable), (void **)&func_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* insert opline num breakpoint information */
|
||||||
zend_hash_index_update(func_table, opline_break.opline, &opline_break, sizeof(phpdbg_breakopline_t), NULL);
|
zend_hash_index_update(func_table, opline_break.opline, &opline_break, sizeof(phpdbg_breakopline_t), NULL);
|
||||||
|
|
||||||
phpdbg_notice("Breakpoint #%d added at %#lx",
|
/* insert opline breakpoint */
|
||||||
new_break.id, new_break.opline);
|
new_break.name = NULL;
|
||||||
|
new_break.opline = opline;
|
||||||
|
new_break.id = opline_break.id; /* use same id to identify */
|
||||||
|
zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline,
|
||||||
|
&new_break, sizeof(phpdbg_breakline_t), NULL);
|
||||||
|
|
||||||
|
phpdbg_notice("Breakpoint #%d added at %#lx (opcode #%ld in %s %s%s%s)",
|
||||||
|
new_break.id,
|
||||||
|
new_break.opline,
|
||||||
|
(opline - opcodes) / sizeof(zend_op),
|
||||||
|
branch->info.func_name?(branch->info.class_name?"method":"function"):"file",
|
||||||
|
branch->info.func_name?branch->info.func_name:"",
|
||||||
|
branch->info.func_name&&branch->info.class_name?"::":"",
|
||||||
|
branch->info.class_name?branch->info.class_name:"");
|
||||||
} else {
|
} else {
|
||||||
phpdbg_notice("Breakpoint exists at %#lx", opline);
|
phpdbg_notice("Breakpoint exists at %#lx", opline);
|
||||||
}
|
}
|
||||||
|
@ -528,6 +587,8 @@ PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const cha
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHPDBG_G(flags) |= PHPDBG_HAS_METHOD_OPLINE_BP;
|
||||||
|
|
||||||
zend_hash_index_update(method_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
|
zend_hash_index_update(method_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +599,8 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, int
|
||||||
|
|
||||||
new_break.func_len = strlen(function);
|
new_break.func_len = strlen(function);
|
||||||
new_break.func_name = estrndup(function, new_break.func_len);
|
new_break.func_name = estrndup(function, new_break.func_len);
|
||||||
|
new_break.class_len = 0;
|
||||||
|
new_break.class_name = NULL;
|
||||||
new_break.opline = opline;
|
new_break.opline = opline;
|
||||||
new_break.id = PHPDBG_G(bp_count)++;
|
new_break.id = PHPDBG_G(bp_count)++;
|
||||||
|
|
||||||
|
@ -564,12 +627,14 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, int
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zend_hash_index_exists(func_table, opline)) {
|
if (zend_hash_index_exists(func_table, opline)) {
|
||||||
phpdbg_notice("Breakpoint already exists for %s:%d", new_break.func_len, opline);
|
phpdbg_notice("Breakpoint already exists for %s:%d", new_break.func_name, opline);
|
||||||
efree(new_break.func_name);
|
efree(new_break.func_name);
|
||||||
PHPDBG_G(bp_count)--;
|
PHPDBG_G(bp_count)--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHPDBG_G(flags) |= PHPDBG_HAS_FUNCTION_OPLINE_BP;
|
||||||
|
|
||||||
zend_hash_index_update(func_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
|
zend_hash_index_update(func_table, new_break.opline, &new_break, sizeof(phpdbg_breakopline_t), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ typedef struct _phpdbg_breakopline_t {
|
||||||
typedef struct _phpdbg_breakline_t {
|
typedef struct _phpdbg_breakline_t {
|
||||||
const char *name;
|
const char *name;
|
||||||
zend_ulong opline;
|
zend_ulong opline;
|
||||||
|
zend_uchar type;
|
||||||
int id;
|
int id;
|
||||||
} phpdbg_breakline_t;
|
} phpdbg_breakline_t;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue