• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

            使用PHP Embed SAPI實(shí)現(xiàn)Opcodes查看器

            http://www.laruence.com/2008/09/23/539.html

             

            PHP提供了一個(gè)Embed SAPI,也就是說,PHP容許你在C/C++語言中調(diào)用PHP/ZE提供的函數(shù)。本文就通過基于Embed SAPI實(shí)現(xiàn)一個(gè)PHP的opcodes查看器。
            首先,下載PHP源碼以供編譯, 我現(xiàn)在使用的是PHP5.3 alpha2
            進(jìn)入源碼目錄:

            1. ./configure --enable-embed --with-config-file-scan-dir=/etc/php.d --with-mysql --with-config-file-path=/etc/
            2. ./make
            3. ./make instal

            最后,記得要將生成的libphp5.so復(fù)制到運(yùn)行時(shí)庫的目錄,我直接拷貝到了/lib/, 否則會(huì)在運(yùn)行你自己的embed程序的時(shí)候報(bào)錯(cuò):

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

            如果你對PHP的SAPI還不熟悉的話,我建議你看看我的這篇文章:深入理解Zend SAPIs(Zend SAPI Internals)
            這個(gè)時(shí)候,你就可以在你的C代碼中,嵌入PHP腳本解析器了, 我的例子:

            1. #include "sapi/embed/php_embed.h"
            2.  
            3. int main(int argc, char * argv[]){
            4.     PHP_EMBED_START_BLOCK(argc,argv);
            5.     char * script = " print 'Hello World!';";
            6.     zend_eval_string(script, NULL,
            7.                                       "Simple Hello World App" TSRMLS_CC);
            8.     PHP_EMBED_END_BLOCK();
            9.     return 0;
            10. }
            11.  

            然后就是要指明include path了,一個(gè)簡單的Makefile

            1. CC = gcc
            2. CFLAGS = -I/usr/local/include/php/ \
            3.             -I/usr/local/include/php/main \
            4.             -I/usr/local/include/php/Zend \
            5.             -I/usr/local/include/php/TSRM \
            6.             -Wall -g
            7. LDFLAGS = -lstdc++ -L/usr/local/lib -lphp5
            8. ALL:
            9.     $(CC) -o embed embed.cpp $(CFLAGS) $(LDFLAGS

            編譯成功以后, 運(yùn)行,我們可以看到, stdout輸出 Hello World!

            基于這個(gè),我們就可以很容易的實(shí)現(xiàn)一個(gè)類似于vld的Opcodes dumper:
            首先我們定義opcode的轉(zhuǎn)換函數(shù)(全部的opcodes可以查看Zend/zend_vm_opcodes.h);

            1. char *opname(zend_uchar opcode){
            2.     switch(opcode) {
            3.         case ZEND_NOP: return "ZEND_NOP"; break;
            4.         case ZEND_ADD: return "ZEND_ADD"; break;
            5.         case ZEND_SUB: return "ZEND_SUB"; break;
            6.         case ZEND_MUL: return "ZEND_MUL"; break;
            7.         case ZEND_DIV: return "ZEND_DIV"; break;
            8.         case ZEND_MOD: return "ZEND_MOD"; break;
            9.         case ZEND_SL: return "ZEND_SL"; break;
            10.         case ZEND_SR: return "ZEND_SR"; break;
            11.         case ZEND_CONCAT: return "ZEND_CONCAT"; break;
            12.         case ZEND_BW_OR: return "ZEND_BW_OR"; break;
            13.         case ZEND_BW_AND: return "ZEND_BW_AND"; break;
            14.         case ZEND_BW_XOR: return "ZEND_BW_XOR"; break;
            15.         case ZEND_BW_NOT: return "ZEND_BW_NOT"; break;
            16.         /*...省略 ....*/
            17.         default : return "UNKNOW"; break;

            然后定義zval和znode的輸出函數(shù):

            1.  char *format_zval(zval *z)
            2. {
            3.     static char buffer[BUFFER_LEN];
            4.     int len;
            5.  
            6.     switch(z->type) {
            7.         case IS_NULL:
            8.             return "NULL";
            9.         case IS_LONG:
            10.         case IS_BOOL:
            11.             snprintf(buffer, BUFFER_LEN, "%d", z->value.lval);
            12.             return buffer;
            13.         case IS_DOUBLE:
            14.             snprintf(buffer, BUFFER_LEN, "%f", z->value.dval);
            15.             return buffer;
            16.         case IS_STRING:
            17.             snprintf(buffer, BUFFER_LEN, "\"%s\"", z->value.str.val);
            18.             return buffer;
            19.         case IS_ARRAY:
            20.         case IS_OBJECT:
            21.         case IS_RESOURCE:
            22.         case IS_CONSTANT:
            23.         case IS_CONSTANT_ARRAY:
            24.             return "";
            25.         default:
            26.             return "unknown";
            27.     }
            28. }
            29.  
            30. char * format_znode(znode *n){
            31.     static char buffer[BUFFER_LEN];
            32.  
            33.     switch (n->op_type) {
            34.         case IS_CONST:
            35.             return format_zval(&n->u.constant);
            36.             break;
            37.         case IS_VAR:
            38.             snprintf(buffer, BUFFER_LEN, "$%d", n->u.var/sizeof(temp_variable));
            39.             return buffer;
            40.             break;
            41.         case IS_TMP_VAR:
            42.             snprintf(buffer, BUFFER_LEN, "~%d", n->u.var/sizeof(temp_variable));
            43.             return buffer;
            44.             break;
            45.         default:
            46.             return "";
            47.             break;
            48.     }
            49. }
            50.  

            然后定義op_array的輸出函數(shù):

            1. void dump_op(zend_op *op, int num){
            2.     printf("%5d %5d %30s %040s %040s %040s\n", num, op->lineno,
            3.             opname(op->opcode),
            4.             format_znode(&op->op1),
            5.             format_znode(&op->op2),
            6.             format_znode(&op->result)) ;
            7. }
            8.  
            9. void dump_op_array(zend_op_array *op_array){
            10.     if(op_array) {
            11.         int i;
            12.         printf("%5s %5s %30s %040s %040s %040s\n", "opnum", "line", "opcode", "op1", "op2", "result");
            13.         for(i = 0; i < op_array->last; i++) {
            14.             dump_op(&op_array->opcodes[i], i);
            15.         }
            16.     }
            17. }

            最后,就是程序的主函數(shù)了:

            1. int main(int argc, char **argv){
            2.     zend_op_array *op_array;
            3.     zend_file_handle file_handle;
            4.  
            5.     if(argc != 2) {
            6.         printf("usage: op_dumper <script>\n");
            7.         return 1;
            8.     }
            9.     PHP_EMBED_START_BLOCK(argc,argv);
            10.     printf("Script: %s\n", argv[1]);
            11.     file_handle.filename = argv[1];
            12.     file_handle.free_filename = 0;
            13.     file_handle.type = ZEND_HANDLE_FILENAME;
            14.     file_handle.opened_path = NULL;
            15.     op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
            16.     if(!op_array) {
            17.         printf("Error parsing script: %s\n", file_handle.filename);
            18.         return 1;
            19.     }
            20.     dump_op_array(op_array);
            21.     PHP_EMBED_END_BLOCK();
            22.     return 0;
            23. }

            編譯,運(yùn)行測試腳本(sample.php):
            sample.php:

            1.    echo "laruence";

            命令:

            1. ./opcodes_dumper sample.ph

            得到輸出結(jié)果(如果你對下面的結(jié)果很迷惑,那么建議你再看看我的這篇文章:深入理解PHP原理之Opcodes):

            1. Script: sample.php
            2. opnum line opcode op1 op2 result
            3.     0 2 ZEND_ECHO "laruence"
            4.     1 4 ZEND_RETURN

            呵呵,怎么樣,是不是很好玩呢?
            源碼地址:http://code.google.com/p/opcodesdumper/

            posted on 2011-06-19 20:53 肥仔 閱讀(514) 評論(0)  編輯 收藏 引用 所屬分類: Web-后臺

            伊色综合久久之综合久久| 热久久这里只有精品| 久久人人爽人人爽人人片AV东京热 | 久久精品亚洲福利| 亚洲美日韩Av中文字幕无码久久久妻妇 | 国产精品美女久久久久网| 999久久久国产精品| 日批日出水久久亚洲精品tv| 久久亚洲精品国产精品婷婷| 久久久精品人妻一区二区三区蜜桃| 久久国产精品-久久精品| 久久婷婷五月综合97色直播| 亚洲av伊人久久综合密臀性色| 97超级碰碰碰碰久久久久| 精品一二三区久久aaa片| 色综合合久久天天综合绕视看| 久久久午夜精品福利内容| 久久这里只精品国产99热 | 一本色道久久88精品综合| 色偷偷888欧美精品久久久| 精品国产乱码久久久久软件| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 国产成人无码久久久精品一| 久久天天躁狠狠躁夜夜不卡 | 一本一道久久综合狠狠老 | 久久精品国产男包| 久久久久婷婷| 国产L精品国产亚洲区久久| 欧洲精品久久久av无码电影| 亚洲国产成人精品无码久久久久久综合 | 久久精品国产亚洲αv忘忧草| 久久久久一本毛久久久| 欧美伊香蕉久久综合类网站| 婷婷久久久亚洲欧洲日产国码AV| 一本一道久久a久久精品综合| 99久久婷婷国产综合精品草原| 精品久久久久久亚洲精品 | 精品无码久久久久国产动漫3d| 亚洲国产成人久久综合碰| 午夜福利91久久福利| 理论片午午伦夜理片久久|