开发者

How to get opcodes of PHP?

开发者 https://www.devze.com 2022-12-12 05:44 出处:网络
<?php $show_value= 123; echo \'sing_quote\'.$show_value; echo \"double_quote{$show_value}\"; ?> Its opcode is:
  <?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).

0

精彩评论

暂无评论...
验证码 换一张
取 消