Tệp .dex
là định dạng truyền tải cho mã byte Dalvik. Có một số ràng buộc về cú pháp và ngữ nghĩa nhất định để một tệp trở thành tệp .dex
hợp lệ và cần có thời gian chạy để chỉ hỗ trợ các tệp .dex hợp lệ.
Các ràng buộc chung về tính toàn vẹn của .dex
Các ràng buộc toàn vẹn chung liên quan đến cấu trúc lớn hơn của tệp .dex
, như được mô tả chi tiết ở định dạng .dex
.
Mã định danh | Sự miêu tả |
---|---|
G1 | Số magic của tệp .dex phải là dex\n035\0 hoặc dex\n037\0 . |
G2 | Tổng kiểm tra phải là tổng kiểm tra Adler-32 của toàn bộ nội dung tệp ngoại trừ trường magic và checksum . |
G3 | Chữ ký phải là hàm băm SHA-1 của toàn bộ nội dung tệp ngoại trừ magic , checksum và signature . |
G4 | file_size phải khớp với kích thước tệp thực tế tính bằng byte. |
G5 | header_size phải có giá trị: 0x70 |
G6 | endian_tag phải có giá trị: ENDIAN_CONSTANT hoặc REVERSE_ENDIAN_CONSTANT |
G7 | Đối với mỗi phần link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs và các phần data , các trường offset và size phải bằng 0 hoặc khác 0. Trong trường hợp sau, phần bù phải được căn chỉnh theo bốn byte. |
G8 | Tất cả các trường offset trong tiêu đề ngoại trừ map_off phải được căn chỉnh theo bốn byte. |
G9 | Trường map_off phải bằng 0 hoặc trỏ vào phần dữ liệu. Trong trường hợp sau, phần data phải tồn tại. |
G10 | Không có phần link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs và phần data nào phải trùng lặp với nhau hoặc phần tiêu đề. |
G11 | Nếu bản đồ tồn tại thì mỗi mục bản đồ phải có loại hợp lệ. Mỗi loại có thể xuất hiện nhiều nhất một lần. |
G12 | Nếu một bản đồ tồn tại thì mỗi mục bản đồ phải có độ lệch và kích thước khác 0. Phần bù phải trỏ vào phần tương ứng của tệp (tức là string_id_item phải trỏ vào phần string_ids ) và kích thước rõ ràng hoặc ẩn của mục phải khớp với nội dung và kích thước thực tế của phần đó. |
G13 | Nếu bản đồ tồn tại thì độ lệch của mục bản đồ n+1 phải lớn hơn hoặc bằng độ lệch của mục bản đồ n plus than size of map entry n . Điều này ngụ ý các mục không chồng chéo và thứ tự từ thấp đến cao. |
G14 | Các loại mục sau đây phải có phần bù được căn chỉnh theo bốn byte: string_id_item , type_id_item , proto_id_item , field_id_item , method_id_item , class_def_item , type_list , code_item , annotations_directory_item . |
G15 | Đối với mỗi string_id_item , trường string_data_off phải chứa tham chiếu hợp lệ vào phần data . Đối với string_data_item được tham chiếu, trường data phải chứa chuỗi MUTF-8 hợp lệ và utf16_size phải khớp với độ dài được giải mã của chuỗi. |
G16 | Đối với mỗi type_id_item , trường descriptor_idx phải chứa tham chiếu hợp lệ vào danh sách string_ids . Chuỗi được tham chiếu phải là một bộ mô tả kiểu hợp lệ. |
G17 | Đối với mỗi proto_id_item , trường shorty_idx phải chứa tham chiếu hợp lệ vào danh sách string_ids . Chuỗi được tham chiếu phải là một bộ mô tả ngắn gọn hợp lệ. Ngoài ra, trường return_type_idx phải là chỉ mục hợp lệ trong phần type_ids và trường parameters_off phải bằng 0 hoặc giá trị offset hợp lệ trỏ vào phần data . Nếu khác 0, danh sách tham số không được chứa bất kỳ mục trống nào. |
G18 | Đối với mỗi field_id_item , cả hai trường class_idx và type_idx phải là chỉ mục hợp lệ trong danh sách type_ids . Mục nhập được tham chiếu bởi class_idx phải là loại tham chiếu không phải mảng. Ngoài ra, trường name_idx phải là tham chiếu hợp lệ vào phần string_ids và nội dung của mục được tham chiếu phải tuân theo đặc tả MemberName . |
G19 | Đối với mỗi method_id_item , trường class_idx phải là chỉ mục hợp lệ trong phần type_ids và mục nhập được tham chiếu phải là loại tham chiếu không phải mảng. Trường proto_id phải là tham chiếu hợp lệ vào danh sách proto_ids . Trường name_idx phải là tham chiếu hợp lệ vào phần string_ids và nội dung của mục được tham chiếu phải tuân theo đặc tả MemberName . |
G20 | Đối với mỗi field_id_item , trường class_idx phải là chỉ mục hợp lệ trong danh sách type_ids . Mục được tham chiếu phải là loại tham chiếu không phải mảng. |
Ràng buộc mã byte tĩnh
Ràng buộc tĩnh là các ràng buộc đối với các phần tử riêng lẻ của mã byte. Chúng thường có thể được kiểm tra mà không cần sử dụng các kỹ thuật điều khiển hoặc phân tích luồng dữ liệu.
Mã định danh | Sự miêu tả |
---|---|
A1 | Mảng insns không được để trống. |
A2 | Opcode đầu tiên trong mảng insns phải có chỉ số bằng 0. |
A3 | Mảng insns chỉ được chứa các opcode Dalvik hợp lệ. |
A4 | Chỉ số của lệnh n+1 phải bằng chỉ số của lệnh n cộng với độ dài của lệnh n , có tính đến các toán hạng có thể có. |
A5 | Lệnh cuối cùng trong mảng insns phải kết thúc ở chỉ mục insns_size-1 . |
A6 | Tất cả các mục tiêu goto và if-<kind> phải là opcode trong cùng một phương thức. |
A7 | Tất cả các mục tiêu của lệnh packed-switch phải là các mã hoạt động trong cùng một phương thức. Quy mô và danh sách các mục tiêu phải nhất quán. |
A8 | Tất cả các mục tiêu của lệnh sparse-switch phải là các mã hoạt động trong cùng một phương thức. Bảng tương ứng phải nhất quán và được sắp xếp từ thấp đến cao. |
A9 | Toán B của các lệnh const-string và const-string/jumbo phải là một chỉ mục hợp lệ trong nhóm hằng chuỗi. |
A10 | Toán hạng C của lệnh iget<kind> và iput<kind> phải là một chỉ mục hợp lệ trong nhóm hằng số trường. Mục được tham chiếu phải đại diện cho một trường mẫu. |
A11 | Toán hạng C của lệnh sget<kind> và sput<kind> phải là một chỉ mục hợp lệ trong nhóm hằng số trường. Mục được tham chiếu phải đại diện cho một trường tĩnh. |
A12 | Toán hạng C của các lệnh invoke-virtual , invoke-super , invoke-direct và invoke-static phải là một chỉ mục hợp lệ trong nhóm hằng số phương thức. |
A13 | Toán B của các lệnh invoke-virtual/range , invoke-super/range , invoke-direct/range và invoke-static/range phải là một chỉ mục hợp lệ trong nhóm hằng số phương thức. |
A14 | Phương thức có tên bắt đầu bằng '<' chỉ được gọi ngầm bởi VM chứ không phải bằng mã có nguồn gốc từ tệp .dex . Ngoại lệ duy nhất là trình khởi tạo cá thể, có thể được gọi bằng invoke-direct . |
A15 | Toán hạng C của lệnh invoke-interface phải là một chỉ mục hợp lệ trong nhóm hằng số phương thức. method_id được tham chiếu phải thuộc về một giao diện (không phải một lớp). |
A16 | Toán B của lệnh invoke-interface/range phải là một chỉ mục hợp lệ trong nhóm hằng số phương thức. method_id được tham chiếu phải thuộc về một giao diện (không phải một lớp). |
A17 | Toán B của const-class , check-cast , new-instance và filled-new-array/range phải là một chỉ mục hợp lệ trong nhóm hằng số loại. |
A18 | Toán hạng C của các lệnh instance-of , new-array và filled-new-array phải là một chỉ mục hợp lệ trong nhóm hằng số kiểu. |
A19 | Kích thước của mảng được tạo bởi lệnh new-array phải nhỏ hơn 256 . |
A20 | Lệnh new không được đề cập đến các lớp mảng, giao diện hoặc lớp trừu tượng. |
A21 | Loại được tham chiếu bởi lệnh new-array phải là loại hợp lệ, không tham chiếu. |
A22 | Tất cả các thanh ghi được tham chiếu bởi một lệnh theo kiểu độ rộng đơn (không phải cặp) phải hợp lệ cho phương thức hiện tại. Nghĩa là, chỉ số của chúng phải không âm và nhỏ hơn registers_size . |
A23 | Tất cả các thanh ghi được tham chiếu bởi một lệnh theo kiểu (cặp) độ rộng kép phải hợp lệ cho phương thức hiện tại. Nghĩa là, chỉ số của chúng phải không âm và nhỏ hơn registers_size-1 . |
A24 | Toán hạng method_id của lệnh invoke-virtual và lệnh invoke-direct phải thuộc về một lớp (không phải giao diện). Trong các tệp Dex trước phiên bản 037 , điều tương tự cũng phải đúng với các hướng dẫn invoke-super và invoke-static . |
A25 | Toán hạng method_id của lệnh invoke-virtual/range và lệnh invoke-direct/range phải thuộc về một lớp (không phải giao diện). Trong các tệp Dex trước phiên bản 037 , điều tương tự cũng phải đúng với các hướng dẫn invoke-super/range và invoke-static/range . |
Các ràng buộc về mã byte cấu trúc
Ràng buộc về cấu trúc là các ràng buộc về mối quan hệ giữa một số phần tử của mã byte. Chúng thường không thể được kiểm tra nếu không sử dụng các kỹ thuật kiểm soát hoặc phân tích luồng dữ liệu.
Mã định danh | Sự miêu tả |
---|---|
B1 | Số lượng và loại đối số (các thanh ghi và giá trị tức thời) phải luôn khớp với lệnh. |
B2 | Các cặp thanh ghi không bao giờ được chia nhỏ. |
B3 | Một thanh ghi (hoặc cặp) phải được chỉ định trước khi có thể đọc được. |
B 4 | Lệnh invoke-direct phải gọi một trình khởi tạo cá thể hoặc một phương thức chỉ trong lớp hiện tại hoặc một trong các siêu lớp của nó. |
B5 | Trình khởi tạo phiên bản chỉ được gọi trên phiên bản chưa được khởi tạo. |
B6 | Các phương thức phiên bản chỉ có thể được gọi trên các trường phiên bản và chỉ có thể được truy cập trên các phiên bản đã được khởi tạo. |
B7 | Không được sử dụng thanh ghi chứa kết quả của một lệnh new-instance nếu cùng một lệnh new-instance được thực thi lại trước khi phiên bản đó được khởi tạo. |
B8 | Trình khởi tạo phiên bản phải gọi một trình khởi tạo phiên bản khác (cùng lớp hoặc siêu lớp) trước khi có thể truy cập bất kỳ thành viên phiên bản nào. Các ngoại lệ là các trường phiên bản không được kế thừa, có thể được chỉ định trước khi gọi một trình khởi tạo khác và lớp Object nói chung. |
B9 | Tất cả các đối số phương thức thực tế phải tương thích với phép gán với các đối số hình thức tương ứng của chúng. |
B10 | Đối với mỗi lệnh gọi phương thức cá thể, cá thể thực tế phải tương thích với phép gán với lớp hoặc giao diện được chỉ định trong lệnh. |
B11 | Lệnh return<kind> phải khớp với kiểu trả về của phương thức của nó. |
B12 | Khi truy cập các thành viên được bảo vệ của siêu lớp, loại thực tế của phiên bản đang được truy cập phải là lớp hiện tại hoặc một trong các lớp con của nó. |
B13 | Loại giá trị được lưu trữ trong trường tĩnh phải tương thích với phép gán hoặc có thể chuyển đổi thành loại của trường. |
B14 | Loại giá trị được lưu trữ trong một trường phải tương thích với phép gán hoặc có thể chuyển đổi thành loại của trường. |
B15 | Loại của mọi giá trị được lưu trữ trong một mảng phải tương thích với phép gán với loại thành phần của mảng. |
B16 | Toán A của lệnh throw phải tương thích với phép gán với java.lang.Throwable . |
B17 | Lệnh có thể truy cập cuối cùng của một phương thức phải là lệnh goto hoặc nhánh ngược, lệnh return hoặc lệnh throw . Không thể để mảng insns ở dưới cùng. |
B18 | Một nửa chưa được gán của cặp thanh ghi cũ có thể không được đọc (được coi là không hợp lệ) cho đến khi nó được gán lại bởi một số lệnh khác. |
B19 | Lệnh move-result<kind> phải được đặt ngay trước (trong mảng insns ) bằng lệnh invoke-<kind> . Ngoại lệ duy nhất là lệnh move-result-object , cũng có thể được bắt đầu bằng lệnh filled-new-array . |
B20 | Lệnh move-result<kind> phải được đặt ngay trước (trong luồng điều khiển thực tế) bằng lệnh return-<kind> phù hợp (không được nhảy tới). Ngoại lệ duy nhất là lệnh move-result-object , cũng có thể được bắt đầu bằng lệnh filled-new-array . |
B21 | Lệnh move-exception chỉ được xuất hiện dưới dạng lệnh đầu tiên trong trình xử lý ngoại lệ. |
B22 | Luồng điều khiển không được phép truy cập các lệnh giả packed-switch-data sparse-switch-data , thưa fill-array-data . |