Giới hạn

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 magicchecksum .
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 , checksumsignature .
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 offsetsize 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_idxtype_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 gotoif-<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-stringconst-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>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>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-directinvoke-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/rangeinvoke-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-instancefilled-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-arrayfilled-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-superinvoke-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/rangeinvoke-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 .