Eine .dex
Datei ist das Transportformat für Dalvik-Bytecode. Es gibt bestimmte syntaktische und semantische Einschränkungen dafür, dass eine Datei eine gültige .dex
Datei ist, und eine Laufzeit ist erforderlich, um nur gültige .dex-Dateien zu unterstützen.
Allgemeine Einschränkungen der .dex-Integrität
Allgemeine Integritätseinschränkungen betreffen die größere Struktur einer .dex
Datei, wie im Detail im .dex
-Format beschrieben.
Kennung | Beschreibung |
---|---|
G1 | Die magic Nummer der .dex Datei muss dex\n035\0 oder dex\n037\0 sein. |
G2 | Die Prüfsumme muss eine Adler-32-Prüfsumme des gesamten Dateiinhalts sein, mit Ausnahme magic und checksum . |
G3 | Die Signatur muss ein SHA-1-Hash des gesamten Dateiinhalts sein, mit Ausnahme magic , checksum und signature . |
G4 | Die file_size muss mit der tatsächlichen Dateigröße in Bytes übereinstimmen. |
G5 | Die header_size muss den Wert haben: 0x70 |
G6 | Das endian_tag muss entweder den Wert ENDIAN_CONSTANT oder REVERSE_ENDIAN_CONSTANT haben |
G7 | Für jeden der link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs und data müssen die Felder offset und size entweder beide Null oder beide ungleich Null sein. Im letzteren Fall muss der Offset auf vier Bytes ausgerichtet sein. |
G8 | Alle Offset-Felder im Header außer map_off müssen auf vier Bytes ausgerichtet sein. |
G9 | Das Feld map_off muss entweder Null sein oder auf den Datenabschnitt zeigen. Im letzteren Fall muss der data vorhanden sein. |
G10 | Keiner der link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs und data darf einander oder den Header überlappen. |
G11 | Wenn eine Karte vorhanden ist, muss jeder Karteneintrag einen gültigen Typ haben. Jeder Typ darf höchstens einmal vorkommen. |
G12 | Wenn eine Karte vorhanden ist, muss jeder Karteneintrag einen Offset und eine Größe ungleich Null haben. Der Offset muss auf den entsprechenden Abschnitt der Datei zeigen (dh ein string_id_item muss auf den Abschnitt string_ids zeigen) und die explizite oder implizite Größe des Elements muss mit dem tatsächlichen Inhalt und der Größe des Abschnitts übereinstimmen. |
G13 | Wenn eine Karte vorhanden ist, muss der Offset des Karteneintrags n+1 größer oder gleich dem Offset des Karteneintrags n plus than size of map entry n sein. Dies impliziert nicht überlappende Einträge und eine Reihenfolge von unten nach oben. |
G14 | Die folgenden Eintragstypen müssen einen Offset haben, der auf vier Bytes ausgerichtet ist: 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 | Für jedes string_id_item muss das Feld string_data_off einen gültigen Verweis auf den data enthalten. Für das referenzierte string_data_item muss das data eine gültige MUTF-8-Zeichenfolge enthalten und die utf16_size muss mit der dekodierten Länge der Zeichenfolge übereinstimmen. |
G16 | Für jedes type_id_item muss das Feld descriptor_idx einen gültigen Verweis auf die string_ids Liste enthalten. Die referenzierte Zeichenfolge muss ein gültiger Typdeskriptor sein. |
G17 | Für jedes proto_id_item muss das Feld shorty_idx einen gültigen Verweis auf die string_ids Liste enthalten. Die referenzierte Zeichenfolge muss ein gültiger Shorty-Deskriptor sein. Außerdem muss das Feld return_type_idx ein gültiger Index in den Abschnitt „ type_ids sein und das Feld parameters_off muss entweder Null oder ein gültiger Offset sein, der in den Abschnitt data zeigt. Bei einem Wert ungleich Null darf die Parameterliste keine ungültigen Einträge enthalten. |
G18 | Für jedes field_id_item müssen sowohl das class_idx als auch type_idx Feld gültige Indizes in der type_ids Liste sein. Der von class_idx referenzierte Eintrag muss ein Nicht-Array-Referenztyp sein. Darüber hinaus muss das Feld name_idx ein gültiger Verweis auf den Abschnitt „ string_ids sein und der Inhalt des referenzierten Eintrags muss der MemberName Spezifikation entsprechen. |
G19 | Für jedes method_id_item muss das Feld class_idx ein gültiger Index im Abschnitt type_ids sein und der referenzierte Eintrag muss ein Nicht-Array-Referenztyp sein. Das Feld proto_id muss eine gültige Referenz in der proto_ids Liste sein. Das Feld name_idx muss ein gültiger Verweis auf den Abschnitt string_ids sein und der Inhalt des referenzierten Eintrags muss der MemberName Spezifikation entsprechen. |
G20 | Für jedes field_id_item muss das Feld class_idx ein gültiger Index in der Liste type_ids sein. Der referenzierte Eintrag muss ein Nicht-Array-Referenztyp sein. |
Statische Bytecode-Einschränkungen
Statische Einschränkungen sind Einschränkungen für einzelne Elemente des Bytecodes. Sie können in der Regel ohne den Einsatz von Kontroll- oder Datenflussanalysetechniken überprüft werden.
Kennung | Beschreibung |
---|---|
A1 | Das insns Array darf nicht leer sein. |
A2 | Der erste Opcode im insns -Array muss den Index Null haben. |
A3 | Das insns Array darf nur gültige Dalvik-Opcodes enthalten. |
A4 | Der Index der Anweisung n+1 muss unter Berücksichtigung möglicher Operanden gleich dem Index der Anweisung n plus der Länge der Anweisung n sein. |
A5 | Die letzte Anweisung im insns Array muss am Index insns_size-1 enden. |
A6 | Alle goto und if-<kind> -Ziele müssen Opcodes innerhalb derselben Methode sein. |
A7 | Alle Ziele einer packed-switch Anweisung müssen Opcodes innerhalb derselben Methode sein. Die Größe und die Liste der Ziele müssen konsistent sein. |
A8 | Alle Ziele einer sparse-switch Anweisung müssen Opcodes innerhalb derselben Methode sein. Die entsprechende Tabelle muss konsistent und von unten nach oben sortiert sein. |
A9 | Der B Operand der Anweisungen const-string und const-string/jumbo muss ein gültiger Index im String-Konstantenpool sein. |
A10 | Der C Operand der Anweisungen iget<kind> und iput<kind> muss ein gültiger Index im Feldkonstantenpool sein. Der referenzierte Eintrag muss ein Instanzfeld darstellen. |
A11 | Der C Operand der Anweisungen sget<kind> und sput<kind> muss ein gültiger Index im Feldkonstantenpool sein. Der referenzierte Eintrag muss ein statisches Feld darstellen. |
A12 | Der C Operand der Anweisungen invoke-virtual , invoke-super , invoke-direct und invoke-static muss ein gültiger Index im Methodenkonstantenpool sein. |
A13 | Der B Operand der Anweisungen invoke-virtual/range , invoke-super/range , invoke-direct/range und invoke-static/range muss ein gültiger Index im Methodenkonstantenpool sein. |
A14 | Eine Methode, deren Name mit „<“ beginnt, darf nur implizit von der VM aufgerufen werden, nicht von Code, der aus einer .dex Datei stammt. Die einzige Ausnahme ist der Instanzinitialisierer, der durch invoke-direct aufgerufen werden kann. |
A15 | Der C Operand der invoke-interface Anweisung muss ein gültiger Index im Methodenkonstantenpool sein. Die referenzierte method_id muss zu einer Schnittstelle (nicht zu einer Klasse) gehören. |
A16 | Der B Operand der invoke-interface/range Anweisung muss ein gültiger Index im Methodenkonstantenpool sein. Die referenzierte method_id muss zu einer Schnittstelle (nicht zu einer Klasse) gehören. |
A17 | Der B Operand der Anweisungen const-class , check-cast , new-instance und filled-new-array/range muss ein gültiger Index im Typkonstantenpool sein. |
A18 | Der C Operand der Anweisungen instance-of , new-array “ und filled-new-array muss ein gültiger Index im Typkonstantenpool sein. |
A19 | Die Abmessungen eines Arrays, das durch eine new-array Anweisung erstellt wurde, müssen kleiner als 256 sein. |
A20 | Die new Anweisung darf sich nicht auf Array-Klassen, Schnittstellen oder abstrakte Klassen beziehen. |
A21 | Der Typ, auf den sich eine new-array Anweisung bezieht, muss ein gültiger Nicht-Referenztyp sein. |
A22 | Alle Register, auf die ein Befehl mit einfacher Breite (nicht paarweise) verweist, müssen für die aktuelle Methode gültig sein. Das heißt, ihre Indizes dürfen nicht negativ und kleiner als registers_size sein. |
A23 | Alle Register, auf die ein Befehl in doppelter Breite (Paar) verweist, müssen für die aktuelle Methode gültig sein. Das heißt, ihre Indizes dürfen nicht negativ und kleiner als registers_size-1 sein. |
A24 | Der Operand method_id der Anweisungen invoke-virtual und invoke-direct muss zu einer Klasse (nicht zu einer Schnittstelle) gehören. In Dex-Dateien vor Version 037 muss das Gleiche auch für die Anweisungen invoke-super und invoke-static gelten. |
A25 | Der Operand method_id der Anweisungen invoke-virtual/range und invoke-direct/range muss zu einer Klasse (nicht zu einer Schnittstelle) gehören. In Dex-Dateien vor Version 037 muss das Gleiche auch für die Anweisungen invoke-super/range und invoke-static/range gelten. |
Strukturelle Bytecode-Einschränkungen
Strukturelle Einschränkungen sind Einschränkungen für Beziehungen zwischen mehreren Elementen des Bytecodes. Sie können normalerweise nicht ohne den Einsatz von Kontroll- oder Datenflussanalysetechniken überprüft werden.
Kennung | Beschreibung |
---|---|
B1 | Anzahl und Art der Argumente (Register und unmittelbare Werte) müssen immer mit der Anweisung übereinstimmen. |
B2 | Registerpaare dürfen niemals aufgelöst werden. |
B3 | Ein Register (oder Paar) muss zuerst zugewiesen werden, bevor es gelesen werden kann. |
B4 | Eine invoke-direct Anweisung darf einen Instanzinitialisierer oder eine Methode nur in der aktuellen Klasse oder einer ihrer Superklassen aufrufen. |
B5 | Ein Instanzinitialisierer darf nur für eine nicht initialisierte Instanz aufgerufen werden. |
B6 | Instanzmethoden dürfen nur auf bereits initialisierten Instanzen aufgerufen werden und auf Instanzfelder kann nur auf bereits initialisierte Instanzen zugegriffen werden. |
B7 | Ein Register, das das Ergebnis eines Befehls für eine new-instance enthält, darf nicht verwendet werden, wenn derselbe Befehl new-instance erneut ausgeführt wird, bevor die Instanz initialisiert wird. |
B8 | Ein Instanzinitialisierer muss einen anderen Instanzinitialisierer (gleiche Klasse oder Oberklasse) aufrufen, bevor auf Instanzmitglieder zugegriffen werden kann. Ausnahmen bilden nicht geerbte Instanzfelder, die vor dem Aufruf eines anderen Initialisierers zugewiesen werden können, und die Object Klasse im Allgemeinen. |
B9 | Alle tatsächlichen Methodenargumente müssen mit ihren jeweiligen formalen Argumenten zuweisungskompatibel sein. |
B10 | Für jeden Instanzmethodenaufruf muss die tatsächliche Instanz mit der in der Anweisung angegebenen Klasse oder Schnittstelle zuweisungskompatibel sein. |
B11 | Eine return<kind> -Anweisung muss mit dem Rückgabetyp ihrer Methode übereinstimmen. |
B12 | Beim Zugriff auf geschützte Mitglieder einer Superklasse muss der tatsächliche Typ der Instanz, auf die zugegriffen wird, entweder die aktuelle Klasse oder eine ihrer Unterklassen sein. |
B13 | Der Typ eines in einem statischen Feld gespeicherten Werts muss mit dem Feldtyp zuweisungskompatibel oder in diesen konvertierbar sein. |
B14 | Der Typ eines in einem Feld gespeicherten Werts muss mit dem Feldtyp zuweisungskompatibel oder in diesen konvertierbar sein. |
B15 | Der Typ jedes in einem Array gespeicherten Werts muss mit dem Komponententyp des Arrays zuweisungskompatibel sein. |
B16 | Der A Operand einer throw Anweisung muss mit java.lang.Throwable zuweisungskompatibel sein. |
B17 | Die letzte erreichbare Anweisung einer Methode muss entweder eine Rückwärts goto oder Branch-Anweisung, eine return -Anweisung oder eine throw -Anweisung sein. Es darf nicht möglich sein, das insns Array unten zu belassen. |
B18 | Die nicht zugewiesene Hälfte eines früheren Registerpaars kann möglicherweise nicht gelesen werden (wird als ungültig betrachtet), bis sie durch einen anderen Befehl neu zugewiesen wurde. |
B19 | Einer move-result<kind> -Anweisung muss (im insns -Array) unmittelbar eine invoke-<kind> -Anweisung vorangehen. Die einzige Ausnahme ist die Anweisung move-result-object , der auch eine Anweisung filled-new-array vorangestellt sein kann. |
B20 | Einer move-result<kind> -Anweisung muss (im tatsächlichen Kontrollfluss) unmittelbar eine passende return-<kind> -Anweisung vorangehen (zu dieser darf nicht gesprungen werden). Die einzige Ausnahme ist die Anweisung move-result-object , der auch eine Anweisung filled-new-array vorangestellt sein kann. |
B21 | Eine move-exception Anweisung darf nur als erste Anweisung in einem Ausnahmehandler erscheinen. |
B22 | Die Pseudoanweisungen packed-switch-data , sparse-switch-data und fill-array-data dürfen für den Kontrollfluss nicht erreichbar sein. |