Skip to content

Commit 7141926

Browse files
committed
Save opline before calling observer begin and end handlers
1 parent 4945bc2 commit 7141926

File tree

5 files changed

+109
-5
lines changed

5 files changed

+109
-5
lines changed

Zend/zend_vm_def.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3956,6 +3956,7 @@ ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
39563956
call->prev_execute_data = execute_data;
39573957
execute_data = call;
39583958
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
3959+
ZEND_OBSERVER_SAVE_OPLINE();
39593960
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
39603961
LOAD_OPLINE_EX();
39613962

@@ -3981,6 +3982,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
39813982
call->prev_execute_data = execute_data;
39823983
execute_data = call;
39833984
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
3985+
ZEND_OBSERVER_SAVE_OPLINE();
39843986
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
39853987
LOAD_OPLINE_EX();
39863988

@@ -4075,13 +4077,15 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
40754077
call->prev_execute_data = execute_data;
40764078
execute_data = call;
40774079
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
4078-
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
40794080

40804081
if (EXPECTED(zend_execute_ex == execute_ex)) {
4082+
ZEND_OBSERVER_SAVE_OPLINE();
4083+
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
40814084
LOAD_OPLINE_EX();
40824085
ZEND_VM_ENTER_EX();
40834086
} else {
40844087
SAVE_OPLINE_EX();
4088+
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
40854089
execute_data = EX(prev_execute_data);
40864090
LOAD_OPLINE();
40874091
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))
42994303
}
43004304
}
43014305
}
4306+
ZEND_OBSERVER_SAVE_OPLINE();
43024307
ZEND_OBSERVER_FCALL_END(execute_data, return_value);
43034308
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
43044309
}
@@ -7705,6 +7710,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca
77057710

77067711
/* Uncaught exception */
77077712
if (zend_observer_fcall_op_array_extension != -1) {
7713+
EX(opline) = opline;
77087714
zend_observer_fcall_end(execute_data, EX(return_value));
77097715
}
77107716
cleanup_live_vars(execute_data, op_num, 0);
@@ -8511,12 +8517,14 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
85118517
}
85128518
execute_data = call;
85138519
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
8514-
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
85158520
if (EXPECTED(zend_execute_ex == execute_ex)) {
8521+
ZEND_OBSERVER_SAVE_OPLINE();
8522+
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
85168523
LOAD_OPLINE_EX();
85178524
ZEND_VM_ENTER_EX();
85188525
} else {
85198526
SAVE_OPLINE_EX();
8527+
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
85208528
execute_data = EX(prev_execute_data);
85218529
LOAD_OPLINE();
85228530
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);

Zend/zend_vm_execute.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV
13511351
execute_data = call;
13521352
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
13531353

1354+
13541355
LOAD_OPLINE_EX();
13551356

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

1379+
13781380
LOAD_OPLINE_EX();
13791381

13801382
ZEND_VM_ENTER_EX();
@@ -1398,6 +1400,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBS
13981400
call->prev_execute_data = execute_data;
13991401
execute_data = call;
14001402
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
1403+
EX(opline) = opline;
14011404
zend_observer_fcall_begin(execute_data);
14021405
LOAD_OPLINE_EX();
14031406

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

1430+
14271431
LOAD_OPLINE_EX();
14281432

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

1525+
15211526
LOAD_OPLINE_EX();
15221527

15231528
ZEND_VM_ENTER_EX();
@@ -1611,6 +1616,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_
16111616
call->prev_execute_data = execute_data;
16121617
execute_data = call;
16131618
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
1619+
EX(opline) = opline;
16141620
zend_observer_fcall_begin(execute_data);
16151621
LOAD_OPLINE_EX();
16161622

@@ -1707,10 +1713,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
17071713
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
17081714

