diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-10-01 15:55:39 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-10-01 15:55:39 (GMT) |
commit | d51fef170f00602744e55a8fdb21a3c7d196696a (patch) | |
tree | 5f51c1cdb09669da974c1b99d280a4e7078aab7f /src/format/dex/pool.c | |
parent | 9aa5b354e83825e2d9843aea742aa62221a2130b (diff) |
Rewritten the whole support of DEX file format.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@581 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/dex/pool.c')
-rw-r--r-- | src/format/dex/pool.c | 472 |
1 files changed, 356 insertions, 116 deletions
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c index a869873..904ab76 100644 --- a/src/format/dex/pool.c +++ b/src/format/dex/pool.c @@ -24,11 +24,13 @@ #include "pool.h" +#include <malloc.h> #include <string.h> #include "dex-int.h" #include "../mangling/demangler.h" +#include "../mangling/dex/context.h" @@ -83,6 +85,7 @@ bool find_all_dex_strings(GDexFormat *format) const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) { off_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ string_id_item str_id; /* Identifiant de chaîne */ string_data_item str_data; /* Description de chaîne */ @@ -90,13 +93,15 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) return NULL; pos = format->header.string_ids_off + index * sizeof(string_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) + if (!read_dex_string_id_item(format, &addr, &str_id)) return NULL; pos = str_id.string_data_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_data_item(format, &pos, &str_data)) + if (!read_dex_string_data_item(format, &addr, &str_data)) return NULL; return (const char *)str_data.data; @@ -109,6 +114,49 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) + + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge en mémoire l'ensemble des types du format DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_types(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GDataType *type; /* Type récupéré */ + + result = true; + + format->types = (GDataType **)calloc(format->header.type_ids_size, sizeof(GDataType *)); + + for (i = 0; i < format->header.type_ids_size && result; i++) + { + type = get_type_from_dex_pool(format, i); + + if (type != NULL) + g_object_unref(G_OBJECT(type)); + else + result = false; + + } + + return result; + +} + + /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * @@ -122,89 +170,94 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index) +GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) { - off_t pos; /* Tête de lecture */ + GDataType *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ type_id_item type_id; /* Définition de la classe */ string_id_item str_id; /* Identifiant de chaîne */ string_data_item str_data; /* Description de chaîne */ - - //printf("Tp Index :: %hd / %d\n", index, format->header.type_ids_size); - + result = NULL; if (index >= format->header.type_ids_size) - return NULL; - - pos = format->header.type_ids_off + index * sizeof(type_id_item); + goto gtfdp_error; - if (!read_dex_type_id_item(format, &pos, &type_id)) - return NULL; + if (format->types[index] == NULL) + { + pos = format->header.type_ids_off + index * sizeof(type_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + if (!read_dex_type_id_item(format, &addr, &type_id)) + goto gtfdp_error; + pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + if (!read_dex_string_id_item(format, &addr, &str_id)) + goto gtfdp_error; - pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item); + pos = str_id.string_data_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) - return NULL; + if (!read_dex_string_data_item(format, &addr, &str_data)) + goto gtfdp_error; - pos = str_id.string_data_off; + format->types[index] = demangle_type(G_TYPE_DEX_DEMANGLER, (char *)str_data.data); - if (!read_dex_string_data_item(format, &pos, &str_data)) - return NULL; + } + result = format->types[index]; - //printf(">> String :: '%s'\n", str_data.data); + if (result != NULL) + g_object_ref(G_OBJECT(result)); + gtfdp_error: - return demangle_type(DGT_JAVA, (char *)str_data.data); + return result; } - - - /****************************************************************************** * * -* Paramètres : format = représentation interne du format DEX à consulter. * -* index = index de la classe recherchée. * +* Paramètres : format = description de l'exécutable à compléter. * * * -* Description : Extrait une représentation de classe d'une table DEX. * +* Description : Charge en mémoire l'ensemble des champs du format DEX. * * * -* Retour : Composant GLib créé. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index) +bool load_all_dex_fields(GDexFormat *format) { - GDataType *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ - class_def_item class_def; /* Définition de la classe */ - - if (index >= format->header.class_defs_size) - return NULL; + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GBinVariable *field; /* Champ récupéré */ - pos = format->header.class_defs_off + index * sizeof(class_def_item); - - if (!read_dex_class_def_item(format, &pos, &class_def)) - return NULL; + result = true; + format->fields = (GBinVariable **)calloc(format->header.field_ids_size, sizeof(GBinVariable *)); + for (i = 0; i < format->header.field_ids_size && result; i++) + { + field = get_field_from_dex_pool(format, i); - result = NULL; + if (field != NULL) + g_object_unref(G_OBJECT(field)); + else + result = false; + } return result; } - - /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * @@ -218,48 +271,67 @@ GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) +GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) { GBinVariable *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ field_id_item field_id; /* Description du champ */ GDataType *type; /* Type du champ */ const char *name; /* Désignation humaine */ + GBinVariable *field; /* Instance nouvelle à définir */ GDataType *owner; /* Propriétaire du champ */ + result = NULL; + if (index >= format->header.field_ids_size) - return NULL; + goto gffdp_error; - pos = format->header.field_ids_off + index * sizeof(field_id_item); + if (format->fields[index] == NULL) + { + pos = format->header.field_ids_off + index * sizeof(field_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_field_id_item(format, &pos, &field_id)) - return NULL; + if (!read_dex_field_id_item(format, &addr, &field_id)) + goto gffdp_error; - type = get_type_from_dex_pool(format, field_id.type_idx); + type = get_type_from_dex_pool(format, field_id.type_idx); + if (type == NULL) goto gffdp_error; - name = get_string_from_dex_pool(format, field_id.name_idx); - if (name == NULL) goto bad_name; + name = get_string_from_dex_pool(format, field_id.name_idx); + if (name == NULL) goto gffdp_bad_name; - result = g_binary_variable_new(type); - g_binary_variable_set_name(result, name); + field = g_binary_variable_new(type); + g_binary_variable_set_name(field, name); - if (field_id.class_idx != NO_INDEX) - { - owner = get_type_from_dex_pool(format, field_id.class_idx); - if (owner == NULL) goto bad_owner; + if (field_id.class_idx != NO_INDEX) + { + owner = get_type_from_dex_pool(format, field_id.class_idx); + if (owner == NULL) goto gffdp_bad_owner; + + g_binary_variable_set_owner(field, owner); + + } - g_binary_variable_set_owner(result, owner); + format->fields[index] = field; } + result = format->fields[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + gffdp_error: + return result; - bad_owner: + gffdp_bad_owner: g_object_ref(G_OBJECT(type)); g_object_unref(G_OBJECT(result)); - bad_name: + gffdp_bad_name: g_object_unref(G_OBJECT(type)); @@ -270,6 +342,44 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) /****************************************************************************** * * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge tous les prototypes listés dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_prototypes(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GBinRoutine *proto; /* Prototype récupéré */ + + result = true; + + format->prototypes = (GBinRoutine **)calloc(format->header.proto_ids_size, sizeof(GBinRoutine *)); + + for (i = 0; i < format->header.proto_ids_size && result; i++) + { + proto = get_prototype_from_dex_pool(format, i); + + if (proto != NULL) + g_object_unref(G_OBJECT(proto)); + else + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * * index = index de la routine recherchée. * * * @@ -281,114 +391,244 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index) +GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) { GBinRoutine *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ - method_id_item meth_id; /* Description de la méthode */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + proto_id_item proto_id; /* Prototype de routine */ + GDataType *type; /* Type de retour */ + const char *name; /* Description compressée */ + type_list args; /* Liste des arguments */ + uint32_t i; /* Boucle de parcours */ + GBinVariable *arg; /* Argument reconstitué */ + if (index >= format->header.method_ids_size) + goto grfdp_error; - GDataType *type; + if (format->prototypes[index] == NULL) + { + pos = format->header.proto_ids_off + index * sizeof(proto_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - string_id_item str_id; /* Identifiant de chaîne */ - string_data_item str_data; /* Description de chaîne */ + if (!read_dex_proto_id_item(format, &addr, &proto_id)) + goto grfdp_error; + /* Type de retour */ - proto_id_item proto_id; /* Information de prototypage */ - type_list args; /* Liste des arguments */ + type = get_type_from_dex_pool(format, proto_id.return_type_idx); + + /* Nom de la méthode */ + + name = get_string_from_dex_pool(format, proto_id.shorty_idx); + + /* Liste des arguments */ + + pos = proto_id.parameters_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + + if (read_dex_type_list(format, &addr, &args)) + for (i = 0; i < args.size; i++) + { + type = get_type_from_dex_pool(format, args.list[i].type_idx); + if (type == NULL) continue; + + arg = g_binary_variable_new(type); + //g_binary_routine_add_arg(result, arg); + + } + + /* Mise en place finale */ + + format->prototypes[index] = demangle_routine(G_TYPE_DEX_DEMANGLER, name); + +#if 0 + if (format->prototypes[index] != NULL) + g_binary_routine_set_return_type(format->prototypes[index], type); +#endif + + } + + result = format->prototypes[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + grfdp_error: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge toutes les méthodes listées dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_methods(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ uint32_t i; /* Boucle de parcours */ - GBinVariable *arg; /* Argument reconstitué */ + GDexMethod *method; /* Méthode récupérée */ - if (index >= format->header.method_ids_size) - return NULL; + result = true; - pos = format->header.method_ids_off + index * sizeof(method_id_item); + format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *)); - if (!read_dex_method_id_item(format, &pos, &meth_id)) - return NULL; + for (i = 0; i < format->header.method_ids_size && result; i++) + { + method = get_method_from_dex_pool(format, i); + if (method != NULL) + g_object_unref(G_OBJECT(method)); + else + result = false; + } + return result; +} - type = get_type_from_dex_pool(format, meth_id.class_idx); +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la classe recherchée. * +* * +* Description : Extrait une représentation de méthode d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ - /* - if (type == NULL) - printf("class is nil\n"); +GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index) +{ + GDexMethod *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + method_id_item method_id; /* Définition de la méthode */ - else - printf("class = '%s'\n", g_data_type_to_string(type)); - */ + result = NULL; - /* Nom de la méthode */ + if (index >= format->header.method_ids_size) + goto gmfdp_error; - pos = format->header.string_ids_off + meth_id.name_idx * sizeof(string_id_item); + if (format->methods[index] == NULL) + { + pos = format->header.method_ids_off + index * sizeof(method_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) - return NULL; + if (!read_dex_method_id_item(format, &addr, &method_id)) + goto gmfdp_error; - pos = str_id.string_data_off; + format->methods[index] = g_dex_method_new_empty(format, &method_id); - if (!read_dex_string_data_item(format, &pos, &str_data)) - return NULL; + } + result = format->methods[index]; - //printf("String :: '%s'\n", str_data.data); + if (result != NULL) + g_object_ref(G_OBJECT(result)); + gmfdp_error: - result = g_binary_routine_new(); + return result; - g_binary_routine_set_name(result, (char *)str_data.data); +} - if (type != NULL) - g_binary_routine_set_namespace(result, type); +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge toutes les classes listées dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ +bool load_all_dex_classes(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GDexClass *class; /* Classe récupérée */ - /* - printf(" ####\n"); - printf(" #### ROUTINE '%s'\n", g_binary_routine_to_string(result)); - printf(" ####\n"); - printf(" ####\n"); - */ + result = true; - //printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result)); + format->classes = (GDexClass **)calloc(format->header.class_defs_size, sizeof(GDexClass *)); + for (i = 0; i < format->header.class_defs_size && result; i++) + { + class = get_class_from_dex_pool(format, i); + if (class != NULL) + g_object_unref(G_OBJECT(class)); + else + result = false; + } + return result; +} - /* Retour de la routine */ +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la classe recherchée. * +* * +* Description : Extrait une représentation de classe d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ - pos = format->header.proto_ids_off + meth_id.proto_idx * sizeof(proto_id_item); +GDexClass *get_class_from_dex_pool(GDexFormat *format, uint32_t index) +{ + GDexClass *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + class_def_item class_def; /* Définition de la classe */ - if (!read_dex_proto_id_item(format, &pos, &proto_id)) - goto no_more_info; + result = NULL; - type = get_type_from_dex_pool(format, proto_id.return_type_idx); + if (index >= format->header.class_defs_size) + goto gcfdp_error; - g_binary_routine_set_return_type(result, type); + if (format->classes[index] == NULL) + { + pos = format->header.class_defs_off + index * sizeof(class_def_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - /* Arguments de la routine */ + if (!read_dex_class_def_item(format, &addr, &class_def)) + goto gcfdp_error; - pos = proto_id.parameters_off; + format->classes[index] = g_dex_class_new(format, &class_def); - if (read_dex_type_list(format, &pos, &args)) - for (i = 0; i < args.size; i++) - { - type = get_type_from_dex_pool(format, args.list[i].type_idx); - if (type == NULL) continue; + } - arg = g_binary_variable_new(type); - g_binary_routine_add_arg(result, arg); + result = format->classes[index]; - } + if (result != NULL) + g_object_ref(G_OBJECT(result)); - no_more_info: + gcfdp_error: return result; |