Skip to content

[Observer] Save opline before calling begin/end handlers #6421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -3956,6 +3956,7 @@ ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
ZEND_OBSERVER_SAVE_OPLINE();
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();

Expand All @@ -3981,6 +3982,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
ZEND_OBSERVER_SAVE_OPLINE();
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();

Expand Down Expand Up @@ -4075,13 +4077,15 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
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)) {
ZEND_OBSERVER_SAVE_OPLINE();
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();
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);
Expand Down Expand Up @@ -4299,6 +4303,7 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
}
}
}
ZEND_OBSERVER_SAVE_OPLINE();
ZEND_OBSERVER_FCALL_END(execute_data, return_value);
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
Expand Down Expand Up @@ -8511,12 +8516,13 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
}
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)) {
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
LOAD_OPLINE_EX();
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);
Expand Down
32 changes: 29 additions & 3 deletions Zend/zend_vm_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);


LOAD_OPLINE_EX();

ZEND_VM_ENTER_EX();
Expand All @@ -1375,6 +1376,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);


LOAD_OPLINE_EX();

ZEND_VM_ENTER_EX();
Expand All @@ -1398,6 +1400,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBS
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
EX(opline) = opline;
zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();

Expand All @@ -1424,6 +1427,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);


LOAD_OPLINE_EX();

ZEND_VM_ENTER_EX();
Expand Down Expand Up @@ -1518,6 +1522,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);


LOAD_OPLINE_EX();

ZEND_VM_ENTER_EX();
Expand Down Expand Up @@ -1611,6 +1616,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
EX(opline) = opline;
zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();

Expand Down Expand Up @@ -1707,10 +1713,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
i_init_func_execute_data(&fbc->op_array, ret, 1 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);
Expand Down Expand Up @@ -1812,10 +1821,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
i_init_func_execute_data(&fbc->op_array, ret, 1 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);
Expand Down Expand Up @@ -1915,13 +1927,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS
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)) {
EX(opline) = opline;
zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();
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);
Expand Down Expand Up @@ -3136,12 +3150,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
}
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);
Expand Down Expand Up @@ -3270,12 +3285,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_
}
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)) {
zend_observer_fcall_begin(execute_data);
LOAD_OPLINE_EX();
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);
Expand Down Expand Up @@ -4069,6 +4085,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_
}
}


ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}

Expand Down Expand Up @@ -4141,6 +4158,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER
}
}
}
EX(opline) = opline;
zend_observer_fcall_end(execute_data, return_value);
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
Expand Down Expand Up @@ -18574,6 +18592,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA
}
}


ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}

Expand Down Expand Up @@ -21139,6 +21158,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA
}
}


ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}

Expand Down Expand Up @@ -37670,6 +37690,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN
}
}


ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}

Expand Down Expand Up @@ -54736,6 +54757,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
}
}


goto zend_leave_helper_SPEC_LABEL;
}

Expand Down Expand Up @@ -54809,6 +54831,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
}
}
}
EX(opline) = opline;
zend_observer_fcall_end(execute_data, return_value);
goto zend_leave_helper_SPEC_LABEL;
}
Expand Down Expand Up @@ -56344,6 +56367,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
}
}


goto zend_leave_helper_SPEC_LABEL;
}

Expand Down Expand Up @@ -56642,6 +56666,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
}
}


goto zend_leave_helper_SPEC_LABEL;
}

Expand Down Expand Up @@ -57756,6 +57781,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
}
}


goto zend_leave_helper_SPEC_LABEL;
}

Expand Down
1 change: 1 addition & 0 deletions Zend/zend_vm_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null)
($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 ? "EX(opline) = opline" : "",
"/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ?
($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)")
: "",
Expand Down
13 changes: 13 additions & 0 deletions ext/zend_test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
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)

Expand Down Expand Up @@ -330,6 +331,7 @@ PHP_INI_BEGIN()
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);
Expand Down Expand Up @@ -441,6 +443,14 @@ PHP_MSHUTDOWN_FUNCTION(zend_test)
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)) {
Expand All @@ -457,6 +467,7 @@ static void observer_begin(zend_execute_data *execute_data)
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)
Expand Down Expand Up @@ -485,6 +496,7 @@ static void observer_end(zend_execute_data *execute_data, zval *retval)
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};
Expand Down Expand Up @@ -541,6 +553,7 @@ static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execu
if (ZT_G(observer_show_init_backtrace)) {
observer_show_init_backtrace(execute_data);
}
observer_show_opcode(execute_data);
}

if (ZT_G(observer_observe_all)) {
Expand Down
53 changes: 53 additions & 0 deletions ext/zend_test/tests/observer_opline_01.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--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'>