Ce document décrit la mise en page et le contenu des fichiers .dex
, qui sont utilisés pour contenir un ensemble de définitions de classe et leurs données complémentaires associées.
Guide des types
Nom | Description |
---|---|
octet | Entier signé de 8 bits |
ubyte | Entier non signé de 8 bits |
court | Entier signé de 16 bits, little-endian |
ushort | Entier non signé 16 bits, little-endian |
int | Entier signé de 32 bits, little-endian |
uint | Entier non signé de 32 bits, little-endian |
long | Entier signé de 64 bits, little-endian |
ulong | Entier non signé de 64 bits, little-endian |
sleb128 | LEB128 signé, longueur variable (voir ci-dessous) |
uleb128 | LEB128 non signé, longueur variable (voir ci-dessous) |
uleb128p1 | LEB128 non signé plus 1 , longueur variable (voir ci-dessous) |
LEB128
LEB128 ("Little-Endian Base 128") est un encodage de longueur variable pour les quantités entières signées ou non signées arbitraires. Le format a été emprunté à la spécification DWARF3. Dans un fichier .dex
, LEB128 n'est utilisé que pour encoder des quantités de 32 bits.
Chaque valeur encodée LEB128 se compose d'un à cinq octets, qui représentent ensemble une seule valeur de 32 bits. Le bit le plus significatif de chaque octet est défini, à l'exception de l'octet final de la séquence, dont le bit le plus significatif est effacé. Les sept bits restants de chaque octet sont une charge utile, avec les sept bits les moins significatifs de la quantité dans le premier octet, les sept suivants dans le deuxième octet, et ainsi de suite. Dans le cas d'un LEB128 signé (sleb128
), le bit de charge utile le plus significatif du dernier octet de la séquence est étendu au signe pour produire la valeur finale. Dans le cas non signé (uleb128
), tous les bits qui ne sont pas explicitement représentés sont interprétés comme 0
.
Diagramme bit à bit d'une valeur LEB128 de deux octets | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Premier octet | Deuxième octet | ||||||||||||||
1 |
bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 0 |
bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 |
La variante uleb128p1
est utilisée pour représenter une valeur signée, où la représentation est celle de la valeur plus un encodée en tant que uleb128
. Cela permet d'encoder -1
(ou la valeur non signée 0xffffffff
) sur un seul octet, mais pas les autres nombres négatifs. C'est utile dans les cas où le nombre représenté doit être non négatif ou égal à -1
(ou 0xffffffff
), et où aucune autre valeur négative n'est autorisée (ou lorsque de grandes valeurs non signées ne sont pas susceptibles d'être nécessaires).
Voici quelques exemples de formats :
Séquence encodée | En tant que sleb128 |
En tant que uleb128 |
En tant que uleb128p1 |
---|---|---|---|
00 | 0 | 0 | -1 |
01 | 1 | 1 | 0 |
7f | -1 | 127 | 126 |
80 7f | -128 | 16256 | 16255 |
Disposition du fichier
Nom | Format | Description |
---|---|---|
en-tête | header_item | l'en-tête ; |
string_ids | string_id_item[] | Liste d'identifiants de chaînes. Il s'agit d'identifiants pour toutes les chaînes utilisées par ce fichier, soit pour la dénomination interne (par exemple, les descripteurs de type), soit en tant qu'objets constants auxquels le code fait référence. Cette liste doit être triée par contenu de chaîne, à l'aide des valeurs de point de code UTF-16 (et non d'une manière sensible aux paramètres régionaux). Elle ne doit pas contenir d'entrées en double. |
type_ids | type_id_item[] | Liste des identifiants de type. Il s'agit d'identifiants pour tous les types (classes, tableaux ou types primitifs) auxquels ce fichier fait référence, qu'ils soient définis ou non dans le fichier. Cette liste doit être triée par index string_id et ne doit contenir aucune entrée en double.
|
proto_ids | proto_id_item[] | Liste des identifiants de prototype de méthode. Il s'agit des identifiants de tous les prototypes auxquels ce fichier fait référence. Cette liste doit être triée par ordre décroissant de type de retour (par index type_id ), puis par liste d'arguments (ordre lexicographique, arguments individuels triés par index type_id ). La liste ne doit pas contenir d'entrées en double.
|
field_ids | field_id_item[] | liste des identifiants de champ. Il s'agit des identifiants de tous les champs auxquels ce fichier fait référence, qu'ils soient définis ou non dans le fichier. Cette liste doit être triée, où le type de définition (par index type_id ) est l'ordre principal, le nom du champ (par index string_id ) est l'ordre intermédiaire et le type (par index type_id ) est l'ordre secondaire. La liste ne doit pas contenir d'entrées en double.
|
method_ids | method_id_item[] | liste des identifiants de méthode. Il s'agit d'identifiants pour toutes les méthodes auxquelles ce fichier fait référence, qu'elles soient définies ou non dans le fichier. Cette liste doit être triée, où le type de définition (par index type_id ) est l'ordre principal, le nom de la méthode (par index string_id ) est l'ordre intermédiaire et le prototype de la méthode (par index proto_id ) est l'ordre secondaire. La liste ne doit pas contenir d'entrées en double.
|
class_defs | class_def_item[] | Liste des définitions de classe. Les classes doivent être ordonnées de sorte que la superclasse et les interfaces implémentées d'une classe donnée apparaissent dans la liste avant la classe référente. De plus, il n'est pas valide qu'une définition pour la classe du même nom apparaisse plusieurs fois dans la liste. |
call_site_ids | call_site_id_item[] | Liste des identifiants de site d'appel. Il s'agit des identifiants de tous les sites d'appel auxquels ce fichier fait référence, qu'ils soient définis ou non dans le fichier. Cette liste doit être triée par ordre croissant de call_site_off .
|
method_handles | method_handle_item[] | liste des handles de méthode. Liste de tous les gestionnaires de méthodes auxquels ce fichier fait référence, qu'ils soient définis ou non dans le fichier. Cette liste n'est pas triée et peut contenir des doublons qui correspondent logiquement à différentes instances de gestionnaire de méthode. |
de données | ubyte[] | zone de données, qui contient toutes les données d'assistance pour les tableaux listés ci-dessus. Différents éléments ont des exigences d'alignement différentes, et des octets de remplissage sont insérés avant chaque élément si nécessaire pour obtenir un alignement correct. |
link_data | ubyte[] | les données utilisées dans les fichiers liés de manière statique. Le format des données de cette section n'est pas spécifié dans ce document. Cette section est vide dans les fichiers non associés, et les implémentations d'exécution peuvent l'utiliser comme elles le souhaitent. |
Format du conteneur
La version 41 introduit un nouveau format de conteneur pour les données DEX afin de gagner de l'espace. Ce format de conteneur permet de combiner plusieurs fichiers DEX logiques en un seul fichier physique. Le nouveau format est principalement une simple concaténation des fichiers de l'ancien format, avec quelques différences :
file_size
correspond à la taille du fichier logique, et non du fichier physique. Il peut être utilisé pour parcourir tous les fichiers logiques du conteneur.- Les fichiers dex logiques peuvent faire référence à des données ultérieures dans le conteneur (mais pas antérieures). Cela permet aux fichiers dex de partager des données, telles que des chaînes, entre eux.
- Tous les décalages sont relatifs au fichier physique. Aucun décalage n'est relatif à l'en-tête. Cela permet de partager des sections avec des décalages entre des fichiers logiques.
- L'en-tête ajoute deux nouveaux champs pour décrire les limites du conteneur. Il s'agit d'un contrôle de cohérence supplémentaire qui facilite le portage du code vers le nouveau format.
- Les champs
data_size
etdata_off
ne sont plus utilisés. Les données peuvent être réparties sur plusieurs fichiers logiques et ne doivent pas nécessairement être contiguës.
Définitions de bitfield, de chaîne et de constante
DEX_FILE_MAGIC
Intégré dans header_item
La chaîne/le tableau constant DEX_FILE_MAGIC
correspond à la liste des octets qui doivent figurer au début d'un fichier .dex
pour qu'il soit reconnu comme tel. La valeur contient intentionnellement un caractère de nouvelle ligne ("\n"
ou 0x0a
) et un octet nul ("\0"
ou 0x00
) pour faciliter la détection de certaines formes de corruption. La valeur encode également un numéro de version du format sous la forme de trois chiffres décimaux, qui devrait augmenter de manière monotone au fil du temps à mesure que le format évolue.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
Remarque : La prise en charge de la version 041
du format a été ajoutée dans la version 16 d'Android, qui est compatible avec le format de conteneur.
Remarque : La prise en charge de la version 040
du format a été ajoutée dans la version Android 10.0, qui a étendu l'ensemble des caractères autorisés dans SimpleNames.
Remarque : La prise en charge de la version 039
du format a été ajoutée dans la version Android 9.0, qui a introduit deux nouveaux bytecodes, const-method-handle
et const-method-type
. (Chacun d'eux est décrit dans le tableau Résumé de l'ensemble de bytecode.) Dans Android 10, la version 039
étend le format de fichier DEX pour inclure des informations d'API masquées qui ne s'appliquent qu'aux fichiers DEX sur le chemin de classe de démarrage.
Remarque : La prise en charge de la version 038
du format a été ajoutée dans la version Android 8.0. La version 038
a ajouté de nouveaux codes d'octet (invoke-polymorphic
et invoke-custom
) et des données pour les gestionnaires de méthodes.
Remarque : La prise en charge de la version 037
du format a été ajoutée dans la version 7.0 d'Android. Avant la version 037
, la plupart des versions d'Android utilisaient la version 035
du format. La seule différence entre les versions 035
et 037
est l'ajout de méthodes par défaut et l'ajustement de invoke
.
Remarque : Au moins deux versions antérieures du format ont été utilisées dans des versions logicielles publiques largement disponibles. Par exemple, la version 009
a été utilisée pour les versions M3 de la plate-forme Android (novembre-décembre 2007) et la version 013
pour les versions M5 de la plate-forme Android (février-mars 2008). À plusieurs égards, ces versions antérieures du format diffèrent considérablement de la version décrite dans ce document.
ENDIAN_CONSTANT et REVERSE_ENDIAN_CONSTANT
Intégré dans header_item
La constante ENDIAN_CONSTANT
est utilisée pour indiquer l'endianness du fichier dans lequel elle se trouve. Bien que le format standard .dex
soit little-endian, les implémentations peuvent choisir d'effectuer un échange d'octets. Si une implémentation rencontre un en-tête dont endian_tag
est REVERSE_ENDIAN_CONSTANT
au lieu de ENDIAN_CONSTANT
, elle saura que le fichier a été inversé par octets par rapport à la forme attendue.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
Intégré dans class_def_item et debug_info_item
La constante NO_INDEX
est utilisée pour indiquer qu'une valeur d'index est absente.
Remarque : Cette valeur n'est pas définie sur 0
, car il s'agit généralement d'un index valide.
La valeur choisie pour NO_INDEX
est représentable sous la forme d'un seul octet dans l'encodage uleb128p1
.
uint NO_INDEX = 0xffffffff; // == -1 if treated as a signed int
Définitions des indicateurs d'accès
Intégré dans class_def_item, encoded_field, encoded_method et InnerClass
Les champs de bits de ces indicateurs sont utilisés pour indiquer l'accessibilité et les propriétés générales des classes et des membres de classe.
Nom | Valeur | Pour les classes (et les annotations InnerClass ) |
Pour les champs | Pour les méthodes |
---|---|---|---|---|
ACC_PUBLIC | 0x1 | public : visible partout |
public : visible partout |
public : visible partout |
ACC_PRIVATE | 0x2 | private : visible uniquement par la classe de définition
|
private : visible uniquement pour la classe de définition |
private : visible uniquement pour la classe de définition |
ACC_PROTECTED | 0x4 | protected : visible pour le package et les sous-classes
|
protected : visible pour le package et les sous-classes |
protected : visible pour le package et les sous-classes |
ACC_STATIC | 0x8 | static : n'est pas construit avec une référence this externe |
static : portée globale à la classe de définition |
static : n'accepte pas d'argument this |
ACC_FINAL | 0x10 | final : non sous-classable |
final : immuable après la construction |
final : non modifiable |
ACC_SYNCHRONIZED | 0x20 | synchronized : le verrou associé est automatiquement acquis lors de l'appel à cette méthode. Remarque : Cette valeur ne peut être définie que si |
||
ACC_VOLATILE | 0x40 | volatile : règles d'accès spécial pour assurer la sécurité des threads |
||
ACC_BRIDGE | 0x40 | méthode pont, ajoutée automatiquement par le compilateur en tant que pont de type sécurisé | ||
ACC_TRANSIENT | 0x80 | transient : ne pas enregistrer par sérialisation par défaut |
||
ACC_VARARGS | 0x80 | Le dernier argument doit être traité comme un argument "rest" par le compilateur. | ||
ACC_NATIVE | 0x100 | native : implémenté dans le code natif |
||
ACC_INTERFACE | 0x200 | interface : classe abstraite à implémentation multiple |
||
ACC_ABSTRACT | 0x400 | abstract : non directement instanciable |
abstract : non implémenté par cette classe |
|
ACC_STRICT | 0x800 | strictfp : règles strictes pour l'arithmétique à virgule flottante |
||
ACC_SYNTHETIC | 0x1000 | non directement définies dans le code source. | non directement définies dans le code source. | non directement définies dans le code source. |
ACC_ANNOTATION | 0x2000 | déclarée comme classe d'annotation | ||
ACC_ENUM | 0x4000 | déclaré comme type énuméré | déclarée comme valeur énumérée | |
(non utilisé) | 0x8000 | |||
ACC_CONSTRUCTOR | 0x10000 | méthode constructeur (initialiseur de classe ou d'instance) | ||
ACC_DECLARED_ SYNCHRONIZED |
0x20000 | a déclaré synchronized . Remarque : Cela n'a aucun effet sur l'exécution (autre que dans la réflexion de cet indicateur, en soi). |
InnerClass
et jamais pour les class_def_item
.
Encodage UTF-8 modifié
Pour faciliter la prise en charge des anciens formats, le format .dex
encode ses données de chaîne dans un format UTF-8 modifié, qui est devenu une norme de facto et que nous appellerons MUTF-8. Cette forme est identique à la forme UTF-8 standard, à quelques exceptions près :
- Seuls les encodages sur un, deux et trois octets sont utilisés.
- Les points de code compris dans la plage
U+10000
…U+10ffff
sont encodés sous forme de paire de substitution, dont chacun est représenté par une valeur encodée sur trois octets. - Le point de code
U+0000
est encodé sur deux octets. - Un simple octet nul (valeur
0
) indique la fin d'une chaîne, conformément à l'interprétation standard du langage C.
Les deux premiers éléments ci-dessus peuvent être résumés comme suit : MUTF-8 est un format d'encodage pour UTF-16, au lieu d'être un format d'encodage plus direct pour les caractères Unicode.
Les deux derniers éléments ci-dessus permettent à la fois d'inclure le point de code U+0000
dans une chaîne et de le manipuler comme une chaîne de style C terminée par un caractère nul.
Toutefois, l'encodage spécial de U+0000
signifie que, contrairement à l'UTF-8 normal, le résultat de l'appel de la fonction C standard strcmp()
sur une paire de chaînes MUTF-8 n'indique pas toujours le résultat correctement signé de la comparaison de chaînes inégales.
Lorsque l'ordre (et pas seulement l'égalité) est important, le moyen le plus simple de comparer les chaînes MUTF-8 consiste à les décoder caractère par caractère et à comparer les valeurs décodées. (Toutefois, des implémentations plus astucieuses sont également possibles.)
Pour en savoir plus sur l'encodage des caractères, veuillez consulter The Unicode Standard. MUTF-8 est en fait plus proche de l'encodage CESU-8 (relativement moins connu) que d'UTF-8 en soi.
Encodage de la valeur encodée
Intégré dans annotation_element et encoded_array_item
Un encoded_value
est un élément encodé de données structurées hiérarchiquement (presque) arbitraires. L'encodage est conçu pour être à la fois compact et facile à analyser.
Nom | Format | Description |
---|---|---|
(value_arg << 5) | value_type | ubyte | octet indiquant le type de value immédiatement suivant, avec un argument de clarification facultatif dans les trois bits de poids fort.
Vous trouverez ci-dessous les différentes définitions de value .
Dans la plupart des cas, value_arg code la longueur du value immédiatement suivant en octets, sous la forme (size - 1) , par exemple : 0 signifie que la valeur nécessite un octet, et 7 signifie qu'elle en nécessite huit. Toutefois, il existe des exceptions, comme indiqué ci-dessous.
|
value | ubyte[] | Octets représentant la valeur, de longueur variable et interprétés différemment pour différents octets value_type , mais toujours en little-endian. Pour en savoir plus, consultez les différentes définitions de valeurs ci-dessous.
|
Formats de valeurs
Nom du type | value_type |
Format value_arg |
Format value |
Description |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (aucune ; doit être 0 ) |
ubyte[1] | valeur entière signée d'un octet |
VALUE_SHORT | 0x02 | Taille : 1 (0…1) | ubyte[size] | Valeur entière signée de deux octets, avec extension du signe |
VALUE_CHAR | 0x03 | Taille : 1 (0…1) | ubyte[size] | Valeur entière non signée de deux octets, étendue à zéro |
VALUE_INT | 0x04 | Taille : 1 (0…3) | ubyte[size] | valeur entière signée de quatre octets, avec extension du signe |
VALUE_LONG | 0x06 | Taille : 1 (0…7) | ubyte[size] | Valeur entière signée de huit octets, avec extension du signe |
VALUE_FLOAT | 0x10 | Taille : 1 (0…3) | ubyte[size] | Modèle de bits de quatre octets, étendu à zéro à droite et interprété comme une valeur à virgule flottante IEEE754 32 bits |
VALUE_DOUBLE | 0x11 | Taille : 1 (0…7) | ubyte[size] | un modèle de bits de huit octets, étendu à zéro à droite et interprété comme une valeur à virgule flottante IEEE754 de 64 bits. |
VALUE_METHOD_TYPE | 0x15 | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section proto_ids et représentant une valeur de type de méthode
|
VALUE_METHOD_HANDLE | 0x16 | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section method_handles et représentant une valeur de handle de méthode
|
VALUE_STRING | 0x17 | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section string_ids et représentant une valeur de chaîne
|
VALUE_TYPE | 0x18 | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section type_ids et représentant une valeur de type/classe réflexive
|
VALUE_FIELD | 0x19 | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section field_ids et représentant une valeur de champ réfléchissante
|
VALUE_METHOD | 0x1a | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section method_ids et représentant une valeur de méthode réflexive
|
VALUE_ENUM | 0x1b | Taille : 1 (0…3) | ubyte[size] | Valeur entière non signée (étendue à zéro) de quatre octets, interprétée comme un index dans la section field_ids et représentant la valeur d'une constante de type énuméré
|
VALUE_ARRAY | 0x1c | (aucune ; doit être 0 ) |
encoded_array | un tableau de valeurs, au format spécifié par "Format encoded_array " ci-dessous. La taille de value est implicite dans l'encodage.
|
VALUE_ANNOTATION | 0x1d | (aucune ; doit être 0 ) |
encoded_annotation | une sous-annotation, au format spécifié par "encoded_annotation format" ci-dessous. La taille de value est implicite dans l'encodage.
|
VALUE_NULL | 0x1e | (aucune ; doit être 0 ) |
(aucun) | Valeur de référence null |
VALUE_BOOLEAN | 0x1f | booléen (0…1) | (aucun) | Valeur d'un bit : 0 pour false et 1 pour true . Le bit est représenté dans value_arg .
|
Format encoded_array
Nom | Format | Description |
---|---|---|
taille | uleb128 | nombre d'éléments du tableau |
values | encoded_value[size] | une série de séquences d'octets size encoded_value au format spécifié dans cette section, concaténées de manière séquentielle.
|
Format encoded_annotation
Nom | Format | Description |
---|---|---|
type_idx | uleb128 | Type de l'annotation. Il doit s'agir d'un type de classe (et non d'un type de tableau ou primitif). |
taille | uleb128 | Nombre de mappages nom-valeur dans cette annotation |
éléments | annotation_element[size] | éléments de l'annotation, représentés directement en ligne (et non sous forme de décalages). Les éléments doivent être triés par ordre croissant selon l'index string_id .
|
Format de annotation_element
Nom | Format | Description |
---|---|---|
name_idx | uleb128 | Nom de l'élément, représenté sous la forme d'un index dans la section string_ids . La chaîne doit être conforme à la syntaxe de MemberName, définie ci-dessus.
|
value | encoded_value | valeur de l'élément |
Syntaxe des chaînes
Un fichier .dex
contient plusieurs types d'éléments qui font référence à une chaîne. Les définitions de style BNF suivantes indiquent la syntaxe acceptable pour ces chaînes.
SimpleName
Un SimpleName constitue la base de la syntaxe des noms d'autres éléments. Le format .dex
offre une grande marge de manœuvre (bien plus que la plupart des langues sources courantes). En bref, un nom simple se compose de n'importe quel caractère alphabétique ou chiffre ASCII en minuscules, de quelques symboles ASCII en minuscules spécifiques et de la plupart des points de code non ASCII qui ne sont pas des caractères de contrôle, des espaces ou des caractères spéciaux. À partir de la version 040
, le format autorise également les caractères d'espacement (catégorie Unicode Zs
). Notez que les points de code de substitution (dans la plage U+d800
… U+dfff
) ne sont pas considérés comme des caractères de nom valides en soi, mais que les caractères Unicode supplémentaires sont valides (ils sont représentés par l'alternative finale de la règle pour SimpleNameChar) et doivent être représentés dans un fichier sous forme de paires de points de code de substitution dans l'encodage MUTF-8.
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
depuis la version 040 de DEX |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
depuis la version 040 de DEX |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
depuis la version 040 de DEX |
| | U+2010 … U+2027 |
|
| | U+202f |
depuis la version 040 de DEX |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
MemberName
utilisé par field_id_item et method_id_item
Un MemberName est le nom d'un membre d'une classe, les membres étant des champs, des méthodes et des classes internes.
MemberName → | |
SimpleName | |
| | '<' SimpleName '>' |
FullClassName
Un FullClassName est un nom de classe complet, y compris un spécificateur de package facultatif suivi d'un nom obligatoire.
FullClassName → | |
OptionalPackagePrefix SimpleName | |
OptionalPackagePrefix → | |
(SimpleName '/' )* |
TypeDescriptor
Utilisé par type_id_item
Un TypeDescriptor est la représentation de n'importe quel type, y compris les primitives, les classes, les tableaux et void
. Vous trouverez ci-dessous la signification des différentes versions.
TypeDescriptor → | |
'V' |
|
| | FieldTypeDescriptor |
FieldTypeDescriptor → | |
NonArrayFieldTypeDescriptor | |
| | ('[' * 1…255)
NonArrayFieldTypeDescriptor |
NonArrayFieldTypeDescriptor→ | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' FullClassName ';' |
ShortyDescriptor
Utilisé par proto_id_item
Un ShortyDescriptor est la représentation abrégée d'un prototype de méthode, y compris les types de retour et de paramètre, à l'exception du fait qu'il n'y a pas de distinction entre les différents types de référence (classe ou tableau). Au lieu de cela, tous les types de référence sont représentés par un seul caractère 'L'
.
ShortyDescriptor → | |
ShortyReturnType (ShortyFieldType)* | |
ShortyReturnType → | |
'V' |
|
| | ShortyFieldType |
ShortyFieldType → | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' |
Sémantique de TypeDescriptor
Voici la signification de chacune des variantes de TypeDescriptor.
Syntaxe | Signification |
---|---|
V | void ; valide uniquement pour les types de retour |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
Lfully/qualified/Name; | la classe fully.qualified.Name |
[descriptor | Tableau de descriptor , utilisable de manière récursive pour les tableaux de tableaux, bien qu'il ne soit pas valide d'avoir plus de 255 dimensions.
|
Éléments et structures associées
Cette section inclut des définitions pour chacun des éléments de premier niveau qui peuvent apparaître dans un fichier .dex
.
header_item
Apparaît dans la section d'en-tête
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
magique | ubyte[8] = DEX_FILE_MAGIC | valeur magique. Pour en savoir plus, consultez la section "DEX_FILE_MAGIC " ci-dessus.
|
somme de contrôle | uint | Somme de contrôle Adler32 du reste du fichier (tout sauf magic et ce champ). Elle permet de détecter la corruption du fichier.
|
signature | ubyte[20] | Signature SHA-1 (hachage) du reste du fichier (tout sauf magic , checksum et ce champ) ; utilisée pour identifier de manière unique les fichiers
|
file_size | uint |
Taille de l'intégralité du fichier (y compris l'en-tête), en octets (v40 ou version antérieure) Distance en octets entre le début de cet en-tête et l'en-tête suivant ou la fin du fichier entier (le conteneur). (v41 ou version ultérieure) |
header_size | uint |
Taille de l'en-tête (toute cette section), en octets. Cela permet au moins une compatibilité limitée en amont/en aval sans invalider le format. doit être de 0x70 (112) octets (v40 ou version antérieure) doit être de 0x78 (120) octets (v41 ou version ultérieure) |
endian_tag | uint = ENDIAN_CONSTANT | tag endianness. Pour en savoir plus, consultez la section "ENDIAN_CONSTANT et REVERSE_ENDIAN_CONSTANT " ci-dessus.
|
link_size | uint | Taille de la section de lien ou 0 si ce fichier n'est pas lié statiquement |
link_off | uint | Décalage depuis le début du fichier jusqu'à la section de liens, ou
0 si link_size == 0 . Si le décalage n'est pas nul, il doit correspondre à un décalage dans la section link_data . Le format des données pointées n'est pas spécifié dans ce document. Ce champ d'en-tête (et le précédent) sont laissés en tant que hooks pour être utilisés par les implémentations d'exécution.
|
map_off | uint | Décalage depuis le début du fichier jusqu'à l'élément de carte. Le décalage, qui doit être non nul, doit être un décalage dans la section data , et les données doivent être au format spécifié par "map_list " ci-dessous.
|
string_ids_size | uint | Nombre de chaînes dans la liste des identifiants de chaîne |
string_ids_off | uint | décalage du début du fichier à la liste des identifiants de chaîne, ou
0 si string_ids_size == 0 (cas limite étrange, il faut l'admettre). Si le décalage n'est pas nul, il doit être défini au début de la section string_ids .
|
type_ids_size | uint | Nombre d'éléments dans la liste des identifiants de type (65 535 au maximum) |
type_ids_off | uint | décalage du début du fichier à la liste des identifiants de type, ou 0 si type_ids_size == 0 (cas limite étrange, il faut l'admettre). Si le décalage n'est pas nul, il doit être défini au début de la section type_ids .
|
proto_ids_size | uint | Nombre d'éléments dans la liste des identifiants de prototype (65 535 au maximum) |
proto_ids_off | uint | décalage du début du fichier à la liste des identifiants de prototype, ou
0 si proto_ids_size == 0 (cas limite étrange, il faut l'admettre). Si le décalage n'est pas nul, il doit être défini au début de la section proto_ids .
|
field_ids_size | uint | Nombre d'éléments dans la liste des identifiants de champ |
field_ids_off | uint | Décalage par rapport au début du fichier jusqu'à la liste des identifiants de champ, ou 0 si field_ids_size == 0 . Si le décalage n'est pas nul, il doit être défini au début de la section field_ids . |
method_ids_size | uint | Nombre d'éléments dans la liste des identifiants de méthode |
method_ids_off | uint | Décalage du début du fichier à la liste des identifiants de méthode, ou 0 si method_ids_size == 0 . Si le décalage n'est pas nul, il doit être défini au début de la section method_ids . |
class_defs_size | uint | Nombre d'éléments dans la liste des définitions de classe |
class_defs_off | uint | décalage du début du fichier à la liste des définitions de classe, ou 0 si class_defs_size == 0 (cas limite étrange, il faut l'admettre). Si le décalage n'est pas nul, il doit être défini au début de la section class_defs .
|
data_size | uint |
Taille de la section Non utilisé (v41 ou version ultérieure) |
data_off | uint |
Décalage entre le début du fichier et le début de la section Non utilisé (v41 ou version ultérieure) |
container_size | uint |
Ce champ n'existe pas. Elle peut être considérée comme égale à Taille de l'intégralité du fichier (y compris les autres en-têtes dex et leurs données). (v41 ou version ultérieure) |
header_offset | uint |
Ce champ n'existe pas. Elle peut être considérée comme égale à Décalage entre le début du fichier et le début de cet en-tête. (v41 ou version ultérieure) |
map_list
Apparaît dans la section "Données"
Référencé à partir de header_item
Alignement : 4 octets
Il s'agit d'une liste de l'intégralité du contenu d'un fichier, dans l'ordre. Il contient une certaine redondance par rapport à header_item
, mais est conçu pour être un formulaire facile à utiliser pour parcourir un fichier entier. Un type donné ne doit apparaître qu'une seule fois dans une carte, mais il n'y a aucune restriction sur l'ordre dans lequel les types peuvent apparaître, à l'exception des restrictions impliquées par le reste du format (par exemple, une section header
doit apparaître en premier, suivie d'une section string_ids
, etc.). De plus, les entrées de la carte doivent être ordonnées par décalage initial et ne doivent pas se chevaucher.
Nom | Format | Description |
---|---|---|
taille | uint | Taille de la liste, en entrées |
liste | map_item[size] | éléments de la liste |
Format map_item
Nom | Format | Description |
---|---|---|
type | ushort | Type des articles (voir le tableau ci-dessous) |
unused | ushort | (non utilisé) |
taille | uint | Nombre d'éléments à trouver au décalage indiqué |
compensés en carbone | uint | Décalage depuis le début du fichier jusqu'aux éléments en question |
Codes de type
Type d'article | Constante | Valeur | Taille de l'élément en octets |
---|---|---|---|
header_item | TYPE_HEADER_ITEM | 0x0000 | 0x70 |
string_id_item | TYPE_STRING_ID_ITEM | 0x0001 | 0x04 |
type_id_item | TYPE_TYPE_ID_ITEM | 0x0002 | 0x04 |
proto_id_item | TYPE_PROTO_ID_ITEM | 0x0003 | 0x0c |
field_id_item | TYPE_FIELD_ID_ITEM | 0x0004 | 0x08 |
method_id_item | TYPE_METHOD_ID_ITEM | 0x0005 | 0x08 |
class_def_item | TYPE_CLASS_DEF_ITEM | 0x0006 | 0x20 |
call_site_id_item | TYPE_CALL_SITE_ID_ITEM | 0x0007 | 0x04 |
method_handle_item | TYPE_METHOD_HANDLE_ITEM | 0x0008 | 0x08 |
map_list | TYPE_MAP_LIST | 0x1000 | 4 + (item.size * 12) |
type_list | TYPE_TYPE_LIST | 0x1001 | 4 + (item.size * 2) |
annotation_set_ref_list | TYPE_ANNOTATION_SET_REF_LIST | 0x1002 | 4 + (item.size * 4) |
annotation_set_item | TYPE_ANNOTATION_SET_ITEM | 0x1003 | 4 + (item.size * 4) |
class_data_item | TYPE_CLASS_DATA_ITEM | 0x2000 | implicit; must parse |
code_item | TYPE_CODE_ITEM | 0x2001 | implicit; must parse |
string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | implicit; must parse |
debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | implicit; must parse |
annotation_item | TYPE_ANNOTATION_ITEM | 0x2004 | implicit; must parse |
encoded_array_item | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | implicit; must parse |
annotations_directory_item | TYPE_ANNOTATIONS_DIRECTORY_ITEM | 0x2006 | implicit; must parse |
hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | implicit; must parse |
string_id_item
Apparaît dans la section string_ids
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
string_data_off | uint | Décalage entre le début du fichier et les données de chaîne pour cet élément. Le décalage doit correspondre à un emplacement dans la section data , et les données doivent être au format spécifié par "string_data_item " ci-dessous.
Aucune exigence d'alignement n'est requise pour le décalage.
|
string_data_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
Nom | Format | Description |
---|---|---|
utf16_size | uleb128 | Taille de cette chaîne, en unités de code UTF-16 (qui correspond à la "longueur de la chaîne" dans de nombreux systèmes). Autrement dit, il s'agit de la longueur décodée de la chaîne. (La longueur encodée est implicite en fonction de la position de l'octet 0 .) |
de données | ubyte[] | une série d'unités de code MUTF-8 (également appelées octets ou bytes) suivie d'un octet de valeur 0 . Pour en savoir plus sur le format des données, consultez la section "Encodage MUTF-8 (UTF-8 modifié)" ci-dessus.
Remarque : Il est acceptable d'avoir une chaîne qui inclut (la forme encodée de) des unités de code de substitution UTF-16 (c'est-à-dire |
type_id_item
Apparaît dans la section "type_ids"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
descriptor_idx | uint | index dans la liste string_ids pour la chaîne de descripteur de ce type. La chaîne doit être conforme à la syntaxe de TypeDescriptor, définie ci-dessus.
|
proto_id_item
Apparaît dans la section proto_ids
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
shorty_idx | uint | Index dans la liste string_ids pour la chaîne de description courte de ce prototype. La chaîne doit respecter la syntaxe de ShortyDescriptor, définie ci-dessus, et doit correspondre au type renvoyé et aux paramètres de cet élément.
|
return_type_idx | uint | index dans la liste type_ids pour le type renvoyé de ce prototype
|
parameters_off | uint | Décalage depuis le début du fichier jusqu'à la liste des types de paramètres pour ce prototype, ou 0 si ce prototype ne comporte aucun paramètre. Si ce décalage est non nul, il doit figurer dans la section data , et les données doivent être au format spécifié par "type_list" ci-dessous. De plus, la liste ne doit pas faire référence au type void .
|
field_id_item
Apparaît dans la section "field_ids"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
class_idx | ushort | index dans la liste type_ids pour le définisseur de ce champ. Il doit s'agir d'un type de classe, et non d'un type primitif ou d'un tableau.
|
type_idx | ushort | Index dans la liste type_ids pour le type de ce champ
|
name_idx | uint | Index dans la liste string_ids pour le nom de ce champ. La chaîne doit être conforme à la syntaxe de MemberName, définie ci-dessus.
|
method_id_item
Apparaît dans la section "method_ids"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
class_idx | ushort | Index dans la liste type_ids pour le définisseur de cette méthode. Il doit s'agir d'un type de classe ou de tableau, et non d'un type primitif.
|
proto_idx | ushort | Index dans la liste proto_ids pour le prototype de cette méthode
|
name_idx | uint | index dans la liste string_ids pour le nom de cette méthode. La chaîne doit être conforme à la syntaxe de MemberName, définie ci-dessus.
|
class_def_item
Apparaît dans la section "class_defs"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
class_idx | uint | index dans la liste type_ids pour cette classe.
Il doit s'agir d'un type de classe, et non d'un type primitif ou d'un tableau.
|
access_flags | uint | Indicateurs d'accès pour la classe (public , final , etc.). Pour en savoir plus, consultez "Définitions de access_flags ".
|
superclass_idx | uint | index dans la liste type_ids pour la super-classe, ou la valeur constante NO_INDEX si cette classe n'a pas de super-classe (c'est-à-dire qu'il s'agit d'une classe racine telle que Object ). Si elle est présente, il doit s'agir d'un type de classe, et non d'un tableau ou d'un type primitif.
|
interfaces_off | uint | Décalage du début du fichier par rapport à la liste des interfaces, ou 0 s'il n'y en a pas. Ce décalage doit figurer dans la section data , et les données doivent être au format spécifié par "type_list " ci-dessous. Chacun des éléments de la liste doit être un type de classe (et non un tableau ni un type primitif), et il ne doit pas y avoir de doublons.
|
source_file_idx | uint | index dans la liste string_ids pour le nom du fichier contenant la source d'origine (au moins la plupart) de cette classe, ou la valeur spéciale NO_INDEX pour représenter l'absence de cette information. Le debug_info_item d'une méthode donnée peut remplacer ce fichier source, mais la plupart des classes ne devraient provenir que d'un seul fichier source.
|
annotations_off | uint | Décalage du début du fichier à la structure des annotations pour cette classe, ou 0 s'il n'y a pas d'annotations sur cette classe. Si ce décalage est non nul, il doit figurer dans la section data . Les données doivent y être au format spécifié par "annotations_directory_item " ci-dessous, avec tous les éléments faisant référence à cette classe en tant que définisseur.
|
class_data_off | uint | Décalage depuis le début du fichier jusqu'aux données de classe associées à cet élément, ou 0 s'il n'y a pas de données de classe pour cette classe. (Cela peut être le cas, par exemple, si cette classe est une interface de marqueur.) Si le décalage est non nul, il doit figurer dans la section data . Les données doivent y être au format spécifié par "class_data_item " ci-dessous, avec tous les éléments faisant référence à cette classe comme définisseur.
|
static_values_off | uint | Décalage par rapport au début du fichier vers la liste des valeurs initiales pour les champs static , ou 0 s'il n'y en a pas (et que tous les champs static doivent être initialisés avec 0 ou null ). Ce décalage doit se trouver dans la section data , et les données doivent y être au format spécifié par "encoded_array_item " ci-dessous. La taille du tableau ne doit pas dépasser le nombre de champs static déclarés par cette classe, et les éléments correspondent aux champs static dans le même ordre que celui déclaré dans le field_list correspondant. Le type de chaque élément de tableau doit correspondre au type déclaré de son champ correspondant.
S'il y a moins d'éléments dans le tableau que de champs static , les champs restants sont initialisés avec un 0 ou un null approprié au type.
|
call_site_id_item
Apparaît dans la section "call_site_ids"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
call_site_off | uint | Décalage par rapport au début du fichier pour appeler la définition du site. Le décalage doit figurer dans la section de données, et les données doivent être au format spécifié par "call_site_item" ci-dessous. |
call_site_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
call_site_item est un encoded_array_item dont les éléments correspondent aux arguments fournis à une méthode de l'éditeur de liens bootstrap. Les trois premiers arguments sont les suivants :
- Handle de méthode représentant la méthode de liaison du bootstrap (VALUE_METHOD_HANDLE).
- Nom de méthode que le bootstrap linker doit résoudre (VALUE_STRING).
- Type de méthode correspondant au type du nom de méthode à résoudre (VALUE_METHOD_TYPE).
Tous les arguments supplémentaires sont des valeurs constantes transmises à la méthode de l'éditeur de liens de bootstrap. Ces arguments sont transmis dans l'ordre et sans aucune conversion de type.
Le handle de méthode représentant la méthode de l'éditeur de liens d'amorçage doit avoir le type de retour java.lang.invoke.CallSite
. Voici les trois premiers types de paramètres :
java.lang.invoke.Lookup
java.lang.String
java.lang.invoke.MethodType
Les types de paramètres des arguments supplémentaires sont déterminés à partir de leurs valeurs constantes.
method_handle_item
Apparaît dans la section "method_handles"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
method_handle_type | ushort | type du handle de méthode (voir le tableau ci-dessous) |
unused | ushort | (non utilisé) |
field_or_method_id | ushort | ID de champ ou de méthode selon que le type de handle de méthode est un accesseur ou un appelant de méthode |
unused | ushort | (non utilisé) |
Codes de type de handle de méthode
Constante | Valeur | Description |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | Le handle de méthode est un setter (accesseur) de champ statique. |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | Le handle de méthode est un getter (accesseur) de champ statique. |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | Le handle de méthode est un setter (accesseur) de champ d'instance. |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | Le handle de méthode est un getter (accesseur) de champ d'instance. |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | Le handle de méthode est un appelant de méthode statique. |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | Le handle de méthode est un appelant de méthode d'instance |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | Un handle de méthode est un appelant de méthode de constructeur. |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | Le handle de méthode est un appelant de méthode directe |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | Un handle de méthode est un appelant de méthode d'interface. |
class_data_item
Référencé depuis class_def_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
Nom | Format | Description |
---|---|---|
static_fields_size | uleb128 | Nombre de champs statiques définis dans cet élément |
instance_fields_size | uleb128 | le nombre de champs d'instance définis dans cet élément ; |
direct_methods_size | uleb128 | le nombre de méthodes directes définies dans cet élément ; |
virtual_methods_size | uleb128 | nombre de méthodes virtuelles définies dans cet élément |
static_fields | encoded_field[static_fields_size] | les champs statiques définis, représentés sous la forme d'une séquence d'éléments encodés. Les champs doivent être triés par field_idx dans l'ordre croissant.
|
instance_fields | encoded_field[instance_fields_size] | les champs d'instance définis, représentés sous la forme d'une séquence d'éléments encodés. Les champs doivent être triés par field_idx dans l'ordre croissant.
|
direct_methods | encoded_method[direct_methods_size] | les méthodes directes définies (static , private ou constructeur), représentées sous la forme d'une séquence d'éléments encodés. Les méthodes doivent être triées par method_idx dans l'ordre croissant.
|
virtual_methods | encoded_method[virtual_methods_size] | les méthodes virtuelles définies (aucune des méthodes static , private ou constructeur), représentées sous la forme d'une séquence d'éléments encodés. Cette liste ne doit pas inclure les méthodes héritées, sauf si elles sont remplacées par la classe que cet élément représente. Les méthodes doivent être triées par method_idx dans l'ordre croissant.
Le method_idx d'une méthode virtuelle ne doit pas être identique à celui d'une méthode directe.
|
Remarque : Toutes les instances field_id
et method_id
des éléments doivent faire référence à la même classe de définition.
Format de encoded_field
Nom | Format | Description |
---|---|---|
field_idx_diff | uleb128 | Index dans la liste field_ids pour l'identité de ce champ (y compris le nom et le descripteur), représenté comme une différence par rapport à l'index de l'élément précédent de la liste. L'index du premier élément d'une liste est représenté directement.
|
access_flags | uleb128 | Indicateurs d'accès au champ (public , final , etc.). Pour en savoir plus, consultez "Définitions de access_flags ".
|
Format de encoded_method
Nom | Format | Description |
---|---|---|
method_idx_diff | uleb128 | Index dans la liste method_ids pour l'identité de cette méthode (y compris le nom et le descripteur), représenté comme une différence par rapport à l'index de l'élément précédent de la liste. L'index du premier élément d'une liste est représenté directement.
|
access_flags | uleb128 | Indicateurs d'accès pour la méthode (public , final , etc.). Pour en savoir plus, consultez "Définitions de access_flags ".
|
code_off | uleb128 | Décalage du début du fichier à la structure du code pour cette méthode, ou 0 si cette méthode est abstract ou native . Le décalage doit être défini sur un emplacement de la section data . Le format des données est spécifié par "code_item " ci-dessous.
|
type_list
Référencé à partir de class_def_item et proto_id_item
Apparaît dans la section "Données"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
taille | uint | Taille de la liste, en entrées |
liste | type_item[size] | éléments de la liste |
Format type_item
Nom | Format | Description |
---|---|---|
type_idx | ushort | index dans la liste type_ids |
code_item
Référencé à partir de encoded_method
Apparaît dans la section "Données"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
registers_size | ushort | le nombre de registres utilisés par ce code ; |
ins_size | ushort | Nombre de mots des arguments entrants de la méthode à laquelle ce code est destiné. |
outs_size | ushort | Nombre de mots de l'espace d'arguments sortants requis par ce code pour l'appel de méthode |
tries_size | ushort | le nombre de try_item pour cette instance. Si la valeur est différente de zéro, ces valeurs apparaissent sous forme de tableau tries juste après insns dans cette instance.
|
debug_info_off | uint | Décalage du début du fichier à la séquence d'informations de débogage (numéros de ligne + informations sur les variables locales) pour ce code, ou 0 s'il n'y a tout simplement aucune information. Si le décalage n'est pas nul, il doit correspondre à un emplacement dans la section data . Le format des données est spécifié par "debug_info_item " ci-dessous.
|
insns_size | uint | Taille de la liste d'instructions, en unités de code de 16 bits |
insns | ushort[insns_size] | tableau réel de bytecode. Le format du code dans un tableau insns est spécifié dans le document associé Bytecode Dalvik. Notez que, bien que cela soit défini comme un tableau de ushort , certaines structures internes préfèrent l'alignement sur quatre octets. De plus, si cela se produit dans un fichier dont l'endianness a été inversée, l'inversion n'est effectuée que sur les instances ushort individuelles et non sur les structures internes plus grandes.
|
padding | ushort (facultatif) = 0 | deux octets de marge intérieure pour que tries soit aligné sur quatre octets.
Cet élément n'est présent que si tries_size est différent de zéro et si insns_size est impair.
|
essaie | try_item[tries_size] (facultatif) | Tableau indiquant où les exceptions sont détectées dans le code et comment les gérer. Les éléments du tableau ne doivent pas se chevaucher en termes de plage et doivent être classés par ordre croissant d'adresses. Cet élément n'est présent que si tries_size est différent de zéro.
|
gestionnaires | encoded_catch_handler_list (facultatif) | Octets représentant une liste de listes de types de capture et d'adresses de gestionnaires associés. Chaque try_item possède un décalage en octets dans cette structure. Cet élément n'est présent que si tries_size est différent de zéro.
|
Format try_item
Nom | Format | Description |
---|---|---|
start_addr | uint | Adresse de début du bloc de code couvert par cette entrée. L'adresse correspond à un nombre d'unités de code de 16 bits jusqu'au début de la première instruction couverte. |
insn_count | ushort | Nombre d'unités de code de 16 bits couvertes par cette entrée. La dernière unité de code couverte (incluse) est start_addr + insn_count - 1 .
|
handler_off | ushort | Décalage en octets entre le début du encoded_catch_hander_list associé et le encoded_catch_handler pour cette entrée. Il doit s'agir d'un décalage par rapport au début d'un encoded_catch_handler .
|
Format de encoded_catch_handler_list
Nom | Format | Description |
---|---|---|
taille | uleb128 | Taille de cette liste, en nombre d'entrées |
liste | encoded_catch_handler[handlers_size] | Liste réelle des listes de gestionnaires, représentée directement (et non sous forme de décalages) et concaténée séquentiellement |
Format de encoded_catch_handler
Nom | Format | Description |
---|---|---|
taille | sleb128 | Nombre de types de capture dans cette liste. Si la valeur n'est pas positive, il s'agit de l'opposé du nombre de types de capture, et les captures sont suivies d'un gestionnaire général. Par exemple, une valeur size de 0 signifie qu'il existe une clause catch-all, mais pas de clauses catch explicitement typées.
Une valeur 2 de 2 signifie qu'il existe deux captures de type explicite et aucune capture générique.size Un size de -1 signifie qu'il existe une capture typée ainsi qu'une capture générique.
|
gestionnaires | encoded_type_addr_pair[abs(size)] | Flux d'éléments encodés abs(size) , un pour chaque type détecté, dans l'ordre dans lequel les types doivent être testés.
|
catch_all_addr | uleb128 (facultatif) | Adresse du bytecode du gestionnaire catch-all. Cet élément n'est présent que si size est non positif.
|
Format de encoded_type_addr_pair
Nom | Format | Description |
---|---|---|
type_idx | uleb128 | index dans la liste type_ids pour le type d'exception à intercepter.
|
addr | uleb128 | Adresse du code octet du gestionnaire d'exceptions associé |
debug_info_item
Référencé à partir de code_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
Chaque debug_info_item
définit une machine à états codée en octets inspirée de DWARF3 qui, une fois interprétée, émet la table des positions et (potentiellement) les informations sur les variables locales pour un code_item
. La séquence commence par un en-tête de longueur variable (dont la longueur dépend du nombre de paramètres de méthode), est suivie des bytecodes de la machine à états et se termine par un octet DBG_END_SEQUENCE
.
La machine à états se compose de cinq registres. Le registre address
représente le décalage d'instruction dans le insns_item
associé en unités de code 16 bits. Le registre address
commence à 0
au début de chaque séquence debug_info
et ne doit augmenter que de manière monotone.
Le registre line
représente le numéro de ligne source qui doit être associé à la prochaine entrée de table des positions émise par la machine à états. Il est initialisé dans l'en-tête de séquence et peut changer dans le sens positif ou négatif, mais ne doit jamais être inférieur à 1
. Le registre source_file
représente le fichier source auquel font référence les entrées de numéro de ligne. Elle est initialisée sur la valeur de source_file_idx
dans class_def_item
.
Les deux autres variables, prologue_end
et epilogue_begin
, sont des indicateurs booléens (initialisés sur false
) qui indiquent si la prochaine position émise doit être considérée comme un prologue ou un épilogue de méthode. La machine à états doit également suivre le nom et le type de la dernière variable locale en direct dans chaque registre pour le code DBG_RESTART_LOCAL
.
L'en-tête est le suivant :
Nom | Format | Description |
---|---|---|
line_start | uleb128 | Valeur initiale du registre line de la machine à états.
Ne représente pas une entrée de position réelle.
|
parameters_size | uleb128 | Nombre de noms de paramètres encodés. Il doit y en avoir un par paramètre de méthode, à l'exclusion de this d'une méthode d'instance, le cas échéant.
|
parameter_names | uleb128p1[parameters_size] | Index de chaîne du nom du paramètre de méthode. Une valeur encodée de NO_INDEX indique qu'aucun nom n'est disponible pour le paramètre associé. Le descripteur et la signature de type sont implicites à partir du descripteur et de la signature de méthode.
|
Les valeurs de code d'octet sont les suivantes :
Nom | Valeur | Format | Arguments | Description |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (aucun) | met fin à une séquence d'informations de débogage pour un code_item . |
|
DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff : montant à ajouter au registre d'adresses |
fait progresser le registre d'adresses sans émettre d'entrée de position. |
DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff : montant de la modification du registre des lignes |
avance le registre de ligne sans émettre d'entrée de position. |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : registre qui contiendra localname_idx : index de chaîne du nomtype_idx : index de type du type
|
introduit une variable locale à l'adresse actuelle. name_idx ou type_idx peuvent être NO_INDEX pour indiquer que cette valeur est inconnue.
|
DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num : registre qui contiendra localname_idx : index de chaîne du nomtype_idx : index de type du typesig_idx : index de chaîne de la signature de type
|
introduit un local avec une signature de type à l'adresse actuelle.
Les valeurs name_idx , type_idx ou sig_idx peuvent être NO_INDEX pour indiquer que la valeur est inconnue. (Si sig_idx est -1 , les mêmes données peuvent être représentées plus efficacement à l'aide du code d'opération DBG_START_LOCAL .)
Remarque : Pour connaître les mises en garde concernant la gestion des signatures, consultez la discussion sous " |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : registre contenant des informations locales. |
marque une variable locale actuellement active comme hors champ d'application à l'adresse actuelle. |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : s'inscrire pour redémarrer |
réintroduit une variable locale à l'adresse actuelle. Le nom et le type sont identiques à ceux de la dernière variable locale active dans le registre spécifié. |
DBG_SET_PROLOGUE_END | 0x07 | (aucun) | définit le registre de la machine à états prologue_end , en indiquant que la prochaine entrée de position ajoutée doit être considérée comme la fin d'un prologue de méthode (un emplacement approprié pour un point d'arrêt de méthode). Le registre prologue_end est effacé par n'importe quel opcode spécial (>= 0x0a ).
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (aucun) | définit le registre de la machine à états epilogue_begin , indiquant que la prochaine entrée de position ajoutée doit être considérée comme le début d'un épilogue de méthode (un emplacement approprié pour suspendre l'exécution avant la sortie de la méthode).
Le registre epilogue_begin est effacé par n'importe quel opcode spécial (>= 0x0a ).
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : index de chaîne du nom de fichier source ; NO_INDEX si inconnu
|
indique que toutes les entrées de numéro de ligne suivantes font référence à ce nom de fichier source, au lieu du nom par défaut spécifié dans code_item .
|
Codes d'opération spéciaux | 0x0a…0xff | (aucun) | fait progresser les registres line et address , émet une entrée de position et efface prologue_end et epilogue_begin . Voir la description ci-dessous.
|
Codes d'opération spéciaux
Les codes d'opération dont les valeurs sont comprises entre 0x0a
et 0xff
(inclus) déplacent légèrement les registres line
et address
, puis émettent une nouvelle entrée dans la table des positions.
La formule pour les incréments est la suivante :
DBG_FIRST_SPECIAL = 0x0a // the smallest special opcode DBG_LINE_BASE = -4 // the smallest line number increment DBG_LINE_RANGE = 15 // the number of line increments represented adjusted_opcode = opcode - DBG_FIRST_SPECIAL line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE) address += (adjusted_opcode / DBG_LINE_RANGE)
annotations_directory_item
Référencé depuis class_def_item
Apparaît dans la section "Données"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
class_annotations_off | uint | décalage par rapport au début du fichier pour les annotations effectuées directement sur la classe, ou 0 si la classe ne comporte aucune annotation directe.
Si le décalage n'est pas nul, il doit correspondre à un emplacement dans la section data . Le format des données est spécifié par "annotation_set_item " ci-dessous.
|
fields_size | uint | Nombre de champs annotés par cet élément |
annotated_methods_size | uint | Nombre de méthodes annotées par cet élément |
annotated_parameters_size | uint | Nombre de listes de paramètres de méthode annotées par cet élément |
field_annotations | field_annotation[fields_size] (facultatif) | Liste des annotations de champ associées. Les éléments de la liste doivent être triés par ordre croissant, par field_idx .
|
method_annotations | method_annotation[methods_size] (facultatif) | Liste des annotations de méthode associées. Les éléments de la liste doivent être triés par ordre croissant, par method_idx .
|
parameter_annotations | parameter_annotation[parameters_size] (facultatif) | Liste des annotations de paramètres de méthode associées. Les éléments de la liste doivent être triés par ordre croissant, par method_idx .
|
Remarque : Toutes les instances field_id
et method_id
des éléments doivent faire référence à la même classe de définition.
Format de field_annotation
Nom | Format | Description |
---|---|---|
field_idx | uint | index dans la liste field_ids pour l'identité du champ annoté.
|
annotations_off | uint | Décalage entre le début du fichier et la liste des annotations pour le champ. Le décalage doit être associé à un emplacement dans la section data . Le format des données est spécifié par "annotation_set_item " ci-dessous.
|
Format de method_annotation
Nom | Format | Description |
---|---|---|
method_idx | uint | Index dans la liste method_ids pour l'identité de la méthode annotée
|
annotations_off | uint | Décalage du début du fichier à la liste des annotations pour la méthode. Le décalage doit être défini sur un emplacement de la section data . Le format des données est spécifié par "annotation_set_item " ci-dessous.
|
Format de parameter_annotation
Nom | Format | Description |
---|---|---|
method_idx | uint | index dans la liste method_ids pour l'identité de la méthode dont les paramètres sont annotés
|
annotations_off | uint | Décalage entre le début du fichier et la liste des annotations pour les paramètres de la méthode. Le décalage doit être défini sur un emplacement de la section data . Le format des données est spécifié par "annotation_set_ref_list " ci-dessous.
|
annotation_set_ref_list
Référencé à partir de parameter_annotations_item
Apparaît dans la section "Données"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
taille | uint | Taille de la liste, en entrées |
liste | annotation_set_ref_item[size] | éléments de la liste |
Format annotation_set_ref_item
Nom | Format | Description |
---|---|---|
annotations_off | uint | Décalage par rapport au début du fichier jusqu'à l'ensemble d'annotations référencé ou 0 s'il n'y a pas d'annotations pour cet élément.
Si le décalage n'est pas nul, il doit correspondre à un emplacement dans la section data . Le format des données est spécifié par "annotation_set_item " ci-dessous.
|
annotation_set_item
Référencé à partir de annotations_directory_item, field_annotations_item, method_annotations_item et annotation_set_ref_item
Apparaît dans la section "Données"
Alignement : 4 octets
Nom | Format | Description |
---|---|---|
taille | uint | Taille de l'ensemble, en entrées |
participations | annotation_off_item[size] | éléments de l'ensemble. Les éléments doivent être triés par ordre croissant, par type_idx .
|
Format annotation_off_item
Nom | Format | Description |
---|---|---|
annotation_off | uint | décalage du début du fichier à une annotation.
Le décalage doit correspondre à un emplacement dans la section data , et le format des données à cet emplacement est spécifié par "annotation_item " ci-dessous.
|
annotation_item
Référencé à partir de annotation_set_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
Nom | Format | Description |
---|---|---|
visibilité | ubyte | Visibilité prévue de cette annotation (voir ci-dessous) |
annotation | encoded_annotation | Contenu des annotations encodé, au format décrit par "encoded_annotation format" sous "encoded_value encoding" ci-dessus.
|
Valeurs de visibilité
Voici les options du champ visibility
dans un annotation_item
:
Nom | Valeur | Description |
---|---|---|
VISIBILITY_BUILD | 0x00 | ne sont censés être visibles qu'au moment de la compilation (par exemple, lors de la compilation d'un autre code). |
VISIBILITY_RUNTIME | 0x01 | destinés à être visibles au moment de l'exécution |
VISIBILITY_SYSTEM | 0x02 | destiné à être visible lors de l'exécution, mais uniquement par le système sous-jacent (et non par le code utilisateur normal) |
encoded_array_item
Référencé depuis class_def_item
Apparaît dans la section "Données"
Alignement : aucun (alignement sur les octets)
Nom | Format | Description |
---|---|---|
value | encoded_array | octets représentant la valeur du tableau encodé, au format spécifié par "Format encoded_array " sous "Encodage encoded_value " ci-dessus.
|
hiddenapi_class_data_item
Cette section contient des données sur les interfaces restreintes utilisées par chaque classe.
Remarque : La fonctionnalité d'API masquée a été introduite dans Android 10.0 et ne s'applique qu'aux fichiers DEX des classes dans le chemin de classe de démarrage. La liste des indicateurs décrits ci-dessous pourra être étendue dans les futures versions d'Android. Pour en savoir plus, consultez les restrictions concernant les interfaces non SDK.
Nom | Format | Description |
---|---|---|
taille | uint | taille totale de la section |
compensations | uint[] | Tableau de décalages indexé par class_idx .
Une entrée de tableau nulle à l'index class_idx signifie qu'il n'y a pas de données pour ce class_idx ou que tous les indicateurs d'API masqués sont nuls.
Sinon, l'entrée du tableau est non nulle et contient un décalage du début de la section vers un tableau d'indicateurs d'API masqués pour ce class_idx .
|
indicateurs | uleb128[] | Tableaux concaténés des indicateurs d'API masqués pour chaque classe. Les valeurs de signalement possibles sont décrites dans le tableau ci-dessous. Les indicateurs sont encodés dans le même ordre que les champs et les méthodes sont encodés dans les données de classe. |
Types de signalements de restriction :
Nom | Valeur | Description |
---|---|---|
liste blanche | 0 | Interfaces pouvant être utilisées librement et prises en charge dans l'index des packages du framework Android officiellement documenté. |
liste grise | 1 | Interfaces non SDK qui peuvent être utilisées quel que soit le niveau d'API cible de l'application. |
ajouter à la liste noire | 2 | Interfaces non SDK qui ne peuvent pas être utilisées quel que soit le niveau d'API cible de l'application. L'accès à l'une de ces interfaces entraîne une erreur d'exécution. |
greylist‑max‑o | 3 | Interfaces non SDK qui peuvent être utilisées pour Android 8.x et versions antérieures, sauf si elles sont restreintes. |
greylist‑max‑p | 4 | Interfaces non SDK qui peuvent être utilisées pour Android 9.x, sauf si elles sont restreintes. |
greylist‑max‑q | 5 | Interfaces non SDK qui peuvent être utilisées pour Android 10.x, sauf si elles sont restreintes. |
greylist‑max‑r | 6 | Interfaces non SDK qui peuvent être utilisées pour Android 11.x, sauf si elles sont restreintes. |
Annotations système
Les annotations système sont utilisées pour représenter diverses informations réflexives sur les classes (ainsi que les méthodes et les champs). Ces informations ne sont généralement accessibles qu'indirectement par le code client (non système).
Les annotations système sont représentées dans les fichiers .dex
en tant qu'annotations dont la visibilité est définie sur VISIBILITY_SYSTEM
.
dalvik.annotation.AnnotationDefault
Apparaît sur les méthodes dans les interfaces d'annotation
Une annotation AnnotationDefault
est associée à chaque interface d'annotation qui souhaite indiquer des liaisons par défaut.
Nom | Format | Description |
---|---|---|
value | Annotation | Liaisons par défaut pour cette annotation, représentées sous la forme d'une annotation de ce type. L'annotation n'a pas besoin d'inclure tous les noms définis par l'annotation. Les noms manquants n'ont tout simplement pas de valeurs par défaut. |
dalvik.annotation.EnclosingClass
S'affiche dans les cours
Une annotation EnclosingClass
est associée à chaque classe qui est définie en tant que membre d'une autre classe, en soi, ou qui est anonyme, mais pas définie dans le corps d'une méthode (par exemple, une classe interne synthétique). Chaque classe comportant cette annotation doit également comporter une annotation InnerClass
. De plus, une classe ne doit pas comporter à la fois une annotation EnclosingClass
et une annotation EnclosingMethod
.
Nom | Format | Description |
---|---|---|
value | Classe | la classe qui englobe le plus étroitement cette classe au niveau lexical. |
dalvik.annotation.EnclosingMethod
S'affiche dans les cours
Une annotation EnclosingMethod
est associée à chaque classe définie dans le corps d'une méthode. Chaque classe comportant cette annotation doit également comporter une annotation InnerClass
.
De plus, une classe ne doit pas comporter à la fois une annotation EnclosingClass
et une annotation EnclosingMethod
.
Nom | Format | Description |
---|---|---|
value | Méthode | la méthode qui délimite le plus précisément cette classe au niveau lexical. |
dalvik.annotation.InnerClass
S'affiche dans les cours
Une annotation InnerClass
est associée à chaque classe définie dans le champ d'application lexical de la définition d'une autre classe.
Toute classe comportant cette annotation doit également comporter soit une annotation EnclosingClass
, soit une annotation EnclosingMethod
.
Nom | Format | Description |
---|---|---|
nom | Chaîne | Nom simple initialement déclaré de cette classe (sans préfixe de package). Si cette classe est anonyme, le nom est null .
|
accessFlags | int | les indicateurs d'accès initialement déclarés de la classe (qui peuvent différer des indicateurs effectifs en raison d'une incompatibilité entre les modèles d'exécution du langage source et de la machine virtuelle cible) |
dalvik.annotation.MemberClasses
S'affiche dans les cours
Une annotation MemberClasses
est associée à chaque classe qui déclare les classes membres. (Une classe membre est une classe interne directe qui possède un nom.)
Nom | Format | Description |
---|---|---|
value | Classe[] | Tableau des classes de membres |
dalvik.annotation.MethodParameters
Apparaît sur les méthodes
Remarque : Cette annotation a été ajoutée après Android 7.1. Sa présence sur les versions antérieures d'Android sera ignorée.
Une annotation MethodParameters
est facultative et peut être utilisée pour fournir des métadonnées de paramètre telles que les noms et les modificateurs de paramètre.
L'annotation peut être omise d'une méthode ou d'un constructeur sans risque lorsque les métadonnées de paramètre ne sont pas requises au moment de l'exécution.
java.lang.reflect.Parameter.isNamePresent()
peut être utilisé pour vérifier si des métadonnées sont présentes pour un paramètre. Les méthodes de réflexion associées, telles que java.lang.reflect.Parameter.getName()
, reviendront au comportement par défaut au moment de l'exécution si les informations ne sont pas présentes.
Lorsque vous incluez des métadonnées de paramètres, les compilateurs doivent inclure des informations pour les classes générées telles que les énumérations, car les métadonnées de paramètres indiquent si un paramètre est synthétique ou obligatoire.
Une annotation MethodParameters
ne décrit que les paramètres de méthode individuels. Par conséquent, les compilateurs peuvent omettre complètement l'annotation pour les constructeurs et les méthodes sans paramètre, dans un souci de taille du code et d'efficacité de l'exécution.
Les tableaux documentés ci-dessous doivent avoir la même taille que pour la structure dex method_id_item
associée à la méthode. Dans le cas contraire, une java.lang.reflect.MalformedParametersException
sera générée au moment de l'exécution.
Autrement dit, method_id_item.proto_idx
-> proto_id_item.parameters_off
-> type_list.size
doit être identique à names().length
et accessFlags().length
.
Étant donné que MethodParameters
décrit tous les paramètres de méthode formels, même ceux qui ne sont pas explicitement ou implicitement déclarés dans le code source, la taille des tableaux peut différer des informations de signature ou d'autres métadonnées qui ne sont basées que sur les paramètres explicites déclarés dans le code source. MethodParameters
n'inclura pas non plus d'informations sur les paramètres de récepteur d'annotation de type qui n'existent pas dans la signature de méthode réelle.
Nom | Format | Description |
---|---|---|
noms | String[] | Noms des paramètres formels de la méthode associée. Le tableau ne doit pas être nul, mais doit être vide s'il n'y a pas de paramètres formels. Une valeur du tableau doit être nulle si le paramètre formel avec cet index n'a pas de nom. Si les chaînes de nom de paramètre sont vides ou contiennent ".", ";", "[" ou "/", une java.lang.reflect.MalformedParametersException sera générée lors de l'exécution.
|
accessFlags | int[] | Indicateurs d'accès des paramètres formels de la méthode associée. Le tableau ne doit pas être nul, mais doit être vide s'il n'y a pas de paramètres formels. La valeur est un masque de bits avec les valeurs suivantes :
java.lang.reflect.MalformedParametersException sera générée au moment de l'exécution.
|
dalvik.annotation.Signature
Apparaît sur les classes, les champs et les méthodes
Une annotation Signature
est associée à chaque classe, champ ou méthode définie en termes de type plus complexe que celui représentable par un type_id_item
. Le format .dex
ne définit pas le format des signatures. Il est simplement destiné à pouvoir représenter toutes les signatures dont une langue source a besoin pour implémenter correctement la sémantique de cette langue. Par conséquent, les signatures ne sont généralement pas analysées (ni vérifiées) par les implémentations de machines virtuelles. Les signatures sont simplement transmises à des API et des outils de niveau supérieur (tels que les débogueurs). Par conséquent, toute utilisation d'une signature doit être écrite de manière à ne faire aucune hypothèse sur la réception de signatures valides uniquement, en se protégeant explicitement contre la possibilité de rencontrer une signature syntaxiquement invalide.
Étant donné que les chaînes de signature ont tendance à contenir beaucoup de contenu en double, une annotation Signature
est définie comme un tableau de chaînes, où les éléments en double font naturellement référence aux mêmes données sous-jacentes, et la signature est considérée comme la concaténation de toutes les chaînes du tableau. Il n'existe aucune règle concernant la manière de séparer une signature en chaînes distinctes. Cela dépend entièrement des outils qui génèrent les fichiers .dex
.
Nom | Format | Description |
---|---|---|
value | String[] | Signature de cette classe ou de ce membre, sous la forme d'un tableau de chaînes à concaténer |
dalvik.annotation.Throws
Apparaît sur les méthodes
Une annotation Throws
est associée à chaque méthode déclarée pour générer un ou plusieurs types d'exception.
Nom | Format | Description |
---|---|---|
value | Classe[] | Tableau des types d'exception générés |