您好,欢迎访问一九零五行业门户网

如何使用PHP Embed SAPI实现Opcodes查看器,sapiopcodes_PHP教程

如何使用php embed sapi实现opcodes查看器,sapiopcodesphp提供了一个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.hint 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; }}
然后定义op_array的输出函数:
void dump_op(zend_op *op, int num){ printf(%5d %5d %30s %040s %040s %040s\n, num, op->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 %040s\n, opnum, line, opcode, op1, op2, result); for(i = 0; i last; i++) { dump_op(&op_array->opcodes[i], i); } }}
最后,就是程序的主函数了:
int main(int argc, char **argv){ zend_op_array *op_array; zend_file_handle file_handle; if(argc != 2) { printf(usage: op_dumper \n); return 1; } php_embed_start_block(argc,argv); printf(script: %s\n, 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: %s\n, file_handle.filename); return 1; } dump_op_array(op_array); php_embed_end_block(); return 0;}
编译,运行测试脚本(sample.php):
复制代码 代码如下:
sample.php:
   echo laruence;
命令:
复制代码 代码如下:
./opcodes_dumper  sample.php
得到输出结果(如果你对下面的结果很迷惑,那么建议你再看看我的这篇文章:深入理解php原理之opcodes):
script: sample.php
opnum   line                         opcode                                      op1                                      op2                                   result
    0      2                      zend_echo                               laruence
    1      4                    zend_return                                        1
呵呵,怎么样,是不是很好玩呢?
http://www.bkjia.com/phpjc/1069344.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/1069344.htmltecharticle如何使用php embed sapi实现opcodes查看器,sapiopcodes php提供了一个embed sapi,也就是说,php容许你在c/c++语言中调用php/ze提供的函数。本文就通过...
其它类似信息

推荐信息