加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

如何使用PHP Embed SAPI实现Opcodes查看器

发布时间:2020-05-23 18:54:35 所属栏目:PHP 来源:互联网
导读:这篇文章主要介绍了如何使用PHP Embed SAPI实现Opcodes查看器的相关资料,需要的朋友可以参考下

PHP提供了一个Embed SAPI,也就是说,PHP容许你在C/C++语言中调用PHP/ZE提供的函数。本文就通过基于Embed SAPI实现一个PHP的opcodes查看器。

首先,下载PHP源码以供编译, 我现在使用的是PHP5.3 alpha2

进入源码目录:

./configure --enable-embed --with-config-file-scan-dir=/etc/php.d --with-mysql --with-config-file-path=/etc/ ./make ./make install

最后,记得要将生成的libphp5.so复制到运行时库的目录,我直接拷贝到了/lib/,否则会在运行你自己的embed程序的时候报错:

./embed: error while loading shared libraries: libphp5.so: cannot open shared object file: No such file or directory

如果你对PHP的SAPI还不熟悉的话,我建议你看看我的这篇文章:深入理解Zend SAPIs(Zend SAPI Internals) 这个时候,你就可以在你的C代码中,嵌入PHP脚本解析器了, 我的例子:

然后就是要指明include path了,一个简单的Makefile

编译成功以后, 运行,我们可以看到, stdout输出 Hello World!

基于这个,我们就可以很容易的实现一个类似于vld的Opcodes dumper: 首先我们定义opcode的转换函数(全部的opcodes可以查看Zend/zend_vm_opcodes.h);

然后定义zval和znode的输出函数:

type) { case IS_NULL: return "NULL"; case IS_LONG: case IS_BOOL: snprintf(buffer,BUFFER_LEN,"%d",z->value.lval); return buffer; case IS_DOUBLE: snprintf(buffer,"%f",z->value.dval); return buffer; case IS_STRING: snprintf(buffer,""%s"",z->value.str.val); return buffer; case IS_ARRAY: case IS_OBJECT: case IS_RESOURCE: case IS_CONSTANT: case IS_CONSTANT_ARRAY: return ""; default: return "unknown"; } } char * format_znode(znode *n){ static char buffer[BUFFER_LEN]; switch (n->op_type) { case IS_CONST: return format_zval(&n->u.constant); break; case IS_VAR: snprintf(buffer,"$%d",n->u.var/sizeof(temp_variable)); return buffer; break; case IS_TMP_VAR: snprintf(buffer,"~%d",n->u.var/sizeof(temp_variable)); return buffer; break; default: return ""; break; } }

然后定义op_array的输出函数:

lineno,opname(op->opcode),format_znode(&op->op1),format_znode(&op->op2),format_znode(&op->result)) ; } void dump_op_array(zend_op_array *op_array){ if(op_array) { int i; printf("%5s %5s %30s %040s %040s %040sn","opnum","line","opcode","op1","op2","result"); for(i = 0; i < op_array->last; i++) { dump_op(&op_array->opcodes[i],i); } } }

最后,就是程序的主函数了:

n"); return 1; } PHP_EMBED_START_BLOCK(argc,argv); printf("Script: %sn",argv[1]); file_handle.filename = argv[1]; file_handle.free_filename = 0; file_handle.type = ZEND_HANDLE_FILENAME; file_handle.opened_path = NULL; op_array = zend_compile_file(&file_handle,ZEND_INCLUDE TSRMLS_CC); if(!op_array) { printf("Error parsing script: %sn",file_handle.filename); return 1; } dump_op_array(op_array); PHP_EMBED_END_BLOCK(); return 0; }

编译,运行测试脚本(sample.php):

代码如下:

命令:

代码如下:

得到输出结果(如果你对下面的结果很迷惑,那么建议你再看看我的这篇文章:

Script: sample.php

opnum line opcode op1 op2 result 0 2 ZEND_ECHO "laruence" 1 4 ZEND_RETURN 1

呵呵,怎么样,是不是很好玩呢?

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读