summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2015-07-20 20:41:07 +0200
committerBob Weinand <bobwei9@hotmail.com>2015-07-20 20:41:07 +0200
commit6aadeba213305a0b8818c347bea956cb7e258c3a (patch)
tree2b55d65b0d25536f93895c329946a8956f943925
parent378a05f0de7ff8874a2b97cdc78851eba748d91f (diff)
downloadphp-git-6aadeba213305a0b8818c347bea956cb7e258c3a.tar.gz
Add show_unexecuted option to phpdbg_end_oplog()
-rw-r--r--sapi/phpdbg/create-test.php2
-rw-r--r--sapi/phpdbg/phpdbg.c81
-rw-r--r--sapi/phpdbg/tests/phpdbg_oplog_001.phpt56
-rw-r--r--sapi/phpdbg/tests/phpdbg_oplog_002.phpt16
4 files changed, 144 insertions, 11 deletions
diff --git a/sapi/phpdbg/create-test.php b/sapi/phpdbg/create-test.php
index 3bda97670f..6de10bd56f 100644
--- a/sapi/phpdbg/create-test.php
+++ b/sapi/phpdbg/create-test.php
@@ -27,7 +27,7 @@
error_reporting(-1);
$phpdbg = getenv('TEST_PHPDBG_EXECUTABLE') ?: null;
-$pass_options = " -qbI";
+$pass_options = ' -qbI -n -d "error_reporting=32767" -d "display_errors=1" -d "display_startup_errors=1" -d "log_errors=0"';
$file = "";
$cmdargv = "";
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 */
diff --git a/sapi/phpdbg/tests/phpdbg_oplog_001.phpt b/sapi/phpdbg/tests/phpdbg_oplog_001.phpt
new file mode 100644
index 0000000000..4273865bd9
--- /dev/null
+++ b/sapi/phpdbg/tests/phpdbg_oplog_001.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Test phpdbg_*_oplog() functions
+--PHPDBG--
+r
+q
+--EXPECTF--
+[Successful compilation of %s]
+prompt> halloarray(2) {
+ ["%s"]=>
+ array(6) {
+ [11]=>
+ int(0)
+ [13]=>
+ int(1)
+ [17]=>
+ int(2)
+ [18]=>
+ int(2)
+ [19]=>
+ int(3)
+ [21]=>
+ int(4)
+ }
+ ["A::b"]=>
+ array(2) {
+ [5]=>
+ int(5)
+ [4]=>
+ int(1)
+ }
+}
+[Script ended normally]
+prompt>
+--FILE--
+<?php
+
+class A {
+ public function b($c = 1) {
+ if ($c == 1) {
+ // comment
+ }
+ }
+}
+
+phpdbg_start_oplog();
+
+echo "hallo";
+
+// fcalls
+
+$a = new A();
+$a->b();
+$a->b('ha');
+
+var_dump(phpdbg_end_oplog(["functions" => true, "show_unexecuted" => true]));
+
diff --git a/sapi/phpdbg/tests/phpdbg_oplog_002.phpt b/sapi/phpdbg/tests/phpdbg_oplog_002.phpt
new file mode 100644
index 0000000000..b9ba905caa
--- /dev/null
+++ b/sapi/phpdbg/tests/phpdbg_oplog_002.phpt
@@ -0,0 +1,16 @@
+--TEST--
+phpdbg_end_oplog() alone must not crash
+--PHPDBG--
+r
+q
+--EXPECTF--
+[Successful compilation of %s]
+prompt>
+Warning: Can not end an oplog without starting it in %s on line 3
+NULL
+[Script ended normally]
+prompt>
+--FILE--
+<?php
+
+var_dump(phpdbg_end_oplog());