Um arquivo .dex
é o formato de transporte para o bytecode Dalvik. Há certas
restrições sintáticas e semânticas para que um arquivo seja um arquivo .dex
válido, e
um ambiente de execução é necessário para oferecer suporte apenas a arquivos .dex válidos.
Restrições gerais de integridade de .dex
As restrições de integridade geral estão relacionadas à estrutura maior de um
arquivo .dex
, conforme descrito em detalhes no
formato .dex
.
Identificador | Descrição |
---|---|
G1 |
O número magic do arquivo .dex precisa ser
dex\n035\0 para a versão 35 ou semelhante para versões mais recentes.
|
G2 |
A soma de verificação precisa ser uma soma de verificação Adler-32 de todo o conteúdo do arquivo,
exceto os campos magic e checksum .
|
G3 |
A assinatura precisa ser um hash SHA-1 de todo o conteúdo do arquivo, exceto magic , checksum e signature .
|
G4 |
O O |
G5 |
O O |
G6 |
O endian_tag precisa ter o valor:
ENDIAN_CONSTANT ou REVERSE_ENDIAN_CONSTANT
|
G7 |
Para cada uma das seções
Os campos |
G8 |
Todos os campos de deslocamento no cabeçalho, exceto map_off , precisam estar alinhados a quatro bytes.
|
G9 |
O campo map_off precisa ser zero ou apontar para a
seção de dados. No segundo caso, a seção data precisa existir.
|
G10 |
Nenhuma das seções link , string_ids ,
type_ids , proto_ids , field_ids ,
method_ids , class_defs e data
pode se sobrepor ou se sobrepor ao cabeçalho.
|
G11 | Se um mapa existir, cada entrada de mapa precisa ter um tipo válido. Cada tipo pode aparecer no máximo uma vez. |
G12 |
Se um mapa existir, cada entrada de mapa precisa ter um deslocamento e
tamanho diferentes de zero. O deslocamento precisa apontar para a seção correspondente do arquivo (ou seja, um
string_id_item precisa apontar para a seção string_ids ) e o tamanho explícito ou
implícito do item precisa corresponder ao conteúdo e ao tamanho reais da
seção.
|
G13 |
Se um mapa existir, o deslocamento da entrada do mapa n+1 precisará ser maior ou
igual ao deslocamento da entrada do mapa n plus than size of map entry n . Isso implica
entradas que não se sobrepõem e ordenação de baixo para alto.
|
G14 |
Os seguintes tipos de entradas precisam ter um deslocamento alinhado a quatro bytes: string_id_item ,
type_id_item , proto_id_item ,
field_id_item ,
method_id_item , class_def_item ,
type_list , code_item ,
annotations_directory_item .
|
G15 |
Para cada Para cada Para a |
G16 |
Para cada type_id_item , o campo descriptor_idx precisa conter uma referência
válida na lista string_ids . A string referenciada precisa ser um descritor de tipo
válido.
|
G17 |
Para cada proto_id_item , o campo shorty_idx precisa conter uma referência
válida na lista string_ids . A string referenciada precisa ser um descritor
shorty válido. Além disso, o campo return_type_idx precisa ser um índice válido na
seção type_ids , e o campo parameters_off precisa ser zero ou um
deslocamento válido que aponte para a seção data . Se não for igual a zero, a lista de parâmetros
não poderá conter entradas nulas.
|
G18 |
Para cada field_id_item , os campos class_idx e type_idx precisam
ser índices válidos na lista type_ids . A entrada referenciada por class_idx
precisa ser um tipo de referência que não seja de matriz. Além disso, o campo name_idx precisa ser uma referência válida na seção string_ids , e o conteúdo da entrada referenciada precisa estar em conformidade com a especificação MemberName .
|
G19 |
Para cada method_id_item , o campo class_idx precisa ser um índice válido
na seção type_ids , e a entrada referenciada precisa ser um tipo de referência
que não seja uma matriz. O campo proto_id precisa ser uma referência válida na lista
proto_ids . O campo name_idx precisa ser uma referência válida na seção string_ids ,
e o conteúdo da entrada referenciada precisa estar em conformidade com a especificação
MemberName .
|
G20 |
Para cada field_id_item , o campo class_idx precisa ser um índice válido
na lista type_ids . A entrada referenciada precisa ser um tipo de referência
que não seja de matriz.
|
Restrições de bytecode estáticas
As restrições estáticas são restrições em elementos individuais do bytecode. Geralmente, elas podem ser verificadas sem usar técnicas de controle ou de análise de fluxo de dados.
Identificador | Descrição |
---|---|
A1 |
A matriz insns não pode estar vazia.
|
A2 |
O primeiro opcode na matriz insns precisa ter o índice zero.
|
A3 |
A matriz insns precisa conter apenas opcodes Dalvik válidos.
|
A4 |
O índice da instrução n+1 precisa ser igual ao índice da
instrução n mais a duração da instrução
n , considerando possíveis operandos.
|
A5 |
A última instrução na matriz insns precisa terminar no índice
insns_size-1 .
|
A6 |
Todas as metas goto e if-<kind> precisam
ser opcodes no mesmo método.
|
A7 |
Todos os destinos de uma instrução packed-switch precisam ser
opcodes no mesmo método. O tamanho e a lista de destinos
precisam ser consistentes.
|
A8 |
Todos os destinos de uma instrução sparse-switch precisam ser
opcodes no mesmo método. A tabela correspondente precisa ser
consistente e classificada de menor para maior.
|
A9 |
O operando B das instruções const-string e
const-string/jumbo precisa ser um índice válido
no pool de constantes de string.
|
A10 |
O operando C das instruções iget<kind> e
iput<kind> precisa ser um índice válido no
pool de constantes de campo. A entrada referenciada precisa representar um campo de instância.
|
A11 |
O operando C das instruções sget<kind> e
sput<kind> precisa ser um índice válido no
pool de constantes de campo. A entrada referenciada precisa representar um campo
estático.
|
A12 |
O operando C das instruções invoke-virtual ,
invoke-super , invoke-direct e
invoke-static precisa ser um índice válido no
pool de constantes de método.
|
A13 |
O operando B das instruções invoke-virtual/range ,
invoke-super/range , invoke-direct/range e
invoke-static/range precisa ser um índice válido
no pool de constantes do método.
|
A14 |
Um método com nome que começa com '<' só pode ser invocado
implicitamente pela VM, não por código originado de um arquivo .dex . A
única exceção é o inicializador de instância, que pode ser invocado por
invoke-direct .
|
A15 |
O operando C da instrução invoke-interface
precisa ser um índice válido no pool de constantes do método. O
method_id referenciado precisa pertencer a uma interface (não a uma
classe).
|
A16 |
O operando B da instrução invoke-interface/range
precisa ser um índice válido no pool de constantes do método.
O method_id referenciado precisa pertencer a uma interface, não
a uma classe.
|
A17 |
O operando B das instruções const-class ,
check-cast , new-instance e
filled-new-array/range precisa ser um índice válido
no pool de constantes de tipo.
|
A18 |
O operando C das instruções instance-of ,
new-array e filled-new-array
precisa ser um índice válido no pool de constantes do tipo.
|
A19 |
As dimensões de uma matriz criada por uma instrução new-array
precisam ser menores que 256 .
|
A20 |
A instrução new não pode se referir a classes de matriz,
interfaces ou classes abstratas.
|
A21 |
O tipo mencionado por uma instrução new-array precisa ser
um tipo válido sem referência.
|
A22 |
Todos os registros mencionados por uma instrução de largura única
(não em par) precisam ser válidos para o método atual. Ou seja,
os índices precisam ser não negativos e menores que
registers_size .
|
A23 |
Todos os registros mencionados por uma instrução em um formato de largura dupla (par)
precisam ser válidos para o método atual. Ou seja, os índices
precisam ser não negativos e menores que registers_size-1 .
|
A24 |
O operando method_id das instruções invoke-virtual
e invoke-direct precisa pertencer a uma classe
(não a uma interface). Em arquivos Dex anteriores à versão 037 ,
o mesmo precisa ser verdadeiro para as instruções invoke-super e
invoke-static .
|
A25 |
O operando method_id das instruções
invoke-virtual/range e
invoke-direct/range precisa pertencer a uma classe
(não a uma interface). Em arquivos Dex anteriores à versão 037 ,
o mesmo precisa ser verdadeiro para as instruções invoke-super/range e
invoke-static/range .
|
Restrições de bytecode estrutural
As restrições estruturais são restrições sobre as relações entre vários elementos do bytecode. Geralmente, eles não podem ser verificados sem o uso de técnicas de controle ou análise de fluxo de dados.
Identificador | Descrição |
---|---|
B1 | O número e os tipos de argumentos (registradores e valores imediatos) precisam sempre corresponder à instrução. |
B2 | Os pares de registro nunca podem ser divididos. |
B3 | Um registro (ou par) precisa ser atribuído primeiro para poder ser lido. |
B4 |
Uma instrução invoke-direct precisa invocar um inicializador de instância
ou um método apenas na classe atual ou em uma das
superclasses.
|
B5 | Um inicializador de instância precisa ser invocado apenas em uma instância não inicializada. |
B6 | Os métodos de instância só podem ser invocados e os campos de instância só podem ser acessados em instâncias já inicializadas. |
B7 |
Um registro que contém o resultado de uma instrução new-instance
não pode ser usado se a mesma
instrução new-instance for executada novamente antes
da inicialização da instância.
|
B8 |
Um inicializador de instância precisa chamar outro inicializador de instância (mesma
classe ou superclasse) antes que os membros de instância possam ser acessados.
As exceções são campos de instância não herdados, que podem ser atribuídos
antes de chamar outro inicializador e a classe Object
em geral.
|
B9 | Todos os argumentos de método reais precisam ser compatíveis com a atribuição dos respectivos argumentos formais. |
B10 | Para cada invocação de método de instância, a instância real precisa ser compatível com a atribuição da classe ou interface especificada na instrução. |
B11 |
Uma instrução return<kind> precisa corresponder ao
tipo de retorno do método.
|
B12 | Ao acessar membros protegidos de uma superclasse, o tipo real da instância que está sendo acessada precisa ser a classe atual ou uma das subclasses. |
B13 | O tipo de um valor armazenado em um campo estático precisa ser compatível com a atribuição ou convertível para o tipo do campo. |
B14 | O tipo de um valor armazenado em um campo precisa ser compatível com a atribuição ou ser convertível para o tipo do campo. |
B15 | O tipo de cada valor armazenado em uma matriz precisa ser compatível com a atribuição do tipo de componente da matriz. |
B16 |
O operando A de uma instrução throw precisa
ser compatível com a atribuição de java.lang.Throwable .
|
B17 |
A última instrução alcançável de um método precisa ser uma goto
reversiva ou de ramificação, uma return ou uma
instrução throw . Não é possível deixar a
matriz insns na parte de baixo.
|
B18 | A metade não atribuída de um antigo par de registros não pode ser lida (é considerada inválida) até que seja reatribuída por outra instrução. |
B19 |
Uma instrução move-result<kind> precisa ser imediatamente
precedida (na matriz insns ) por uma
instrução invoke-<kind> . A única exceção é
a instrução move-result-object , que também pode ser
precedida por uma instrução filled-new-array .
|
B20 |
Uma instrução move-result<kind> precisa ser imediatamente
precedida (no fluxo de controle real) por uma instrução
return-<kind> correspondente (ela não pode ser pulada). A única exceção é a instrução move-result-object , que também pode ser precedida por uma instrução
filled-new-array .
|
B21 |
Uma instrução move-exception precisa aparecer apenas como a
primeira instrução em um gerenciador de exceções.
|
B22 |
As pseudoinstruções packed-switch-data , sparse-switch-data
e fill-array-data não podem ser
alcançadas pelo fluxo de controle.
|