17091715
if (EXPECTED(zend_execute_ex == execute_ex)) {
1716+
1717+
17101718
LOAD_OPLINE_EX();
17111719
ZEND_VM_ENTER_EX();
17121720
} else {
17131721
SAVE_OPLINE_EX();
1722+
17141723
execute_data = EX(prev_execute_data);
17151724
LOAD_OPLINE();
17161725
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
18121821
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
18131822

18141823
if (EXPECTED(zend_execute_ex == execute_ex)) {
1824+
1825+
18151826
LOAD_OPLINE_EX();
18161827
ZEND_VM_ENTER_EX();
18171828
} else {
18181829
SAVE_OPLINE_EX();
1830+
18191831
execute_data = EX(prev_execute_data);
18201832
LOAD_OPLINE();
18211833
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
19151927
call->prev_execute_data = execute_data;
19161928
execute_data = call;
19171929
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
1918-
zend_observer_fcall_begin(execute_data);
19191930

19201931
if (EXPECTED(zend_execute_ex == execute_ex)) {
1932+
EX(opline) = opline;
1933+
zend_observer_fcall_begin(execute_data);
19211934
LOAD_OPLINE_EX();
19221935
ZEND_VM_ENTER_EX();
19231936
} else {
19241937
SAVE_OPLINE_EX();
1938+
zend_observer_fcall_begin(execute_data);
19251939
execute_data = EX(prev_execute_data);
19261940
LOAD_OPLINE();
19271941
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
28952909

28962910
/* Uncaught exception */
28972911
if (zend_observer_fcall_op_array_extension != -1) {
2912+
EX(opline) = opline;
28982913
zend_observer_fcall_end(execute_data, EX(return_value));
28992914
}
29002915
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
31363151
}
31373152
execute_data = call;
31383153
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
3139-
31403154
if (EXPECTED(zend_execute_ex == execute_ex)) {
3155+
3156+
31413157
LOAD_OPLINE_EX();
31423158
ZEND_VM_ENTER_EX();
31433159
} else {
31443160
SAVE_OPLINE_EX();
3161+
31453162
execute_data = EX(prev_execute_data);
31463163
LOAD_OPLINE();
31473164
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
@@ -3270,12 +3287,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_
32703287
}
32713288
execute_data = call;
32723289
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
3273-
zend_observer_fcall_begin(execute_data);
32743290
if (EXPECTED(zend_execute_ex == execute_ex)) {
3291+
EX(opline) = opline;
3292+
zend_observer_fcall_begin(execute_data);
32753293
LOAD_OPLINE_EX();
32763294
ZEND_VM_ENTER_EX();
32773295
} else {
32783296
SAVE_OPLINE_EX();
3297+
zend_observer_fcall_begin(execute_data);
32793298
execute_data = EX(prev_execute_data);
32803299
LOAD_OPLINE();
32813300
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_
40694088
}
40704089
}
40714090

4091+
40724092
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
40734093
}
40744094

@@ -4141,6 +4161,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER
41414161
}
41424162
}
41434163
}
4164+
EX(opline) = opline;
41444165
zend_observer_fcall_end(execute_data, return_value);
41454166
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
41464167
}
@@ -18574,6 +18595,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA
1857418595
}
1857518596
}
1857618597

18598+
1857718599
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
1857818600
}
1857918601

@@ -21139,6 +21161,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA
2113921161
}
2114021162
}
2114121163

21164+
2114221165
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
2114321166
}
2114421167

@@ -37670,6 +37693,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN
3767037693
}
3767137694
}
3767237695

37696+
3767337697
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
3767437698
}
3767537699

@@ -54736,6 +54760,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5473654760
}
5473754761
}
5473854762

54763+
5473954764
goto zend_leave_helper_SPEC_LABEL;
5474054765
}
5474154766

@@ -54809,6 +54834,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5480954834
}
5481054835
}
5481154836
}
54837+
EX(opline) = opline;
5481254838
zend_observer_fcall_end(execute_data, return_value);
5481354839
goto zend_leave_helper_SPEC_LABEL;
5481454840
}
@@ -56344,6 +56370,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5634456370
}
5634556371
}
5634656372

56373+
5634756374
goto zend_leave_helper_SPEC_LABEL;
5634856375
}
5634956376

@@ -56642,6 +56669,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5664256669
}
5664356670
}
5664456671

56672+
5664556673
goto zend_leave_helper_SPEC_LABEL;
5664656674
}
5664756675

@@ -57756,6 +57784,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5775657784
}
5775757785
}
5775857786

57787+
5775957788
goto zend_leave_helper_SPEC_LABEL;
5776057789
}
5776157790

Zend/zend_vm_gen.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null)
794794
($extra_spec['ISSET'] == 0 ? "\\0" : "opline->extended_value")
795795
: "\\0",
796796
"/ZEND_OBSERVER_ENABLED/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0",
797+
"/ZEND_OBSERVER_SAVE_OPLINE\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "EX(opline) = opline" : "",
797798
"/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ?
798799
($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)")
799800
: "",

