2011-12-01 18 views
15

test.php como texto sin formato:¿cómo se relaciona el código de operación de PHP con el código binario realmente ejecutado?

<?php 
$x = "a"; 
echo $x; 

test.php como código de operación:

debian:~ php -d vld.active=1 -d vld.execute=0 -f test.php 

Finding entry points 
Branch analysis from position: 0 
Return found 
filename:  /root/test.php 
function name: (null) 
number of ops: 5 
compiled vars: !0 = $x 
line  # * op       fetch   ext return operands 
--------------------------------------------------------------------------------- 
    2  0 > EXT_STMT 
     1  ASSIGN             !0, 'a' 
    3  2  EXT_STMT 
     3  ECHO              !0 
    4  4 > RETURN             1 

branch: # 0; line:  2- 4; sop:  0; eop:  4 
path #1: 0, 

test.php como representación binaria:

debian:~ php -d apc.stat=0 -r " 
    require '/root/test.php'; 
    echo PHP_EOL; 
    echo chunk_split(bin2hex(
    apc_bin_dump(array('/root/test.php')) 
),64); 
" 

(saltando el eco-salida de test.php)

b110000001000000325dedaa64d801bca2f73027abf0d5ab67f3023901000000 
    2c0000000a000000871000000300000000000000000000004c0000005b000000 
    8a0200008a020000650000002f726f6f742f746573742e7068700002070f9c00 
    00000000000000000000000000000000000000000000000000000000000100fa 
    000000fe00000005000000050000007c02000001000000100000000100000000 
    00000000000000ffffffff0000000000000000000000000000000000000000ff 
    ffffffeb00000000000000000000000000000000000000ffffffff0000000000 
    00000001000000000000002f726f6f742f746573742e7068700001000000204a 
    3308080000000000000000000000000000000000000008000000000000000000 
    0000000000000000000008000000000000000000000000000000000000000000 
    00000200000065000000204a3308040000000000000001000000000000000000 
    00001000000000000000100000000100000006000000010000007a0200000100 
    00000100000006000000000000000200000026000000204a3308080000000000 
    0000000000000000000000000000080000000000000000000000000000000000 
    0000080000000000000000000000000000000000000000000000030000006500 
    0000900f34080800000000000000000000000000000000000000100000000000 
    0000100000000100000006000000080000000000000000000000000000000000 
    0000000000000300000028000000204a33080800000000000000000000000000 
    00000000000001000000010000002c70d7b6010000000100d7b6080000000000 
    000000000000000000000000000000000000040000003e000000610088020000 
    01000000bd795900780000000000000000000000000000000000000000000000 
[ ... a lot of lines just containing 0s ... ] 
    0000000000000038000000c30000007f0000007a010000830000007c0200008f 
    0000003c000000400000004400000008 

Ahora quiero obtener más información acerca de cómo el opcode se traduce a la representación binaria.

La editado y aclarado pregunta:

¿Cómo se traduce el código de operación en la versión binaria? ¿Puedes ver allí la ASIGNACIÓN de 'a' a! 0? ¿Hay alguna parte de la declaración de ECHO y su resultado?

Encontré algunos patrones en la versión binaria que sugieren una representación línea por línea del código de operación.

("2f726f6f742f746573742e706870" es la representación hexadecimal de "/root/test.php")

EDITAR:

la representación hexadecimal revela patrones cuando el la línea de longitud se establece en 4 bytes y comparado entre diferentes programas.

... 
00000002 // 2 seems to be something like the "line number" 
00000065 // seems to increase by 1 for every subsequent statement. 
00000040 // 
06330808 // seems to mark the START of a statement 
00000000 
00000000 
00000000 
00000000 
00000001 // 
00000012 // In a program with three echo statements, 
03000007 // this block was present three times. With mild 
00000001 // changes that seem to represent the spot where 
00000006 // the output-string is located. 
00000008 // 
00000000 
00000000 
00000000 
00000000 
00000000 
00000002 // 2 seems to be something like the "line number" 
00000028 // 
00000020 // 
4a330808 // seems to mark the END of a statement 
00000000 
00000000 
00000000 
00000000 
00000008 // repeating between (echo-)statements 
00000000 
00000000 
00000000 
00000000 
00000008 // repeating between (echo-)statements 
... 

Pero mi conocimiento de cómo funcionan las máquinas virtuales en un nivel tal es demasiado débil para ser capaz de analizar realmente tan propperly y vincularlo con el código C.

EDITAR:

Does PHP have a virtual machine like Java?

Is the Zend engine embeddable outside of PHP?

Respuesta

9

Gran pregunta ...

ACTUALIZACIÓN: códigos de operación son ejecutados directamente por la máquina virtual de PHP (Zend Engine). Parece como si fueran ejecutados por diferentes funciones de controlador definidas en ./Zend/zend_vm_execute.h

Consulte the architecture of the Zend Engine para obtener más información sobre cómo se ejecutan los códigos de operación de Zend.

Estos recursos pueden ayudar un poco:

http://php.net/manual/en/internals2.opcodes.list.php

http://www.php.net/manual/en/internals2.opcodes.ops.php

Además, voy a la caja de los PECL VLD Fuente de más pistas ...

http://pecl.php.net/package/vld

http://derickrethans.nl/projects.html#vld

Además, la escritura de los autores del VLD extensión PECL puede ayudar: Derick Rethans, Andrei Zmievski o Marcus Börger

Sus direcciones de correo electrónico están en la parte superior de srm_oparray. c en la fuente de extensión.

ACTUALIZACIÓN: encontrado algunas pistas más

En PHP 5.3.8, me encontré con tres conductores para donde se ejecutan los códigos de operación:

./Zend/zend_execute.c:1270 
ZEND_API void execute_internal 

./Zend/zend.c:1214:ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) 
./Zend/zend.c:1236:     zend_execute(EG(active_op_array) TSRMLS_CC); 

./Zend/zend_vm_gen.php 

no pude encontrar la definición para zend_execute(), pero supongo que podría ser generado con ./zend_vm_gen.php

Creo que lo encontré ...

./Zend/zend_vm_execute.h:42 
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) 

Podría estar equivocado, pero parece que todos los manejadores de código de operación están definidos en ./Zend/zend_vm_execute.h también.

Consulte ./Zend/zend_vm_execute.h:2413 para ver un ejemplo de lo que parece ser el código de operación "entero agregado".

+0

ya verificó esos recursos; ya que estoy usando VLD arriba. Simplemente parecen cubrir la transición del código PHP al código de operación. – Raffael

+0

Actualizado ... sugerencia de dirección de correo electrónico agregada. – Homer6

+0

¿Ya has verificado el código fuente? Esto llevaría a algún lugar seguro. Pero no estoy familiarizado con C, esa es mi desventaja. Todo lo que encontré hasta ahora es que T_ECHO está asignado al número 316. – Raffael

3

apc_bin_dump() devuelve la representación sin formato de una entrada de memoria caché en memoria.

Devuelve el contenido de apc_bd_t struct.

Esta estructura es una matriz de apc_bd_entry_t con algunas sumas de comprobación para la detección de errores.

apc_bd_entry_t contiene un apc_cache_entry_value_t.

Puede consultar las funciones internas apc_bin_dump y apc_bin_load para ver cómo se realizan el volcado y la carga.

+0

que es una pista valiosa – Raffael

Cuestiones relacionadas