Plik .dex
to format transportu dla kodu bajtowego Dalvik. Aby plik był prawidłowym plikiem .dex
, musi spełniać określone ograniczenia składni i semantyki, a czas wykonywania musi obsługiwać tylko prawidłowe pliki .dex.
Ogólne ograniczenia integralności pliku .dex
Ogólne ograniczenia integralności dotyczą szerszej struktury pliku .dex
, jak opisano szczegółowo w pliku .dex
.
Identyfikator | Opis |
---|---|
G1 |
Numer magic pliku .dex musi być dex\n035\0 w przypadku wersji 35 lub podobny w przypadku nowszych wersji.
|
G2 |
Suma kontrolna musi być sumą kontrolną Adlera-32 całej zawartości pliku (z wyjątkiem pól magic i checksum ).
|
G3 |
Podpis musi być skrótem SHA-1 całej zawartości pliku z wyjątkiem magic , checksum i signature .
|
G4 |
Wartość Wartość |
G5 |
Wartość Wartość parametru |
G6 |
W polu endian_tag musi być wartość:ENDIAN_CONSTANT lub REVERSE_ENDIAN_CONSTANT
|
G7 |
W przypadku pól
Pola |
G8 |
Wszystkie pola przesunięcia w nagłówku (z wyjątkiem pola map_off ) muszą być wyrównane co 4 bajty.
|
G9 |
Pole map_off musi zawierać wartość 0 lub wskazywać sekcję danych. W tym drugim przypadku musi istnieć sekcja data .
|
G10 |
Sekcje link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs i data nie mogą na siebie nachodzić ani zachodzić na nagłówek.
|
G11 | Jeśli mapa istnieje, każdy wpis mapy musi mieć prawidłowy typ. Każdy typ może się pojawić maksymalnie raz. |
G12 |
Jeśli mapa istnieje, każdy jej wpis musi mieć niezerową wartość przesunięcia i rozmiaru. Odsunięcie musi wskazywać na odpowiednią sekcję pliku (tzn. string_id_item musi wskazywać na sekcję string_ids ), a rozmiar elementu (wyrażony wprost lub domyślnie) musi odpowiadać rzeczywistej zawartości i rozmiarowi sekcji.
|
G13 |
Jeśli mapa istnieje, przesunięcie pozycji mapy n+1 musi być większe lub równe przesunięciu pozycji mapy n plus than size of map entry n . Oznacza to, że wpisy nie mogą się pokrywać, a uporządkowanie musi być od najniższej do najwyższej wartości.
|
G14 |
Te typy wpisów muszą mieć przesunięcie wyrównane do 4 bajtów: 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 |
W przypadku każdego W przypadku każdego W przypadku odwołania do pola |
G16 |
W przypadku każdego elementu type_id_item pole descriptor_idx musi zawierać prawidłowe odwołanie do listy string_ids . Odwołujący się ciąg musi być prawidłowym opisem typu.
|
G17 |
W przypadku każdego elementu proto_id_item pole shorty_idx musi zawierać prawidłowe odwołanie do listy string_ids . Odwołujący się ciąg musi być prawidłowym opisem shorty. Ponadto pole return_type_idx musi być prawidłowym indeksem w sekcji type_ids , a pole parameters_off musi zawierać wartość zero lub prawidłowy przesunięcie wskazujące sekcję data . Jeśli wartość jest niezerowa, lista parametrów nie może zawierać żadnych pustych wpisów.
|
G18 |
W przypadku każdego elementu field_id_item pola class_idx i type_idx muszą być prawidłowymi indeksami na liście type_ids . Wpis, do którego odwołuje się class_idx , musi być typem odniesienia innego niż tablica. Dodatkowo pole name_idx musi być prawidłowym odwołaniem do sekcji string_ids , a zawartość odwołania musi być zgodna ze specyfikacją MemberName .
|
G19 |
W przypadku każdego elementu method_id_item pole class_idx musi być prawidłowym indeksem w sekcji type_ids , a odwołujący się do niego wpis musi być typem odniesienia innego niż tablica. Pole proto_id musi być prawidłowym odwołaniem do listy proto_ids . Pole name_idx musi być prawidłowym odwołaniem do sekcji string_ids , a zawartość odwołanego wpisu musi być zgodna ze specyfikacją MemberName .
|
G20 |
W przypadku każdego elementu field_id_item pole class_idx musi być prawidłowym indeksem na liście type_ids . Odwołujący się wpis musi być typem niebędącym tablicą.
|
Statyczne ograniczenia kodu bajtowego
Ograniczenia statyczne to ograniczenia dotyczące poszczególnych elementów kodu bajtowego. Zwykle można je sprawdzić bez stosowania technik kontroli czy analizy przepływu danych.
Identyfikator | Opis |
---|---|
A1 |
Tablica insns nie może być pusta.
|
A2 |
Pierwszy kod operacji w tablicy insns musi mieć indeks 0.
|
A3 |
Tablica insns musi zawierać tylko prawidłowe instrukcje Dalvik.
|
A4 |
Indeks instrukcji n+1 musi być równy indeksowi instrukcji n plus długość instrukcji n , biorąc pod uwagę możliwe operandy.
|
A5 |
Ostatnia instrukcja w tablicy insns musi kończyć się na indeksie insns_size-1 .
|
A6 |
Wszystkie wartości docelowe goto i if-<kind> muszą być instrukcjami w ramach tej samej metody.
|
A7 |
Wszystkie cele instrukcji packed-switch muszą być instrukcjami w ramach tej samej metody. Rozmiar i lista docelów muszą być spójne.
|
A8 |
Wszystkie cele instrukcji sparse-switch muszą być instrukcjami w ramach tej samej metody. Odpowiednia tabela musi być spójna i posortowana od najniższej do najwyższej wartości.
|
A9 |
Operand B instrukcji const-string i const-string/jumbo musi być prawidłowym indeksem w pulie stałych ciągu znaków.
|
A10 |
Operand C instrukcji iget<kind> i iput<kind> musi być prawidłowym indeksem w polu puli stałych. Odwołujący się wpis musi reprezentować pole instancji.
|
A11 |
Operand C instrukcji sget<kind> i sput<kind> musi być prawidłowym indeksem w polu puli stałych. Odwołujący się wpis musi reprezentować statyczne pole.
|
A12 |
Operand C instrukcji invoke-virtual , invoke-super , invoke-direct i invoke-static musi być prawidłowym indeksem w stałej puli metody.
|
A13 |
Operand B instrukcji invoke-virtual/range , invoke-super/range , invoke-direct/range i invoke-static/range musi być prawidłowym indeksem w stałej puli metody.
|
A14 |
Metoda, której nazwa zaczyna się od „<”, może być wywoływana tylko niejawnie przez maszynę wirtualną, a nie przez kod pochodzący z pliku .dex . Jedynym wyjątkiem jest inicjalizator instancji, który może być wywoływany przez invoke-direct .
|
A15 |
Operand C instrukcji invoke-interface musi być prawidłowym indeksem w stałej puli metody. Odwołujący się method_id musi należeć do interfejsu (a nie klasy).
|
A16 |
Operand B instrukcji invoke-interface/range musi być prawidłowym indeksem w stałej puli metody.
Odwołujący się element method_id musi należeć do interfejsu (a nie klasy).
|
A17 |
Operand B w instrukcjach const-class , check-cast , new-instance i filled-new-array/range musi być prawidłowym indeksem w puli stałych typu.
|
A18 |
Operand C instrukcji instance-of , new-array i filled-new-array musi być prawidłowym indeksem w stałej puli typów.
|
A19 |
Wymiary tablicy utworzonej za pomocą instrukcji new-array muszą być mniejsze niż 256 .
|
A20 |
Instrukcja new nie może się odwoływać do klas tablic, interfejsów ani klas abstrakcyjnych.
|
A21 |
Typ, do którego odwołuje się instrukcja new-array , musi być prawidłowym typem nieodwołującym się do innego typu.
|
A22 |
Wszystkie rejestry, do których odwołuje się instrukcja w sposób jednoliniowy (nieparowy), muszą być prawidłowe w przypadku bieżącej metody. Oznacza to, że ich indeksy muszą być nieujemne i mniejsze niż registers_size .
|
A23 |
Wszystkie rejestry, do których odwołuje się instrukcja w podwójnej szerokości (para), muszą być prawidłowe w przypadku bieżącej metody. Oznacza to, że ich indeksy muszą być nieujemne i mniejsze niż registers_size-1 .
|
24A |
Operand method_id instrukcji invoke-virtual i invoke-direct musi należeć do klasy (a nie interfejsu). W plikach Dex starszych niż wersja 037
instrukcje invoke-super i invoke-static muszą być takie same.
|
A25 |
Operand method_id instrukcji invoke-virtual/range i invoke-direct/range musi należeć do klasy (a nie interfejsu). W plikach Dex starszych niż wersja 037
instrukcje invoke-super/range i invoke-static/range muszą być takie same.
|
Ograniczenia dotyczące struktury kodu bajtowego
Ograniczenia strukturalne to ograniczenia dotyczące relacji między kilkoma elementami kodu bajtowego. Zwykle nie można ich sprawdzić bez użycia technik kontroli lub analizy przepływu danych.
Identyfikator | Opis |
---|---|
B1 | Liczba i typy argumentów (rejestry i wartości natychmiastowe) muszą zawsze być zgodne z instrukcją. |
B2 | Pary rejestrów nie mogą być rozdzielane. |
B3 | Zanim rejestr (lub para) zostanie odczytany, musi zostać przypisany. |
B4 |
Instrukcja invoke-direct musi wywoływać konstruktor wystąpienia lub metodę tylko w bieżącej klasie lub jednej z jej nadklas.
|
B5 | Inicjalizator instancji musi być wywoływany tylko w przypadku niezainicjalizowanej instancji. |
B6 | Metody instancji mogą być wywoływane tylko w przypadku pól instancji, a do pól instancji można uzyskać dostęp tylko w przypadku już zainicjowanych instancji. |
B7 |
Nie można używać rejestru, który zawiera wynik instrukcji new-instance , jeśli ta sama instrukcja new-instance zostanie ponownie wykonana przed zainicjowaniem instancji.
|
B8 |
Inicjalizator instancji musi wywołać inny inicjalizator instancji (tą samą klasę lub superklasę), zanim będzie można uzyskać dostęp do dowolnych elementów instancji.
Wyjątki to nieodziedziczone pola instancji, które można przypisać przed wywołaniem innego inicjalizatora oraz klasy Object w ogóle.
|
B9 | Wszystkie rzeczywiste argumenty metody muszą być zgodne z odpowiednimi argumentami formalnymi. |
B10 | W przypadku każdego wywołania metody instancji rzeczywista instancja musi być przypisana do klasy lub interfejsu określonego w instrukcji. |
B11 |
Instrukcja return<kind> musi być zgodna z typem zwracanym metody.
|
B12 | Podczas uzyskiwania dostępu do chronionych elementów superklasy rzeczywisty typ wystąpienia, do którego uzyskujesz dostęp, musi być bieżącą klasą lub jedną z jej podklas. |
B13 | Typ wartości przechowywanej w polu statycznym musi być zgodny z typem przypisania lub musi być możliwy do konwersji na typ pola. |
B14 | Typ wartości przechowywanej w polu musi być zgodny z typem pola lub musi być możliwy do konwersji na typ pola. |
B15 | Typ każdej wartości przechowywanej w tablicy musi być zgodny z typem komponentu tablicy. |
B16 |
Operand A instrukcji throw musi być zgodny z instrukcją java.lang.Throwable .
|
B17 |
Ostatnia instrukcja metody, do której można dotrzeć, musi być instrukcją goto lub gałęzi return , return lub throw . Nie można pozostawić tablicy insns na dole.
|
B18 | Nieprzypisana połowa pary rejestrów może nie być odczytywana (jest uznawana za nieważną), dopóki nie zostanie ponownie przypisana przez inną instrukcję. |
B19 |
Instrukcja move-result<kind> musi być bezpośrednio poprzedzona (w tablicy insns ) instrukcją invoke-<kind> . Jedynym wyjątkiem jest instrukcja move-result-object , która może być poprzedzona instrukcją filled-new-array .
|
B20 |
Instrukcja move-result<kind> musi być bezpośrednio (w ramach rzeczywistego przepływu sterowania) poprzedzona instrukcją return-<kind> (nie może być do niej przeskakiwana). Jedynym wyjątkiem jest instrukcja move-result-object , która może być poprzedzona instrukcją filled-new-array .
|
B21 |
Instrukcja move-exception musi występować tylko jako pierwsza instrukcja w obiekcie wyjątku.
|
B22 |
Pseudoinstrukcje packed-switch-data , sparse-switch-data i fill-array-data nie mogą być dostępne dla sterowania przepływem.
|