How to get opcodes of PHP?
<?php
$show_value = 123;
echo 'sing_quote'.$show_value;
echo "double_quote{$show_value}";
?>
Its opcode is:
1: <?php
2: $show_value = 123;
0 ASSIGN !0, 123
3: echo 'sing_quote'.$show_value;
1 CONCAT 'sing_quote', !0 =>RES[~1]
2 ECHO ~1
4: echo "double_quote{$show_value}";
3 ADD_STRING 'double_quote' =>RES[~2]
4 ADD_VAR ~2, !0 =开发者_Go百科>RES[~2]
5 ECHO ~2
6 RETURN 1
Check out the Vulcan Logic Disassembler PECL extension - see author's home page for more info.
The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. It was written as as a beginning of an encoder, but I never got the time for that. It can be used to see what is going on in the Zend Engine.
Once installed, you can use it like this:
php -d vld.active=1 -d vld.execute=0 -f yourscript.php
See also this interesting blog post on opcode extraction, and the PHP manual page listing the available opcodes.
Parsekit has parsekit_compile_string().
sudo pecl install parsekit
var_dump(parsekit_compile_string(<<<PHP \$show_value = 123; echo 'sing_quote'.\$show_value; echo "double_quote{\$show_value}"; PHP ));
The output is quite verbose, so you'd need to process it to get assembler-like format.
["opcodes"]=> array(10) { [0]=> array(9) { ["address"]=> int(44682716) ["opcode"]=> int(101) ["opcode_name"]=> string(13) "ZEND_EXT_STMT" ["flags"]=> int(4294967295) ["result"]=> array(8) { ["type"]=> int(8) ["type_name"]=> string(9) "IS_UNUSED" ["var"]=> int(0) ["opline_num"]=> string(1) "0" ["op_array"]=> string(1) "0" ["jmp_addr"]=> string(1) "0" ["jmp_offset"]=> string(8) "35419039" ["EA.type"]=> int(0) } ["op1"]=> array(8) { ["type"]=> int(8) ["type_name"]=> string(9) "IS_UNUSED" ["var"]=> int(0) ["opline_num"]=> string(1) "0" ["op_array"]=> string(1) "0" ["jmp_addr"]=> string(1) "0" ["jmp_offset"]=> string(8) "35419039" ["EA.type"]=> int(0) }
You can run code and also see the opcodes if you use https://3v4l.org/
Note: It automatically shows the Vulcan Logic Disassembler (VLD) output, but only if you have "all supported versions" selected in the version dropdown.
Here's a simple example (shown below for posterity): https://3v4l.org/Gt8fd/vld
Code:
<?php
$arr = [1, 2, 3, 4];
print_r(array_map(fn(int $i): int => $i * $i, $arr));
Result:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/Gt8fd
function name: (null)
number of ops: 10
compiled vars: !0 = $arr
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > ASSIGN !0, <array>
3 1 INIT_FCALL 'print_r'
2 INIT_FCALL 'array_map'
3 DECLARE_LAMBDA_FUNCTION '%00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240'
4 SEND_VAL ~2
5 SEND_VAR !0
6 DO_ICALL $3
7 SEND_VAR $3
8 DO_ICALL
9 > RETURN 1
Function %00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/Gt8fd
function name: {closure}
number of ops: 6
compiled vars: !0 = $i
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
0 E > RECV !0
1 MUL ~1 !0, !0
2 VERIFY_RETURN_TYPE ~1
3 > RETURN ~1
4* VERIFY_RETURN_TYPE
5* > RETURN null
End of function %00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240
Generated using Vulcan Logic Dumper, using php 8.0.0
Two options are, setting opcache.opt_debug_level
INI setting or using phpdbg
binary provided in a debug-enabled PHP environment (e.g. requiring you to either compile PHP from source or install the related package on Linux).
For more information and a full guide, refer to this php.watch article (also credits to this article).
精彩评论