Questo documento descrive il layout e il contenuto dei file .dex
, che vengono utilizzati per contenere una serie di definizioni di classi e i dati aggiuntivi associati.
Guida ai tipi
Nome | Descrizione |
---|---|
byte | Intero con segno a 8 bit |
ubyte | Intero senza segno a 8 bit |
corto | Intero con segno a 16 bit, little-endian |
breve | Intero senza segno a 16 bit, little-endian |
int | Int con segno a 32 bit, little-endian |
uint | Intero senza segno a 32 bit, little-endian |
lungo | Int con segno a 64 bit, little-endian |
ulong | Intero senza segno a 64 bit, little-endian |
sleb128 | siglato LEB128, lunghezza variabile (vedi sotto) |
uleb128 | LEB128 senza segno, lunghezza variabile (vedi sotto) |
uleb128p1 | LEB128 senza segno più 1 , lunghezza variabile (vedi sotto) |
LEB128
LEB128 (" L ittle- E ndian B ase 128 ") è una codifica a lunghezza variabile per quantità intere arbitrarie con o senza segno. Il formato è stato preso in prestito dalla specifica DWARF3 . In un file .dex
, LEB128 viene utilizzato sempre e solo per codificare quantità a 32 bit.
Ciascun valore codificato LEB128 è costituito da uno a cinque byte, che insieme rappresentano un singolo valore a 32 bit. Ogni byte ha il bit più significativo impostato, tranne per il byte finale della sequenza, che ha il bit più significativo cancellato. I restanti sette bit di ciascun byte costituiscono il carico utile, con i sette bit meno significativi della quantità nel primo byte, i successivi sette nel secondo byte e così via. Nel caso di un LEB128 firmato ( sleb128
), il bit di carico utile più significativo del byte finale nella sequenza viene esteso con segno per produrre il valore finale. Nel caso senza segno ( uleb128
), tutti i bit non rappresentati esplicitamente vengono interpretati come 0
.
Diagramma bit a bit di un valore LEB128 a due byte | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Primo byte | Secondo byte | ||||||||||||||
1 | po' 6 | po' 5 | po ' 4 | po ' 3 | po' 2 | po' 1 | po ' 0 | 0 | po' 13 | po' 12 | po ' 11 | po ' 10 | po' 9 | po ' 8 | po ' 7 |
La variante uleb128p1
viene utilizzata per rappresentare un valore con segno, dove la rappresentazione è del valore più uno codificato come uleb128
. Ciò rende la codifica di -1
(in alternativa pensata come il valore senza segno 0xffffffff
) - ma nessun altro numero negativo - un singolo byte, ed è utile esattamente in quei casi in cui il numero rappresentato deve essere non negativo o -1
(o 0xffffffff
) e dove non sono consentiti altri valori negativi (o dove è improbabile che siano necessari valori senza segno di grandi dimensioni).
Ecco alcuni esempi dei 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 |
Disposizione dell'archivio
Nome | Formato | Descrizione |
---|---|---|
intestazione | intestazione_oggetto | l'intestazione |
string_ids | string_id_item[] | elenco degli identificatori di stringhe. Questi sono identificatori per tutte le stringhe utilizzate da questo file, sia per la denominazione interna (ad esempio, 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 valori di punti di codice UTF-16 (non in modo sensibile alle impostazioni locali) e non deve contenere voci duplicate. |
type_ids | type_id_item[] | elenco degli identificatori di tipo. Questi sono identificatori per tutti i tipi (classi, array 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 degli identificatori del prototipo del metodo. Questi sono identificatori per tutti i prototipi a cui fa riferimento questo file. Questo elenco deve essere ordinato in ordine principale del tipo restituito (per indice type_id ) e quindi per elenco di argomenti (ordinamento lessicografico, argomenti individuali ordinati per indice type_id ). L'elenco non deve contenere voci duplicate. |
field_ids | campo_id_oggetto[] | elenco degli identificatori di campo. Questi sono identificatori per tutti i campi a cui fa riferimento questo file, definiti o meno nel file. Questo elenco deve essere ordinato, dove il tipo di definizione (per indice type_id ) è l'ordine maggiore, il nome del campo (per indice string_id ) è l'ordine intermedio e il tipo (per indice type_id ) è l'ordine minore. L'elenco non deve contenere voci duplicate. |
metodo_id | oggetto_id_metodo[] | elenco degli identificatori del metodo. Questi sono identificatori per tutti i metodi a cui fa riferimento questo file, definiti o meno nel file. Questo elenco deve essere ordinato, dove il tipo di definizione (per indice type_id ) è l'ordine maggiore, il nome del metodo (per indice string_id ) è l'ordine intermedio e il prototipo del metodo (per indice proto_id ) è l'ordine minore. L'elenco non deve contenere voci duplicate. |
class_defs | oggetto_def_classe[] | elenco delle definizioni di classe. Le classi devono essere ordinate in modo tale che la superclasse di una determinata classe e le interfacce implementate appaiano 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_id | 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, definiti o meno nel file. Questo elenco deve essere ordinato in ordine crescente di call_site_off . |
metodo_handles | metodo_handle_elemento[] | elenco di maniglie del metodo. Un elenco di tutti gli handle di metodo a cui fa riferimento questo file, definiti o meno nel file. Questo elenco non è ordinato e potrebbe contenere duplicati che corrisponderanno logicamente a diverse istanze di handle del metodo. |
dati | ubyte[] | area dati, contenente tutti i dati di supporto alle tabelle sopra elencate. Elementi diversi hanno requisiti di allineamento diversi e, se necessario, i byte di riempimento vengono inseriti prima di ciascun elemento per ottenere un allineamento corretto. |
link_data | ubyte[] | dati utilizzati nei file collegati staticamente. Il formato dei dati in questa sezione non è specificato da questo documento. Questa sezione è vuota nei file non collegati e le implementazioni runtime possono utilizzarla come ritengono opportuno. |
Definizioni di bitfield, stringhe e costanti
DEX_FILE_MAGIC
incorporato in header_item
La costante array/stringa DEX_FILE_MAGIC
è l'elenco di byte che deve apparire all'inizio di un file .dex
affinché venga riconosciuto come tale. Il valore contiene intenzionalmente una nuova riga ( "\n"
o 0x0a
) e un byte nullo ( "\0"
o 0x00
) per facilitare il rilevamento di alcune forme di corruzione. Il valore codifica anche un numero di versione del formato come tre cifre decimali, che si prevede aumenterà monotonicamente 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 per la versione 039
del formato è stato aggiunto nella versione Android 9.0, che ha introdotto due nuovi bytecode, const-method-handle
e const-method-type
. (Ognuno di essi è descritto nella tabella Riepilogo del set di bytecode .) In Android 10, la versione 039
estende il formato di file DEX per includere informazioni API nascoste applicabili solo ai file DEX nel percorso della classe di avvio.
Nota: il supporto per la versione 038
del formato è stato aggiunto nella versione 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 per la versione 037
del formato è stato aggiunto nella versione Android 7.0. Prima della versione 037
la maggior parte delle versioni di Android utilizzavano la versione 035
del formato. L'unica differenza tra le versioni 035
e 037
è l'aggiunta di metodi predefiniti e la regolazione invoke
.
Nota: almeno un paio di versioni precedenti del formato sono state utilizzate in versioni di software pubblico ampiamente disponibili. Ad esempio, la versione 009
è stata utilizzata per le versioni M3 della piattaforma Android (novembre-dicembre 2007) e la versione 013
è stata utilizzata per le versioni M5 della piattaforma Android (febbraio-marzo 2008). Sotto 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 dovesse imbattersi in un'intestazione il cui endian_tag
è REVERSE_ENDIAN_CONSTANT
invece di ENDIAN_CONSTANT
, saprebbe che il file è stato scambiato in byte dalla forma prevista.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NESSUN_INDICE
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 genere si tratta di 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 bitfield di questi flag vengono utilizzati per indicare l'accessibilità e le proprietà generali delle classi e dei membri della classe.
Nome | Valore | Per le classi (e le annotazioni InnerClass ) | Per i campi | Per metodi |
---|---|---|---|---|
ACC_PUBBLICO | 0x1 | public : visibile ovunque | public : visibile ovunque | public : visibile ovunque |
ACC_PRIVATO | 0x2 | private : visibile solo alla classe di definizione | private : visibile solo alla classe di definizione | private : visibile solo alla classe di definizione |
ACC_PROTETTO | 0x4 | protected : visibile al pacchetto e alle sottoclassi | protected : visibile al pacchetto e alle sottoclassi | protected : visibile al pacchetto e alle sottoclassi |
ACC_STATICO | 0x8 | static : non è costruito con un riferimento esterno this | static : globale per definire la classe | static : non accetta this argomento |
ACC_FINAL | 0x10 | final : non sottoclassabile | final : immutabile dopo la costruzione | final : non sovrascrivibile |
ACC_SINCRONIZZATO | 0x20 | synchronized : blocco associato acquisito automaticamente durante la chiamata a questo metodo. Nota: questa impostazione è valida solo quando è impostato anche | ||
ACC_VOLATILE | 0x40 | volatile : regole di accesso speciali per aiutare con la sicurezza del thread | ||
ACC_BRIDGE | 0x40 | metodo bridge, aggiunto automaticamente dal compilatore come bridge indipendente dai tipi | ||
ACC_TRANSIENTE | 0x80 | transient : da non salvare per serializzazione predefinita | ||
ACC_VARARGS | 0x80 | l'ultimo argomento dovrebbe essere trattato come un argomento "resto" dal compilatore | ||
ACC_NATIVE | 0x100 | native : implementato nel codice nativo | ||
ACC_INTERFACCIA | 0x200 | interface : classe astratta moltiplicabile e implementabile | ||
ACC_ABSTRACT | 0x400 | abstract : non direttamente istanziabile | abstract : non implementato da questa classe | |
ACC_STRICT | 0x800 | strictfp : regole rigide per l'aritmetica in virgola mobile | ||
ACC_SINTETICO | 0x1000 | non direttamente definito nel codice sorgente | non direttamente definito nel codice sorgente | non direttamente definito nel codice sorgente |
ACC_ANNOTAZIONE | 0x2000 | dichiarato come classe di annotazione | ||
ACC_ENUM | 0x4000 | dichiarato come tipo enumerato | dichiarato come valore enumerato | |
(non utilizzato) | 0x8000 | |||
ACC_COSTRUTTORE | 0x10000 | metodo del costruttore (inizializzatore di classe o istanza) | ||
ACC_DICHIARATO_ SINCRONIZZATO | 0x20000 | dichiarato synchronized .Nota: ciò non ha alcun effetto sull'esecuzione (a parte il riflesso di questo flag, di per sé). |
InnerClass
e non deve mai essere attivo in un class_def_item
.
Codifica MUTF-8 (UTF-8 modificato).
Come concessione a un supporto legacy più semplice, il formato .dex
codifica i suoi dati di stringa in un formato UTF-8 modificato standard di fatto, di seguito denominato MUTF-8. Questo formato è identico allo standard UTF-8, tranne:
- Vengono utilizzate solo le codifiche a uno, due e tre byte.
- I punti di codice nell'intervallo
U+10000
…U+10ffff
sono codificati come una coppia surrogata, ciascuno dei quali è rappresentato come un valore codificato a tre byte. - Il punto di codice
U+0000
è codificato nel formato a due byte. - Un semplice byte nullo (valore
0
) indica la fine di una stringa, come è l'interpretazione standard del linguaggio C.
I primi due elementi sopra possono essere riassunti come: MUTF-8 è un formato di codifica per UTF-16, invece di essere un formato di codifica più diretto per i caratteri Unicode.
Gli ultimi due elementi precedenti rendono contemporaneamente possibile includere il punto di codice U+0000
in una stringa e comunque manipolarlo come una stringa con terminazione null in stile C.
Tuttavia, la codifica speciale di U+0000
significa che, a differenza del normale UTF-8, il risultato della chiamata della funzione C standard strcmp()
su una coppia di stringhe MUTF-8 non sempre indica il risultato con segno corretto del confronto di stringhe non uguali . Quando l'ordine (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.)
Fare riferimento allo standard Unicode per ulteriori informazioni sulla codifica dei caratteri. MUTF-8 è in realtà più vicino alla codifica CESU-8 (relativamente meno conosciuta) che a UTF-8 di per sé.
codifica valore_codificato
incorporato in annotation_element e encoded_array_item
Un encoded_value
è un pezzo codificato di dati strutturati gerarchicamente (quasi) arbitrari. La codifica è pensata per essere compatta e semplice da analizzare.
Nome | Formato | Descrizione |
---|---|---|
(valore_arg << 5) | tipo_valore | ubyte | byte che indica il tipo del value immediatamente successivo insieme a un argomento chiarificatore facoltativo nei tre bit di ordine superiore. Vedi sotto per le varie definizioni value . Nella maggior parte dei casi, value_arg codifica la lunghezza del value immediatamente successivo in byte, come (size - 1) , ad esempio, 0 significa che il valore richiede un byte e 7 significa che richiede otto byte; tuttavia, ci sono delle eccezioni come indicato di seguito. |
valore | ubyte[] | byte che rappresentano il valore, di lunghezza variabile e interpretati in modo diverso per diversi byte value_type , sebbene sempre little-endian. Per i dettagli, vedere le varie definizioni di valore riportate di seguito. |
Formati di valore
Digitare Nome | value_type | formato value_arg | formato value | Descrizione |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (nessuno; deve essere 0 ) | ubyte[1] | valore intero a un byte con segno |
VALUE_SHORT | 0x02 | dimensione - 1 (0…1) | ubyte[dimensione] | valore intero a due byte con segno, estensione del segno |
VALUE_CHAR | 0x03 | dimensione - 1 (0…1) | ubyte[dimensione] | valore intero a due byte senza segno, esteso con zero |
VALORE_INT | 0x04 | dimensione - 1 (0…3) | ubyte[dimensione] | valore intero a quattro byte con segno, estensione del segno |
VALUE_LONG | 0x06 | dimensione - 1 (0…7) | ubyte[dimensione] | Valore intero a otto byte con segno, esteso con segno |
VALUE_FLOAT | 0x10 | dimensione - 1 (0…3) | ubyte[dimensione] | modello di bit a quattro byte, zero esteso a destra e interpretato come un valore in virgola mobile a 32 bit IEEE754 |
VALUE_DOUBLE | 0x11 | dimensione - 1 (0…7) | ubyte[dimensione] | modello di bit a otto byte, zero esteso a destra e interpretato come un valore in virgola mobile IEEE754 a 64 bit |
VALUE_METHOD_TYPE | 0x15 | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione proto_ids e che rappresenta un valore del tipo di metodo |
VALUE_METHOD_HANDLE | 0x16 | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione method_handles e che rappresenta un valore di handle del metodo |
VALUE_STRING | 0x17 | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione string_ids e che rappresenta un valore di stringa |
VALUE_TYPE | 0x18 | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione type_ids e che rappresenta un valore riflettente di tipo/classe |
VALUE_FIELD | 0x19 | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione field_ids e che rappresenta un valore di campo riflettente |
VALUE_METODO | 0x1a | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella sezione method_ids e rappresentante un valore del metodo riflettente |
VALUE_ENUM | 0x1b | dimensione - 1 (0…3) | ubyte[dimensione] | Valore intero a quattro byte senza segno (esteso con zero), interpretato come un indice nella 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. La dimensione del value è implicita nella codifica. |
VALUE_ANNOTAZIONE | 0x1d | (nessuno; deve essere 0 ) | annotazione_codificata | una sottoannotazione, nel formato specificato da "formato encoded_annotation " di seguito. La dimensione del 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 un bit; 0 per false e 1 per true . Il bit è rappresentato in value_arg . |
formato array_codificato
Nome | Formato | Descrizione |
---|---|---|
misurare | uleb128 | numero di elementi nell'array |
valori | valore_codificato[dimensione] | una serie di sequenze di byte size encoded_value nel formato specificato da questa sezione, concatenate in sequenza. |
formato annotazione_codificata
Nome | Formato | Descrizione |
---|---|---|
tipo_idx | uleb128 | tipo di annotazione. Deve essere un tipo di classe (non array o primitivo). |
misurare | uleb128 | numero di mappature nome-valore in questa annotazione |
elementi | elemento_annotazione[dimensione] | 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 elemento_annotazione
Nome | Formato | Descrizione |
---|---|---|
nome_idx | uleb128 | nome dell'elemento, rappresentato come indice nella sezione string_ids . La stringa deve essere conforme alla sintassi per MemberName , definita sopra. |
valore | valore_codificato | valore dell'elemento |
Sintassi delle stringhe
Esistono diversi tipi di elementi in un file .dex
che in definitiva si riferiscono a una stringa. Le seguenti definizioni in stile BNF indicano la sintassi accettabile per queste stringhe.
Nome semplice
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 a basso ASCII, alcuni simboli specifici a basso ASCII e la maggior parte dei punti di codice non ASCII che non siano controllo, spazio o caratteri speciali. A partire dalla versione 040
il formato consente inoltre i caratteri di spazio (categoria Unicode Zs
). Tieni presente che i punti di codice surrogati (nell'intervallo U+d800
… U+dfff
) non sono considerati caratteri di nome validi, di per sé, ma sono validi i caratteri supplementari Unicode (che sono rappresentati dall'alternativa finale della regola per SimpleNameChar ), e loro dovrebbero essere rappresentati in un file come coppie di punti di codice surrogati nella codifica MUTF-8.
NomeSemplice → | ||
CarNomeSemplice ( CarNomeSemplice )* | ||
NomeSempliceCar → | ||
'A' ... 'Z' | ||
| | 'a' ... 'z' | |
| | '0' ... '9' | |
| | ' ' | dalla versione DEX 040 |
| | '$' | |
| | '-' | |
| | '_' | |
| | U+00a0 | dalla versione DEX 040 |
| | U+00a1 … U+1fff | |
| | U+2000 … U+200a | dalla versione DEX 040 |
| | U+2010 … U+2027 | |
| | U+202f | dalla versione DEX 040 |
| | U+2030 … U+d7ff | |
| | U+e000 … U+ffef | |
| | U+10000 … U+10ffff |
Nome del membro
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.
Nomemembro → | |
Nome semplice | |
| | '<' NomeSemplice '>' |
NomeClasseCompleta
Un FullClassName è un nome di classe completo, incluso uno specificatore di pacchetto facoltativo seguito da un nome obbligatorio.
NomeClasseCompleto → | |
FacoltativoPackagePrefix SimpleName | |
Prefisso pacchetto opzionale → | |
( NomeSemplice '/' )* |
TypeDescriptor
utilizzato da type_id_item
Un TypeDescriptor è la rappresentazione di qualsiasi tipo, inclusi primitivi, classi, array e void
. Vedi sotto per il significato delle varie versioni.
TipoDescrittore → | |
'V' | |
| | FieldTypeDescriptor |
FieldTypeDescriptor → | |
NonArrayFieldTypeDescriptor | |
| | ( '[' * 1…255) NonArrayFieldTypeDescriptor |
NonArrayFieldTypeDescriptor → | |
'Z' | |
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' FullClassName ';' |
ShortyDescrittore
utilizzato da proto_id_item
Uno ShortyDescriptor è la rappresentazione in forma breve di un prototipo di metodo, inclusi i tipi di ritorno e di parametro, tranne per il fatto che non esiste alcuna distinzione tra vari tipi di riferimento (classe o array). Tutti i tipi di riferimento sono invece rappresentati da un singolo carattere 'L'
.
ShortyDescrittore → | |
ShortyReturnType ( ShortyFieldType )* | |
ShortyReturnType → | |
'V' | |
| | ShortyFieldType |
ShortyFieldType → | |
'Z' | |
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' |
Semantica del descrittore di tipo
Questo è il significato di ciascuna delle varianti di TypeDescriptor .
Sintassi | Senso |
---|---|
V | void ; valido solo per i tipi di reso |
Z | boolean |
B | byte |
S | short |
C | char |
IO | int |
J | long |
F | float |
D | double |
L completo/qualificato/Nome ; | la classe fully.qualified.Name |
[ descrittore | array di descriptor , utilizzabile ricorsivamente per array di array, sebbene non sia valido avere più di 255 dimensioni. |
Elementi e strutture correlate
Questa sezione include le definizioni per ciascuno degli elementi di primo livello che possono essere visualizzati in un file .dex
.
intestazione_oggetto
appare nella sezione dell'intestazione
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
Magia | ubyte[8] = DEX_FILE_MAGIC | valore magico. Per ulteriori dettagli, vedere la discussione sopra in " DEX_FILE_MAGIC ". |
somma di controllo | uint | checksum adler32 del resto del file (tutto tranne magic e questo campo); utilizzato per rilevare la corruzione dei file |
firma | ubyte[20] | Firma SHA-1 (hash) del resto del file (tutto tranne magic , checksum e questo campo); utilizzato per identificare in modo univoco i file |
dimensione del file | uint | dimensione dell'intero file (inclusa l'intestazione), in byte |
dimensione_intestazione | uint = 0x70 | dimensione dell'intestazione (l'intera sezione), in byte. Ciò consente almeno una quantità limitata di compatibilità indietro/in avanti senza invalidare il formato. |
endian_tag | uint = COSTANTE_ENDIAN | tag endianness. Per ulteriori dettagli, consulta la discussione sopra in " ENDIAN_CONSTANT e REVERSE_ENDIAN_CONSTANT ". |
dimensione_collegamento | uint | dimensione della sezione di collegamento o 0 se questo file non è collegato staticamente |
link_off | uint | offset dall'inizio del file alla sezione del collegamento o 0 se link_size == 0 . L'offset, se diverso da zero, dovrebbe essere un offset nella sezione link_data . Il formato dei dati indicati non è specificato da questo documento; questo campo di intestazione (e il precedente) vengono lasciati come hook per l'utilizzo da parte delle implementazioni runtime. |
map_off | uint | offset dall'inizio del file all'elemento della mappa. L'offset, che deve essere diverso da zero, dovrebbe corrispondere a un offset nella sezione data e i dati dovrebbero essere nel formato specificato da " map_list " di seguito. |
string_ids_size | uint | conteggio delle stringhe nell'elenco degli identificatori di stringhe |
string_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori di stringa, o 0 se string_ids_size == 0 (certamente uno strano caso limite). L'offset, se diverso da zero, dovrebbe 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, o 0 se type_ids_size == 0 (certamente uno strano caso limite). L'offset, se diverso da zero, dovrebbe essere all'inizio della sezione type_ids . |
proto_ids_size | uint | conteggio degli elementi nell'elenco degli identificatori del prototipo, al massimo 65535 |
proto_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori del prototipo, o 0 se proto_ids_size == 0 (certamente uno strano caso limite). L'offset, se diverso da zero, dovrebbe 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 o 0 se field_ids_size == 0 . L'offset, se diverso da zero, dovrebbe essere all'inizio della sezione field_ids . |
metodo_id_dimensione | uint | conteggio degli elementi nell'elenco degli identificatori del metodo |
metodo_ids_off | uint | offset dall'inizio del file all'elenco degli identificatori del metodo o 0 se method_ids_size == 0 . L'offset, se diverso da zero, dovrebbe 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, o 0 se class_defs_size == 0 (certamente uno strano caso limite). L'offset, se diverso da zero, dovrebbe essere all'inizio della sezione class_defs . |
dimensione_dati | uint | Dimensione della sezione data in byte. Deve essere un multiplo pari di sizeof(uint). |
dati_off | uint | offset dall'inizio del file all'inizio della sezione data . |
map_list
appare nella sezione dati
referenziato da header_item
allineamento: 4 byte
Questo è un elenco dell'intero contenuto di un file, in ordine. Contiene una certa ridondanza rispetto a header_item
ma è concepito per essere un modulo semplice da utilizzare per scorrere un intero file. Un dato tipo deve apparire al massimo una volta in una mappa, ma non c'è alcuna restrizione sull'ordine in cui possono apparire i tipi, oltre alle restrizioni implicite nel resto del formato (ad esempio, deve apparire per prima una sezione header
, seguita da una string_ids
sezione, ecc.). Inoltre, le voci della mappa devono essere ordinate in base all'offset iniziale e non devono sovrapporsi.
Nome | Formato | Descrizione |
---|---|---|
misurare | uint | dimensione dell'elenco, in voci |
elenco | elemento_mappa[dimensione] | elementi della lista |
formato mappa_elemento
Nome | Formato | Descrizione |
---|---|---|
tipo | breve | tipologia degli articoli; vedere la tabella seguente |
inutilizzato | breve | (non utilizzato) |
misurare | uint | conteggio del numero di elementi da trovare all'offset indicato |
compensare | uint | offset dall'inizio del file agli elementi in questione |
Codici tipo
Tipo di elemento | Costante | Valore | Dimensioni dell'elemento in byte |
---|---|---|---|
intestazione_oggetto | TIPO_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 | TIPO_PROTO_ID_ITEM | 0x0003 | 0x0c |
campo_id_oggetto | TIPO_FIELD_ID_ITEM | 0x0004 | 0x08 |
metodo_id_elemento | TIPO_METODO_ID_ITEM | 0x0005 | 0x08 |
class_def_item | TYPE_CLASS_DEF_ITEM | 0x0006 | 0x20 |
call_site_id_item | TYPE_CALL_SITE_ID_ITEM | 0x0007 | 0x04 |
metodo_handle_elemento | TYPE_METHOD_HANDLE_ITEM | 0x0008 | 0x08 |
map_list | TYPE_MAP_LIST | 0x1000 | 4 + (dimensione articolo * 12) |
type_list | TYPE_TYPE_LIST | 0x1001 | 4 + (dimensione articolo * 2) |
annotation_set_ref_list | TYPE_ANNOTATION_SET_REF_LIST | 0x1002 | 4 + (dimensione articolo * 4) |
annotation_set_item | TYPE_ANNOTATION_SET_ITEM | 0x1003 | 4 + (dimensione articolo * 4) |
oggetto_dati_classe | TYPE_CLASS_DATA_ITEM | 0x2000 | implicito; deve analizzare |
codice_articolo | TIPO_CODE_ITEM | 0x2001 | implicito; deve analizzare |
string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | implicito; deve analizzare |
debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | implicito; deve analizzare |
annotazione_oggetto | TYPE_ANNOTATION_ITEM | 0x2004 | implicito; deve analizzare |
elemento_array_codificato | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | implicito; deve analizzare |
annotations_directory_elemento | TYPE_ANNOTAZIONI_DIRECTORY_ITEM | 0x2006 | implicito; deve analizzare |
hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | implicito; deve analizzare |
string_id_item
appare 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 dovrebbe essere in una posizione nella sezione data e i dati dovrebbero essere nel formato specificato da " string_data_item " di seguito. Non esiste alcun requisito di allineamento per l'offset. |
string_data_item
appare nella sezione dati
allineamento: nessuno (allineato ai byte)
Nome | Formato | Descrizione |
---|---|---|
utf16_dimensione | uleb128 | dimensione di questa stringa, in unità di codice UTF-16 (che è la "lunghezza della stringa" in molti sistemi). Cioè, questa è la lunghezza decodificata della stringa. (La lunghezza codificata è implicita nella posizione del byte 0 ) |
dati | ubyte[] | una serie di unità di codice MUTF-8 (ovvero ottetti, ovvero byte) seguite da un byte di valore 0 . Vedere "Codifica MUTF-8 (UTF-8 modificata)" sopra per dettagli e discussioni sul formato dei dati. Nota: è accettabile avere una stringa che includa (la forma codificata di) unità di codice surrogato UTF-16 (ovvero |
type_id_item
appare nella sezione type_ids
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
descrittore_idx | uint | indice nell'elenco string_ids per la stringa descrittiva di questo tipo. La stringa deve essere conforme alla sintassi per TypeDescriptor , definita sopra. |
proto_id_item
appare nella sezione proto_ids
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
shorty_idx | uint | indice nell'elenco string_ids per la stringa descrittiva in forma abbreviata 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 |
parametri_disattivati | uint | offset dall'inizio del file all'elenco dei tipi di parametri per questo prototipo o 0 se questo prototipo non ha parametri. Questo offset, se diverso da zero, dovrebbe essere nella sezione data e i dati dovrebbero essere nel formato specificato da "type_list" di seguito. Inoltre, non dovrebbe esserci alcun riferimento al tipo void nell'elenco. |
campo_id_oggetto
appare nella sezione field_ids
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | breve | indice nell'elenco type_ids per il definitore di questo campo. Deve essere un tipo di classe e non un array o un tipo primitivo. |
tipo_idx | breve | indice nell'elenco type_ids per il tipo di questo campo |
nome_idx | uint | indice nell'elenco string_ids per il nome di questo campo. La stringa deve essere conforme alla sintassi per MemberName , definita sopra. |
metodo_id_elemento
appare nella sezione Method_ids
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | breve | indice nell'elenco type_ids per il definitore di questo metodo. Deve essere un tipo di classe o di array e non un tipo primitivo. |
proto_idx | breve | indice nell'elenco proto_ids per il prototipo di questo metodo |
nome_idx | uint | indice nell'elenco string_ids per il nome di questo metodo. La stringa deve essere conforme alla sintassi per MemberName , definita sopra. |
class_def_item
appare nella sezione class_defs
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_idx | uint | indice nell'elenco type_ids per questa classe. Deve essere un tipo di classe e non un array o un tipo primitivo. |
access_flags | uint | flag di accesso per la classe ( public , final , ecc.). Per i dettagli vedere " access_flags Definitions". |
superclass_idx | uint | indice nell'elenco type_ids per la superclasse, o il valore costante NO_INDEX se questa classe non ha una superclasse (cioè è una classe root come Object ). Se presente, deve essere un tipo di classe e non un array o un tipo primitivo. |
interfacce_disattivate | uint | offset dall'inizio del file all'elenco delle interfacce o 0 se non ce ne sono. Questo offset dovrebbe trovarsi nella sezione data e i dati dovrebbero essere nel formato specificato da " type_list " di seguito. Ciascuno degli elementi dell'elenco deve essere un tipo di classe (non un array o un tipo primitivo) e non devono esserci duplicati. |
source_file_idx | uint | indice nell'elenco string_ids per il nome del file contenente la fonte originale per (almeno la maggior parte) di questa classe, o il valore speciale NO_INDEX per rappresentare una mancanza di queste informazioni. Il debug_info_item di qualsiasi metodo può sovrascrivere questo file sorgente, ma l'aspettativa è che la maggior parte delle classi provenga da un solo file sorgente. |
annotazioni_off | uint | offset dall'inizio del file alla struttura delle annotazioni per questa classe o 0 se non sono presenti annotazioni su questa classe. Questo offset, se diverso da zero, dovrebbe essere nella sezione data e i dati dovrebbero essere nel formato specificato da " annotations_directory_item " di seguito, con tutti gli elementi che si riferiscono a questa classe come definitore. |
class_data_off | uint | offset dall'inizio del file ai dati della classe associata per questo elemento o 0 se non sono presenti dati della classe per questa classe. (Questo potrebbe essere il caso, ad esempio, se questa classe è un'interfaccia marcatore.) L'offset, se diverso da zero, dovrebbe essere nella sezione data e i dati dovrebbero essere nel formato specificato da " class_data_item " di seguito, con tutti gli elementi che si riferiscono a questa classe come definitore. |
valori_statici_disabilitati | 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 dovrebbe trovarsi nella sezione data e i dati dovrebbero essere nel formato specificato da " encoded_array_item " di seguito. La dimensione dell'array non deve essere maggiore del numero di campi static dichiarati da questa classe e gli elementi corrispondono ai campi static nello stesso ordine dichiarato nel corrispondente field_list . Il tipo di ciascun 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 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 dovrebbe trovarsi nella sezione dati e i dati dovrebbero essere nel formato specificato da "call_site_item" di seguito. |
chiamata_sito_elemento
appare nella sezione dati
allineamento: nessuno (byte allineato)
call_site_item è un encoded_array_item i cui elementi corrispondono agli argomenti forniti a un metodo del linker bootstrap. I primi tre argomenti sono:
- Un handle di metodo che rappresenta il metodo del linker bootstrap (VALUE_METHOD_HANDLE).
- Un nome di metodo che il linker bootstrap dovrebbe 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 bootstrap. Questi argomenti vengono passati in ordine e senza alcuna conversione di tipo.
L'handle del metodo che rappresenta il metodo del linker 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 parametro di eventuali argomenti aggiuntivi sono determinati dai relativi valori costanti.
metodo_handle_elemento
appare nella sezione Method_handles
allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
metodo_handle_tipo | breve | tipo di maniglia del metodo; Vedi la tabella sotto |
inutilizzato | ushort | (inutilizzato) |
field_or_method_id | ushort | ID campo o metodo a seconda che il tipo di maniglia del metodo sia un accessorio o un metodo invocatore |
inutilizzato | ushort | (inutilizzato) |
Codici del tipo di manico del metodo
Costante | Valore | Descrizione |
---|---|---|
Method_handle_type_static_put | 0x00 | La maniglia del metodo è un setter di campo statico (accessorio) |
Method_handle_type_static_get | 0x01 | La maniglia del metodo è un campo da campo statico (accessorio) |
Method_handle_type_instance_put | 0x02 | La maniglia del metodo è un setter di campo di istanza (accessorio) |
Method_handle_type_instance_get | 0x03 | Il metodo Handle è un campo di istanza getter (accessori) |
Method_handle_type_invoke_static | 0x04 | La maniglia del metodo è un metodo statico invocatore |
Method_handle_type_invoke_instance | 0x05 | La maniglia del metodo è un metodo invocatore di istanza |
Method_handle_type_invoke_constructor | 0x06 | La maniglia del metodo è un invocatore metodo di costruttore |
Method_handle_type_invoke_direct | 0x07 | Il metodo Handle è un metodo diretto invocatore |
Method_handle_type_invoke_interface | 0x08 | La maniglia del metodo è un metodo invocatore di interfaccia |
class_data_item
Rifrenato da class_def_item
appare nella sezione dati
Allineamento: nessuno (allineato al byte)
Nome | Formato | Descrizione |
---|---|---|
static_fields_size | uleb128 | il numero di campi statici definiti in questo articolo |
Instance_fields_size | uleb128 | il numero di campi di istanza definiti in questo articolo |
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 da field_idx in ordine crescente. |
Instance_fields | encoded_field [Instance_fields_size] | I campi di istanza definiti, rappresentati come una sequenza di elementi codificati. I campi devono essere ordinati da field_idx in ordine crescente. |
Direct_Methods | ECCODED_METHOD [Direct_methods_size] | I metodi definiti diretti (uno dei metodi static , private o costruttori), rappresentati come una sequenza di elementi codificati. I metodi devono essere ordinati tramite method_idx in ordine crescente. |
virtual_methods | ECCODED_METHOD [virtual_methods_size] | I metodi virtuali (nessuno dei metodi static , private o costruttori), rappresentati come una sequenza di elementi codificati. Questo elenco non dovrebbe includere metodi ereditari se non sovrascritti dalla classe che questo elemento rappresenta. I metodi devono essere ordinati tramite method_idx in ordine crescente. Il method_idx di un metodo virtuale non deve essere uguale a qualsiasi metodo diretto. |
NOTA: tutti gli elementi field_id
s e method_id
s devono fare riferimento alla stessa classe di definizione.
formato coded_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 in un elenco è rappresentato direttamente. |
Access_Flags | uleb128 | Accedi a flag per il campo ( public , final , ecc.). Vedere " access_flags Definitions" per i dettagli. |
formato coded_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 in un elenco è rappresentato direttamente. |
Access_Flags | uleb128 | Accedi flag per il metodo ( public , final , ecc.). Vedere " access_flags Definitions" per i dettagli. |
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 dovrebbe essere in una posizione nella sezione data . Il formato dei dati è specificato da " code_item " di seguito. |
type_list
riferito da class_def_item e proto_id_item
appare nella sezione dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
misurare | uint | Dimensione dell'elenco, nelle voci |
elenco | type_item [dimensione] | elementi dell'elenco |
formato type_item
Nome | Formato | Descrizione |
---|---|---|
type_idx | ushort | indice nell'elenco type_ids |
code_item
referenziato da coded_method
appare nella sezione dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
register_size | ushort | il numero di registri utilizzati da questo codice |
ins_size | ushort | il numero di parole degli argomenti in arrivo al metodo a cui questo codice è |
outs -size | ushort | Il numero di parole dello spazio degli argomenti in uscita richiesto da questo codice per l'invocazione del metodo |
tenta_size | ushort | Il numero di try_item S per questa istanza. Se diverso da zero, questi appaiono come Array tries subito dopo gli insns in questo caso. |
debug_info_off | uint | Offset dall'inizio del file alla sequenza di informazioni di debug (numeri di riga + informazioni variabili locali) per questo codice o 0 se semplicemente non ci sono informazioni. L'offset, se diverso da zero, dovrebbe essere in una posizione nella sezione data . Il formato dei dati è specificato da " debug_info_item " di seguito. |
insns_size | uint | Dimensione dell'elenco delle 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 compagno Dalvik Bytecode . Si noti che sebbene questo sia definito come un array di ushort , ci sono alcune strutture interne che preferiscono l'allineamento a quattro byte. Inoltre, se ciò accade in un file subappato Endian, lo scambio viene eseguito solo su ushort Singor e non sulle strutture interne più grandi. |
imbottitura | ushort (opzionale) = 0 | Due byte di imbottitura da fare in linea con tries a quattro byte. Questo elemento è presente solo se tries_size è diverso da zero e insns_size è dispari. |
cerca | try_item [TRITES_SIZE] (opzionale) | Array che indica dove vengono catturate le eccezioni del codice e come gestirle. Gli elementi dell'array devono essere non sovrapposti nell'intervallo e in ordine da un indirizzo basso a alto. Questo elemento è presente solo se tries_size è diverso da zero. |
gestori | ECCODED_CATCH_HANDLER_LIST (opzionale) | Byte che rappresentano un elenco di elenchi di tipi di cattura e indirizzi di gestori associati. Ogni try_item ha un offset di byte in questa struttura. Questo elemento è presente solo se tries_size è diverso da zero. |
formato try_item
Nome | Formato | Descrizione |
---|---|---|
start_addr | uint | Inizia l'indirizzo del blocco del codice coperto da questa voce. L'indirizzo è un conteggio di unità di codice a 16 bit 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 (inclusiva) è start_addr + insn_count - 1 . |
gestore_off | ushort | Offset in byte dall'inizio del encoded_catch_hander_list associato a encoded_catch_handler per questa voce. Questo deve essere un offset all'inizio di un encoded_catch_handler . |
formato coded_catch_handler_list
Nome | Formato | Descrizione |
---|---|---|
misurare | uleb128 | Dimensione di questo elenco, nelle voci |
elenco | ECCODED_CATCH_HANDLER [HANDLERS_SIZE] | Elenco effettivo di elenchi di gestori, rappresentati direttamente (non come offset) e concatenati in sequenza |
formato coded_catch_handler
Nome | Formato | Descrizione |
---|---|---|
misurare | SLEB128 | Numero di tipi di cattura in questo elenco. Se non positivo, questo è il negativo del numero di tipi di cattura e le catture sono seguite da un conduttore di cattura. Ad esempio: una size di 0 significa che esiste una cattura ma nessuna cattura esplicito. Una size di 2 significa che ci sono due catture esplicitamente digitate e nessuna cattura. E una size di -1 significa che c'è una cattura digitata insieme a una cattura. |
gestori | ECCODED_TYPE_ADDR_PAIR [ABS (dimensione)] | flusso di elementi codificati abs(size) , uno per ogni tipo catturato, nell'ordine in cui i tipi devono essere testati. |
catch_all_addr | ULEB128 (opzionale) | Indirizzo bytecode del gestore catch-all. Questo elemento è presente solo se size non è positiva. |
ECCODED_TYPE_ADDR_PAIR FORMAT
Nome | Formato | Descrizione |
---|---|---|
type_idx | uleb128 | indice nell'elenco type_ids per il tipo di eccezione da catturare |
indirizzo | uleb128 | Indirizzo bytecode del gestore delle eccezioni associato |
debug_info_item
Rifrenato da Code_Item
appare nella sezione dati
Allineamento: nessuno (allineato al byte)
Ogni debug_info_item
definisce una macchina a stato codificata da byte ispirata a Dwarf3 che, se interpretato, emette la tabella delle posizioni e (potenzialmente) le informazioni variabili locali per un code_item
. La sequenza inizia con un'intestazione a lunghezza variabile (la cui lunghezza dipende dal numero di parametri del metodo), è seguita dai bytecodi della macchina a stato e termina con un byte DBG_END_SEQUENCE
.
La macchina statale è composta da cinque registri. Il registro address
rappresenta l'offset di istruzioni nelle insns_item
associate in unità di codice a 16 bit. Il registro address
inizia a 0
all'inizio di ciascuna sequenza debug_info
e deve solo aumentare monotonicamente. Il registro delle line
rappresenta quale numero di riga di origine dovrebbe essere associato alla voce Tabella delle posizioni successive emessa dalla macchina a stato. È inizializzato nell'intestazione della sequenza e può cambiare in direzioni positive o negative ma non deve mai essere inferiore a 1
. Il registro source_file
rappresenta il file di origine a cui si riferiscono le voci del numero di riga. È inizializzato sul valore di source_file_idx
in class_def_item
. Le altre due variabili, prologue_end
e epilogue_begin
, sono bandiere booleane (inizializzate su false
) che indicano se la posizione successiva emessa debba essere considerata un prologo o epilogo. La macchina a stato deve anche tenere traccia del nome e del tipo dell'ultima variabile locale in diretta in ciascun 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 di stato. Non rappresenta una voce di posizioni effettive. |
parametri_size | uleb128 | Il numero di nomi dei parametri codificati. Dovrebbe esserci un parametro per metodo, escluso un metodo di istanza, se this . |
parametro_names | uleb128p1 [parametri_size] | Indice 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 e la firma del tipo sono impliciti dal descrittore e dalla 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 posizioni |
Dbg_advance_line | 0x02 | sleb128 line_diff | line_diff : importo per modificare il registro delle righe di | fa avanzare il registro delle linee senza emettere una voce di posizioni |
Dbg_start_local | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx | register_num : registro che conterrà localename_idx : indice stringa del nometype_idx : tipo indice del tipo | Introduce una variabile locale all'indirizzo corrente. name_idx o type_idx può essere NO_INDEX per indicare che quel valore è sconosciuto. |
Dbg_start_local_extended | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx ULEB128P1 SIG_IDX | register_num : registro che conterrà localename_idx : indice stringa del nometype_idx : tipo indice del tiposig_idx : indice di stringa della firma del tipo | Introduce un locale con una firma di tipo all'indirizzo corrente. Qualsiasi name_idx , type_idx o sig_idx può essere NO_INDEX per indicare che quel valore è sconosciuto. (Se sig_idx è -1 , tuttavia, gli stessi dati potrebbero essere rappresentati in modo più efficiente usando il codice OPDODE DBG_START_LOCAL .) Nota: vedere la discussione in " |
Dbg_end_local | 0x05 | uleb128 register_num | register_num : registro che conteneva locale | Contrassegna una variabile locale attualmente rivolta a livello di portata all'attuale indirizzo |
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 che era in diretta nel registro specificato. |
Dbg_set_prologue_end | 0x07 | (nessuno) | Imposta il registro delle macchine a stato prologue_end , indicando che la voce di posizione successiva che viene aggiunta dovrebbe essere considerata la fine di un metodo Prologo (un luogo appropriato per un interruzione del metodo). Il registro prologue_end è cancellato da qualsiasi OpCode speciale ( >= 0x0a ). | |
Dbg_set_epilogue_begin | 0x08 | (nessuno) | Imposta il registro delle macchine a stato epilogue_begin , indicando che la voce di posizione successiva che viene aggiunta dovrebbe essere considerata l'inizio di un metodo Epilogo (un luogo appropriato per sospendere l'esecuzione prima dell'uscita del metodo). Il registro epilogue_begin è cancellato da qualsiasi OpCode speciale ( >= 0x0a ). | |
Dbg_set_file | 0x09 | uleb128p1 name_idx | name_idx : indice String 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é il nome predefinito specificato in code_item |
Opcodi speciali | 0x0a… 0xff | (nessuno) | Fa avanzare i registri line e address , emette una voce di posizione e cancella prologue_end e epilogue_begin . Vedi sotto per la descrizione. |
Opcodi speciali
Opcodi con valori tra 0x0a
e 0xff
(inclusivo) spostano sia la line
che i registri address
di una piccola quantità e quindi emettere una nuova voce della tabella di posizione. 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
Rifrenato da class_def_item
appare nella sezione dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
class_annotations_off | uint | Offset dall'inizio del file alle annotazioni realizzate direttamente sulla classe o 0 se la classe non ha annotazioni dirette. L'offset, se diverso da zero, dovrebbe essere in 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 articolo |
annotato_methods_size | uint | Conteggio dei metodi annotati da questo articolo |
annotato_parameters_size | uint | Conteggio dei parametri del metodo elenchi annotati da questo elemento |
Field_annotations | field_annotation [Fields_size] (Opzionale) | Elenco delle annotazioni di campo associate. Gli elementi dell'elenco devono essere ordinati in ordine crescente, tramite field_idx . |
Method_annotations | Method_Annotation [Method_Size] (Opzionale) | Elenco delle annotazioni del metodo associato. Gli elementi dell'elenco devono essere ordinati in ordine crescente, tramite method_idx . |
parametro_annotazioni | Parameter_Annotation [parametri_size] (opzionale) | Elenco delle annotazioni dei parametri del metodo associato. Gli elementi dell'elenco devono essere ordinati in ordine crescente, tramite method_idx . |
NOTA: tutti gli elementi field_id
s e method_id
s devono fare riferimento alla stessa classe di definizione.
Field_Annotation Formato
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 dovrebbe essere in una posizione nella sezione data . Il formato dei dati è specificato da " annotation_set_item " di seguito. |
Method_Annotation Formato
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 dovrebbe 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 dovrebbe essere in una posizione nella sezione data . Il formato dei dati è specificato da " annotation_set_ref_list " di seguito. |
annotazione_set_ref_list
Rifrenato da Parameter_Annotations_Item
appare nella sezione dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
misurare | uint | Dimensione dell'elenco, nelle voci |
elenco | annotazione_set_ref_item [dimensione] | elementi dell'elenco |
formato annotazione_set_ref_item
Nome | Formato | Descrizione |
---|---|---|
annotations_off | uint | Offset dall'inizio del file al set di annotazione referenziata o 0 se non ci sono annotazioni per questo elemento. L'offset, se diverso da zero, dovrebbe essere in una posizione nella sezione data . Il formato dei dati è specificato da " annotation_set_item " di seguito. |
annotazione_set_item
Riferimenti da annotations_directory_item, field_annotations_item, metod_annotations_item e annotation_set_ref_item
appare nella sezione dati
Allineamento: 4 byte
Nome | Formato | Descrizione |
---|---|---|
misurare | uint | dimensione del set, in voci |
inserimenti | annotazione_off_item [dimensione] | elementi del set. Gli elementi devono essere ordinati in ordine crescente, tramite type_idx . |
formato annotazione_off_item
Nome | Formato | Descrizione |
---|---|---|
annotazione_off | uint | Offset dall'inizio del file a un'annotazione. L'offset dovrebbe essere in una posizione nella sezione data e il formato dei dati in quella posizione è specificato da " annotation_item " di seguito. |
annotazione_item
Rifrenato da annotation_set_item
appare nella sezione dati
Allineamento: nessuno (allineato al byte)
Nome | Formato | Descrizione |
---|---|---|
visibilità | ubyte | Visibilità prevista di questa annotazione (vedi sotto) |
annotazione | ECCODED_ANNOTATION | Contenuto di annotazione codificata, nel formato descritto da "formato encoded_annotation " in "codifica encoded_value " sopra. |
Valori di visibilità
Queste sono le opzioni per il campo visibility
in un annotation_item
:
Nome | Valore | Descrizione |
---|---|---|
Visibilità_build | 0x00 | destinato solo a essere visibile al momento della costruzione (ad es. Durante la compilazione di altro codice) |
Visibilità_runtime | 0x01 | destinato a visibile in fase di esecuzione |
Visibilità_system | 0x02 | destinato a visibile in fase di esecuzione, ma solo al sistema sottostante (e non al codice utente normale) |
ECCODED_ARRAY_ITEM
Rifrenato da class_def_item
appare nella sezione dati
Allineamento: nessuno (allineato al byte)
Nome | Formato | Descrizione |
---|---|---|
valore | ECCODED_ARRAY | byte che rappresentano il valore dell'array codificato, nel formato specificato da "formato encoded_array " in "codifica encoded_value " sopra. |
hiddenapi_class_data_item
Questa sezione contiene dati su interfacce limitate utilizzate da ciascuna classe.
Nota: la funzione API nascosta è stata introdotta in Android 10.0 ed è applicabile solo ai file DEX delle classi nel percorso della classe di avvio. L'elenco delle bandiere descritte di seguito può essere esteso nelle versioni future di Android. Per ulteriori informazioni, consultare le restrizioni sulle interfacce non SDK .
Nome | Formato | Descrizione |
---|---|---|
misurare | uint | Dimensione totale della sezione |
compensazioni | uint [] | Array di offset indicizzati da class_idx . Una voce di array zero su indice class_idx significa che non ci sono dati per questo class_idx o tutti i flag API nascosti sono zero. Altrimenti 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 . |
bandiere | uleb128 [] | Array concatenate di bandiere API nascoste per ogni classe. I possibili valori di 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 restrizione:
Nome | Valore | Descrizione |
---|---|---|
lista bianca | 0 | Interfacce che possono essere utilizzate liberamente e sono supportate come parte dell'indice del pacchetto Framework Android ufficialmente documentato. |
Greylist | 1 | Interfacce non SDK che possono essere utilizzate indipendentemente dal livello di API target dell'applicazione. |
lista nera | 2 | Interfacce non SDK che non possono essere utilizzate indipendentemente dal livello di API target dell'applicazione. L'accesso a una di queste interfacce provoca un errore di runtime . |
Greylist - Max - o | 3 | Interfacce non SDK che possono essere utilizzate per Android 8.x e inferiore 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 pezzi di informazioni riflettenti su classi (e metodi e campi). Queste informazioni sono generalmente accessibili solo indirettamente dal codice client (non sistema).
Le annotazioni di sistema sono rappresentate in file .dex
come annotazioni con visibilità impostata su VISIBILITY_SYSTEM
.
Dalvik.Annotation.AnnotationDefault
appare sui metodi nelle interfacce di annotazione
Un'annotazione AnnotationDefault
è allegata a ciascuna interfaccia di annotazione che desidera indicare assistenti predefiniti.
Nome | Formato | Descrizione |
---|---|---|
valore | Annotazione | I legami 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 impostazioni predefinite. |
Dalvik.Annotation.enclosingclass
appare nelle classi
Un'annotazione EnclosingClass
è allegata a ciascuna classe che è definita come membro di un'altra classe, di per sé, o è anonima ma non definita all'interno di un corpo di metodo (ad es. Una classe interna sintetica). Ogni classe che ha questa annotazione deve anche avere un'annotazione InnerClass
. Inoltre, una classe non deve avere sia una EnclosingClass
e un EnclosingMethod
annotazione.
Nome | Formato | Descrizione |
---|---|---|
valore | Classe | La classe che si accoppa più lessicamente questa classe |
Dalvik.Annotation.enclosingMethod
appare nelle classi
Un'annotazione EnclosingMethod
è collegato a ciascuna classe definita all'interno di un corpo del metodo. Ogni classe che ha questa annotazione deve anche avere un'annotazione InnerClass
. Inoltre, una classe non deve avere sia una EnclosingClass
e un EnclosingMethod
annotazione.
Nome | Formato | Descrizione |
---|---|---|
valore | Metodo | Il metodo che si accoppa più lessicamente questa classe |
Dalvik.Annotation.innerclass
appare nelle classi
Un'annotazione InnerClass
è allegata a ciascuna classe che è definita nell'ambito lessicale della definizione di un'altra classe. Qualsiasi classe che ha questa annotazione deve anche avere un'annotazione EnclosingClass
o un'annotazione EnclosingMethod
.
Nome | Formato | Descrizione |
---|---|---|
nome | Corda | Il nome semplice originariamente dichiarato di questa classe (esclusa alcun prefisso del pacchetto). Se questa classe è anonima, il nome è null . |
AccessFlags | int | Le flag di accesso originariamente dichiarate della classe (che possono differire dalle flag efficaci a causa di una mancata corrispondenza tra i modelli di esecuzione del linguaggio di origine e la macchina virtuale target) |
Dalvik.Annotation.memberclasses
appare nelle classi
Un'annotazione MemberClasses
è allegata a ciascuna classe che dichiara le classi di membri. (Una classe membro è una classe interna diretta che ha un nome.)
Nome | Formato | Descrizione |
---|---|---|
valore | Classe[] | Array delle lezioni di membro |
Dalvik.Annotation.MethodParameters
appare sui metodi
Nota: questa annotazione è stata aggiunta dopo Android 7.1. La sua presenza su precedenti versioni Android verrà ignorata.
Un'annotazione MethodParameters
è facoltativa e può essere utilizzata per fornire metadati dei parametri come nomi di parametri e modificatori.
L'annotazione può essere omessa da un metodo o un costruttore in modo sicuro quando i metadati dei parametri non sono richiesti in fase di esecuzione. java.lang.reflect.Parameter.isNamePresent()
può essere utilizzato per verificare se i metadati sono presenti per un parametro e i metodi di riflessione associati come java.lang.reflect.Parameter.getName()
ricaderanno al comportamento di inadempienza in fase di esecuzione Se le informazioni non sono presenti.
Quando includono i metadati dei parametri, i compilatori devono includere informazioni per classi generate come ENUM, poiché i metadati dei parametri includono se un parametro è sintetico o obbligatorio.
Un'annotazione MethodParameters
descrive solo i parametri del metodo individuale. Pertanto, i compilatori possono omettere interamente l'annotazione per costruttori e metodi che non hanno parametri, per motivi di efficienza del codice e di runtime.
Gli array documentati di seguito devono avere le stesse dimensioni della struttura Dex method_id_item
associata al metodo, altrimenti un java.lang.reflect.MalformedParametersException
verrà lanciato in fase di esecuzione.
Cioè: 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 esplicitamente o implicitamente nel codice sorgente, la dimensione degli array può differire dalla firma o da altre informazioni sui metadati che si basano solo su parametri espliciti dichiarati nel codice sorgente. MethodParameters
non includerà inoltre alcuna informazione sui parametri del ricevitore di annotazione di tipo che non esistono nella firma del metodo effettivo.
Nome | Formato | Descrizione |
---|---|---|
nomi | Corda[] | I nomi dei parametri formali per il metodo associato. L'array non deve essere nullo ma deve essere vuoto se non ci sono parametri formali. Un valore nell'array deve essere nullo se il parametro formale con quell'indice non ha nome. Se le stringhe del nome del parametro sono vuote o contengono '.', ';', '[' O '/' allora un java.lang.reflect.MalformedParametersException verrà lanciato in fase di esecuzione. |
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 ci sono parametri formali. Il valore è una maschera bit con i seguenti valori:
java.lang.reflect.MalformedParametersException verrà lanciato in fase di esecuzione. |
Dalvik.Annotation.Signature
appare su classi, campi e metodi
Un'annotazione Signature
è allegata a ciascuna classe, campo o metodo definito in termini di un tipo più complicato di quanto sia rappresentabile da un type_id_item
. Il formato .dex
non definisce il formato per le firme; È semplicemente pensato per essere in grado di rappresentare qualsiasi firma che una lingua di origine richiede per una corretta implementazione della semantica di quella lingua. Pertanto, le firme non sono generalmente analizzate (o verificate) dalle implementazioni della macchina virtuale. Le firme vengono semplicemente consegnate a API e strumenti di livello superiore (come i debugger). Qualsiasi uso di una firma, pertanto, dovrebbe essere scritto in modo da non fare alcuna ipotesi sulla ricezione solo di firme valide, a guardia esplicitamente dalla possibilità di imbattersi in una firma sintatticamente non valida.
Poiché le stringhe di firma tendono ad avere un sacco di contenuti duplicati, un'annotazione Signature
è definita come una serie di stringhe, in cui elementi duplicati si riferiscono naturalmente agli stessi dati sottostanti e la firma è considerata la concatenazione di tutte le stringhe nella matrice . Non ci sono regole su come staccare una firma in stringhe separate; Ciò dipende interamente agli strumenti che generano file .dex
.
Nome | Formato | Descrizione |
---|---|---|
valore | Corda[] | La firma di questa classe o membro, come una serie di stringhe che devono essere concatenate insieme |
Dalvik.Annotation.throws
appare sui metodi
Un'annotazione Throws
è collegata a ciascun metodo che viene dichiarato per lanciare uno o più tipi di eccezione.
Nome | Formato | Descrizione |
---|---|---|
valore | Classe[] | la serie di tipi di eccezione lanciati |