Questo documento descrive il layout e i contenuti dei file .dex
, che vengono utilizzati per contenere un insieme di definizioni di classi e i relativi dati aggiuntivi associati.
Guida ai tipi
Nome | Descrizione |
---|---|
byte | Numero intero a 8 bit firmato |
ubyte | Intero senza segno a 8 bit |
video breve | Intero a 16 bit con segno, little-endian |
ushort | Intero senza segno a 16 bit, little-endian |
int | Intero a 32 bit con segno, little-endian |
uint | Intero non firmato a 32 bit, little-endian |
lunghi | Numero intero a 64 bit con segno, little-endian |
ulong | Intero senza segno a 64 bit, little-endian |
sleb128 | LEB128 firmato, di lunghezza variabile (vedi di seguito) |
uleb128 | LEB128 non firmato, di lunghezza variabile (vedi di seguito) |
uleb128p1 | LEB128 non firmato più 1 , di lunghezza variabile (vedi di seguito) |
LEB128
LEB128 ("Little-Endian Base 128") è una codifica a lunghezza variabile per quantità intere con segno o senza segno arbitrarie. Il formato è stato mutuato dalla specifica DWARF3. In un file .dex
, LEB128 viene utilizzato solo per codificare quantità a 32 bit.
Ogni valore con codifica LEB128 è composto da uno a cinque
byte, che insieme rappresentano un singolo valore a 32 bit. Per ogni byte è impostato il bit più significativo, ad eccezione del byte finale nella sequenza, che ha il suo bit più significativo chiaro. I rimanenti sette bit di ogni byte sono il payload, con i sette bit meno significativi della quantità nel primo byte, i sette successivi nel secondo byte e così via. Nel caso di un LEB128 con segno (sleb128
), il bit del payload più significativo del byte finale della sequenza viene esteso con segno per produrre il valore finale. Nel caso senza segno
(uleb128
), tutti i bit non rappresentati esplicitamente sono
interpretati come 0
.
Diagramma a livello di bit di un valore LEB128 di due byte | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Primo byte | Secondo byte | ||||||||||||||
1 |
bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 0 |
bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 |
La variante uleb128p1
viene utilizzata per rappresentare un valore con segno, dove la rappresentazione è del valore più uno codificato come uleb128
. In questo modo, la codifica di -1
(in alternativa, il valore non firmato 0xffffffff
)
- ma nessun altro numero negativo - è un singolo byte ed è utile esattamente nei casi in cui il numero rappresentato deve essere positivo o -1
(o 0xffffffff
)
e dove non sono consentiti altri valori negativi (o dove è improbabile che siano necessari valori non firmati di grandi dimensioni).
Ecco alcuni esempi di formati:
Sequenza codificata | Come sleb128 |
Come uleb128 |
Come uleb128p1 |
---|---|---|---|
00 | 0 | 0 | -1 |
01 | 1 | 1 | 0 |
7f | -1 | 127 | 126 |
80 7f | -128 | 16256 | 16255 |
Layout del file
Nome | Formato | Descrizione |
---|---|---|
intestazione | header_item | l'intestazione |
string_ids | string_id_item[] | Elenco di identificatori di stringa. Si tratta di identificatori per tutte le stringhe utilizzate da questo file, sia per la denominazione interna (ad es. descrittori di tipo) sia come oggetti costanti a cui fa riferimento il codice. Questo elenco deve essere ordinato in base ai contenuti delle stringhe, utilizzando i valori dei punti di codice UTF-16 (non in modo sensibile alla lingua) e non deve contenere voci duplicate. |
type_ids | type_id_item[] | Elenco di identificatori di tipo. Si tratta di identificatori per tutti i tipi (classi, آرایه o tipi primitivi) a cui fa riferimento questo file, definiti o meno nel file. Questo elenco deve essere ordinato in base all'indice string_id
e non deve contenere voci duplicate.
|
proto_ids | proto_id_item[] | Elenco di identificatori di prototipi di metodi. Si tratta di identificatori per tutti
i prototipi a cui fa riferimento questo file. Questo elenco deve essere ordinato in ordine di importanza per il tipo di ritorno (in base all'indice type_id ) e poi per elenco di argomenti (ordine lessicografico, singoli argomenti ordinati in base all'indice type_id ). L'elenco non deve contenere voci duplicate.
|
field_ids | field_id_item[] | elenco di identificatori di campo. Si tratta di identificatori per tutti i campi
a cui fa riferimento questo file, indipendentemente dal fatto che siano definiti o meno nel file. Questo
elenco deve essere ordinato, dove il tipo di definizione (in base all'indice type_id ) è l'ordine principale, il nome del campo (in base all'indice string_id )
è l'ordine intermedio e il tipo (in base all'indice type_id )
è l'ordine secondario. L'elenco non deve contenere voci duplicate.
|
method_ids | method_id_item[] | Elenco di identificatori dei metodi. Si tratta di identificatori per tutti i metodi
a cui fa riferimento questo file, indipendentemente dal fatto che siano definiti o meno nel file. Questo
elenco deve essere ordinato, dove il tipo di definizione (in base all'indice type_id ) è l'ordine principale, il nome del metodo (in base all'indice string_id ) è l'ordine intermedio e il prototipo del metodo (in base all'indice proto_id ) è l'ordine secondario. L'elenco non deve contenere voci duplicate.
|
class_defs | class_def_item[] | Elenco delle definizioni di classi. Le classi devono essere ordinate in modo che la superclasse e le interfacce implementate di una determinata classe vengano visualizzate nell'elenco prima della classe di riferimento. Inoltre, non è valida una definizione per un corso con lo stesso nome che appare più di una volta nell'elenco. |
call_site_ids | call_site_id_item[] | elenco di identificatori dei siti di chiamata. Si tratta di identificatori per tutti i siti di chiamata
a cui fa riferimento questo file, indipendentemente dal fatto che siano definiti o meno nel file. Questo elenco deve essere ordinato in ordine crescente di call_site_off .
|
method_handles | method_handle_item[] | Elenco dei handle dei metodi. Un elenco di tutti i handle dei metodi a cui fa riferimento questo file, indipendentemente dal fatto che siano definiti o meno nel file. Questo elenco non è ordinato e potrebbe contenere duplicati che corrisponderanno logicamente a istanze di handle dei metodi diverse. |
di dati | ubyte[] | area di dati, contenente tutti i dati di supporto per le tabelle elencate sopra. Gli elementi diversi hanno requisiti di allineamento diversi e, se necessario, vengono inseriti byte di spaziatura prima di ogni elemento per ottenere un allineamento corretto. |
link_data | ubyte[] | dati utilizzati nei file collegati in modo statico. Il formato dei dati in questa sezione non è specificato da questo documento. Questa sezione è vuota nei file scollegati e le implementazioni di runtime possono utilizzarla come meglio credono. |
Formato del contenitore
La versione 41 introduce un nuovo formato contenitore per i dati DEX allo scopo di risparmiare spazio. Questo formato contenitore consente di combinare più file DEX logici in un unico file fisico. Il nuovo formato è per lo più una semplice concatenazione di file nel formato precedente, con alcune differenze:
file_size
indica le dimensioni del file logico, non del file fisico. Può essere utilizzato per eseguire l'iterazione su tutti i file logici del contenitore.- I file dex logici possono fare riferimento a qualsiasi dato successivo nel contenitore (ma non a quelli precedenti). In questo modo, i file dex possono condividere dati, ad esempio stringhe, tra loro.
- Tutti gli offset sono relativi al file fisico. Nessun offset è relativo all'intestazione. In questo modo, le sezioni con gli offset possono essere condivise tra i file logici.
- L'intestazione aggiunge due nuovi campi per descrivere i limiti del contenitore. Si tratta di un controllo di coerenza aggiuntivo che semplifica il porting del codice al nuovo formato.
data_size
edata_off
non sono più utilizzati. I dati possono essere distribuiti su più file logici e non devono essere contigui.
Definizioni di campi di bit, stringhe e costanti
DEX_FILE_MAGIC
Incorporato in header_item
L'array/stringa costante DEX_FILE_MAGIC
è l'elenco di
byte che deve apparire all'inizio di un file .dex
perché venga riconosciuto come tale. Il valore contiene intenzionalmente un a capo ("\n"
o 0x0a
) e un byte nullo ("\0"
o 0x00
) per contribuire al rilevamento di determinate forme di corruzione. Il valore codifica anche un numero di versione del formato sotto forma di tre cifre decimali, che dovrebbe aumentare in modo monotonico nel tempo con l'evoluzione del formato.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
Nota: il supporto della versione 040
del formato è stato aggiunto nella release di Android 10.0, che ha esteso l'insieme di caratteri consentiti in SimpleNames.
Nota: il supporto della versione 039
del formato è stato aggiunto nella release di Android 9.0, che ha introdotto due nuovi bytecode, const-method-handle
e const-method-type
. Questi sono descritti nella tabella
Riepilogo dell'insieme di bytecode. In Android 10, la versione 039
estende il formato del file DEX per includere informazioni sull'API nascoste applicabili solo ai file DEX nel percorso della classe di avvio.
Nota: il supporto della versione 038
del formato è stato aggiunto nella release di Android 8.0. La versione 038
ha aggiunto nuovi bytecode
(invoke-polymorphic
e invoke-custom
) e
dati per gli handle dei metodi.
Nota: il supporto della versione 037
del formato è stato aggiunto nella release di Android 7.0. Prima della versione 037
, la maggior parte delle versioni di Android ha utilizzato la versione 035
del formato. L'unica
differenza tra le versioni 035
e 037
è l'
aggiunta di metodi predefiniti e la regolazione del invoke
.
Nota:almeno un paio di versioni precedenti del formato sono state utilizzate nelle release software pubbliche ampiamente disponibili. Ad esempio, la versione 009
è stata utilizzata per le release M3 della piattaforma Android (novembre-dicembre 2007) e la versione 013
per le release M5 della piattaforma Android (febbraio-marzo 2008). Per diversi aspetti, queste versioni precedenti del formato differiscono notevolmente dalla versione descritta in questo documento.
ENDIAN_CONSTANT e REVERSE_ENDIAN_CONSTANT
Incorporato in header_item
La costante ENDIAN_CONSTANT
viene utilizzata per indicare il endianness del file in cui si trova. Sebbene il formato.dex
standard sia little-endian, le implementazioni possono scegliere di eseguire lo scambio di byte. Se un'implementazione trova un header il cui endian_tag
è REVERSE_ENDIAN_CONSTANT
invece di ENDIAN_CONSTANT
, saprà che il file è stato sottoposto a byte-swapping rispetto al formato previsto.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
Incorporato in class_def_item e debug_info_item
La costante NO_INDEX
viene utilizzata per indicare che un valore dell'indice è assente.
Nota: questo valore non è definito come
0
, perché in genere è un indice valido.
Il valore scelto per NO_INDEX
è rappresentabile come un singolo byte nella codifica uleb128p1
.
uint NO_INDEX = 0xffffffff; // == -1 if treated as a signed int
Definizioni di access_flags
Incorporato in class_def_item, encoded_field, encoded_method e InnerClass
I campi di bit di questi flag vengono utilizzati per indicare l'accessibilità e le proprietà complessive di classi e membri di classe.
Nome | Valore | Per i corsi (e le annotazioni InnerClass ) |
Per i campi | Per i metodi |
---|---|---|---|---|
ACC_PUBLIC | 0x1 | public : visibile ovunque |
public : visibile ovunque |
public : visibile ovunque |
ACC_PRIVATE | 0x2 | private : visibile solo alla classe di definizione
|
private : visibile solo alla classe di definizione |
private : visibile solo alla classe di definizione |
ACC_PROTECTED | 0x4 | protected : visibile al pacchetto e alle sottoclassi
|
protected : visibile al pacchetto e alle sottoclassi |
protected : visibile al pacchetto e alle sottoclassi |
ACC_STATIC | 0x8 | static : non è costruito con un riferimento this esterno |
static : globale per la classe di definizione |
static : non accetta un argomento this |
ACC_FINAL | 0x10 | final : non può essere sottoclassificato |
final : immutabile dopo la creazione |
final : non sostituibile |
ACC_SYNCHRONIZED | 0x20 | synchronized : blocco associato acquisito automaticamente
intorno alla chiamata a questo metodo. Nota:questa impostazione è valida solo se è impostato anche |
||
ACC_VOLATILE | 0x40 | volatile : regole di accesso speciale per contribuire alla sicurezza del thread |
||
ACC_BRIDGE | 0x40 | metodo bridge, aggiunto automaticamente dal compilatore come bridge sicuro per i tipi | ||
ACC_TRANSIENT | 0x80 | transient : non deve essere salvato per la serializzazione predefinita |
||
ACC_VARARGS | 0x80 | L'ultimo argomento deve essere considerato un argomento "rimanente" dal compilatore | ||
ACC_NATIVE | 0x100 | native : implementato in codice nativo |
||
ACC_INTERFACE | 0x200 | interface : classe astratta implementabile più volte |
||
ACC_ABSTRACT | 0x400 | abstract : non può essere istanziato direttamente |
abstract : non implementato da questa classe |
|
ACC_STRICT | 0x800 | strictfp : regole rigorose per l'aritmetica a virgola mobile |
||
ACC_SYNTHETIC | 0x1000 | non definito direttamente nel codice sorgente | non definito direttamente nel codice sorgente | non definito direttamente nel codice sorgente |
ACC_ANNOTATION | 0x2000 | dichiarato come classe di annotazione | ||
ACC_ENUM | 0x4000 | dichiarato come tipo enumerato | dichiarato come valore enumerato | |
(non utilizzato) | 0x8000 | |||
ACC_CONSTRUCTOR | 0x10000 | metodo costruttore (inizializzatore di classe o istanza) | ||
ACC_DECLARED_ SYNCHRONIZED |
0x20000 | dichiarato synchronized . Nota:questo non influisce sull'esecuzione (tranne che per la riflessione di questo flag). |
InnerClass
e non deve mai essere attivo in un class_def_item
.
Codifica UTF-8 modificata
Per semplificare il supporto della versione precedente, il formato .dex
codifica i dati di stringa in un formato UTF-8 modificato standard de facto, di seguito denominato MUTF-8. Questo formato è identico all'UTF-8 standard, tranne che per quanto segue:
- Vengono utilizzate solo le codifiche di uno, due e tre byte.
- I punti di codice nell'intervallo
U+10000
…U+10ffff
vengono codificati come coppia di surrogati, ciascuno rappresentato come valore codificato di tre byte. - Il punto di codice
U+0000
è codificato in formato a due byte. - Un byte nullo normale (valore
0
) indica la fine di una stringa, come nell'interpretazione standard del linguaggio C.
I primi due punti sopra riportati possono essere riassunti come segue: MUTF-8 è un formato di codifica per UTF-16, anziché un formato di codifica più diretto per i caratteri Unicode.
Gli ultimi due elementi sopra riportati consentono contemporaneamente di includere il punto di codice U+0000
in una stringa e di manipolarlo come stringa terminata da nullo in stile C.
Tuttavia, la codifica speciale di U+0000
significa che, a differenza del normale UTF-8, il risultato dell'chiamata della funzione C standard strcmp()
su una coppia di stringhe MUTF-8 non sempre indica il risultato correttamente firmato del confronto di stringhe non uguali.
Quando l'ordinamento (non solo l'uguaglianza) è un problema, il modo più semplice per confrontare le stringhe UTF-8 è decodificarle carattere per carattere e confrontare i valori decodificati. Tuttavia, sono possibili anche implementazioni più intelligenti.
Per ulteriori informazioni sulla codifica dei caratteri, consulta lo standard Unicode. MUTF-8 è in realtà più simile alla codifica (relativamente meno nota) CESU-8 rispetto a UTF-8 per se.
Codifica di encoded_value
Incorporato in annotation_element e encoded_array_item
Un encoded_value
è un frammento codificato di dati (quasi)
arbitrari strutturati in modo gerarchico. La codifica deve essere compatta e facile da analizzare.
Nome | Formato | Descrizione |
---|---|---|
(value_arg << 5) | value_type | ubyte | byte che indica il tipo di value immediatamente successivo insieme a un argomento facoltativo di chiarimento nei tre bit di ordine superiore.
Di seguito sono riportate le varie definizioni di value .
Nella maggior parte dei casi, value_arg codifica la lunghezza del value immediatamente successivo in byte, come (size - 1) , ad esempio 0 indica che il valore richiede un byte e 7 indica che richiede otto byte. Tuttavia, esistono delle eccezioni, come indicato di seguito.
|
valore | ubyte[] | byte che rappresentano il valore, di lunghezza variabile e interpretati diversamente per byte value_type diversi, anche se sempre in little-endian. Per maggiori dettagli, consulta le varie definizioni di valore riportate di seguito.
|
Formati dei valori
Nome tipo | value_type |
Formato value_arg |
Formato value |
Descrizione |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (nessuno; deve essere 0 ) |
ubyte[1] | valore intero con segno di un byte |
VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | valore intero a due byte con segno, con estensione del segno |
VALUE_CHAR | 0x03 | size - 1 (0…1) | ubyte[size] | Valore intero senza segno di due byte, esteso a zero |
VALUE_INT | 0x04 | size - 1 (0…3) | ubyte[size] | valore intero a quattro byte con segno, con estensione del segno |
VALUE_LONG | 0x06 | size - 1 (0…7) | ubyte[size] | valore intero a 8 byte con segno, con estensione del segno |
VALUE_FLOAT | 0x10 | size - 1 (0…3) | ubyte[size] | pattern di bit di quattro byte, esteso a zero a destra e interpretato come valore in virgola mobile a 32 bit IEEE754 |
VALUE_DOUBLE | 0x11 | size - 1 (0…7) | ubyte[size] | pattern di bit di otto byte, esteso a zero a destra e interpretato come valore in virgola mobile a 64 bit IEEE754 |
VALUE_METHOD_TYPE | 0x15 | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione proto_ids e che rappresenta un valore di tipo di metodo
|
VALUE_METHOD_HANDLE | 0x16 | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione method_handles e che rappresenta un valore handle metodo
|
VALUE_STRING | 0x17 | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione string_ids e che rappresenta un valore di stringa
|
VALUE_TYPE | 0x18 | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione type_ids e che rappresenta un valore di tipo/classe riflettente
|
VALUE_FIELD | 0x19 | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione field_ids e che rappresenta un valore di campo riflettente
|
VALUE_METHOD | 0x1a | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione method_ids e che rappresenta un valore del metodo riflessivo
|
VALUE_ENUM | 0x1b | size - 1 (0…3) | ubyte[size] | Valore intero a quattro byte non firmato (con estensione a zero), interpretato come indice della sezione field_ids e che rappresenta il valore di una costante di tipo enumerato
|
ARRAY_VALORI | 0x1c | (nessuno; deve essere 0 ) |
array_codificato | un array di valori nel formato specificato da "Formato encoded_array " di seguito. Le dimensioni
dell'value sono implicite nella codifica.
|
VALUE_ANNOTATION | 0x1d | (nessuno; deve essere 0 ) |
encoded_annotation | una sottoannotazione, nel formato specificato da "Formato encoded_annotation " di seguito. Le dimensioni
dell'value sono implicite nella codifica.
|
VALUE_NULL | 0x1e | (nessuno; deve essere 0 ) |
(none) | Valore di riferimento null |
VALUE_BOOLEAN | 0x1f | booleano (0…1) | (none) | Valore di un bit: 0 per false e
1 per true . Il bit è rappresentato in
value_arg .
|
Formato dell'array codificato
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uleb128 | numero di elementi nell'array |
valori | encoded_value[size] | una serie di sequenze di byte size encoded_value nel formato specificato da questa sezione, concatenate in sequenza.
|
Formato dell'annotazione codificata
Nome | Formato | Descrizione |
---|---|---|
type_idx | uleb128 | del tipo di annotazione. Deve essere un tipo di classe (non array o primitivo). |
dimensioni | uleb128 | numero di mappature nome-valore in questa annotazione |
elementi | annotation_element[size] | elementi dell'annotazione, rappresentati direttamente in linea (non come offset). Gli elementi devono essere ordinati in ordine crescente in base all'indice string_id .
|
formato dell'elemento annotation_element
Nome | Formato | Descrizione |
---|---|---|
name_idx | uleb128 | elemento, rappresentato come indice della sezione
string_ids . La stringa deve essere conforme alla sintassi di MemberName, definita sopra.
|
valore | valore_codificato | valore dell'elemento |
Sintassi delle stringhe
In un file .dex
esistono diversi tipi di elementi che fanno tutti riferimento a una stringa. Le seguenti definizioni in stile BNF indicano la sintassi accettabile per queste stringhe.
NomeSemplice
Un SimpleName è la base per la sintassi dei nomi di altre cose. Il formato .dex
consente una certa libertà in questo senso (molto più delle lingue di origine più comuni). In breve, un nome semplice è costituito da qualsiasi carattere alfabetico o cifra ASCII basso, da alcuni simboli ASCII bassi specifici e dalla maggior parte dei punti di codice non ASCII che non sono caratteri di controllo, spazi o speciali. A partire dalla versione 040
il formato consente inoltre i caratteri di spaziatura (categoria Unicode Zs
). Tieni presente che i punti di codice surrogato
(nell'intervallo U+d800
… U+dfff
) non sono
considerati caratteri di nome validi, in quanto tali, ma i caratteri supplementari Unicode
sono validi (rappresentati dall'alternativa finale della regola per SimpleNameChar) e devono essere rappresentati in un file come coppie di punti di codice surrogato nella codifica MUTF-8.
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
a partire dalla versione DEX 040 |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
a partire dalla versione DEX 040 |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
a partire dalla versione DEX 040 |
| | U+2010 … U+2027 |
|
| | U+202f |
a partire dalla versione DEX 040 |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
MemberName
utilizzato da field_id_item e method_id_item
Un MemberName è il nome di un membro di una classe, ovvero campi, metodi e classi interne.
MemberName → | |
SimpleName | |
| | '<' NomeSemplice '>' |
FullClassName
Un FullClassName è un nome di classe completo, che include un specificatore del pacchetto facoltativo seguito da un nome obbligatorio.
FullClassName → | |
OptionalPackagePrefix SimpleName | |
OptionalPackagePrefix → | |
(SimpleName '/' )* |
TypeDescriptor
Utilizzato da type_id_item
Un TypeDescriptor è la rappresentazione di qualsiasi tipo, inclusi elementi primitivi, classi, array e void
. Di seguito è riportato il significato delle varie versioni.
TypeDescriptor → | |
'V' |
|
| | FieldTypeDescriptor |
FieldTypeDescriptor → | |
NonArrayFieldTypeDescriptor | |
| | ('[' * 1…255)
NonArrayFieldTypeDescriptor |
NonArrayFieldTypeDescriptor→ | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' FullClassName ';' |
ShortyDescriptor
Utilizzato da proto_id_item
Un ShortyDescriptor è la rappresentazione in forma breve di un prototipo di metodo, inclusi i tipi di ritorno e parametro, tranne per il fatto che non viene fatta alcuna distinzione tra i vari tipi di riferimento (classe o array). Invece, tutti i tipi di riferimento sono rappresentati da un singolo carattere 'L'
.
ShortyDescriptor → | |
ShortyReturnType (ShortyFieldType)* | |
ShortyReturnType → | |
'V' |
|
| | ShortyFieldType |
ShortyFieldType → | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' |
Semantica di TypeDescriptor
Questo è il significato di ciascuna delle varianti di TypeDescriptor.
Sintassi | Significato |
---|---|
V | void ; valido solo per i tipi di reso |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
Lnome/completo/; | il corso fully.qualified.Name |
[descriptor | array di descriptor , utilizzabile in modo ricorsivo per
array di array, anche se non è valido avere più di 255
dimensioni.
|
Elementi e strutture correlate
Questa sezione include le definizioni di ciascuno degli elementi di primo livello che possono comparire in un file .dex
.
header_item
Viene visualizzato nella sezione dell'intestazione
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
magia | ubyte[8] = DEX_FILE_MAGIC | valore magico. Per ulteriori dettagli, consulta la sezione "DEX_FILE_MAGIC " sopra.
|
checksum | uint | checksum adler32 del resto del file (tutto tranne
magic e questo campo); utilizzato per rilevare la corruzione del file
|
firma | ubyte[20] | Firma (hash) SHA-1 del resto del file (tutto tranne
magic , checksum e questo campo); utilizzata
per identificare in modo univoco i file
|
file_size | uint |
dimensioni dell'intero file (inclusa l'intestazione), in byte (v40 o precedenti) distanza in byte dall'inizio di questa intestazione all'intestazione successiva o alla fine dell'intero file (il contenitore). (v41 o successive) |
header_size | uint |
dimensioni dell'intestazione (l'intera sezione), in byte. Ciò consente almeno una compatibilità limitata con le versioni precedenti/successive senza invalidare il formato. Deve essere pari a 0x70 (112) byte (v40 o precedenti) Deve essere pari a 0x78 (120) byte (v41 o successive) |
endian_tag | uint = ENDIAN_CONSTANT | tag endianness. Per ulteriori dettagli, consulta la sezione "ENDIAN_CONSTANT
e REVERSE_ENDIAN_CONSTANT " qui sopra.
|
link_size | uint | dimensioni della sezione del link o 0 se il file non è collegato staticamente |
link_off | uint | offset dall'inizio del file alla sezione del link oppure
0 se link_size == 0 . L'offset, se diverso da zero, deve fare riferimento a un offset nella sezione link_data . Il formato dei dati a cui si fa riferimento non è specificato in questo documento. Questo campo dell'intestazione (e quello precedente) vengono lasciati come hook per l'utilizzo da parte delle implementazioni di runtime.
|
map_off | uint | offset dall'inizio del file all'elemento mappa. L'offset, che deve essere diverso da zero, deve essere un offset nella sezione data e i dati devono essere nel formato specificato da "map_list " di seguito.
|
string_ids_size | uint | conteggio delle stringhe nell'elenco degli identificatori di stringa |
string_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di stringa oppure
0 se string_ids_size == 0 (un caso limite strano). L'offset, se diverso da zero, deve essere all'inizio della sezione string_ids .
|
type_ids_size | uint | numero di elementi nell'elenco degli identificatori di tipo, massimo 65535 |
type_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di tipo oppure
0 se type_ids_size == 0 (ovviamente un
caso limite strano). L'offset, se diverso da zero, deve essere all'inizio della sezione type_ids .
|
proto_ids_size | uint | numero di elementi nell'elenco degli identificatori del prototipo, massimo 65535 |
proto_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori del prototipo oppure
0 se proto_ids_size == 0 (un caso limite strano). L'offset, se diverso da zero, deve essere all'inizio della sezione proto_ids .
|
field_ids_size | uint | conteggio degli elementi nell'elenco degli identificatori di campo |
field_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di campo oppure
0 se field_ids_size == 0 . L'offset, se diverso da zero, deve essere all'inizio della sezione field_ids . |
method_ids_size | uint | conteggio degli elementi nell'elenco degli identificatori di metodi |
method_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori dei metodi oppure
0 se method_ids_size == 0 . L'offset, se diverso da zero, deve essere all'inizio della sezione method_ids . |
class_defs_size | uint | conteggio degli elementi nell'elenco delle definizioni di classe |
class_defs_off | uint | offset dall'inizio del file all'elenco delle definizioni di classe oppure
0 se class_defs_size == 0 (ovviamente un
caso limite strano). L'offset, se diverso da zero, deve essere all'inizio della sezione class_defs .
|
data_size | uint |
Dimensioni della sezione Non utilizzato (v41 o versioni successive) |
data_off | uint |
offset dall'inizio del file all'inizio della sezione Non utilizzato (v41 o versioni successive) |
container_size | uint |
Questo campo non esiste. Si può presumere che sia uguale a la dimensione dell'intero file (incluse altre intestazioni dex e i relativi dati). (v41 o successive) |
header_offset | uint |
Questo campo non esiste. Si può presumere che sia uguale a dall'inizio del file all'inizio di questa intestazione. (v41 o successive) |
map_list
Viene visualizzato nella sezione Dati
Riferimento da header_item
Allineamento: 4 byte
Si tratta di un elenco in ordine di tutti i contenuti di un file. Contiene alcune ridondanze rispetto a header_item
, ma è pensato per essere un modulo facile da utilizzare per eseguire l'iterazione su un intero file. Un determinato tipo deve apparire al massimo una volta in una mappa, ma non esistono limitazioni sui tipi di ordini che possono essere visualizzati, ad eccezione delle limitazioni implicite nel resto del formato (ad es. deve apparire prima una sezione header
, seguita da una sezione string_ids
e così via). Inoltre, le voci della mappa devono essere ordinate in base all'offset iniziale e non devono sovrapporsi.
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensioni dell'elenco, in voci |
lista | map_item[size] | elementi dell'elenco |
formato map_item
Nome | Formato | Descrizione |
---|---|---|
digita | ushort | tipo di articoli; vedi la tabella di seguito |
unused | ushort | (non utilizzato) |
dimensioni | uint | conteggio del numero di elementi da trovare nell'offset indicato |
offset | uint | l'offset dall'inizio del file agli elementi in questione |
Digita i codici
Tipo di elemento | Costante | Valore | Dimensioni elemento in byte |
---|---|---|---|
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
Viene visualizzato nella sezione string_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
string_data_off | uint | dall'inizio del file ai dati di stringa per questo
elemento. L'offset deve fare riferimento a una posizione
nella sezione data e i dati devono essere nel
formato specificato da "string_data_item " di seguito.
Non è richiesto alcun allineamento per l'offset.
|
string_data_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
Nome | Formato | Descrizione |
---|---|---|
utf16_size | uleb128 | la dimensione di questa stringa, in unità di codice UTF-16 (ovvero la "lunghezza della stringa" in molti sistemi). ovvero la lunghezza decodificata della stringa. La lunghezza codificata è implicita dalla posizione del byte 0 . |
di dati | ubyte[] | una serie di unità di codice MUTF-8 (noti anche come ottetti o byte) followed by a byte of value 0 . Consulta la sezione "Codifica MUTF-8 (UTF-8 modificato)" sopra per informazioni dettagliate e discussioni sul formato dei dati.
Nota: è accettabile avere una stringa che includa
(la forma codificata di) unità di codice surrogate UTF-16 (ovvero
|
type_id_item
Viene visualizzato nella sezione type_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
descriptor_idx | uint | nell'elenco string_ids per la stringa del descrittore di questo tipo. La stringa deve essere conforme alla sintassi di
TypeDescriptor, definita sopra.
|
proto_id_item
Viene visualizzato nella sezione proto_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
shorty_idx | uint | indice nell'elenco string_ids per la stringa del descrittore in forma breve di questo prototipo. La stringa deve essere conforme alla
sintassi di ShortyDescriptor, definita sopra, e deve corrispondere
al tipo di ritorno e ai parametri di questo elemento.
|
return_type_idx | uint | indice nell'elenco type_ids per il tipo di ritorno
di questo prototipo
|
parameters_off | uint | offset dall'inizio del file all'elenco dei tipi di parametri
per questo prototipo oppure 0 se questo prototipo non ha parametri. Questo offset, se diverso da zero, deve trovarsi nella sezione data e i dati devono essere nel formato specificato da "type_list" di seguito. Inoltre, nell'elenco non deve essere presente alcun riferimento al tipo void .
|
field_id_item
Viene visualizzato nella sezione field_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | ushort | nell'elenco type_ids per il definitore di questo
campo. Deve essere un tipo di classe e non un array o un tipo primitivo.
|
type_idx | ushort | indice nell'elenco type_ids per il tipo di questo campo
|
name_idx | uint | nell'elenco string_ids per il nome di questo
campo. La stringa deve essere conforme alla sintassi di MemberName,
definita sopra.
|
method_id_item
Viene visualizzato nella sezione method_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | ushort | indice nell'elenco type_ids per il definitore di questo
metodo. Deve essere un tipo di classe o array e non un tipo primitivo.
|
proto_idx | ushort | indice nell'elenco proto_ids per il prototipo di questo metodo
|
name_idx | uint | nell'elenco string_ids per il nome di questo metodo. La stringa deve essere conforme alla sintassi di MemberName,
definita sopra.
|
class_def_item
Viene visualizzato nella sezione class_defs
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | uint | nell'elenco type_ids per questo corso.
Deve essere un tipo di classe e non un array o un tipo primitivo.
|
access_flags | uint | flag di accesso per il corso (public , final ecc.). Per maggiori dettagli, consulta "access_flags Definizioni".
|
superclass_idx | uint | indice nell'elenco type_ids per la superclasse o
il valore costante NO_INDEX se questa classe non ha superclasse (ovvero è una classe di primo livello come Object ).
Se presente, deve essere un tipo di classe e non un array o un tipo primitivo.
|
interfaces_off | uint | offset dall'inizio del file all'elenco delle interfacce o
0 se non ce ne sono. Questo offset deve essere nella sezione data e i dati devono essere nel formato specificato da "type_list " di seguito. Ciascun elemento dell'elenco deve essere un tipo di classe (non un array o un tipo primitivo) e non devono esserci duplicati.
|
source_file_idx | uint | l'indice nell'elenco string_ids per il nome del
file contenente l'origine originale per (almeno la maggior parte di) questa classe,
o il valore speciale NO_INDEX per rappresentare l'assenza di queste informazioni. Il debug_info_item di un determinato metodo
può sostituire questo file di origine, ma si prevede che la maggior parte delle classi
provenga da un solo file di origine.
|
annotations_off | uint | offset dall'inizio del file alla struttura delle annotazioni per questo corso oppure 0 se non sono presenti annotazioni per questo corso. Questo offset, se diverso da zero, deve trovarsi nella sezione data e i dati al suo interno devono essere nel formato specificato da "annotations_directory_item " di seguito, con tutti gli elementi che fanno riferimento a questa classe come definitore.
|
class_data_off | uint | offset dall'inizio del file ai dati del corso associati per questo elemento oppure 0 se non sono presenti dati del corso per questo corso. ad esempio se questa classe è un'interfaccia di indicatore. L'offset, se diverso da zero, deve trovarsi nella sezione data e i dati al suo interno devono essere nel formato specificato da "class_data_item " di seguito, con tutti gli elementi che fanno riferimento a questa classe come definitore.
|
static_values_off | uint | offset dall'inizio del file all'elenco dei valori iniziali per i campi static oppure 0 se non sono presenti (e tutti i campi static devono essere inizializzati con 0 o null ). Questo offset deve trovarsi nella sezione data e i dati al suo interno devono essere nel formato specificato da "encoded_array_item " di seguito. La dimensione
dell'array non deve essere superiore al numero di campi static
dichiarati da questa classe e gli elementi devono corrispondere ai campi
static nello stesso ordine dichiarato in field_list corrispondente. Il tipo di ogni elemento dell'array deve corrispondere al tipo dichiarato del campo corrispondente.
Se nell'array sono presenti meno elementi rispetto ai campi static , i campi rimanenti vengono inizializzati con un 0 o un null appropriato per il tipo.
|
call_site_id_item
Viene visualizzato nella sezione call_site_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
call_site_off | uint | offset dall'inizio del file per chiamare la definizione del sito. L'offset deve essere nella sezione dei dati e i dati devono essere nel formato specificato da "call_site_item" di seguito. |
call_site_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
call_site_item è un elemento encoded_array_item i cui elementi corrispondono agli argomenti forniti a un metodo di linker di bootstrap. I primi tre argomenti sono:
- Un handle metodo che rappresenta il metodo del linker di bootstrap (VALUE_METHOD_HANDLE).
- Un nome di metodo che il linker di bootstrap deve risolvere (VALUE_STRING).
- Un tipo di metodo corrispondente al tipo del nome del metodo da risolvere (VALUE_METHOD_TYPE).
Eventuali argomenti aggiuntivi sono valori costanti passati al metodo del linker di bootstrap. Questi argomenti vengono passati in ordine e senza conversioni di tipo.
L'handle del metodo che rappresenta il metodo del linker di bootstrap deve avere il tipo di ritorno java.lang.invoke.CallSite
. I primi tre tipi di parametri sono:
java.lang.invoke.Lookup
java.lang.String
java.lang.invoke.MethodType
I tipi di parametro di eventuali argomenti aggiuntivi vengono determinati dai relativi valori costanti.
method_handle_item
Viene visualizzato nella sezione method_handles
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
method_handle_type | ushort | tipo di handle del metodo; vedi la tabella di seguito |
unused | ushort | (non utilizzato) |
field_or_method_id | ushort | ID campo o metodo a seconda che il tipo di handle del metodo sia un accessor o un invocatore di metodo |
unused | ushort | (non utilizzato) |
Codici tipo di handle metodo
Costante | Valore | Descrizione |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | L'handle del metodo è un settatore di campo statico (accessore) |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | L'handle del metodo è un getter (accessore) di campo statico |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | L'handle del metodo è un settatore del campo dell'istanza (accessore) |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | L'handle del metodo è un getter (accessore) del campo dell'istanza |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | L'handle del metodo è un invocatore di metodo statico |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | L'handle del metodo è un invocatore del metodo dell'istanza |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | L'handle del metodo è un invocatore del metodo del costruttore |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | L'handle del metodo è un invocatore di metodo diretto |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | L'handle del metodo è un invocatore del metodo dell'interfaccia |
class_data_item
Riferimento da class_def_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
Nome | Formato | Descrizione |
---|---|---|
static_fields_size | uleb128 | il numero di campi statici definiti in questo elemento |
instance_fields_size | uleb128 | il numero di campi istanza definiti in questo elemento |
direct_methods_size | uleb128 | il numero di metodi diretti definiti in questo elemento |
virtual_methods_size | uleb128 | il numero di metodi virtuali definiti in questo elemento |
static_fields | encoded_field[static_fields_size] | I campi statici definiti, rappresentati come una sequenza di elementi codificati. I campi devono essere ordinati per
field_idx in ordine crescente.
|
instance_fields | encoded_field[instance_fields_size] | I campi istanza definiti, rappresentati come una sequenza di elementi codificati. I campi devono essere ordinati per
field_idx in ordine crescente.
|
direct_methods | encoded_method[direct_methods_size] | i metodi diretti (qualsiasi static , private o metodi del costruttore) definiti, rappresentati come una sequenza di elementi codificati. I metodi devono essere ordinati per
method_idx in ordine crescente.
|
virtual_methods | encoded_method[virtual_methods_size] | I metodi virtuali (diversi da static , private o
costruttore) definiti, rappresentati come una sequenza di
elementi codificati. Questo elenco non deve includere metodi ereditati, a meno che non vengano sostituiti dalla classe rappresentata da questo elemento. I metodi devono essere ordinati per method_idx in ordine crescente.
Il method_idx di un metodo virtuale non deve essere uguale a quello di qualsiasi metodo diretto.
|
Nota:tutte le istanze field_id
e
method_id
degli elementi devono fare riferimento alla stessa classe di definizione.
Formato del campo encoded_field
Nome | Formato | Descrizione |
---|---|---|
field_idx_diff | uleb128 | indice nell'elenco field_ids per l'identità di questo
campo (include il nome e il descrittore), rappresentato come differenza
dall'indice dell'elemento precedente nell'elenco. L'indice del
primo elemento di un elenco è rappresentato direttamente.
|
access_flags | uleb128 | flag di accesso per il campo (public , final ecc.). Per maggiori dettagli, consulta "access_flags Definizioni".
|
Formato di encoded_method
Nome | Formato | Descrizione |
---|---|---|
method_idx_diff | uleb128 | indice nell'elenco method_ids per l'identità di questo
metodo (include il nome e il descrittore), rappresentato come differenza
dall'indice dell'elemento precedente nell'elenco. L'indice del
primo elemento di un elenco è rappresentato direttamente.
|
access_flags | uleb128 | flag di accesso per il metodo (public , final ,
ecc.). Per maggiori dettagli, consulta "access_flags Definizioni".
|
code_off | uleb128 | offset dall'inizio del file alla struttura di codice per questo
metodo oppure 0 se questo metodo è abstract
o native . L'offset deve fare riferimento a una posizione nella sezione
data . Il formato dei dati è specificato da "code_item " di seguito.
|
type_list
A cui si fa riferimento da class_def_item e proto_id_item
Viene visualizzato nella sezione Dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensioni dell'elenco, in voci |
lista | type_item[size] | elementi dell'elenco |
Formato type_item
Nome | Formato | Descrizione |
---|---|---|
type_idx | ushort | indice nell'elenco type_ids |
code_item
Riferimento da encoded_method
Viene visualizzato nella sezione Dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
registers_size | ushort | il numero di registri utilizzati da questo codice |
ins_size | ushort | il numero di parole degli argomenti in entrata per il metodo a cui è destinato questo codice |
outs_size | ushort | il numero di parole di spazio per gli argomenti in uscita richiesto da questo codice per l'invocazione del metodo |
tries_size | ushort | il numero di try_item per questa istanza. Se diverso da zero,
vengono visualizzati come array tries subito dopo il
insns in questa istanza.
|
debug_info_off | uint | offset dall'inizio del file alla sequenza di informazioni di debug (numeri di riga + informazioni sulle variabili locali) per questo codice oppure 0 se non sono presenti informazioni. L'offset, se diverso da zero, deve essere
associato a una posizione nella sezione data . Il formato
dei dati è specificato da "debug_info_item " di seguito.
|
insns_size | uint | dimensioni dell'elenco di istruzioni, in unità di codice a 16 bit |
insns | ushort[insns_size] | array effettivo di bytecode. Il formato del codice in un array insns
è specificato dal documento aggiuntivo
Bytecode Dalvik. Tieni presente
che, anche se è definito come un array di ushort , esistono
alcune strutture interne che preferiscono l'allineamento a quattro byte. Inoltre, se si tratta di un file con ordine di byte invertito, lo scambio viene eseguito solo sulle singole istanze ushort e non sulle strutture interne più grandi.
|
padding | ushort (facoltativo) = 0 | due byte di spaziatura per allineare tries a quattro byte.
Questo elemento è presente solo se tries_size è diverso da zero
e insns_size è dispari.
|
tentativi | try_item[tries_size] (facoltativo) | array che indica dove nel codice vengono rilevate le eccezioni e come gestirle. Gli elementi dell'array non devono sovrapporsi nell'intervallo e devono essere in ordine dall'indirizzo più basso a quello più alto. Questo elemento è presente solo se tries_size è diverso da zero.
|
gestori | encoded_catch_handler_list (facoltativo) | byte che rappresentano un elenco di elenchi di tipi di errori e indirizzi di gestori associati. Ogni try_item ha un offset in byte
in questa struttura. Questo elemento è presente solo se
tries_size è diverso da zero.
|
Formato di try_item
Nome | Formato | Descrizione |
---|---|---|
start_addr | uint | indirizzo iniziale del blocco di codice coperto da questa voce. L'indirizzo è un conteggio di unità di codice di 16 bit fino all'inizio della prima istruzione coperta. |
insn_count | ushort | numero di unità di codice a 16 bit coperte da questa voce. L'ultima unità di codice
coperta (inclusa) è start_addr + insn_count - 1 .
|
handler_off | ushort | offset in byte dall'inizio del
encoded_catch_hander_list al
encoded_catch_handler per questa voce. Deve essere un offset rispetto all'inizio di un encoded_catch_handler .
|
formato encoded_catch_handler_list
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uleb128 | dimensione di questo elenco, in voci |
lista | encoded_catch_handler[handlers_size] | elenco effettivo degli elenchi di gestori, rappresentato direttamente (non come offset) e concatenato in sequenza |
Formato di encoded_catch_handler
Nome | Formato | Descrizione |
---|---|---|
dimensioni | sleb128 | numero di tipi di catture in questo elenco. Se non è positivo, è uguale al numero negativo di tipi di eccezioni e queste sono seguite da un gestore generico. Ad esempio, un size di 0
indica che esiste una regola generica, ma non sono presenti regole con tipi espliciti.
Un size di 2 indica che sono presenti due catture esplicitamente
digitate e nessuna generica. Un size di -1
indica che esiste una regola di cattura digitata insieme a una regola generica.
|
gestori | encoded_type_addr_pair[abs(size)] | uno stream di elementi codificati abs(size) , uno per ogni tipo rilevato, nell'ordine in cui devono essere testati i tipi.
|
catch_all_addr | uleb128 (facoltativo) | Indirizzo bytecode dell'handler catch-all. Questo elemento è presente solo se size non è positivo.
|
Formato della coppia di indirizzi di tipo codificati
Nome | Formato | Descrizione |
---|---|---|
type_idx | uleb128 | indice dell'elenco type_ids per il tipo di eccezione da gestire
|
addr | uleb128 | Indirizzo bytecode del gestore delle eccezioni associato |
debug_info_item
Riferimento da code_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
Ogni debug_info_item
definisce una macchina a stati con codifica in byte ispirata a DWARF3 che, quando viene interpretata, emette la tabella delle posizioni e (potenzialmente) le informazioni sulle variabili locali per un code_item
. La sequenza inizia con un header di lunghezza variabile (la cui lunghezza dipende dal numero di parametri del metodo), seguita dai bytecode della macchina a stati e termina con un byte DBG_END_SEQUENCE
.
La macchina a stati è composta da cinque registri. Il registrante address
rappresenta l'offset dell'istruzione nel insns_item
associato in unità di codice a 16 bit. Il registro address
inizia da 0
all'inizio di ogni sequenza debug_info
e deve aumentare solo in modo monotono.
Il registro line
rappresenta il numero di riga di origine
che deve essere associato alla voce della tabella delle posizioni successive emessa dalla
macchina a stati. Viene inizializzato nell'intestazione della sequenza e può cambiare in direzione positiva o negativa, ma non deve mai essere inferiore a 1
. Il registro source_file
rappresenta il
file di origine a cui fanno riferimento le voci del numero di riga. Viene inizializzato con il valore di source_file_idx
in class_def_item
.
Le altre due variabili, prologue_end
e
epilogue_begin
, sono flag booleani (inizializzati a
false
) che indicano se la posizione successiva emessa
deve essere considerata un prologo o un epilogo del metodo. La macchina a stati deve anche monitorare il nome e il tipo dell'ultima variabile locale attiva in ogni registro per il codice DBG_RESTART_LOCAL
.
L'intestazione è la seguente:
Nome | Formato | Descrizione |
---|---|---|
line_start | uleb128 | il valore iniziale per il registro line della macchina a stati.
Non rappresenta una voce di posizioni effettiva.
|
parameters_size | uleb128 | il numero di nomi di parametri codificati. Deve essercene uno per parametro di metodo, escluso this di un metodo di istanza, se presente.
|
parameter_names | uleb128p1[parameters_size] | indice di stringa del nome del parametro del metodo. Un valore codificato di
NO_INDEX indica che non è disponibile alcun nome
per il parametro associato. Il descrittore di tipo
e la firma sono impliciti nel descrittore e nella firma del metodo.
|
I valori del codice a byte sono i seguenti:
Nome | Valore | Formato | Argomenti | Descrizione |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (none) | termina una sequenza di informazioni di debug per un code_item |
|
DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff : importo da aggiungere al registro degli indirizzi |
avanza il registro degli indirizzi senza emettere una voce di posizione |
DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff : importo per cui modificare il registro riga |
avanza il registro riga senza emettere una voce di posizione |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : registro che conterrà la variabile localename_idx : indice di stringa del nometype_idx : indice di tipo del tipo
|
introduce una variabile locale nell'indirizzo corrente. Puoi scegliere tra name_idx o type_idx per indicare che il valore è sconosciuto.NO_INDEX
|
DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num : registro che conterrà localname_idx : indice di stringa del nometype_idx : indice di tipo del tiposig_idx : indice di stringa della firma del tipo
|
introduce un locale con una firma di tipo nell'indirizzo corrente.
Qualsiasi valore tra name_idx , type_idx o
sig_idx può essere NO_INDEX
per indicare che il valore è sconosciuto. Tuttavia, se sig_idx è
-1 , gli stessi dati potrebbero essere rappresentati in modo più
efficiente utilizzando l'opcode DBG_START_LOCAL .
Nota: consulta la sezione " |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : registro contenente il valore locale |
contrassegnare una variabile locale attualmente attiva come non nell'ambito all'indirizzo corrente |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : registrazione per il riavvio |
re-introduces a local variable at the current address. Il nome e il tipo sono gli stessi dell'ultimo locale attivo nel registro specificato. |
DBG_SET_PROLOGUE_END | 0x07 | (none) | imposta il registro della macchina a stati prologue_end , indicando che la voce di posizione successiva aggiunta deve essere considerata la fine del prologo di un metodo (un punto appropriato per un breakpoint del metodo). Il registro prologue_end viene cleared da qualsiasi codice operativo speciale (>= 0x0a ).
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (none) | imposta il registro della macchina a stati epilogue_begin , indicando che la voce di posizione successiva aggiunta deve essere considerata l'inizio dell'epilogo di un metodo (un punto appropriato per sospendere l'esecuzione prima dell'uscita dal metodo).
Il registro epilogue_begin viene cancellato da qualsiasi opcode
(>= 0x0a ) speciale.
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : indice di stringa del nome del file di origine;
NO_INDEX se sconosciuto
|
indica che tutte le voci del numero di riga successive fanno riferimento a questo
nome del file di origine, anziché al nome predefinito specificato in
code_item
|
Opcode speciali | 0x0a…0xff | (none) | avanza i registri line e address ,
emette una voce di posizione e azzera prologue_end e
epilogue_begin . Vedi di seguito per una descrizione.
|
Opcode speciali
Gli opcode con valori compresi tra 0x0a
e 0xff
(inclusi) spostano entrambi i registri line
e address
di una piccola quantità e poi emettono una nuova voce della tabella delle posizioni.
La formula per gli incrementi è la seguente:
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
Riferimento da class_def_item
Viene visualizzato nella sezione Dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_annotations_off | uint | offset dall'inizio del file alle annotazioni apportate direttamente
al corso oppure 0 se il corso non contiene annotazioni dirette.
L'offset, se diverso da zero, deve fare riferimento a una posizione nella sezione data . Il formato dei dati è specificato
da "annotation_set_item " di seguito.
|
fields_size | uint | Conteggio dei campi annotati da questo elemento |
annotated_methods_size | uint | conteggio dei metodi annotati da questo elemento |
annotated_parameters_size | uint | conteggio degli elenchi di parametri dei metodi annotati da questo elemento |
field_annotations | field_annotation[fields_size] (facoltativo) | elenco delle annotazioni dei campi associate. Gli elementi dell'elenco devono essere
ordinati in ordine crescente in base a field_idx .
|
method_annotations | method_annotation[methods_size] (facoltativo) | elenco di annotazioni dei metodi associati. Gli elementi dell'elenco devono essere
ordinati in ordine crescente in base a method_idx .
|
annotationi_parametro | annotatione_parametro[dimensione_parametri] (facoltativo) | elenco di annotazioni dei parametri del metodo associati. Gli elementi dell'elenco devono essere ordinati in ordine crescente in base a method_idx .
|
Nota:tutte le istanze field_id
e
method_id
degli elementi devono fare riferimento alla stessa classe di definizione.
Formato di annotazione_campo
Nome | Formato | Descrizione |
---|---|---|
field_idx | uint | indice nell'elenco field_ids per l'identità del
campo da annotare
|
annotations_off | uint | dall'inizio del file all'elenco di annotazioni per il campo. L'offset deve fare riferimento a una posizione nella sezione data . Il formato dei dati è specificato da "annotation_set_item " di seguito.
|
formato dell'annotazione del metodo
Nome | Formato | Descrizione |
---|---|---|
method_idx | uint | indice nell'elenco method_ids per l'identità del
metodo da annotare
|
annotations_off | uint | dall'inizio del file all'elenco di annotazioni per il metodo. L'offset deve fare riferimento a una posizione nella sezione
data . Il formato dei dati è specificato da "annotation_set_item " di seguito.
|
formato dell'annotazione del parametro
Nome | Formato | Descrizione |
---|---|---|
method_idx | uint | indice nell'elenco method_ids per l'identità del
metodo di cui vengono annotati i parametri
|
annotations_off | uint | offset dall'inizio del file all'elenco di annotazioni per
i parametri del metodo. L'offset deve fare riferimento a una posizione nella sezione
data . Il formato dei dati è specificato da "annotation_set_ref_list " di seguito.
|
annotation_set_ref_list
Riferimenti da parameter_annotations_item
Viene visualizzato nella sezione Dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensioni dell'elenco, in voci |
lista | annotation_set_ref_item[size] | elementi dell'elenco |
formato annotation_set_ref_item
Nome | Formato | Descrizione |
---|---|---|
annotations_off | uint | offset dall'inizio del file all'insieme di annotazioni a cui si fa riferimento
oppure 0 se non sono presenti annotazioni per questo elemento.
L'offset, se diverso da zero, deve fare riferimento a una posizione nella sezione data . Il formato dei dati è specificato da "annotation_set_item " di seguito.
|
annotation_set_item
A cui viene fatto riferimento da annotations_directory_item, field_annotations_item, method_annotations_item e annotation_set_ref_item
Viene visualizzato nella sezione Dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensioni dell'insieme, in voci |
voci | annotation_off_item[size] | elementi dell'insieme. Gli elementi devono essere ordinati in ordine crescente,
per type_idx .
|
formato annotation_off_item
Nome | Formato | Descrizione |
---|---|---|
annotation_off | uint | offset dall'inizio del file a un'annotazione.
L'offset deve fare riferimento a una posizione nella sezione data e il formato dei dati in quella posizione è specificato da "annotation_item " di seguito.
|
annotation_item
Riferimento da annotation_set_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
Nome | Formato | Descrizione |
---|---|---|
visibilità | ubyte | la visibilità prevista di questa annotazione (vedi di seguito) |
annotazione | encoded_annotation | Contenuti delle annotazioni codificati, nel formato descritto da
"Formato encoded_annotation " in
"Codifica encoded_value " sopra.
|
Valori di visibilità
Di seguito sono riportate le opzioni per il campo visibility
in un
annotation_item
:
Nome | Valore | Descrizione |
---|---|---|
VISIBILITY_BUILD | 0x00 | destinati a essere visibili solo in fase di compilazione (ad es. durante la compilazione di altro codice) |
VISIBILITY_RUNTIME | 0x01 | deve essere visibile in fase di esecuzione |
VISIBILITY_SYSTEM | 0x02 | destinati a essere visibili in fase di runtime, ma solo al sistema di base (e non al codice utente normale) |
encoded_array_item
Riferimento da class_def_item
Viene visualizzato nella sezione Dati
Allineamento: nessuno (allineato a byte)
Nome | Formato | Descrizione |
---|---|---|
valore | array_codificato | byte che rappresentano il valore dell'array codificato, nel formato specificato da "encoded_array Formato" in "encoded_value Codifica" sopra.
|
hiddenapi_class_data_item
Questa sezione contiene dati sulle interfacce con limitazioni utilizzate da ogni classe.
Nota: la funzionalità dell'API nascosta è stata introdotta in Android 10.0 ed è applicabile solo ai file DEX delle classi nel percorso della classe di avvio. L'elenco dei flag descritto di seguito potrebbe essere esteso nelle release future di Android. Per ulteriori informazioni, consulta le limitazioni relative alle interfacce non SDK.
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensione totale della sezione |
offset | uint[] | array di offset indicizzati da class_idx .
Una voce dell'array pari a zero all'indice class_idx indica che non esistono dati per questo class_idx o che tutti i flag dell'API nascosti sono pari a zero.
In caso contrario, la voce dell'array è diversa da zero e contiene un offset dall'inizio della sezione a un array di flag API nascosti per questo class_idx .
|
flags | uleb128[] | Array concatenati di flag API nascosti per ogni classe. I possibili valori del flag sono descritti nella tabella seguente. I flag vengono codificati nello stesso ordine in cui i campi e i metodi vengono codificati nei dati di classe. |
Tipi di flag di restrizione:
Nome | Valore | Descrizione |
---|---|---|
lista consentita | 0 | Interfacce che possono essere utilizzate liberamente e sono supportate nell'Indice dei pacchetti del framework Android documentato ufficialmente. |
greylist | 1 | Interfacce non SDK che possono essere utilizzate indipendentemente dal livello API target dell'applicazione. |
Inserisci nella blacklist | 2 | Interfacce non SDK che non possono essere utilizzate indipendentemente dal livello API target dell'applicazione. L'accesso a una di queste interfacce causa un errore di runtime. |
greylist‑max‑o | 3 | Interfacce non SDK che possono essere utilizzate per Android 8.x e versioni precedenti a meno che non siano limitate. |
greylist‑max‑p | 4 | Interfacce non SDK che possono essere utilizzate per Android 9.x a meno che non siano limitate. |
greylist‑max‑q | 5 | Interfacce non SDK che possono essere utilizzate per Android 10.x a meno che non siano limitate. |
greylist‑max‑r | 6 | Interfacce non SDK che possono essere utilizzate per Android 11.x a meno che non siano limitate. |
Annotazioni di sistema
Le annotazioni di sistema vengono utilizzate per rappresentare vari elementi di informazioni riflessive sulle classi (e sui metodi e sui campi). Generalmente, a queste informazioni viene eseguito accesso solo indirettamente dal codice client (non di sistema).
Le annotazioni di sistema sono rappresentate nei file .dex
come annotazioni con visibilità impostata su VISIBILITY_SYSTEM
.
dalvik.annotation.AnnotationDefault
Viene visualizzato nei metodi delle interfacce di annotazione
A ogni interfaccia di annotazione che vuole indicare le associazioni predefinite è associata un'annotazione AnnotationDefault
.
Nome | Formato | Descrizione |
---|---|---|
valore | Annotazione | le associazioni predefinite per questa annotazione, rappresentate come un'annotazione di questo tipo. L'annotazione non deve includere tutti i nomi definiti dall'annotazione; i nomi mancanti non hanno valori predefiniti. |
dalvik.annotation.EnclosingClass
Compare nei corsi
Un'annotazione EnclosingClass
è collegata a ogni classe definita come membro di un'altra classe di per sé o che è anonima, ma non definita all'interno del corpo di un metodo (ad es. una classe interna sintetica). Ogni classe con questa annotazione deve avere anche un'annotazione InnerClass
. Inoltre, un corso non deve avere
contemporaneamente un'annotazione EnclosingClass
e un'annotazione
EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
valore | Classe | la classe che ha l'ambito lessicale più simile a questo |
dalvik.annotation.EnclosingMethod
Compare nei corsi
A ogni classe viene associata un'annotazione EnclosingMethod
, che viene definita all'interno del corpo di un metodo. Ogni classe con questa annotazione deve avere anche un'annotazione InnerClass
.
Inoltre, un corso non deve avere sia un'annotazione EnclosingClass
che un'annotazione EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
valore | Metodo | il metodo che definisce l'ambito lessicale di questa classe |
dalvik.annotation.InnerClass
Compare nei corsi
A ogni classe è associata un'annotazione InnerClass
, che è definita nell'ambito lessicale della definizione di un'altra classe.
Qualsiasi classe con questa annotazione deve avere anche un'annotazione EnclosingClass
o EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
nome | Stringa | Il nome semplice dichiarato originariamente di questa classe (senza alcun prefisso del pacchetto). Se il corso è anonimo, il nome è
null .
|
accessFlags | int | i flag di accesso dichiarati originariamente della classe (che possono essere diversi dai flag effettivi a causa di una mancata corrispondenza tra i modelli di esecuzione del linguaggio di origine e della macchina virtuale di destinazione) |
dalvik.annotation.MemberClasses
Compare su
A ogni classe è associata un'annotazione MemberClasses
che dichiara le classi di membri. Una classe membro è una classe interna diretta con un nome.
Nome | Formato | Descrizione |
---|---|---|
valore | Class[] | array delle classi di membri |
dalvik.annotation.MethodParameters
Compare su
Nota:questa annotazione è stata aggiunta dopo Android 7.1. La sua presenza nelle release precedenti di Android verrà ignorata.
Un'annotazione MethodParameters
è facoltativa e può essere utilizzata per fornire i metadati dei parametri, come i nomi e i modificatori dei parametri.
L'annotazione può essere omessa da un metodo o un costruttore in sicurezza quando i metadati del parametro non sono richiesti in fase di esecuzione.
java.lang.reflect.Parameter.isNamePresent()
può essere utilizzato per verificare se sono presenti metadati per un parametro e i metodi di riflessione associati, come java.lang.reflect.Parameter.getName()
, torneranno al comportamento predefinito in fase di esecuzione se le informazioni non sono presenti.
Quando includono i metadati dei parametri, i compilatori devono includere informazioni per le classi generate, come gli enum, poiché i metadati dei parametri indicano se un parametro è sintetico o obbligatorio.
Un'annotazione MethodParameters
descrive solo i singoli parametri del metodo. Pertanto, i compilatori potrebbero omettere del tutto l'annotazione per i costruttori e i metodi senza parametri, in nome delle dimensioni del codice e dell'efficienza di runtime.
Gli array descritti di seguito devono avere le stesse dimensioni della struttura dex method_id_item
associata al metodo, altrimenti verrà generato un java.lang.reflect.MalformedParametersException
in fase di runtime.
In altre parole: method_id_item.proto_idx
->
proto_id_item.parameters_off
->
type_list.size
deve essere uguale a names().length
e
accessFlags().length
.
Poiché MethodParameters
descrive tutti i parametri metodi formali, anche quelli non dichiarati esplicitamente o implicitamente nel codice sorgente, le dimensioni degli array possono essere diverse dalla firma o da altre informazioni sui metadati che si basano solo su parametri espliciti dichiarati nel codice sorgente. MethodParameters
non includerà inoltre informazioni sui parametri di ricezione dell'annotazione del tipo che non esistono nella firma del metodo effettiva.
Nome | Formato | Descrizione |
---|---|---|
nomi | Stringa[] | I nomi dei parametri formali per il metodo associato. L'array non deve essere nullo, ma deve essere vuoto se non sono presenti parametri formali. Un valore nell'array deve essere null se il parametro formale con quell'indice non ha nome. Se le stringhe dei nomi dei parametri sono vuote o contengono ".", ";', "[" o "/", verrà generato un java.lang.reflect.MalformedParametersException al
runtime.
|
accessFlags | int[] | I flag di accesso dei parametri formali per il metodo associato. L'array non deve essere nullo, ma deve essere vuoto se non sono presenti parametri formali. Il valore è una maschera di bit con i seguenti valori:
java.lang.reflect.MalformedParametersException in fase di esecuzione.
|
dalvik.annotation.Signature
Viene visualizzato in classi, campi e metodi
A ogni classe,
campo o metodo definito in termini di un tipo più complicato
di quanto sia rappresentabile da un type_id_item
è associata un'annotazione Signature
. Il formato .dex
non definisce il formato delle firme; deve semplicemente essere in grado di rappresentare le firme richieste da un linguaggio di origine per l'implementazione corretta della semantica di quel linguaggio. Di conseguenza, le firme non vengono generalmente analizzate (o verificate) dalle implementazioni delle macchine virtuali. Le firme vengono semplicemente trasferite ad API e strumenti di livello superiore (come i debugger). Pertanto, qualsiasi utilizzo di una firma deve essere scritto in modo da non fare supposizioni sulla ricezione di firme valide, proteggendosi esplicitamente dalla possibilità di trovare una firma sintatticamente non valida.
Poiché le stringhe di firma tendono ad avere molti contenuti duplicati,
un'annotazione Signature
è definita come un array di
stringhe, in cui gli elementi duplicati fanno naturalmente riferimento agli stessi
dati sottostanti e la firma è considerata la concatenazione di
tutte le stringhe nell'array. Non esistono regole su come suddividere una firma in stringhe separate; questo dipende interamente dagli strumenti che generano i file .dex
.
Nome | Formato | Descrizione |
---|---|---|
valore | Stringa[] | la firma di questa classe o di questo membro, come array di stringhe da concatenare |
dalvik.annotation.Throws
Compare su
A ogni metodo dichiarato per generare uno o più tipi di eccezioni è associata un'annotazione Throws
.
Nome | Formato | Descrizione |
---|---|---|
valore | Class[] | l'array di tipi di eccezioni lanciate |