From 3284ce333cc4b09d9150b59c60005af8e4ddc417 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 23 Apr 2016 22:23:33 +0200 Subject: Loaded all Dex methods in a proper way. --- ChangeLog | 14 ++++++++++ src/format/dex/class.c | 24 ++++++++++++++++-- src/format/dex/dex-int.h | 1 - src/format/dex/dex.c | 14 +++++----- src/format/dex/method.c | 26 ++++++++++--------- src/format/dex/method.h | 4 +-- src/format/dex/pool.c | 66 +++++++++++------------------------------------- 7 files changed, 75 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd855bc..cfc9c84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +16-04-23 Cyrille Bagard + + * src/format/dex/class.c: + Register all loaded class methods as symbols. + + * src/format/dex/dex-int.h: + * src/format/dex/dex.c: + Update code. + + * src/format/dex/method.c: + * src/format/dex/method.h: + * src/format/dex/pool.c: + Load all Dex methods in a proper way. + 16-04-22 Cyrille Bagard * src/analysis/disass/output.c: diff --git a/src/format/dex/class.c b/src/format/dex/class.c index a5181d2..02ac19d 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -196,6 +196,8 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) uleb128_t index; /* Conservation du dernier id */ uleb128_t i; /* Boucle de parcours */ GDexMethod *method; /* Méthode chargée */ + GBinRoutine *routine; /* Version interne de méthode */ + GBinSymbol *symbol; /* Nouveau symbole construit */ init_vmpa(&addr, def->class_data_off, VMPA_NO_VIRTUAL); @@ -219,11 +221,20 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) for (i = 0; i < data.direct_methods_size; i++) { - method = g_dex_method_new(format, &data.direct_methods[i], &index); + method = g_dex_method_new_defined(format, &data.direct_methods[i], &index); if (method == NULL) goto gdcn_bad_method; result->direct_methods[i] = method; + /* Ajout à la liste des symboles */ + + routine = g_dex_method_get_routine(method); + + symbol = g_binary_symbol_new(STP_ROUTINE); + g_binary_symbol_attach_routine(symbol, routine); + + _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false); + } index = 0; @@ -233,11 +244,20 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) for (i = 0; i < data.virtual_methods_size; i++) { - method = g_dex_method_new(format, &data.virtual_methods[i], &index); + method = g_dex_method_new_defined(format, &data.virtual_methods[i], &index); if (method == NULL) goto gdcn_bad_method; result->virtual_methods[i] = method; + /* Ajout à la liste des symboles */ + + routine = g_dex_method_get_routine(method); + + symbol = g_binary_symbol_new(STP_ROUTINE); + g_binary_symbol_attach_routine(symbol, routine); + + _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false); + } gdcn_done: diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h index a5f39a6..ee43bc8 100755 --- a/src/format/dex/dex-int.h +++ b/src/format/dex/dex-int.h @@ -43,7 +43,6 @@ struct _GDexFormat GDataType **types; /* Types partagés pour Dalvik */ GBinVariable **fields; /* Champs de données partagés */ - GDexMethod **methods; /* Méthodes retrouvées */ GDexClass **classes; /* Classes retrouvées */ }; diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index a918c31..51938f9 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -245,11 +245,14 @@ static void g_dex_format_finalize(GDexFormat *format) GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) { GDexFormat *result; /* Structure à retourner */ + GBinFormat *base; /* Version basique du format */ vmpa2t pos; /* Position de tête de lecture */ result = g_object_new(G_TYPE_DEX_FORMAT, NULL); - g_binary_format_set_content(G_BIN_FORMAT(result), content); + base = G_BIN_FORMAT(result); + + g_binary_format_set_content(base, content); init_vmpa(&pos, 0, VMPA_NO_VIRTUAL); @@ -267,16 +270,15 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) if (!load_all_dex_fields(result)) goto gdfn_error; - if (!load_all_dex_methods(result)) - goto gdfn_error; - if (!load_all_dex_classes(result)) goto gdfn_error; - if (!g_binary_format_complete_loading(G_BIN_FORMAT(result))) + g_binary_format_sort_symbols(base); + + if (!g_binary_format_complete_loading(base)) goto gdfn_error; - return G_BIN_FORMAT(result); + return base; gdfn_error: diff --git a/src/format/dex/method.c b/src/format/dex/method.c index bc4a063..f91af0d 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -24,6 +24,7 @@ #include "method.h" +#include #include @@ -174,12 +175,12 @@ static void g_dex_method_finalize(GDexMethod *method) * * ******************************************************************************/ -GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, uleb128_t *last) +GDexMethod *g_dex_method_new_defined(GDexFormat *format, const encoded_method *seed, uleb128_t *last) { GDexMethod *result; /* Composant à retourner */ vmpa2t addr; /* Tête de lecture générique */ code_item item; /* Corps de la méthode */ - GBinRoutine *routine; /* Routine représentée */ + phys_t ins_offset; /* Position physique du code */ mrange_t range; /* Emplacement du code associé */ init_vmpa(&addr, seed->code_off, VMPA_NO_VIRTUAL); @@ -188,23 +189,24 @@ GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, ule return NULL; *last += seed->method_idx_diff; - routine = get_prototype_from_dex_pool(format, *last); - if (routine == NULL) return NULL; + ins_offset = seed->code_off + offsetof(code_item, insns); - result = g_object_new(G_TYPE_DEX_METHOD, NULL); + if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), ins_offset, &addr)) + return NULL; + + result = get_method_from_dex_pool(format, *last); + + if (result == NULL) + return NULL; result->info = *seed; result->body = item; - result->offset = seed->code_off + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t);/* TODO : faire plus propre ! */ + result->offset = ins_offset; - init_vmpa(&addr, result->offset, VMPA_NO_VIRTUAL); init_mrange(&range, &addr, item.insns_size * sizeof(uint16_t)); - - g_binary_routine_set_range(routine, &range); - - result->routine = routine; + g_binary_routine_set_range(result->routine, &range); return result; @@ -224,7 +226,7 @@ GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, ule * * ******************************************************************************/ -GDexMethod *g_dex_method_new_empty(GDexFormat *format, const method_id_item *method_id) +GDexMethod *g_dex_method_new_callable(GDexFormat *format, const method_id_item *method_id) { GDexMethod *result; /* Composant à retourner */ const char *name; /* Nom de la routine finale */ diff --git a/src/format/dex/method.h b/src/format/dex/method.h index cb85bc6..c7e945d 100644 --- a/src/format/dex/method.h +++ b/src/format/dex/method.h @@ -67,10 +67,10 @@ typedef enum _DexVariableIndex GType g_dex_method_get_type(void); /* Crée une nouvelle représentation de methode issue de code. */ -GDexMethod *g_dex_method_new(GDexFormat *, const encoded_method *, uleb128_t *); +GDexMethod *g_dex_method_new_defined(GDexFormat *, const encoded_method *, uleb128_t *); /* Crée une nouvelle représentation de methode vide. */ -GDexMethod *g_dex_method_new_empty(GDexFormat *, const method_id_item *); +GDexMethod *g_dex_method_new_callable(GDexFormat *, const method_id_item *); /* Fournit les indications Dex concernant la méthode. */ const encoded_method *g_dex_method_get_dex_info(const GDexMethod *); diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c index 056443e..3842aa9 100644 --- a/src/format/dex/pool.c +++ b/src/format/dex/pool.c @@ -443,44 +443,6 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) /****************************************************************************** * * -* 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 */ - GDexMethod *method; /* Méthode récupérée */ - - result = true; - - format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *)); - - 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; - -} - - -/****************************************************************************** -* * * Paramètres : format = représentation interne du format DEX à consulter. * * index = index de la classe recherchée. * * * @@ -504,22 +466,24 @@ GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index) if (index >= format->header.method_ids_size) goto gmfdp_error; - 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_method_id_item(format, &addr, &method_id)) - goto gmfdp_error; - - format->methods[index] = g_dex_method_new_empty(format, &method_id); + /** + * On charge ici une méthode à partir de la définition de 'method_id_item'. + * + * C'est l'élément 'encoded_method' qui référence cette cette définition et qui + * applique ensuite les attributs finaux de la méthode. La classe parente est + * précisée en outre bien en amont. + * + * Comme une même définition peut donc servir à plusieurs instances, + * on ne peut pas conserver un tableau d'allocations communes. + */ - } + pos = format->header.method_ids_off + index * sizeof(method_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - result = format->methods[index]; + if (!read_dex_method_id_item(format, &addr, &method_id)) + goto gmfdp_error; - if (result != NULL) - g_object_ref(G_OBJECT(result)); + result = g_dex_method_new_callable(format, &method_id); gmfdp_error: -- cgit v0.11.2-87-g4458