From 7141926b654d5e7d981f2ad31f6921970263b43b Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Tue, 10 Nov 2020 10:11:29 -0800 Subject: [PATCH 1/2] Save opline before calling observer begin and end handlers --- Zend/zend_vm_def.h | 12 ++++- Zend/zend_vm_execute.h | 35 ++++++++++++-- Zend/zend_vm_gen.php | 1 + ext/zend_test/test.c | 13 +++++ ext/zend_test/tests/observer_opline_01.phpt | 53 +++++++++++++++++++++ 5 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 ext/zend_test/tests/observer_opline_01.phpt diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cff1012acae92..073e2fe165408 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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(); @@ -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(); @@ -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); @@ -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); } @@ -7705,6 +7710,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { + EX(opline) = opline; zend_observer_fcall_end(execute_data, EX(return_value)); } cleanup_live_vars(execute_data, op_num, 0); @@ -8511,12 +8517,14 @@ 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_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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1786cfcc83a91..275bd299681ec 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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); @@ -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); @@ -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); @@ -2895,6 +2909,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { + EX(opline) = opline; zend_observer_fcall_end(execute_data, EX(return_value)); } cleanup_live_vars(execute_data, op_num, 0); @@ -3136,12 +3151,14 @@ 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); @@ -3270,12 +3287,14 @@ 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)) { + 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); @@ -4069,6 +4088,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)); } @@ -4141,6 +4161,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)); } @@ -18574,6 +18595,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)); } @@ -21139,6 +21161,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)); } @@ -37670,6 +37693,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)); } @@ -54736,6 +54760,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } + goto zend_leave_helper_SPEC_LABEL; } @@ -54809,6 +54834,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; } @@ -56344,6 +56370,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } + goto zend_leave_helper_SPEC_LABEL; } @@ -56642,6 +56669,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } + goto zend_leave_helper_SPEC_LABEL; } @@ -57756,6 +57784,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } + goto zend_leave_helper_SPEC_LABEL; } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 3346a59cfa620..f36bb83c32ab2 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -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)") : "", diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 08d91c361aa86..ef6d45b84986b 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -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) @@ -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); @@ -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\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)) { @@ -457,6 +467,7 @@ static void observer_begin(zend_execute_data *execute_data) php_printf("%*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) @@ -485,6 +496,7 @@ static void observer_end(zend_execute_data *execute_data, zval *retval) if (EG(exception)) { php_printf("%*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}; @@ -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)) { diff --git a/ext/zend_test/tests/observer_opline_01.phpt b/ext/zend_test/tests/observer_opline_01.phpt new file mode 100644 index 0000000000000..d7d17f2b47747 --- /dev/null +++ b/ext/zend_test/tests/observer_opline_01.phpt @@ -0,0 +1,53 @@ +--TEST-- +Observer: Ensure opline exists on the execute_data +--SKIPIF-- + +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_opcode=1 +--FILE-- + +--EXPECTF-- + + + + + + + + +Foo + + + + + + + + + + +foo_observer_test + + + + +6 + + +Foo + + + + From 2b65e5b1667996ca4b4dfc1056092dacb8749b28 Mon Sep 17 00:00:00 2001 From: Sammy Kaye Powers Date: Tue, 10 Nov 2020 15:50:21 -0800 Subject: [PATCH 2/2] Fix build on macOS --- Zend/zend_vm_def.h | 2 -- Zend/zend_vm_execute.h | 3 --- 2 files changed, 5 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 073e2fe165408..c10054e4ad06d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7710,7 +7710,6 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { - EX(opline) = opline; zend_observer_fcall_end(execute_data, EX(return_value)); } cleanup_live_vars(execute_data, op_num, 0); @@ -8518,7 +8517,6 @@ 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); if (EXPECTED(zend_execute_ex == execute_ex)) { - ZEND_OBSERVER_SAVE_OPLINE(); ZEND_OBSERVER_FCALL_BEGIN(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 275bd299681ec..846258389f001 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2909,7 +2909,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try /* Uncaught exception */ if (zend_observer_fcall_op_array_extension != -1) { - EX(opline) = opline; zend_observer_fcall_end(execute_data, EX(return_value)); } cleanup_live_vars(execute_data, op_num, 0); @@ -3153,7 +3152,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z 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 { @@ -3288,7 +3286,6 @@ 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); if (EXPECTED(zend_execute_ex == execute_ex)) { - EX(opline) = opline; zend_observer_fcall_begin(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX();