2011-12-01 27 views
15

test.php dưới dạng văn bản đơn giản:PHP opcode liên quan đến mã nhị phân thực thi như thế nào?

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

test.php như opcode:

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 như biểu diễn nhị phân:

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); 
" 

(bỏ qua đầu ra echo của 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 

Bây giờ tôi muốn tìm hiểu thêm về cách opcode dịch sang biểu diễn nhị phân.

Các biên tập và làm sáng tỏ câu hỏi:

Làm thế nào là opcode dịch sang phiên bản nhị phân? Bạn có thể thấy ở đó ASSIGN của 'a' đến 0 không? Có trong đó một nơi nào đó tuyên bố ECHO và những gì nó kết quả đầu ra?

Tôi đã tìm thấy một số mẫu trong phiên bản nhị phân gợi ý tại một dòng bằng cách trình bày dòng của opcode.

("2f726f6f742f746573742e706870" là đại diện thập lục phân của "/root/test.php")

EDIT:

đại diện thập lục phân tiết lộ mẫu khi dòng dài được thiết lập đến 4 byte và so sánh giữa các chương trình khác nhau.

... 
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 
... 

Nhưng kiến ​​thức về cách máy ảo hoạt động ở mức quá yếu để có thể phân tích thật kỹ và liên kết mã đó với mã C.

EDIT:

Does PHP have a virtual machine like Java?

Is the Zend engine embeddable outside of PHP?

Trả lời

9

Great câu hỏi ...

UPDATE: opcodes được thực hiện trực tiếp bởi PHP Virtual Machine (Zend Engine). Dường như chúng được thực hiện bởi các hàm xử lý khác nhau được xác định trong ./Zend/zend_vm_execute.h

Xem the architecture of the Zend Engine để biết thêm thông tin về cách thực hiện mã lệnh Zend.

Những nguồn này có thể giúp đỡ một chút:

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

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

Ngoài ra, tôi sẽ kiểm tra các PECL VLD Nguồn để biết thêm manh mối ...

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

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

Ngoài ra, viết các tác giả của VLD PECL phần mở rộng có thể giúp: Derick Rethans, Andrei Zmievski hoặc Marcus Borger

địa chỉ email của họ là ở đầu srm_oparray. c trong nguồn mở rộng.

UPDATE: tìm thấy một số manh mối hơn

Trong PHP 5.3.8, tôi thấy ba dẫn cho nơi opcodes được thực hiệ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 

tôi không thể tìm thấy định nghĩa cho zend_execute(), nhưng tôi đoán nó có thể được tạo ra với ./zend_vm_gen.php

tôi nghĩ rằng tôi thấy nó ...

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

Tôi có thể sai, nhưng có vẻ như tất cả các trình xử lý opcode được định nghĩa trong ./Zend/zend_vm_execute.h.

Xem ./Zend/zend_vm_execute.h:2413 để biết ví dụ về những gì có vẻ là opcode "số nguyên bổ sung".

+0

đã kiểm tra các tài nguyên đó; như tôi đang sử dụng VLD ở trên. Họ dường như bao gồm việc chuyển đổi từ mã PHP sang mã opcode. – Raffael

+0

Đã cập nhật ... đã thêm đề xuất địa chỉ email. – Homer6

+0

Vì vậy, bạn đã kiểm tra mã nguồn? Điều này sẽ dẫn đến một nơi nào đó chắc chắn. Nhưng tôi không giao tiếp với C, đó là điểm chấp của tôi. Tất cả những gì tôi thấy cho đến nay là T_ECHO được gán cho số 316. – Raffael

3

apc_bin_dump() trả về biểu diễn thô của mục nhập bộ nhớ cache trong bộ nhớ.

Nó trả về nội dung của apc_bd_t struct.

Cấu trúc này là một mảng apc_bd_entry_t với một số tổng kiểm tra để phát hiện lỗi.

apc_bd_entry_t chứa apc_cache_entry_value_t.

Bạn có thể xem các chức năng nội bộ apc_bin_dumpapc_bin_load để xem cách kết xuất và tải.

+0

đó là gợi ý có giá trị – Raffael

Các vấn đề liên quan