Как PHP-код операции связан с фактически исполняемым двоичным кодом?
test.php как обычный текст:
<?php
$x = "a";
echo $x;
test.php как код операции:
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 как двоичное представление:
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);
"
(пропустить эхо-выход 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
Теперь я хочу узнать больше о том, как код операции переводится в двоичное представление.
Отредактированный и уточненный вопрос:
Как код кода переведен в двоичную версию?
Вы можете увидеть там ASSIGN of 'a' to! 0?
Есть ли где-то инструкция ECHO и что она выводит?
Я нашел несколько шаблонов в двоичной версии, которые намекают на линейное представление кода операции.
( "2f726f6f742f746573742e706870" - это шестнадцатеричное представление "/root/test.php" )
ИЗМЕНИТЬ
шестнадцатеричное представление показывает шаблоны, когда длина строки равна 4 байтам и сравнивается между различными программами.
...
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
...
Но мои знания о том, как виртуальные машины работают на таком уровне, слишком слабы, чтобы иметь возможность реально проанализировать это и связать его с кодом C.
ИЗМЕНИТЬ
Есть ли у PHP виртуальная машина, например Java?
Является ли механизм Zend встроенным вне PHP?
Ответы
Ответ 1
Отличный вопрос...
UPDATE: коды операций выполняются непосредственно виртуальной машиной PHP (Zend Engine). Похоже, что они выполняются различными функциями обработчика, определенными в. /Zend/zend _vm_execute.h
Обратитесь к к архитектуре Zend Engine для получения дополнительной информации о том, как выполняются коды операций Zend.
Эти ресурсы могут немного помочь:
http://php.net/manual/en/internals2.opcodes.list.php
http://www.php.net/manual/en/internals2.opcodes.ops.php
Кроме того, я собираюсь проверить источник VLD PECL для получения дополнительных подсказок...
http://pecl.php.net/package/vld
http://derickrethans.nl/projects.html#vld
Кроме того, написание авторами расширения VLD Pecl может помочь:
Дерик Ретанс, Андрей Змиевский или Маркус Бёргер
Их адреса электронной почты находятся в верхней части srm_oparray.c в источнике расширения.
UPDATE: нашел еще несколько подсказок
В PHP 5.3.8 я нашел три вывода для того, где выполняются коды операций:
./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
Я не смог найти определение для zend_execute(), но я предполагаю, что он может быть сгенерирован с помощью. /zend _vm_gen.php
Я думаю, что нашел...
./Zend/zend_vm_execute.h:42
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
Я мог ошибаться, но похоже, что все обработчики кода операции также определены в. /Zend/zend _vm_execute.h.
См../Zend/zend_vm_execute.h:2413 для примера того, что выглядит как код операции "целочисленное добавление".
Ответ 2
apc_bin_dump() возвращает необработанное представление записи в кэш памяти.
Он возвращает содержимое apc_bd_t struct.
Эта структура представляет собой массив apc_bd_entry_t с некоторыми контрольными суммами для обнаружения ошибок.
apc_bd_entry_t содержит apc_cache_entry_value_t.
Вы можете посмотреть apc_bin_dump и apc_bin_load внутренние функции чтобы увидеть, как сделаны дамп и нагрузка.