How to implement opcodes Viewer using PHP Embed SAPI, sapiopcodes_php tutorial

Source: Internet
Author: User
Tags php source code sapi

How to implement the Opcodes Viewer using PHP Embed SAPI, Sapiopcodes


PHP provides a embed SAPI, which means that PHP allows you to invoke functions provided by php/ze in the C + + language. This article implements a PHP Opcodes viewer based on the embed SAPI.

First of all, download the PHP source code for compiling, I now use PHP5.3 alpha2

Enter the source directory:

./configure--enable-embed--WITH-CONFIG-FILE-SCAN-DIR=/ETC/PHP.D--with-mysql--with-config-file-path=/etc/
./make
./make Install

Finally, remember to copy the generated libphp5.so to the runtime library directory, I copied directly to the/lib/, otherwise you will run your own embed program when the error:

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

If you are not familiar with PHP SAPI, I suggest you look at my article: in-depth understanding Zend Sapis (Zend SAPI Internals)
This time, you can embed the PHP script parser in your C code, my example:

#include "sapi/embed/php_embed.h" int main (int argc, char * argv[]) {php_embed_start_block (ARGC,ARGV); char * script = "PR int ' Hello world! '; "; zend_eval_string (script, NULL,          "Simple Hello World App" TSRMLS_CC); Php_embed_end_block (); return 0;}

Then it is to indicate the include path, a simple 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)

After the compilation succeeds, run, we can see that the stdout output Hello world!

Based on this, we can easily implement a VLD-like opcodes dumper:
First we define the opcode conversion function (all opcodes can see the zend/zend_vm_opcodes.h);

Char *opname (Zend_uchar opcode) {switch (opcode) {case  Zend_nop:return "Zend_nop";  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;  /*... Omit .... */  Default:return "unknow"; break;

Then define the output functions for Zval and 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 }}

Then define the output function of the Op_array:

void Dump_op (zend_op *op, int num) {printf ("%5d%5d%30s%040s%040s%040s\n", num, Op->lineno, Opname   (op->opcod e),   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 < op_array->last; i++) {   dump_op (&op_array->opcodes[i], i);}}}  

Finally, the main function of the program is:

int main (int argc, char **argv) {Zend_op_array *op_array; zend_file_handle file_handle; if (argc! = 2) {printf ("Usage:op _dumper
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.