summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/phpdbg.c
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/phpdbg/phpdbg.c')
-rw-r--r--sapi/phpdbg/phpdbg.c81
1 files changed, 71 insertions, 10 deletions
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c
index db830f2d28..3fdc7cbe30 100644
--- a/sapi/phpdbg/phpdbg.c
+++ b/sapi/phpdbg/phpdbg.c
@@ -443,16 +443,54 @@ static PHP_FUNCTION(phpdbg_start_oplog)
PHPDBG_G(oplog_list)->start = PHPDBG_G(oplog_cur);
}
+static void phpdbg_oplog_fill_executable(zend_op_array *op_array, HashTable *insert_ht, zend_bool by_opcode) {
+ /* ignore RECV_* opcodes */
+ zend_op *cur = op_array->opcodes + op_array->num_args + !!(op_array->fn_flags & ZEND_ACC_VARIADIC);
+ zend_op *end = op_array->opcodes + op_array->last;
+
+ zend_long insert_idx;
+ zval zero;
+ ZVAL_LONG(&zero, 0);
+
+ /* ignore autogenerated return (well, not too precise with finally branches, but that's okay) */
+ if (op_array->last > 1 && (end - 1)->opcode == ZEND_RETURN && ((end - 2)->opcode == ZEND_RETURN || (end - 2)->opcode == ZEND_GENERATOR_RETURN || (end - 2)->opcode == ZEND_THROW)) {
+ end--;
+ }
+
+ for (; cur < end; cur++) {
+ if (cur->opcode == ZEND_NOP || cur->opcode == ZEND_OP_DATA || cur->opcode == ZEND_FE_FREE || cur->opcode == ZEND_FREE || cur->opcode == ZEND_ASSERT_CHECK
+ || cur->opcode == ZEND_DECLARE_CONST || cur->opcode == ZEND_DECLARE_CLASS || cur->opcode == ZEND_DECLARE_INHERITED_CLASS || cur->opcode == ZEND_DECLARE_FUNCTION
+ || cur->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED || cur->opcode == ZEND_VERIFY_ABSTRACT_CLASS || cur->opcode == ZEND_ADD_TRAIT || cur->opcode == ZEND_BIND_TRAITS
+ || cur->opcode == ZEND_DECLARE_ANON_CLASS || cur->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS || cur->opcode == ZEND_FAST_RET || cur->opcode == ZEND_TICKS
+ || cur->opcode == ZEND_EXT_STMT || cur->opcode == ZEND_EXT_FCALL_BEGIN || cur->opcode == ZEND_EXT_FCALL_END || cur->opcode == ZEND_EXT_NOP || cur->opcode == ZEND_BIND_GLOBAL) {
+ continue;
+ }
+
+ if (by_opcode) {
+ insert_idx = cur - op_array->opcodes;
+ } else {
+ insert_idx = cur->lineno;
+ }
+
+ if (cur->opcode == ZEND_NEW && (cur + 1)->opcode == ZEND_DO_FCALL) {
+ cur++;
+ }
+
+ zend_hash_index_update(insert_ht, insert_idx, &zero);
+ }
+}
+
/* {{{ proto void phpdbg_end_oplog() */
static PHP_FUNCTION(phpdbg_end_oplog)
{
- phpdbg_oplog_entry *cur = PHPDBG_G(oplog_list)->start;
- phpdbg_oplog_list *prev = PHPDBG_G(oplog_list)->prev;
+ phpdbg_oplog_entry *cur;
+ phpdbg_oplog_list *prev;
HashTable *options = NULL;
zval *option_buffer;
zend_bool by_function = 0;
zend_bool by_opcode = 0;
+ zend_bool show_unexecuted = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) {
return;
@@ -463,6 +501,9 @@ static PHP_FUNCTION(phpdbg_end_oplog)
return;
}
+ cur = PHPDBG_G(oplog_list)->start;
+ prev = PHPDBG_G(oplog_list)->prev;
+
efree(PHPDBG_G(oplog_list));
PHPDBG_G(oplog_list) = prev;
@@ -476,6 +517,10 @@ static PHP_FUNCTION(phpdbg_end_oplog)
}
}
+ if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("show_unexecuted")))) {
+ show_unexecuted = zend_is_true(option_buffer);
+ }
+
array_init(return_value);
{
@@ -490,6 +535,9 @@ static PHP_FUNCTION(phpdbg_end_oplog)
do {
zend_op_array *op_array = cur->op_array;
+ zval zero;
+ ZVAL_LONG(&zero, 0);
+
if (op_array->filename != last_file) {
last_file = op_array->filename;
file_buf = zend_hash_find(Z_ARR_P(return_value), last_file);
@@ -497,28 +545,41 @@ static PHP_FUNCTION(phpdbg_end_oplog)
zval ht;
array_init(&ht);
file_buf = zend_hash_add_new(Z_ARR_P(return_value), last_file, &ht);
+
+ if (show_unexecuted) {
+ phpdbg_oplog_fill_executable(op_array, Z_ARR_P(file_buf), by_opcode);
+ }
}
+ insert_ht = Z_ARR_P(file_buf);
}
- insert_ht = Z_ARR_P(file_buf);
if (by_function) {
- if (op_array->function_name != last_function || op_array->scope != last_scope) {
+ if (op_array->function_name == NULL) {
+ if (last_function != NULL) {
+ insert_ht = Z_ARR_P(file_buf);
+ }
+ last_function = NULL;
+ } else if (op_array->function_name != last_function || op_array->scope != last_scope) {
zend_string *fn_name;
last_function = op_array->function_name;
last_scope = op_array->scope;
if (last_scope == NULL) {
- fn_name = zend_string_copy(last_function);
+ fn_name = zend_string_copy(last_function ? last_function : last_file);
} else {
- fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", ZSTR_LEN(last_function), ZSTR_VAL(last_function), ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name));
+ fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), ZSTR_LEN(last_function), ZSTR_VAL(last_function));
}
fn_buf = zend_hash_find(Z_ARR_P(return_value), fn_name);
if (!fn_buf) {
zval ht;
array_init(&ht);
fn_buf = zend_hash_add_new(Z_ARR_P(return_value), fn_name, &ht);
+
+ if (show_unexecuted) {
+ phpdbg_oplog_fill_executable(op_array, Z_ARR_P(fn_buf), by_opcode);
+ }
}
+ insert_ht = Z_ARR_P(fn_buf);
}
- insert_ht = Z_ARR_P(fn_buf);
}
if (by_opcode) {
@@ -530,9 +591,7 @@ static PHP_FUNCTION(phpdbg_end_oplog)
{
zval *num = zend_hash_index_find(insert_ht, insert_idx);
if (!num) {
- zval zv;
- ZVAL_LONG(&zv, 0);
- num = zend_hash_index_add_new(insert_ht, insert_idx, &zv);
+ num = zend_hash_index_add_new(insert_ht, insert_idx, &zero);
}
Z_LVAL_P(num)++;
}
@@ -1675,6 +1734,8 @@ phpdbg_main:
goto phpdbg_out;
}
+ PG(during_request_startup) = 0;
+
phpdbg_fully_started = 1;
/* #ifndef for making compiler shutting up */