diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2012-12-10 23:41:09 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2012-12-10 23:41:09 (GMT) |
commit | 79ec14ee5c1cea5c4ad345a7047b47b9205fc29e (patch) | |
tree | 0596bb4b7910964ef96c3705c80ec5dba677eeb0 /src/format/dex/dex-int.c | |
parent | 42420cfa1f406a5f0a9f062b258ece72098635b5 (diff) |
Took care of Dalvik switch cases.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@299 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/dex/dex-int.c')
-rw-r--r-- | src/format/dex/dex-int.c | 273 |
1 files changed, 244 insertions, 29 deletions
diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c index 200b01f..58211e5 100644 --- a/src/format/dex/dex-int.c +++ b/src/format/dex/dex-int.c @@ -27,11 +27,80 @@ #include <malloc.h> +#include "../../arch/dalvik/instruction-def.h" #include "../../common/endianness.h" /* ---------------------------------------------------------------------------------- */ +/* DESCRIPTION DU FORMAT DALVIK */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* header = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de programme DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + size_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) + result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + + for (i = 0; i < 20 && result; i++) + result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* ELEMENTS DE TABLE DES CONSTANTES */ /* ---------------------------------------------------------------------------------- */ @@ -840,18 +909,87 @@ void reset_dex_code_item(code_item *item) +/* ---------------------------------------------------------------------------------- */ +/* AIGUILLAGES DIVERS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* packed = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage compact. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_packed_switch(const GDexFormat *format, off_t *pos, packed_switch *packed) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + packed->targets = NULL; + + result &= read_u16(&packed->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&packed->size, content, pos, length, SRE_LITTLE); + result &= read_u32(&packed->first_key, content, pos, length, SRE_LITTLE); + if (result && packed->size > 0) + { + packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t)); + + for (i = 0; i < packed->size && result; i++) + result &= read_u32(&packed->targets[i], content, pos, length, SRE_LITTLE); + + } + + if (!result) + reset_dex_packed_switch(packed); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : packed = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +void reset_dex_packed_switch(packed_switch *packed) +{ + if (packed->targets != NULL) + free(packed->targets); +} /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * pos = position de début de lecture. [OUT] * -* header = structure lue à retourner. [OUT] * +* sparse = structure lue à retourner. [OUT] * * * -* Description : Procède à la lecture d'une en-tête de programme DEX. * +* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. * * * * Retour : Bilan de l'opération. * * * @@ -859,54 +997,131 @@ void reset_dex_code_item(code_item *item) * * ******************************************************************************/ -bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch *sparse) { bool result; /* Bilan à retourner */ const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ - size_t i; /* Boucle de parcours */ + uint16_t i; /* Boucle de parcours */ result = true; content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; - for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) - result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + sparse->keys = NULL; + sparse->targets = NULL; - result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->size, content, pos, length, SRE_LITTLE); - for (i = 0; i < 20 && result; i++) - result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + if (result && sparse->size > 0) + { + sparse->keys = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); + sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); - result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->targets[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + } + + if (!result) + reset_dex_sparse_switch(sparse); return result; } +/****************************************************************************** +* * +* Paramètres : sparse = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_sparse_switch(sparse_switch *sparse) +{ + if (sparse->keys != NULL) + free(sparse->keys); + + if (sparse->targets != NULL) + free(sparse->targets); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* dsxitch = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage Dex interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_switch(const GDexFormat *format, off_t *pos, dex_switch *dswitch) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t ident; /* Pseudo-code d'identification*/ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u16(&ident, content, (off_t []) { *pos }, length, SRE_LITTLE); + + if (result) + { + if (ident == DPO_PACKED_SWITCH) + result = read_dex_packed_switch(format, pos, (packed_switch *)dswitch); + + else if (ident == DPO_SPARSE_SWITCH) + result = read_dex_sparse_switch(format, pos, (sparse_switch *)dswitch); + + else + result = false; + } + + return result; +} + +/****************************************************************************** +* * +* Paramètres : dswitch = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_switch(dex_switch *dswitch) +{ + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + reset_dex_packed_switch((packed_switch *)dswitch); + else + reset_dex_sparse_switch((sparse_switch *)dswitch); + +} |