PHP内核之opcode的处理函数查找
2016-08-27 00:01
211 查看
首先我们需要知道有个存放 所有opcode 的 opcode_handler_t 的函数指针字段 的集合 的文件 php-5.5.12\Zend\zend_vm_execute.h
void zend_init_opcodes_handlers(void)
{
/* opcode执行函数的指针字段集合 */
static const opcode_handler_t labels[] = {
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
........
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
}
接下来进入正题:
这里我们使用 日志记录的方式 查找 opcode 对应的处理函数
在 zend_vm_get_opcode_handler 方法中添加以下代码:
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op)
{
static const int zend_vm_decode[] = {
_UNUSED_CODE, /* 0 */
_CONST_CODE, /* 1 = IS_CONST */
_TMP_CODE, /* 2 = IS_TMP_VAR */
_UNUSED_CODE, /* 3 */
_VAR_CODE, /* 4 = IS_VAR */
_UNUSED_CODE, /* 5 */
_UNUSED_CODE, /* 6 */
_UNUSED_CODE, /* 7 */
_UNUSED_CODE, /* 8 = IS_UNUSED */
_UNUSED_CODE, /* 9 */
_UNUSED_CODE, /* 10 */
_UNUSED_CODE, /* 11 */
_UNUSED_CODE, /* 12 */
_UNUSED_CODE, /* 13 */
_UNUSED_CODE, /* 14 */
_UNUSED_CODE, /* 15 */
_CV_CODE /* 16 = IS_CV */
};
/* 日志记录法记录opcode的处理函数 */
int op_index;
FILE *stream;
op_index = opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type];
if((stream = fopen("./tmp/php-opcode.log", "a+")) != NULL){
fprintf(stream, "opcode: %d, zend_opcode_handlers_index: %d\n", opcode, op_index );
}
fclose(stream);
return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];
}
然后编译php源码包,为了方便看代码中的opcode,编译时候记得开启动态链接库 vld
configure --disable-all --enable-snapshot-build --enable-cli --enable-cgi --enable-object-out-dir=..\obj --enable-session --enable-vld=shared
编译完成后
1、在生成的 obj\Release_TS\php-5.5.12 下 手动新建 tmp 文件夹
2、在生成的 obj\Release_TS\php-5.5.12 下 做php.ini文件 并制定ext为扩展目录
3、添加php_vld.dll扩展
至此准备工作完成,接下来 我们看步入真正的查找工作
php代码:
opcode信息:
生成的opcode.log日志
其中的
opcode 数值 可从 http://php.net/manual/zh/internals2.opcodes.list.php 中查找到
zend_opcode_handlers_index 就是 stati cconst opcode_handler_t labels[] 的索引,里面对应了处理函数的名称
void zend_init_opcodes_handlers(void)
{
/* opcode执行函数的指针字段集合 */
static const opcode_handler_t labels[] = {
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
........
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
}
接下来进入正题:
这里我们使用 日志记录的方式 查找 opcode 对应的处理函数
在 zend_vm_get_opcode_handler 方法中添加以下代码:
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op)
{
static const int zend_vm_decode[] = {
_UNUSED_CODE, /* 0 */
_CONST_CODE, /* 1 = IS_CONST */
_TMP_CODE, /* 2 = IS_TMP_VAR */
_UNUSED_CODE, /* 3 */
_VAR_CODE, /* 4 = IS_VAR */
_UNUSED_CODE, /* 5 */
_UNUSED_CODE, /* 6 */
_UNUSED_CODE, /* 7 */
_UNUSED_CODE, /* 8 = IS_UNUSED */
_UNUSED_CODE, /* 9 */
_UNUSED_CODE, /* 10 */
_UNUSED_CODE, /* 11 */
_UNUSED_CODE, /* 12 */
_UNUSED_CODE, /* 13 */
_UNUSED_CODE, /* 14 */
_UNUSED_CODE, /* 15 */
_CV_CODE /* 16 = IS_CV */
};
/* 日志记录法记录opcode的处理函数 */
int op_index;
FILE *stream;
op_index = opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type];
if((stream = fopen("./tmp/php-opcode.log", "a+")) != NULL){
fprintf(stream, "opcode: %d, zend_opcode_handlers_index: %d\n", opcode, op_index );
}
fclose(stream);
return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];
}
然后编译php源码包,为了方便看代码中的opcode,编译时候记得开启动态链接库 vld
configure --disable-all --enable-snapshot-build --enable-cli --enable-cgi --enable-object-out-dir=..\obj --enable-session --enable-vld=shared
编译完成后
1、在生成的 obj\Release_TS\php-5.5.12 下 手动新建 tmp 文件夹
2、在生成的 obj\Release_TS\php-5.5.12 下 做php.ini文件 并制定ext为扩展目录
3、添加php_vld.dll扩展
至此准备工作完成,接下来 我们看步入真正的查找工作
php代码:
opcode信息:
生成的opcode.log日志
其中的
opcode 数值 可从 http://php.net/manual/zh/internals2.opcodes.list.php 中查找到
zend_opcode_handlers_index 就是 stati cconst opcode_handler_t labels[] 的索引,里面对应了处理函数的名称
相关文章推荐
- 利用PHP扩展vld查看PHP opcode操作步骤
- 为PHP5.4开启Zend OPCode缓存
- 深入理解PHP之OpCode原理详解
- PHP内核学习教程之php opcode内核实现
- 深入理解PHP之OpCode原理详解
- Dalvik字节码——初识
- 在RHEL/CentOS 6.3/5.6和Fedora 17/12上安装APC
- 一个简单的反汇编引擎的实现小记
- 64位下对Mod/RM 的解析
- 64位下的操作数大小
- php内核探索=opcode
- 使用 Zend Opcache 加速 PHP
- PHP内核之opcode 变量哪里去了
- PHP内核之opcode解读
- 通过VLD扩展分析PHP opcode
- 操作码OpCode
- PHP里的opcode(2)
- 前端开发中的性能那点事(三)php的opcode缓存
- 安装与使用vld查看php的opcode代码
- 记录一下xcache导致的php-fpm 502问题