ext/zend_test/test.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
3737
int observer_show_return_type;
3838
int observer_show_return_value;
3939
int observer_show_init_backtrace;
40+
int observer_show_opcode;
4041
int observer_nesting_depth;
4142
ZEND_END_MODULE_GLOBALS(zend_test)
4243

@@ -330,6 +331,7 @@ PHP_INI_BEGIN()
330331
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)
331332
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)
332333
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)
334+
STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals)
333335
PHP_INI_END()
334336

335337
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
@@ -441,6 +443,14 @@ PHP_MSHUTDOWN_FUNCTION(zend_test)
441443
return SUCCESS;
442444
}
443445

446+
static void observer_show_opcode(zend_execute_data *execute_data)
447+
{
448+
if (!ZT_G(observer_show_opcode)) {
449+
return;
450+
}
451+
php_printf("%*s<!-- opcode: '%s' -->\n", 2 * ZT_G(observer_nesting_depth), "", zend_get_opcode_name(EX(opline)->opcode));
452+
}
453+
444454
static void observer_begin(zend_execute_data *execute_data)
445455
{
446456
if (!ZT_G(observer_show_output)) {
@@ -457,6 +467,7 @@ static void observer_begin(zend_execute_data *execute_data)
457467
php_printf("%*s<file '%s'>\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(execute_data->func->op_array.filename));
458468
}
459469
ZT_G(observer_nesting_depth)++;
470+
observer_show_opcode(execute_data);
460471
}
461472

462473
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)
485496
if (EG(exception)) {
486497
php_printf("%*s<!-- Exception: %s -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(EG(exception)->ce->name));
487498
}
499+
observer_show_opcode(execute_data);
488500
ZT_G(observer_nesting_depth)--;
489501
if (execute_data->func && execute_data->func->common.function_name) {
490502
smart_str retval_info = {0};
@@ -541,6 +553,7 @@ static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execu
541553
if (ZT_G(observer_show_init_backtrace)) {
542554
observer_show_init_backtrace(execute_data);
543555
}
556+
observer_show_opcode(execute_data);
544557
}
545558

546559
if (ZT_G(observer_observe_all)) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Observer: Ensure opline exists on the execute_data
3+
--SKIPIF--
4+
<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
5+
--INI--
6+
zend_test.observer.enabled=1
7+
zend_test.observer.observe_all=1
8+
zend_test.observer.show_opcode=1
9+
--FILE--
10+
<?php
11+
function foo()
12+
{
13+
echo 'Foo' . PHP_EOL;
14+
}
15+
16+
foo();
17+
include __DIR__ . '/observer.inc';
18+
echo array_sum([1,2,3]) . PHP_EOL;
19+
foo();
20+
?>
21+
--EXPECTF--
22+
<!-- init '%s/observer_opline_%d.php' -->
23+
<!-- opcode: 'ZEND_INIT_FCALL' -->
24+
<file '%s/observer_opline_%d.php'>
25+
<!-- opcode: 'ZEND_INIT_FCALL' -->
26+
<!-- init foo() -->
27+
<!-- opcode: 'ZEND_ECHO' -->
28+
<foo>
29+
<!-- opcode: 'ZEND_ECHO' -->
30+
Foo
31+
<!-- opcode: 'ZEND_RETURN' -->
32+
</foo>
33+
<!-- init '%s/observer.inc' -->
34+
<!-- opcode: 'ZEND_INIT_FCALL' -->
35+
<file '%s/observer.inc'>
36+
<!-- opcode: 'ZEND_INIT_FCALL' -->
37+
<!-- init foo_observer_test() -->
38+
<!-- opcode: 'ZEND_ECHO' -->
39+
<foo_observer_test>
40+
<!-- opcode: 'ZEND_ECHO' -->
41+
foo_observer_test
42+
<!-- opcode: 'ZEND_RETURN' -->
43+
</foo_observer_test>
44+
<!-- opcode: 'ZEND_RETURN' -->
45+
</file '%s/observer.inc'>
46+
6
47+
<foo>
48+
<!-- opcode: 'ZEND_ECHO' -->
49+
Foo
50+
<!-- opcode: 'ZEND_RETURN' -->
51+
</foo>
52+
<!-- opcode: 'ZEND_RETURN' -->
53+
</file '%s/observer_opline_%d.php'>

0 commit comments

Comments
 (0)