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.
Guida ai tipi
Nome | Descrizione |
---|---|
byte | Intero con segno a 8 bit |
ubyte | Intero senza segno a 8 bit |
video breve | Intero con segno a 16 bit, little-endian |
ushort | Intero senza segno a 16 bit, little-endian |
int | Intero con segno a 32 bit, little-endian |
uint | Intero senza segno a 32 bit, little-endian |
lunghi | Numero intero con segno a 64 bit, little-endian |
ulong | Intero senza segno a 64 bit, little-endian |
sleb128 | LEB128 con segno, a lunghezza variabile (vedi di seguito) |
uleb128 | LEB128 senza segno, a lunghezza variabile (vedi sotto) |
uleb128p1 | LEB128 senza segno più 1 , lunghezza variabile (vedi sotto) |
LEB128
LEB128 ("Little-Endian Base 128") è una codifica a lunghezza variabile per quantità intere con segno o senza segno arbitrarie. Il formato è stato
preso in prestito 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. Ogni byte ha il bit più significativo impostato, ad eccezione dell'ultimo byte della sequenza, che ha il bit più significativo disattivato. I sette bit rimanenti di ogni byte sono 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 firmato (sleb128
),
il bit di payload più significativo dell'ultimo byte della sequenza viene
esteso con segno per produrre il valore finale. Nel caso di valori senza segno
(uleb128
), i bit non rappresentati esplicitamente
vengono interpretati come 0
.
Diagramma a livello di bit di un valore LEB128 a 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 senza segno 0xffffffff
)
— ma nessun altro numero negativo — è un singolo byte ed è
utile esattamente nei casi in cui il numero rappresentato deve essere
non negativo o -1
(o 0xffffffff
),
e in cui non sono consentiti altri valori negativi (o in cui è improbabile che siano necessari valori senza segno 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 stringhe. Si tratta di identificatori per tutte le stringhe utilizzate da questo file, per la denominazione interna (ad es. descrittori di tipo) o come oggetti costanti a cui fa riferimento il codice. Questo elenco deve essere ordinato in base al contenuto della stringa, utilizzando i valori dei punti di codice UTF-16 (non in modo sensibile alle impostazioni internazionali) e non deve contenere voci duplicate. |
type_ids | type_id_item[] | elenco degli identificatori di tipo. Si tratta di identificatori per tutti i tipi (classi,
array o tipi primitivi) a cui fa riferimento questo file, indipendentemente dal fatto che siano definiti
nel file o meno. Questo elenco deve essere ordinato in base all'indice string_id e non deve contenere voci duplicate.
|
proto_ids | proto_id_item[] | elenco degli identificatori dei prototipi di metodi. Questi sono gli identificatori di tutti i prototipi a cui fa riferimento questo file. Questo elenco deve essere ordinato in base al tipo di ritorno (in base all'indice type_id ) e poi in base all'elenco degli argomenti (ordine lessicografico, argomenti individuali ordinati in base all'indice type_id ). L'elenco non deve
contenere voci duplicate.
|
field_ids | field_id_item[] | elenco degli identificatori dei campi. 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 degli 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 è valido che una definizione per la classe con lo stesso nome appaia più di una volta nell'elenco. |
call_site_ids | call_site_id_item[] | elenco degli identificatori del sito 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 degli handle dei metodi. Un elenco di tutti gli handle di metodi a cui fa riferimento questo file, definiti o meno nel file. Questo elenco non è ordinato e potrebbe contenere duplicati che corrispondono logicamente a diverse istanze di handle del metodo. |
di dati | ubyte[] | area dati, contenente tutti i dati di supporto per le tabelle elencate sopra. I diversi elementi hanno requisiti di allineamento diversi e i byte di riempimento vengono inseriti prima di ogni elemento, se necessario, per ottenere un allineamento corretto. |
link_data | ubyte[] | dati utilizzati nei file collegati staticamente. Il formato dei dati in questa sezione non è specificato in questo documento. Questa sezione è vuota nei file scollegati e le implementazioni del runtime possono utilizzarla come ritengono opportuno. |
Formato del contenitore
La versione 41 introduce un nuovo formato contenitore per i dati DEX con l'obiettivo 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
è la dimensione del file logico, non di quello fisico. Può essere utilizzato per scorrere tutti i file logici nel contenitore.- I file dex logici possono fare riferimento a dati successivi nel contenitore (ma non precedenti). Ciò consente ai file dex di condividere dati, come le stringhe, tra loro.
- Tutti gli offset sono relativi al file fisico. Nessun offset è relativo all'intestazione. In questo modo, le sezioni con offset possono essere condivise tra 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 nel nuovo formato.
data_size
edata_off
non vengono 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 devono essere presenti all'inizio di un file .dex
affinché venga riconosciuto come tale. Il valore contiene intenzionalmente
un carattere di nuova riga ("\n"
o 0x0a
) e un
byte null ("\0"
o 0x00
) per facilitare
il rilevamento di alcune forme di danneggiamento. Il valore codifica anche un numero di versione del formato come tre cifre decimali, che dovrebbe aumentare monotonicamente nel tempo man mano che il formato si evolve.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
Nota:il supporto della versione 041
del
formato è stato aggiunto nella release Android 16, che supporta il
formato contenitore.
Nota: il supporto della versione 040
del formato è stato aggiunto nella release 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 del set di bytecode. In Android 10, la versione 039
estende il formato del file DEX per includere informazioni
API nascoste applicabili solo ai file DEX nel percorso delle classi di avvio.
Nota: il supporto della versione
038
del formato è stato aggiunto nella release
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 utilizzava la versione 035
del formato. L'unica
differenza tra le versioni 035
e 037
è l'aggiunta di metodi predefiniti e la modifica di invoke
.
Nota:almeno un paio di versioni precedenti del formato sono state utilizzate in versioni 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
è stata utilizzata per le release M5 della piattaforma
Android (febbraio-marzo 2008). Per diversi aspetti, queste versioni precedenti del formato differiscono in modo significativo dalla versione descritta in questo documento.
ENDIAN_CONSTANT e REVERSE_ENDIAN_CONSTANT
Incorporato in header_item
La costante ENDIAN_CONSTANT
viene utilizzata per indicare
l'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 rileva un'intestazione il cui endian_tag
è REVERSE_ENDIAN_CONSTANT
anziché ENDIAN_CONSTANT
, saprà che il file è stato scambiato di byte 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 di indice è assente.
Nota: questo valore non è definito come
0
, perché in realtà è 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 dei flag di accesso
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à generali di classi e membri delle classi.
Nome | Valore | Per le classi (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 alla classe di definizione |
static : non accetta un argomento this |
ACC_FINAL | 0x10 | final : non può essere suddivisa in sottoclassi |
final : immutabile dopo la creazione |
final : non sostituibile |
ACC_SYNCHRONIZED | 0x20 | synchronized : il blocco associato acquisito automaticamente
intorno alla chiamata a questo metodo. Nota: questa opzione è valida solo se è impostata anche
|
||
ACC_VOLATILE | 0x40 | volatile : regole di accesso speciali per garantire la sicurezza
dei thread |
||
ACC_BRIDGE | 0x40 | metodo bridge, aggiunto automaticamente dal compilatore come bridge type-safe | ||
ACC_TRANSIENT | 0x80 | transient : non deve essere salvato dalla serializzazione predefinita |
||
ACC_VARARGS | 0x80 | L'ultimo argomento deve essere considerato come un argomento "rest" dal compilatore | ||
ACC_NATIVE | 0x100 | native : implementato nel codice nativo |
||
ACC_INTERFACE | 0x200 | interface : classe astratta implementabile più volte |
||
ACC_ABSTRACT | 0x400 | abstract : non direttamente istanziabile |
abstract : non implementato da questa classe |
|
ACC_STRICT | 0x800 | strictfp : regole rigorose per l'aritmetica in 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 | dichiarata 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:questa operazione non influisce sull'esecuzione (se non per il riflesso di questo flag, in sé). |
InnerClass
e non deve mai essere attivo in un class_def_item
.
Codifica UTF-8 modificata
Per facilitare il supporto legacy, il formato .dex
codifica i dati stringa in una forma UTF-8 modificata di fatto standard, di seguito
denominata MUTF-8. Questo formato è identico all'UTF-8 standard, tranne per:
- Vengono utilizzate solo le codifiche a 1, 2 e 3 byte.
- I punti di codice nell'intervallo
U+10000
…U+10ffff
sono codificati come una coppia surrogata, ognuno dei quali è rappresentato come un valore codificato di tre byte. - Il punto di codice
U+0000
è codificato in formato a due byte. - Un byte null semplice (valore
0
) indica la fine di una stringa, come nell'interpretazione standard del linguaggio C.
I primi due elementi 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 con terminazione null in stile C.
Tuttavia, la codifica speciale di U+0000
fa sì che, a differenza
dell'UTF-8 normale, il risultato della chiamata della funzione C standard
strcmp()
su una coppia di stringhe MUTF-8 non sempre
indichi il risultato firmato correttamente del confronto di stringhe non uguali.
Quando l'ordinamento (non solo l'uguaglianza) è un problema, il modo più semplice per confrontare le stringhe MUTF-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 che a UTF-8 in sé.
codifica encoded_value
Incorporato in annotation_element e encoded_array_item
Un encoded_value
è un insieme codificato di dati strutturati gerarchicamente (quasi) arbitrari. La codifica è pensata per
essere compatta e semplice da analizzare.
Nome | Formato | Descrizione |
---|---|---|
(value_arg << 5) | value_type | ubyte | byte che indica il tipo di value immediatamente successivo insieme a un argomento di chiarimento facoltativo 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 di
value immediatamente successivo in byte, come
(size - 1) , ad es. 0 significa che
il valore richiede un byte, mentre 7 significa che ne richiede
otto; tuttavia, esistono eccezioni come indicato di seguito.
|
valore | ubyte[] | byte che rappresentano il valore, di lunghezza variabile e interpretati
in modo diverso per i diversi byte value_type , anche se
sempre little-endian. Per ulteriori dettagli, consulta le varie definizioni dei valori riportate di seguito.
|
Formati dei valori
Digita nome | value_type |
Formato value_arg |
Formato value |
Descrizione |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (nessuno; deve essere 0 ) |
ubyte[1] | valore intero con segno a un byte |
VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | valore intero a due byte con segno, 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 | taglia - 1 (0…3) | ubyte[size] | valore intero a quattro byte con segno, estensione del segno |
VALUE_LONG | 0x06 | size - 1 (0…7) | ubyte[size] | valore intero con segno a otto byte, esteso con segno |
VALUE_FLOAT | 0x10 | taglia - 1 (0…3) | ubyte[size] | pattern di bit a 4 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 a otto byte, esteso con zeri a destra e interpretato come valore in virgola mobile a 64 bit IEEE754 |
VALUE_METHOD_TYPE | 0x15 | taglia - 1 (0…3) | ubyte[size] | valore intero di quattro byte non firmato (con estensione zero),
interpretato come indice nella
sezione proto_ids e che rappresenta un valore di tipo di metodo
|
VALUE_METHOD_HANDLE | 0x16 | taglia - 1 (0…3) | ubyte[size] | valore intero a quattro byte non firmato (esteso a zero),
interpretato come indice nella
sezione method_handles e che rappresenta un valore di handle del metodo
|
VALUE_STRING | 0x17 | taglia - 1 (0…3) | ubyte[size] | valore intero di quattro byte non firmato (con estensione zero),
interpretato come indice nella
sezione string_ids e che rappresenta un valore stringa
|
VALUE_TYPE | 0x18 | taglia - 1 (0…3) | ubyte[size] | valore intero a quattro byte non firmato (con estensione a zero),
interpretato come indice nella
sezione type_ids e che rappresenta un valore
di tipo/classe riflessivo
|
VALUE_FIELD | 0x19 | taglia - 1 (0…3) | ubyte[size] | valore intero di quattro byte non firmato (esteso a zero),
interpretato come indice nella
sezione field_ids e che rappresenta un valore
di campo riflessivo
|
VALUE_METHOD | 0x1a | taglia - 1 (0…3) | ubyte[size] | valore intero di quattro byte non firmato (con estensione zero),
interpretato come indice nella
sezione method_ids e che rappresenta un valore
del metodo di riflessione
|
VALUE_ENUM | 0x1b | taglia - 1 (0…3) | ubyte[size] | valore intero a quattro byte non firmato (con estensione a zero),
interpretato come indice nella
sezione field_ids e che rappresenta il valore di
una costante di tipo enumerato
|
VALUE_ARRAY | 0x1c | (nessuno; deve essere 0 ) |
encoded_array | un array di valori nel formato specificato
nella sezione "Formato encoded_array " di seguito. La dimensione
di value è implicita nella codifica.
|
VALUE_ANNOTATION | 0x1d | (nessuno; deve essere 0 ) |
encoded_annotation | una sottotitolo codificato, nel formato specificato da
"Formato encoded_annotation " di seguito. La dimensione
di value è implicita nella codifica.
|
VALUE_NULL | 0x1e | (nessuno; deve essere 0 ) |
(nessuno) | Valore di riferimento null |
VALUE_BOOLEAN | 0x1f | booleano (0…1) | (nessuno) | valore a 1 bit; 0 per false e
1 per true . Il bit è rappresentato in
value_arg .
|
encoded_array format
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 in questa sezione, concatenate in sequenza.
|
encoded_annotation format
Nome | Formato | Descrizione |
---|---|---|
type_idx | uleb128 | tipo di annotazione. Deve essere un tipo di classe (non un array o un tipo 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 .
|
annotation_element format
Nome | Formato | Descrizione |
---|---|---|
name_idx | uleb128 | Nome dell'elemento, rappresentato come indice nella
sezione string_ids . La stringa deve rispettare la sintassi di MemberName, definita sopra.
|
valore | encoded_value | valore dell'elemento |
Sintassi delle stringhe
Esistono diversi tipi di elementi in un file .dex
che
alla fine fanno riferimento a una stringa. Le seguenti definizioni in stile BNF
indicano la sintassi accettabile per queste stringhe.
SimpleName
Un SimpleName è la base per la sintassi dei nomi di altre
cose. Il formato .dex
consente una discreta libertà
in questo caso (molto più della maggior parte delle lingue di origine comuni). In breve, un nome semplice è costituito da qualsiasi carattere alfabetico o cifra ASCII minuscolo, alcuni simboli ASCII minuscoli specifici e la maggior parte dei punti di codice non ASCII che non sono caratteri di controllo, spazi o caratteri speciali. A partire dalla versione 040
il formato consente inoltre caratteri di spaziatura (categoria Unicode Zs
). Tieni presente che i punti di codice surrogati
(nell'intervallo U+d800
…U+dfff
) non sono
considerati caratteri validi per i nomi, 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 surrogati 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, i cui membri sono campi, metodi e classi interne.
MemberName → | |
SimpleName | |
| | '<' SimpleName '>' |
FullClassName
Un FullClassName è un nome di classe completo, incluso uno specificatore di pacchetto facoltativo seguito da un nome obbligatorio.
FullClassName → | |
OptionalPackagePrefix SimpleName | |
OptionalPackagePrefix → | |
(SimpleName '/' )* |
TypeDescriptor
Utilizzata da type_id_item
Un TypeDescriptor è la rappresentazione di qualsiasi tipo, inclusi
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 parametri e di ritorno, tranne che non viene fatta distinzione tra i vari tipi di riferimento (classe o array). Al contrario,
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
Di seguito è riportato 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 |
V | float |
D | double |
Lfully/qualified/Name; | 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 essere visualizzati in un file .dex
.
header_item
Viene visualizzata 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 " riportata sopra.
|
checksum | uint | Checksum Adler-32 del resto del file (tutto tranne
magic e questo campo); utilizzato per rilevare il danneggiamento 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 versioni precedenti) distanza in byte dall'inizio di questa intestazione alla successiva o alla fine dell'intero file (il contenitore). (v41 o versioni successive) |
header_size | uint |
Le 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 di 0x70 (112) byte (v40 o versioni precedenti) deve essere di 0x78 (120) byte (v41 o versioni successive) |
endian_tag | uint = ENDIAN_CONSTANT | tag endianness. Per ulteriori dettagli, consulta la sezione "ENDIAN_CONSTANT
e REVERSE_ENDIAN_CONSTANT " sopra.
|
link_size | uint | dimensione della sezione dei link o 0 se questo file non è
collegato staticamente |
link_off | uint | offset dall'inizio del file alla sezione dei link oppure
0 se link_size == 0 . L'offset, se diverso da zero,
deve essere un offset nella sezione link_data . Il
formato dei dati a cui fa riferimento non è specificato in questo documento;
questo campo dell'intestazione (e il precedente) vengono lasciati come hook da utilizzare
dalle implementazioni di runtime.
|
map_off | uint | offset dall'inizio del file all'elemento della mappa. L'offset, che deve
essere diverso da zero, deve essere un offset nella sezione data
e i dati devono essere nel formato specificato di seguito da "map_list ".
|
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, a dire il vero). L'offset, se diverso da zero,
deve essere all'inizio della sezione string_ids .
|
type_ids_size | uint | Conteggio degli elementi nell'elenco degli identificatori di tipo, al massimo 65535 |
type_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di tipo oppure
0 se type_ids_size == 0 (un caso limite
strano, a dire il vero). L'offset, se diverso da zero,
deve essere all'inizio della sezione type_ids .
|
proto_ids_size | uint | Conteggio degli elementi nell'elenco degli identificatori di prototipi, al 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 metodo |
method_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di 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 delle classi oppure
0 se class_defs_size == 0 (un caso limite
strano, a dire il vero). 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 le dimensioni dell'intero file (incluse le altre intestazioni dex e i relativi dati). (v41 o versioni successive) |
header_offset | uint |
questo campo non esiste. Si può presumere che sia uguale a offset dall'inizio del file all'inizio di questa intestazione. (v41 o versioni successive) |
map_list
Viene visualizzato nella sezione dei dati
Referenziato da header_item
Allineamento: 4 byte
Si tratta di un elenco di tutti i contenuti di un file, in ordine. Contiene
alcune ridondanze rispetto a header_item
ma è pensato per essere un modulo facile da usare per scorrere un intero
file. Un determinato tipo deve apparire al massimo una volta in una mappa, ma non ci sono
limitazioni all'ordine in cui possono apparire i tipi, a parte
le limitazioni implicite nel resto del formato (ad es. una
sezione header
deve apparire per prima, 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 | la dimensione dell'elenco, in voci |
lista | map_item[size] | elementi dell'elenco |
map_item format
Nome | Formato | Descrizione |
---|---|---|
digita | ushort | Tipo di elementi; vedi la tabella riportata di seguito |
unused | ushort | (non utilizzato) |
dimensioni | uint | conteggio del numero di elementi da trovare all'offset indicato |
offset | uint | offset dall'inizio del file agli elementi in questione |
Codici tipo
Tipo di elemento | Costante | Valore | Dimensione 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 | implicito; deve essere analizzato |
code_item | TYPE_CODE_ITEM | 0x2001 | implicito; deve essere analizzato |
string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | implicito; deve essere analizzato |
debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | implicito; deve essere analizzato |
annotation_item | TYPE_ANNOTATION_ITEM | 0x2004 | implicito; deve essere analizzato |
encoded_array_item | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | implicito; deve essere analizzato |
annotations_directory_item | TYPE_ANNOTATIONS_DIRECTORY_ITEM | 0x2006 | implicito; deve essere analizzato |
hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | implicito; deve essere analizzato |
string_id_item
Viene visualizzato nella sezione string_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
string_data_off | uint | offset dall'inizio del file ai dati della stringa per questo
elemento. L'offset deve essere in 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 dei dati
Allineamento: nessuno (allineamento byte)
Nome | Formato | Descrizione |
---|---|---|
utf16_size | uleb128 | dimensione di questa stringa, in unità di codice UTF-16 (che è la "lunghezza
della stringa" in molti sistemi). ovvero la lunghezza decodificata
della stringa. La lunghezza codificata è implicita nella posizione del byte 0 . |
di dati | ubyte[] | una serie di unità di codice MUTF-8 (ovvero ottetti, ovvero byte)
seguita da un byte di valore 0 . Per informazioni dettagliate e una discussione sul formato dei dati, vedi
"Codifica MUTF-8 (UTF-8 modificato)" sopra.
Nota:è accettabile una stringa che includa
(la forma codificata di) unità di codice surrogato UTF-16 (ovvero,
|
type_id_item
Viene visualizzato nella sezione type_ids
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
descriptor_idx | uint | indice 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
descrittore del formato breve di questo prototipo. La stringa deve essere conforme alla
sintassi di ShortyDescriptor, definita sopra, e deve corrispondere
al tipo restituito e ai parametri di questo elemento.
|
return_type_idx | uint | indice nell'elenco type_ids per il tipo restituito
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. Se diverso da zero, questo offset deve essere nella sezione
data e i dati devono essere nel formato
specificato di seguito da "type_list" . 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 | indice nell'elenco type_ids per il definer di questo
campo. Deve essere un tipo di classe e non un tipo primitivo o di array.
|
type_idx | ushort | indice nell'elenco type_ids per il tipo di
questo campo
|
name_idx | uint | Indice nell'elenco string_ids per il nome di questo
campo. La stringa deve rispettare la 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 definer 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 | Indice nell'elenco string_ids per il nome di questo
metodo. La stringa deve rispettare la sintassi di MemberName,
definita sopra.
|
class_def_item
Viene visualizzato nella sezione class_defs
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | uint | indice nell'elenco type_ids per questo corso.
Deve essere un tipo di classe e non un tipo primitivo o di array.
|
access_flags | uint | flag di accesso per il corso (public , final ,
ecc.). Per ulteriori dettagli, consulta la sezione "Definizioni di access_flags ".
|
superclass_idx | uint | Indice nell'elenco type_ids per la superclasse oppure
il valore costante NO_INDEX se questa classe non ha
una superclasse (ovvero è una classe radice come Object ).
Se presente, deve essere un tipo di classe e non un tipo primitivo o di array.
|
interfaces_off | uint | offset dall'inizio del file all'elenco delle interfacce oppure
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. Ogni elemento dell'elenco
deve essere un tipo di classe (non una matrice o un tipo primitivo) e non
devono essere presenti duplicati.
|
source_file_idx | uint | indice nell'elenco string_ids per il nome del file contenente l'origine originale di (almeno la maggior parte di) questa classe o il valore speciale NO_INDEX per rappresentare la mancanza di queste informazioni. L'debug_info_item di qualsiasi metodo
potrebbe sostituire questo file di origine, ma si prevede che la maggior parte delle classi
proverrà da un solo file di origine.
|
annotations_off | uint | offset dall'inizio del file alla struttura delle annotazioni
per questa classe o 0 se non sono presenti annotazioni
in questa classe. Se diverso da zero, questo offset deve essere nella
sezione data e i dati devono essere nel
formato specificato da "annotations_directory_item " di seguito,
con tutti gli elementi che fanno riferimento a questa classe come definitori.
|
class_data_off | uint | offset dall'inizio del file ai dati della classe associati
a questo elemento oppure 0 se non sono presenti dati
della classe per questa classe. (Questo potrebbe essere il caso, ad esempio, se questa classe
è un'interfaccia marker.) Se diverso da zero, l'offset deve essere nella
sezione data e i dati devono essere nel
formato specificato da "class_data_item " di seguito, con tutti
gli elementi che fanno riferimento a questa classe come definente.
|
static_values_off | uint | offset dall'inizio del file all'elenco dei valori iniziali per i campi static o 0 se non ce ne sono (e tutti i campi static devono essere inizializzati con 0 o null ). Questo offset deve trovarsi nella sezione data e i dati devono essere nel formato specificato di seguito da "encoded_array_item ". La dimensione
dell'array non deve essere superiore al numero di campi static
dichiarati da questa classe e gli elementi corrispondono ai
campi static nello stesso ordine in cui sono dichiarati nel
field_list corrispondente. Il tipo di ogni elemento dell'array
deve corrispondere al tipo dichiarato del campo corrispondente.
Se l'array contiene meno elementi rispetto ai campi static , i campi rimanenti vengono inizializzati con un valore 0 o 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 alla definizione del sito di chiamata. L'offset deve trovarsi 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 dei dati
Allineamento: nessuno (allineamento dei byte)
call_site_item è un encoded_array_item i cui elementi corrispondono agli argomenti forniti a un metodo di bootstrap linker. I primi tre argomenti sono:
- Un handle del metodo che rappresenta il metodo di collegamento del bootstrap (VALUE_METHOD_HANDLE).
- Un nome di metodo che il linker di bootstrap deve risolvere (VALUE_STRING).
- Un tipo di metodo corrispondente al tipo di nome del metodo da risolvere (VALUE_METHOD_TYPE).
Eventuali argomenti aggiuntivi sono valori costanti passati al metodo di collegamento 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 restituito 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 parametri 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 una funzione di accesso o un invoker di metodi |
unused | ushort | (non utilizzato) |
Codici dei tipi di handle del metodo
Costante | Valore | Descrizione |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | L'handle del metodo è un setter (funzione di accesso) del campo statico |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | L'handle del metodo è un getter (funzione di accesso) di un campo statico |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | L'handle del metodo è un setter (funzione di accesso) del campo dell'istanza |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | L'handle del metodo è un getter (funzione di accesso) del campo dell'istanza |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | L'handle del metodo è un invoker di metodi statici |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | L'handle del metodo è un invoker del metodo di istanza |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | L'handle del metodo è un invoker del metodo costruttore |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | L'handle del metodo è un invoker diretto del metodo |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | L'handle del metodo è un invoker del metodo di interfaccia |
class_data_item
Referenziato da class_def_item
Viene visualizzato nella sezione dei dati
Allineamento: nessuno (allineamento 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 dell'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 dell'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 definiti (uno qualsiasi di static , private
o costruttore), 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 definiti (nessuno di static , private
o costruttore), rappresentati come una sequenza di
elementi codificati. Questo elenco non deve includere i metodi ereditati
a meno che non vengano sostituiti dalla classe rappresentata da questo elemento. I metodi devono essere ordinati in base a 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.
encoded_field format
Nome | Formato | Descrizione |
---|---|---|
field_idx_diff | uleb128 | indice nell'elenco field_ids per l'identità di questo
campo (inclusi nome e descrittore), rappresentato come differenza
rispetto all'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 ulteriori dettagli, consulta la sezione "Definizioni di access_flags ".
|
encoded_method format
Nome | Formato | Descrizione |
---|---|---|
method_idx_diff | uleb128 | indice nell'elenco method_ids per l'identità di questo
metodo (inclusi nome e descrittore), rappresentato come differenza
rispetto all'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 ulteriori dettagli, consulta la sezione "Definizioni di access_flags ".
|
code_off | uleb128 | offset dall'inizio del file alla struttura del codice per questo
metodo o 0 se questo metodo è abstract
o native . L'offset deve essere in una posizione nella sezione
data . Il formato dei dati è specificato da
"code_item " di seguito.
|
type_list
Referenziato da class_def_item e proto_id_item
Viene visualizzato nella sezione dei dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | la dimensione dell'elenco, in voci |
lista | type_item[size] | elementi dell'elenco |
type_item format
Nome | Formato | Descrizione |
---|---|---|
type_idx | ushort | indice nell'elenco type_ids |
code_item
Referenziato da encoded_method
Viene visualizzato nella sezione dei 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 del metodo a cui si riferisce questo codice |
outs_size | ushort | il numero di parole dello spazio degli 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,
questi vengono visualizzati come array tries subito dopo
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
riferirsi a una posizione nella sezione data . Il formato dei
dati è specificato di seguito in "debug_info_item ".
|
insns_size | uint | dimensione dell'elenco delle istruzioni, in unità di codice a 16 bit |
insns | ushort[insns_size] | l'array effettivo di bytecode. Il formato del codice in un array insns
è specificato dal documento complementare
Bytecode Dalvik. Tieni presente
che, sebbene sia definito come un array di ushort , esistono
alcune strutture interne che preferiscono l'allineamento a 4 byte. Inoltre,
se si tratta di un file con endianness invertito, l'inversione viene
eseguita solo sulle singole istanze ushort e non sulle
strutture interne più grandi.
|
padding | ushort (facoltativo) = 0 | due byte di riempimento per allineare tries a quattro byte.
Questo elemento è presente solo se tries_size è diverso da zero
e insns_size è dispari.
|
prova | 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 crescente di indirizzo. 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 catch e indirizzi
del gestore associati. Ogni try_item ha un offset byte per byte
in questa struttura. Questo elemento è presente solo se
tries_size è diverso da zero.
|
Formato try_item
Nome | Formato | Descrizione |
---|---|---|
start_addr | uint | indirizzo iniziale del blocco di codice coperto da questa voce. L'indirizzo è un conteggio delle unità di codice a 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 associato al encoded_catch_handler per questa voce. Deve essere un
offset rispetto all'inizio di un encoded_catch_handler .
|
encoded_catch_handler_list format
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uleb128 | dimensioni 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 encoded_catch_handler
Nome | Formato | Descrizione |
---|---|---|
dimensioni | sleb128 | numero di tipi di cattura in questo elenco. Se non è positivo, questo è
il negativo del numero di tipi di catch e i catch sono seguiti
da un gestore catch-all. Ad esempio: un size di 0
significa che esiste un catch-all, ma non catch digitati in modo esplicito.
Un size di 2 significa che ci sono due catch digitati in modo esplicito e nessun catch-all. Un size di -1
indica che è presente un catch digitato insieme a un catch-all.
|
gestori | encoded_type_addr_pair[abs(size)] | stream di elementi codificati abs(size) , uno per ogni tipo di cattura, nell'ordine in cui devono essere testati i tipi.
|
catch_all_addr | uleb128 (facoltativo) | indirizzo bytecode del gestore catch-all. Questo elemento è presente solo
se size non è positivo.
|
encoded_type_addr_pair format
Nome | Formato | Descrizione |
---|---|---|
type_idx | uleb128 | indice nell'elenco type_ids per il tipo di
eccezione da rilevare
|
addr | uleb128 | indirizzo bytecode del gestore delle eccezioni associato |
debug_info_item
Referenziato da code_item
Viene visualizzato nella sezione dei dati
Allineamento: nessuno (allineamento byte)
Ogni debug_info_item
definisce una macchina a stati con codifica byte ispirata a DWARF3 che, una volta interpretata, emette la tabella delle posizioni e (potenzialmente) le informazioni sulle variabili locali per una code_item
. La sequenza inizia con un'intestazione 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 registro
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
da associare alla successiva voce della tabella delle posizioni emessa
dalla macchina a stati. Viene inizializzato nell'intestazione della sequenza e può
variare in direzione positiva o negativa, ma non deve mai essere inferiore a
1
. Il registro source_file
rappresenta il file sorgente 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 su
false
) che indicano se la posizione successiva emessa
deve essere considerata un prologo o un epilogo del metodo. La macchina a stati
deve anche tenere traccia del nome e del 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 del registro line della macchina a stati.
Non rappresenta una voce di posizioni effettiva.
|
parameters_size | uleb128 | il numero di nomi dei parametri codificati. Deve essercene
uno per ogni parametro del metodo, escluso this di un metodo di istanza,
se presente.
|
parameter_names | uleb128p1[parameters_size] | Indice della stringa del nome del parametro del metodo. Un valore codificato di
NO_INDEX indica che non è disponibile
un nome per il parametro associato. Il descrittore del tipo
e la firma sono impliciti nel descrittore e nella firma del metodo.
|
I valori del codice byte sono i seguenti:
Nome | Valore | Formato | Argomenti | Descrizione |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (nessuno) | 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 di cui modificare il registro di linea |
avanza il registro delle righe senza emettere una voce di posizioni |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : registro che conterràname_idx : indice stringa del nometype_idx : indice del tipo
|
introduce una variabile locale all'indirizzo attuale. name_idx o type_idx possono essere NO_INDEX per indicare che il valore è sconosciuto.
|
DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num : registro che conterràname_idx : indice della stringa del nometype_idx : indice del tipo di tiposig_idx : indice della stringa della firma del tipo
|
introduce una variabile locale con una firma di tipo all'indirizzo corrente.
name_idx , type_idx o
sig_idx possono essere NO_INDEX
per indicare che il valore è sconosciuto. Se sig_idx è
-1 , tuttavia, gli stessi dati potrebbero essere rappresentati in modo più
efficiente utilizzando il codice operativo DBG_START_LOCAL .
Nota: per i dettagli sulla gestione delle firme, consulta la sezione " |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : il registro che conteneva il locale |
contrassegna una variabile locale attualmente attiva come fuori ambito all'indirizzo attuale |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : registrati per riavviare |
reintroduce una variabile locale all'indirizzo corrente. Il nome e il tipo sono gli stessi dell'ultimo locale attivo nel registro specificato. |
DBG_SET_PROLOGUE_END | 0x07 | (nessuno) | imposta il registro della macchina a stati prologue_end ,
indicando che la successiva voce di posizione aggiunta deve essere
considerata la fine di un prologo del metodo (un punto appropriato per
un punto di interruzione del metodo). Il registro prologue_end viene
cancellato da qualsiasi codice operativo speciale (>= 0x0a ).
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (nessuno) | imposta il registro della macchina a stati epilogue_begin ,
indicando che la successiva voce di posizione aggiunta deve essere
considerata l'inizio di un epilogo del metodo (un punto appropriato
per sospendere l'esecuzione prima dell'uscita dal metodo).
Il registro epilogue_begin viene cancellato da qualsiasi codice operativo speciale
(>= 0x0a ).
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : indice della stringa del nome del file sorgente;
NO_INDEX se sconosciuto
|
indica che tutte le voci successive del numero di riga fanno riferimento a questo
nome del file sorgente, anziché al nome predefinito specificato in
code_item
|
Special Opcodes | 0x0a…0xff | (nessuno) | fa avanzare i registri line e address ,
emette una voce di posizione e cancella prologue_end e
epilogue_begin . Vedi la descrizione di seguito.
|
Special opcodes
I codici operativi con valori compresi tra 0x0a
e 0xff
(inclusi) spostano i registri line
e address
di una piccola quantità, quindi 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
Referenziato da class_def_item
Viene visualizzato nella sezione dei dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_annotations_off | uint | offset dall'inizio del file alle annotazioni apportate direttamente
alla classe o 0 se la classe non ha annotazioni dirette.
L'offset, se diverso da zero, deve essere impostato su 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 del metodo annotati da questo elemento |
field_annotations | field_annotation[fields_size] (facoltativo) | Elenco delle annotazioni dei campi associati. Gli elementi dell'elenco devono
essere ordinati in ordine crescente, per field_idx .
|
method_annotations | method_annotation[methods_size] (facoltativo) | elenco delle annotazioni dei metodi associati. Gli elementi dell'elenco devono
essere ordinati in ordine crescente, per method_idx .
|
parameter_annotations | parameter_annotation[parameters_size] (facoltativo) | elenco delle annotazioni dei parametri del metodo associato. Gli elementi dell'elenco
devono essere ordinati in ordine crescente, per method_idx .
|
Nota:tutte le istanze field_id
e
method_id
degli elementi devono fare riferimento alla stessa classe di definizione.
formato field_annotation
Nome | Formato | Descrizione |
---|---|---|
field_idx | uint | Indice nell'elenco field_ids per l'identità del
campo annotato
|
annotations_off | uint | offset dall'inizio del file all'elenco delle annotazioni per
il campo. L'offset deve essere in una posizione nella sezione data . Il formato dei dati è specificato da
"annotation_set_item " di seguito.
|
formato method_annotation
Nome | Formato | Descrizione |
---|---|---|
method_idx | uint | Indice nell'elenco method_ids per l'identità del
metodo annotato
|
annotations_off | uint | offset dall'inizio del file all'elenco delle annotazioni per
il metodo. L'offset deve essere in una posizione nella sezione
data . Il formato dei dati è specificato da
"annotation_set_item " di seguito.
|
formato parameter_annotation
Nome | Formato | Descrizione |
---|---|---|
method_idx | uint | indice nell'elenco method_ids per l'identità del
metodo i cui parametri vengono annotati
|
annotations_off | uint | offset dall'inizio del file all'elenco delle annotazioni per
i parametri del metodo. L'offset deve essere in una posizione nella sezione
data . Il formato dei dati è specificato da
"annotation_set_ref_list " di seguito.
|
annotation_set_ref_list
Referenziato da parameter_annotations_item
Viene visualizzato nella sezione dei dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | la dimensione dell'elenco, in voci |
lista | annotation_set_ref_item[size] | elementi dell'elenco |
annotation_set_ref_item format
Nome | Formato | Descrizione |
---|---|---|
annotations_off | uint | offset dall'inizio del file al set di annotazioni a cui viene fatto riferimento
o 0 se non sono presenti annotazioni per questo elemento.
L'offset, se diverso da zero, deve essere una posizione nella sezione data . Il formato dei dati è specificato da
"annotation_set_item " di seguito.
|
annotation_set_item
Referenziato da annotations_directory_item, field_annotations_item, method_annotations_item e annotation_set_ref_item
Viene visualizzato nella sezione dei dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensioni del set, in voci |
voci | annotation_off_item[size] | elementi dell'insieme. Gli elementi devono essere ordinati in ordine crescente,
per type_idx .
|
annotation_off_item format
Nome | Formato | Descrizione |
---|---|---|
annotation_off | uint | offset dall'inizio del file a un'annotazione.
L'offset deve essere in una posizione nella sezione data
e il formato dei dati in quella posizione è specificato da
"annotation_item " di seguito.
|
annotation_item
Referenziato da annotation_set_item
Viene visualizzato nella sezione dei dati
Allineamento: nessuno (allineamento byte)
Nome | Formato | Descrizione |
---|---|---|
visibilità | ubyte | visibilità prevista di questa annotazione (vedi sotto) |
annotazione | encoded_annotation | contenuti dell'annotazione codificati, nel formato descritto in
"Formato encoded_annotation " nella sezione
"Codifica encoded_value " riportata sopra.
|
Valori di visibilità
Queste sono 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 | destinati a essere visibili durante il runtime |
VISIBILITY_SYSTEM | 0x02 | destinato a essere visibile in fase di runtime, ma solo al sistema sottostante (e non al codice utente normale) |
encoded_array_item
Referenziato da class_def_item
Viene visualizzato nella sezione dei dati
Allineamento: nessuno (allineamento byte)
Nome | Formato | Descrizione |
---|---|---|
valore | encoded_array | byte che rappresentano il valore dell'array codificato, nel formato specificato
da "encoded_array Format" (Formato) nella sezione "encoded_value
Encoding" (Codifica) riportata sopra.
|
hiddenapi_class_data_item
Questa sezione contiene dati sulle interfacce con limitazioni utilizzate da ciascuna classe.
Nota: La funzionalità 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 descritti di seguito potrebbe essere esteso nelle versioni future di Android. Per ulteriori informazioni, consulta le limitazioni relative alle interfacce non SDK.
Nome | Formato | Descrizione |
---|---|---|
dimensioni | uint | dimensione totale della sezione |
compensazioni | uint[] | array di offset indicizzati da class_idx .
Una voce di array pari a zero all'indice class_idx indica che
non sono presenti dati per questo class_idx oppure che tutti i flag 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 dei flag sono descritti nella tabella seguente. I flag sono codificati nello stesso ordine dei campi e i metodi sono codificati nei dati della classe. |
Tipi di flag di limitazione:
Nome | Valore | Descrizione |
---|---|---|
whitelist | 0 | Interfacce che possono essere utilizzate liberamente e sono supportate come parte del framework Android documentato ufficialmente Package Index. |
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 varie informazioni riflettive su classi (e metodi e campi). Queste informazioni in genere sono accessibili 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 nelle interfacce di annotazione
Un'annotazione AnnotationDefault
è allegata a ogni
interfaccia di annotazione che vuole indicare i binding predefiniti.
Nome | Formato | Descrizione |
---|---|---|
valore | Annotazione | i binding predefiniti per questa annotazione, rappresentati come annotazione di questo tipo. L'annotazione non deve includere tutti i nomi definiti dall'annotazione; i nomi mancanti semplicemente non hanno valori predefiniti. |
dalvik.annotation.EnclosingClass
Visualizzato nei corsi
A ogni classe è associata un'annotazione EnclosingClass
che è definita come membro di un'altra classe o è
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, una classe non deve avere
sia un'annotazione EnclosingClass
sia
un'annotazione EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
valore | Classe | la classe che definisce l'ambito lessicale più vicino a questa classe |
dalvik.annotation.EnclosingMethod
Visualizzato nei corsi
Un'annotazione EnclosingMethod
viene allegata a ogni classe
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 più vicino a questa classe |
dalvik.annotation.InnerClass
Visualizzato nei corsi
Un'annotazione InnerClass
viene allegata a ogni classe
definita nell'ambito lessicale della definizione di un'altra classe.
Qualsiasi classe con questa annotazione deve avere o un'annotazione
EnclosingClass
o un'annotazione
EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
nome | Stringa | il nome semplice dichiarato originariamente di questa classe (senza prefisso del pacchetto). Se questo corso è anonimo, il nome è
null .
|
accessFlags | int | i flag di accesso dichiarati originariamente per la classe (che potrebbero differire 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
Visualizzato nei corsi
A ogni classe che dichiara classi membro è associata un'annotazione MemberClasses
. (Una classe membro è una classe interna diretta
che ha un nome.)
Nome | Formato | Descrizione |
---|---|---|
valore | Classe[] | array delle classi di membri |
dalvik.annotation.MethodParameters
Compare sui metodi
Nota:questa annotazione è stata aggiunta dopo Android 7.1. La sua presenza nelle versioni precedenti di Android verrà ignorata.
Un'annotazione MethodParameters
è facoltativa e può essere utilizzata per
fornire metadati dei parametri come nomi e modificatori.
L'annotazione può essere omessa da un metodo o da un costruttore in modo sicuro quando i metadati del parametro non sono richiesti in fase di runtime.
java.lang.reflect.Parameter.isNamePresent()
può essere utilizzato per verificare
se sono presenti metadati per un parametro e i metodi di reflection associati, come java.lang.reflect.Parameter.getName()
, torneranno al comportamento predefinito in fase di runtime 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 includono se un parametro è sintetico o obbligatorio.
Un'annotazione MethodParameters
descrive solo i singoli parametri del metodo. Pertanto, i compilatori potrebbero omettere completamente l'annotazione
per i costruttori e i metodi senza parametri, per ridurre le dimensioni del codice
e migliorare l'efficienza di runtime.
Gli array documentati di seguito devono avere le stesse dimensioni della struttura dex method_id_item
associata al metodo, altrimenti verrà generato un errore java.lang.reflect.MalformedParametersException
in fase di runtime.
ovvero 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 del metodo formale, anche quelli non dichiarati in modo esplicito o implicito nel codice sorgente, le dimensioni degli array possono differire dalla firma o da altre informazioni sui metadati basate solo sui parametri espliciti dichiarati nel codice sorgente. MethodParameters
non includerà inoltre informazioni sui parametri del ricevitore di annotazioni di tipo che non esistono nella firma del metodo effettivo.
Nome | Formato | Descrizione |
---|---|---|
nomi | Stringa[] | I nomi dei parametri formali per il metodo associato. L'array
non deve essere null, 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 un nome. Se le stringhe dei nomi dei parametri sono vuote o contengono ".", ";", "[" o "/", verrà generato un java.lang.reflect.MalformedParametersException in fase di
runtime.
|
accessFlags | int[] | I flag di accesso dei parametri formali per il metodo associato. L'array non deve essere null, 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 runtime.
|
dalvik.annotation.Signature
Visualizzato in classi, campi e metodi
A ogni classe, campo o metodo definito in termini di un tipo più complesso di quello rappresentabile da un type_id_item
è associata un'annotazione Signature
. Il formato
.dex
non definisce il formato delle firme; è
semplicemente pensato per poter rappresentare le firme richieste da una lingua
di origine per l'implementazione corretta della semantica di quella lingua. Pertanto, le firme non vengono generalmente analizzate (o verificate)
dalle implementazioni delle macchine virtuali. Le firme vengono semplicemente trasferite
a API e strumenti di livello superiore (come i debugger). Qualsiasi utilizzo di una
firma, pertanto, deve essere scritto in modo da non fare alcuna
ipotesi sulla ricezione solo di firme valide, proteggendosi
esplicitamente dalla possibilità di imbattersi in 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 si riferiscono naturalmente agli stessi
dati sottostanti e la firma è considerata la concatenazione di
tutte le stringhe dell'array. Non esistono regole su come separare una firma in stringhe distinte; ciò dipende interamente dagli strumenti che generano i file .dex
.
Nome | Formato | Descrizione |
---|---|---|
valore | Stringa[] | la firma di questa classe o membro, come array di stringhe da concatenare |
dalvik.annotation.Throws
Compare sui metodi
A ogni metodo dichiarato per generare uno o più tipi di eccezione è associata un'annotazione Throws
.
Nome | Formato | Descrizione |
---|---|---|
valore | Classe[] | l'array di tipi di eccezione generati |