Tệp .dex
là định dạng truyền tải cho mã byte Dalvik. Có một số quy tắc 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ó một môi trường thời gian chạy để chỉ hỗ trợ các tệp .dex hợp lệ.
Các quy tắc ràng buộc chung về tính toàn vẹn của tệp .dex
Các quy tắc ràng buộc về tính toàn vẹn chung liên quan đến cấu trúc lớn hơn của tệp .dex
, như mô tả chi tiết trong định dạng .dex
.
Số nhận dạng | Mô tả |
---|---|
G1 |
Số magic của tệp .dex phải là dex\n035\0 đối với phiên bản 35 hoặc tương tự đối với các phiên bản mới hơn.
|
G2 |
Checksum phải là checksum 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 |
|
G5 |
|
G6 |
endian_tag phải có giá trị: ENDIAN_CONSTANT hoặc REVERSE_ENDIAN_CONSTANT
|
G7 |
Đối với mỗi phần
Các trường |
G8 |
Tất cả các trường chênh lệch trong tiêu đề ngoại trừ map_off phải được căn chỉnh 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 nào trong link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs và data được chồng lên nhau hoặc chồng lên tiêu đề.
|
G11 | Nếu có bản đồ, thì mỗi mục nhập bản đồ phải có một loại hợp lệ. Mỗi loại chỉ được xuất hiện tối đa một lần. |
G12 |
Nếu có bản đồ, thì mỗi mục nhập bản đồ phải có độ dời và kích thước khác 0. Độ lệch 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 ngầm ẩ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 có bản đồ, thì độ dời của mục nhập bản đồ n+1 phải lớn hơn hoặc bằng độ dời của mục nhập bản đồ n plus than size of map entry n . Điều này có nghĩa là các mục nhập không trùng lặp và thứ tự từ thấp đến cao.
|
G14 |
Các loại mục nhập sau đây phải có độ dời được căn chỉnh 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 Đối với mỗi Đối với |
G16 |
Đối với mỗi type_id_item , trường descriptor_idx phải chứa một tham chiếu hợp lệ vào danh sách string_ids . Chuỗi được tham chiếu phải là một chỉ số loại hợp lệ.
|
G17 |
Đối với mỗi proto_id_item , trường shorty_idx phải chứa một tham chiếu hợp lệ vào danh sách string_ids . Chuỗi được tham chiếu phải là một chỉ số ngắn hợp lệ. Ngoài ra, trường return_type_idx phải là một chỉ mục hợp lệ vào phần type_ids và trường parameters_off phải bằng 0 hoặc một độ dời hợp lệ trỏ vào phần data . Nếu không bằng 0, danh sách tham số không được chứa mục nhập rỗng.
|
G18 |
Đối với mỗi field_id_item , cả trường class_idx và type_idx đều phải là chỉ mục hợp lệ trong danh sách type_ids . Mục được class_idx tham chiếu phải là loại tham chiếu không phải mảng. Ngoài ra, trường name_idx phải là một tham chiếu hợp lệ vào phần string_ids và nội dung của mục tham chiếu phải tuân thủ quy cách MemberName .
|
G19 |
Đối với mỗi method_id_item , trường class_idx phải là một chỉ mục hợp lệ vào 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à một tham chiếu hợp lệ vào danh sách proto_ids . Trường name_idx phải là một tham chiếu hợp lệ vào phần string_ids , đồng thời nội dung của mục được tham chiếu phải tuân thủ quy cách MemberName .
|
G20 |
Đối với mỗi field_id_item , trường class_idx phải là một chỉ mục hợp lệ vào danh sách type_ids . Mục nhập được tham chiếu phải là loại tham chiếu không phải mảng.
|
Quy tắc ràng buộc mã byte tĩnh
Quy tắc ràng buộc tĩnh là quy tắc ràng buộc đối với từng phần tử của mã byte. Thông thường, bạn có thể kiểm tra các lỗi này mà không cần sử dụng các kỹ thuật kiểm soát hoặc phân tích luồng dữ liệu.
Số nhận dạng | Mô tả |
---|---|
A1 |
Mảng insns không được để trống.
|
A2 |
Mã opcode đầu tiên trong mảng insns phải có chỉ mục 0.
|
A3 |
Mảng insns chỉ được chứa các mã opcode Dalvik hợp lệ.
|
A4 |
Chỉ mục của lệnh n+1 phải bằng chỉ mục 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ả mục tiêu goto và if-<kind> phải là mã opcode trong cùng một phương thức.
|
A7 |
Tất cả mục tiêu của lệnh packed-switch phải là
mã opcode trong cùng một phương thức. Kích thước và danh sách mục tiêu phải nhất quán.
|
A8 |
Tất cả mục tiêu của lệnh sparse-switch phải là
mã opcode 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 hạng B của lệnh const-string và const-string/jumbo phải là một chỉ mục hợp lệ vào nhóm hằng số 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ệ vào nhóm hằng trường. Mục nhập được tham chiếu phải đại diện cho một trường thực thể.
|
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ệ vào nhóm hằng trường. Mục nhập được tham chiếu phải đại diện cho một trường tĩnh.
|
A12 |
Toán hạng C của hướng dẫn invoke-virtual , invoke-super , invoke-direct và invoke-static phải là một chỉ mục hợp lệ vào nhóm hằng số phương thức.
|
A13 |
Toán hạng B của hướng dẫn invoke-virtual/range , invoke-super/range , invoke-direct/range và invoke-static/range phải là một chỉ mục hợp lệ vào nhóm hằng phương thức.
|
A14 |
Phương thức có tên bắt đầu bằng "<" chỉ được máy ảo gọi ngầm, chứ không phải bằng mã bắt nguồn từ tệp .dex . Ngoại lệ duy nhất là trình khởi tạo thực thể, có thể được invoke-direct gọi.
|
A15 |
Toán hạng C của lệnh invoke-interface phải là một chỉ mục hợp lệ vào 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 hạng B của lệnh invoke-interface/range phải là một chỉ mục hợp lệ vào 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 hạng B của hướng dẫn const-class ,
check-cast , new-instance và
filled-new-array/range phải là một chỉ mục hợp lệ
vào nhóm hằng số loại.
|
A18 |
Toán hạng C của 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ố loại.
|
A19 |
Phương diện của một mảng do lệnh new-array tạo phải nhỏ hơn 256 .
|
A20 |
Lệnh new không được tham chiếu đế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ằng lệnh new-array phải là loại hợp lệ, không phải loại tham chiếu.
|
A22 |
Tất cả các thanh ghi được tham chiếu bằng một lệnh theo kiểu một chiều (không phải cặp) phải hợp lệ cho phương thức hiện tại. Tức là, chỉ mục của các phần tử này phải không âm và nhỏ hơn registers_size .
|
A23 |
Tất cả các thanh ghi được tham chiếu bằng một lệnh theo kiểu chiều rộng kép (cặp) phải hợp lệ cho phương thức hiện tại. Tức là chỉ mục của chúng phải là số không âm và nhỏ hơn registers_size-1 .
|
A24 |
Toán hạng method_id của lệnh invoke-virtual và 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 , các lệnh invoke-super và invoke-static cũng phải như vậy.
|
A25 |
Toán hạng method_id của lệnh invoke-virtual/range và invoke-direct/range phải thuộc 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 này cũng phải đúng với các lệnh invoke-super/range và invoke-static/range .
|
Các quy tắc ràng buộc về mã byte cấu trúc
Quy tắc ràng buộc cấu trúc là các quy tắc ràng buộc về mối quan hệ giữa một số phần tử của mã byte. Thông thường, bạn không thể kiểm tra các lỗi này nếu không sử dụng kỹ thuật kiểm soát hoặc phân tích luồng dữ liệu.
Số nhận dạng | Mô tả |
---|---|
B1 | Số lượng và loại đối số (đăng ký và giá trị tức thì) phải luôn khớp với lệnh. |
B2 | Không được chia đôi cặp đăng ký. |
B3 | Bạn phải chỉ định một thanh ghi (hoặc cặp) trước khi có thể đọc thanh ghi đó. |
B4 |
Lệnh invoke-direct phải gọi một trình khởi tạo thự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 lớp cha của lớp đó.
|
B5 | Bạn chỉ được gọi trình khởi tạo thực thể trên một thực thể chưa khởi tạo. |
B6 | Bạn chỉ có thể gọi các phương thức thực thể và chỉ có thể truy cập vào các trường thực thể trên các thực thể đã được khởi chạy. |
B7 |
Bạn không được sử dụng thanh ghi chứa kết quả của lệnh new-instance nếu cùng một lệnh new-instance được thực thi lại trước khi khởi tạo thực thể.
|
B8 |
Trình khởi tạo thực thể phải gọi một trình khởi tạo thực thể khác (cùng lớp hoặc lớp cao cấp) trước khi có thể truy cập vào bất kỳ thành viên thực thể nào.
Các trường hợp ngoại lệ là các trường thực thể 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ả đối số phương thức thực tế phải tương thích với đối số chính thức tương ứng của chúng. |
B10 | Đối với mỗi lệnh gọi phương thức thực thể, thực thể thực tế phải tương thích với lớp hoặc giao diện được chỉ định trong hướng dẫn. |
B11 |
Lệnh return<kind> phải khớp với loại dữ liệu trả về của phương thức.
|
B12 | Khi truy cập vào các thành viên được bảo vệ của một siêu lớp, loại thực tế của thực thể đ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 lớp đó. |
B13 | Loại giá trị được lưu trữ vào trường tĩnh phải tương thích với việc gán hoặc có thể chuyển đổi sang loại của trường. |
B14 | Loại giá trị được lưu trữ vào một trường phải tương thích với việc gán hoặc có thể chuyển đổi sang loại của trường. |
B15 | Loại của mọi giá trị được lưu trữ vào một mảng phải tương thích với loại thành phần của mảng. |
B16 |
Toán hạng A của lệnh throw phải tương thích với việc gán java.lang.Throwable .
|
B17 |
Lệnh có thể truy cập gần đây nhất của một phương thức phải là lệnh goto hoặc nhánh ngược, return hoặc throw . Không được để mảng insns ở dưới cùng.
|
B18 | Bạn không thể đọc nửa chưa được chỉ định của một cặp thanh ghi trước đó (được coi là không hợp lệ) cho đến khi một số lệnh khác chỉ định lại. |
B19 |
Lệnh move-result<kind> phải đứng ngay trước (trong mảng insns ) lệnh invoke-<kind> . Trường hợp ngoại lệ duy nhất là lệnh move-result-object , lệnh này cũng có thể đứng trước lệnh filled-new-array .
|
B20 |
Lệnh move-result<kind> phải được lệnh return-<kind> khớp (không được chuyển đến) đi trước ngay lập tức (trong luồng điều khiển thực tế). Trường hợp ngoại lệ duy nhất là lệnh move-result-object , lệnh này cũng có thể đứng trước lệnh filled-new-array .
|
B21 |
Chỉ thị 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 truy cập được vào các lệnh giả lập packed-switch-data , sparse-switch-data và fill-array-data .
|