]> granicus.if.org Git - php/commitdiff
Add show_unexecuted option to phpdbg_end_oplog()
authorBob Weinand <bobwei9@hotmail.com>
Mon, 20 Jul 2015 18:41:07 +0000 (20:41 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Mon, 20 Jul 2015 18:41:07 +0000 (20:41 +0200)
sapi/phpdbg/create-test.php
sapi/phpdbg/phpdbg.c
sapi/phpdbg/tests/phpdbg_oplog_001.phpt [new file with mode: 0644]
sapi/phpdbg/tests/phpdbg_oplog_002.phpt [new file with mode: 0644]

index 3bda97670f5d8009c68fc01b70c73e207ea10d78..6de10bd56fe0f5fc73d833bfa8a450e16d86bfa7 100644 (file)
@@ -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 = "";
 
index db830f2d28d2cfcb6f4b1053515c7270efebc52c..3fdc7cbe301f173b5316103769960bb716aac686 100644 (file)
@@ -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 (file)
index 0000000..4273865
--- /dev/null
@@ -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 (file)
index 0000000..b9ba905
--- /dev/null
@@ -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());