首页 > 开发 > PHP > 正文

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

2024-05-04 22:34:14
字体:
来源:转载
供稿:网友

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 "sapi/embed/php_embed.h"int main(int argc, char * argv[]){ PHP_EMBED_START_BLOCK(argc,argv); char * script = " print 'Hello World!';"; zend_eval_string(script, NULL,          "Simple Hello World App" TSRMLS_CC); PHP_EMBED_END_BLOCK(); return 0;}

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

CC = gccCFLAGS = -I/usr/local/include/php/ /   -I/usr/local/include/php/main /   -I/usr/local/include/php/Zend /   -I/usr/local/include/php/TSRM /   -Wall -gLDFLAGS = -lstdc++ -L/usr/local/lib -lphp5ALL: $(CC) -o embed embed.cpp $(CFLAGS) $(LDFLAGS)

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

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

char *opname(zend_uchar opcode){ switch(opcode) {  case ZEND_NOP: return "ZEND_NOP"; break;  case ZEND_ADD: return "ZEND_ADD"; break;  case ZEND_SUB: return "ZEND_SUB"; break;  case ZEND_MUL: return "ZEND_MUL"; break;  case ZEND_DIV: return "ZEND_DIV"; break;  case ZEND_MOD: return "ZEND_MOD"; break;  case ZEND_SL: return "ZEND_SL"; break;  case ZEND_SR: return "ZEND_SR"; break;  case ZEND_CONCAT: return "ZEND_CONCAT"; break;  case ZEND_BW_OR: return "ZEND_BW_OR"; break;  case ZEND_BW_AND: return "ZEND_BW_AND"; break;  case ZEND_BW_XOR: return "ZEND_BW_XOR"; break;  case ZEND_BW_NOT: return "ZEND_BW_NOT"; break;  /*...省略 ....*/  default : return "UNKNOW"; break;

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

 char *format_zval(zval *z){ static char buffer[BUFFER_LEN]; int len; switch(z->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, BUFFER_LEN, "%f", z->value.dval);   return buffer;  case IS_STRING:   snprintf(buffer, BUFFER_LEN, "/"%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, BUFFER_LEN, "$%d", n->u.var/sizeof(temp_variable));   return buffer;   break;  case IS_TMP_VAR:   snprintf(buffer, BUFFER_LEN, "~%d", n->u.var/sizeof(temp_variable));   return buffer;   break;  default:   return "";   break; }}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表