call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();
+ ZEND_OBSERVER_SAVE_OPLINE();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
ZEND_VM_ENTER_EX();
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();
+ ZEND_OBSERVER_SAVE_OPLINE();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
ZEND_VM_ENTER_EX();
} else {
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
- ZEND_OBSERVER_FCALL_BEGIN(execute_data);
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+ ZEND_OBSERVER_SAVE_OPLINE();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
}
}
}
+ ZEND_OBSERVER_SAVE_OPLINE();
ZEND_OBSERVER_FCALL_END(execute_data, return_value);
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
}
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- ZEND_OBSERVER_FCALL_BEGIN(execute_data);
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+ ZEND_OBSERVER_SAVE_OPLINE();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+ ZEND_OBSERVER_FCALL_BEGIN(execute_data);
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
-
LOAD_OPLINE_EX();
+
ZEND_VM_ENTER_EX();
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
-
LOAD_OPLINE_EX();
+
ZEND_VM_ENTER_EX();
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();
+ SAVE_OPLINE();
+ zend_observer_fcall_begin(execute_data);
ZEND_VM_ENTER_EX();
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
-
LOAD_OPLINE_EX();
+
ZEND_VM_ENTER_EX();
} else {
zval retval;
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
-
LOAD_OPLINE_EX();
+
ZEND_VM_ENTER_EX();
} else {
zval retval;
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();
+ SAVE_OPLINE();
+ zend_observer_fcall_begin(execute_data);
ZEND_VM_ENTER_EX();
} else {
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+
+
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+
+
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
- zend_observer_fcall_begin(execute_data);
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+ SAVE_OPLINE();
+ zend_observer_fcall_begin(execute_data);
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+ zend_observer_fcall_begin(execute_data);
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
}
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
-
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+
+
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
}
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- zend_observer_fcall_begin(execute_data);
if (EXPECTED(zend_execute_ex == execute_ex)) {
LOAD_OPLINE_EX();
+ SAVE_OPLINE();
+ zend_observer_fcall_begin(execute_data);
ZEND_VM_ENTER_EX();
} else {
SAVE_OPLINE_EX();
+ zend_observer_fcall_begin(execute_data);
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
}
}
+
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
}
+ SAVE_OPLINE();
zend_observer_fcall_end(execute_data, return_value);
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
+
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
+
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
+
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
+
goto zend_leave_helper_SPEC_LABEL;
}
}
}
}
+ SAVE_OPLINE();
zend_observer_fcall_end(execute_data, return_value);
goto zend_leave_helper_SPEC_LABEL;
}
}
}
+
goto zend_leave_helper_SPEC_LABEL;
}
}
}
+
goto zend_leave_helper_SPEC_LABEL;
}
}
}
+
goto zend_leave_helper_SPEC_LABEL;
}
($extra_spec['ISSET'] == 0 ? "\\0" : "opline->extended_value")
: "\\0",
"/ZEND_OBSERVER_ENABLED/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0",
+ "/ZEND_OBSERVER_SAVE_OPLINE\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "SAVE_OPLINE()" : "",
"/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ?
($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)")
: "",
int observer_show_return_type;
int observer_show_return_value;
int observer_show_init_backtrace;
+ int observer_show_opcode;
int observer_nesting_depth;
ZEND_END_MODULE_GLOBALS(zend_test)
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_type", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_type, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_value", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_value, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.observer.show_init_backtrace", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_init_backtrace, zend_zend_test_globals, zend_test_globals)
+ STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals)
PHP_INI_END()
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
return SUCCESS;
}
+static void observer_show_opcode(zend_execute_data *execute_data)
+{
+ if (!ZT_G(observer_show_opcode)) {
+ return;
+ }
+ php_printf("%*s<!-- opcode: '%s' -->\n", 2 * ZT_G(observer_nesting_depth), "", zend_get_opcode_name(EX(opline)->opcode));
+}
+
static void observer_begin(zend_execute_data *execute_data)
{
if (!ZT_G(observer_show_output)) {
php_printf("%*s<file '%s'>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->op_array.filename));
}
ZT_G(observer_nesting_depth)++;
+ observer_show_opcode(execute_data);
}
static void get_retval_info(zval *retval, smart_str *buf)
if (EG(exception)) {
php_printf("%*s<!-- Exception: %s -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(EG(exception)->ce->name));
}
+ observer_show_opcode(execute_data);
ZT_G(observer_nesting_depth)--;
if (execute_data->func && execute_data->func->common.function_name) {
smart_str retval_info = {0};
if (ZT_G(observer_show_init_backtrace)) {
observer_show_init_backtrace(execute_data);
}
+ observer_show_opcode(execute_data);
}
if (ZT_G(observer_observe_all)) {
--- /dev/null
+--TEST--
+Observer: Ensure opline exists on the execute_data
+--SKIPIF--
+<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
+--INI--
+zend_test.observer.enabled=1
+zend_test.observer.observe_all=1
+zend_test.observer.show_opcode=1
+--FILE--
+<?php
+function foo()
+{
+ echo 'Foo' . PHP_EOL;
+}
+
+foo();
+include __DIR__ . '/observer.inc';
+echo array_sum([1,2,3]) . PHP_EOL;
+foo();
+?>
+--EXPECTF--
+<!-- init '%s/observer_opline_%d.php' -->
+<!-- opcode: 'ZEND_INIT_FCALL' -->
+<file '%s/observer_opline_%d.php'>
+ <!-- opcode: 'ZEND_INIT_FCALL' -->
+ <!-- init foo() -->
+ <!-- opcode: 'ZEND_ECHO' -->
+ <foo>
+ <!-- opcode: 'ZEND_ECHO' -->
+Foo
+ <!-- opcode: 'ZEND_RETURN' -->
+ </foo>
+ <!-- init '%s/observer.inc' -->
+ <!-- opcode: 'ZEND_INIT_FCALL' -->
+ <file '%s/observer.inc'>
+ <!-- opcode: 'ZEND_INIT_FCALL' -->
+ <!-- init foo_observer_test() -->
+ <!-- opcode: 'ZEND_ECHO' -->
+ <foo_observer_test>
+ <!-- opcode: 'ZEND_ECHO' -->
+foo_observer_test
+ <!-- opcode: 'ZEND_RETURN' -->
+ </foo_observer_test>
+ <!-- opcode: 'ZEND_RETURN' -->
+ </file '%s/observer.inc'>
+6
+ <foo>
+ <!-- opcode: 'ZEND_ECHO' -->
+Foo
+ <!-- opcode: 'ZEND_RETURN' -->
+ </foo>
+ <!-- opcode: 'ZEND_RETURN' -->
+</file '%s/observer_opline_%d.php'>