PHP VLD扩展使用

PHP VLD扩展使用

VLD(Vulcan Logic Dumper)是一个挂钩在 Zend 引擎下,并且输出PHP脚本生成的中间件代码(执行单元)的扩展。它可以在一定程序上查看 Zend 引擎内部的一些实现原理,是我们学习PHP源码的必备良器。
安装扩展,这里省略
下面看一个简单例子,test.php文件
1
2
3
<?php
$a = 10;
echo $a;

 

在命令行下使用 VLD 扩展来展示信息

1
php -dvld.active=1 test.php

 

-dvld.active=1 表示激活VLD扩展,使用VLD扩展输出中间代码,在命令行输入信息如下

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
[root@localhost code]# /usr/local/php7.1.11/bin/php -dvld.active=1 test.php
Finding entry points                            # 找到入口点
Branch analysis from position: 0                # 分支分析的位置
Jump found. (Code = 62) Position 1 = -2         #
filename:       /test/code/test.php             # 分析的文件名
function name:  (null)                          # 函数名
number of ops:  3                               # 生成的操作数
compiled vars:  !0 = $a                         # 编译期间的变量,变量在PHP源码中以 IS_CV 标记
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   ASSIGN                                                   !0, 10
   3     1        ECHO                                                     !0
         2      > RETURN                                                   1
 
branch: #  0; line:     2-    3; sop:     0; eop:     2; out1:  -2
path #1: 0,
10
-dvld.verbosity=3 参数,查看更多详细信息,最大可以设置为3,再大输出效果一样
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
[root@localhost code]# /usr/local/php7.1.11/bin/php -dvld.active=1 -dvld.verbosity=3 test.php
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Jump found. (Code = 62) Position 1 = -2
filename:       /test/code/test.php
function name:  (null)
number of ops:  3
compiled vars:  !0 = $a
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
144     0  E >   ASSIGN                                                    OP1[  IS_CV !0 ] OP2[ ,  IS_CONST (0) 10 ]
145     1        ECHO                                                      OP1[  IS_CV !0 ]
158     2      > RETURN                                                    OP1[  IS_CONST (1) 1 ]
 
branch: #  0; line:   144-  158; sop:     0; eop:     2; out1:  -2
path #1: 0,
10
以上信息与没有加 -dvld.verbosity=3 输出信息相比,多了 Add 字段,还有中间代码的操作数据类型,如 IS_CV,IS_CONST 等。
PHP代码代码中 $a = 10; 其中10的类型为 IS_CONST,$a作为一个编译期间的一个缓存变量存在,其类型为 IS_CV
-dvld.execute=0 禁止代码执行,只查看输出OPCODE信息
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
[root@localhost code]# /usr/local/php7.1.11/bin/php -dvld.active=1 -dvld.verbosity=3 -dvld.execute=0 test.php
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Jump found. (Code = 62) Position 1 = -2
filename:       /test/code/test.php
function name:  (null)
number of ops:  3
compiled vars:  !0 = $a
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
144     0  E >   ASSIGN                                                    OP1[  IS_CV !0 ] OP2[ ,  IS_CONST (0) 10 ]
145     1        ECHO                                                      OP1[  IS_CV !0 ]
158     2      > RETURN                                                    OP1[  IS_CONST (1) 1 ]
 
branch: #  0; line:   144-  158; sop:     0; eop:     2; out1:  -2
path #1: 0,
VLD 扩展中可以设置的配置项。代码在VLD扩展源码 vld.c 文件中
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("vld.active",       "0", PHP_INI_SYSTEM, OnUpdateBool, active,       zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.skip_prepend", "0", PHP_INI_SYSTEM, OnUpdateBool, skip_prepend, zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.skip_append""0", PHP_INI_SYSTEM, OnUpdateBool, skip_append,  zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.execute",      "1", PHP_INI_SYSTEM, OnUpdateBool, execute,      zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.verbosity",    "1", PHP_INI_SYSTEM, OnUpdateBool, verbosity,    zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.format",       "0", PHP_INI_SYSTEM, OnUpdateBool, format,       zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.col_sep",      "\t", PHP_INI_SYSTEM, OnUpdateString, col_sep,   zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.save_dir",     "/tmp", PHP_INI_SYSTEM, OnUpdateString, save_dir, zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.save_paths",   "0", PHP_INI_SYSTEM, OnUpdateBool, save_paths,   zend_vld_globals, vld_globals)
    STD_PHP_INI_ENTRY("vld.dump_paths",   "1", PHP_INI_SYSTEM, OnUpdateBool, dump_paths,   zend_vld_globals, vld_globals)
PHP_INI_END()
 
# 默认配置项
static void vld_init_globals(zend_vld_globals *vg)
{
    vg->active       = 0;
    vg->skip_prepend = 0;
    vg->skip_append  = 0;
    vg->execute      = 1;
    vg->format       = 0;
    vg->col_sep   = "\t";
    vg->path_dump_file = NULL;
    vg->dump_paths   = 1;
    vg->save_paths   = 0;
    vg->verbosity    = 1;
}
VLD扩展参数列表
  • -dvld.active 是否在执行PHP时激活VLD挂钩,默认为0,表示禁用。可以使用-dvld.active=1启用。
  • -dvld.skip_prepend 是否跳过php.ini配置文件中auto_prepend_file指定的文件, 默认为0,即不跳过包含的文件,显示这些包含的文件中的代码所生成的中间代码。此参数生效有一个前提条件:-dvld.execute=0
  • -dvld.skip_append 是否跳过php.ini配置文件中auto_append_file指定的文件, 默认为0,即不跳过包含的文件,显示这些包含的文件中的代码所生成的中间代码。此参数生效有一个前提条件:-dvld.execute=0
  • -dvld.execute 是否执行这段PHP脚本,默认值为1,表示执行。可以使用-dvld.execute=0, 表示只显示中间代码,不执行生成的中间代码。
  • -dvld.format 是否以自定义的格式显示,默认为0,表示否。可以使用-dvld.format=1, 表示以自己定义的格式显示。这里自定义的格式输出是以-dvld.col_sep指定的参数间隔
  • -dvld.col_sep 在-dvld.format参数启用时此函数才会有效,默认为 “\t”。
  • -dvld.verbosity 是否显示更详细的信息,默认为1,其值可以为0,1,2,3 其实比0小的也可以, 只是效果和0一样,比如0.1之类,但是负数除外,负数和效果和3的效果一样 比3大的值也是可以的,只是效果和3一样。
  • -dvld.save_dir 指定文件输出的路径,默认路径为/tmp。
  • -dvld.save_paths 控制是否输出文件,默认为0,表示不输出文件
  • -dvld.dump_paths 控制输出的内容,现在只有0和1两种情况,默认为1,输出内容

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注