From 53213051036151645ae287436ad94dff92c7fa20 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 23 Jul 2018 09:45:44 +0200 Subject: Changed the way Dex methods are loaded and displayed. --- plugins/dalvik/operands/pool.c | 6 +- plugins/dex/dex-int.h | 1 + plugins/dex/format.c | 3 + plugins/dex/method.c | 18 ++++++ plugins/dex/pool.c | 122 ++++++++++++++++++++++++++++++++++------- plugins/dex/pool.h | 3 + 6 files changed, 129 insertions(+), 24 deletions(-) diff --git a/plugins/dalvik/operands/pool.c b/plugins/dalvik/operands/pool.c index 6e4229b..f4fe1fa 100644 --- a/plugins/dalvik/operands/pool.c +++ b/plugins/dalvik/operands/pool.c @@ -377,12 +377,10 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff if (routine != NULL) { - tmp = g_binary_routine_to_string(routine, true); + tmp = g_binary_symbol_get_label(G_BIN_SYMBOL(routine)); g_object_unref(G_OBJECT(routine)); - g_buffer_line_append_text(line, BLC_ASSEMBLY, "<", 1, RTT_HOOK, NULL); - g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_VAR_NAME, G_OBJECT(operand)); - g_buffer_line_append_text(line, BLC_ASSEMBLY, ">", 1, RTT_HOOK, NULL); + g_buffer_line_append_text(line, BLC_ASSEMBLY, tmp, strlen(tmp), RTT_LABEL, G_OBJECT(operand)); } else diff --git a/plugins/dex/dex-int.h b/plugins/dex/dex-int.h index 5180b58..48a920c 100644 --- a/plugins/dex/dex-int.h +++ b/plugins/dex/dex-int.h @@ -44,6 +44,7 @@ struct _GDexFormat GBinSymbol **strings; /* Symboles pour les chaînes */ GDataType **types; /* Types partagés pour Dalvik */ GBinVariable **fields; /* Champs de données partagés */ + GDexMethod **methods; /* Méthodes déclarées */ GDexClass **classes; /* Classes retrouvées */ }; diff --git a/plugins/dex/format.c b/plugins/dex/format.c index af005e6..d354ad0 100644 --- a/plugins/dex/format.c +++ b/plugins/dex/format.c @@ -405,6 +405,9 @@ static bool g_dex_format_analyze(GDexFormat *format, wgroup_id_t gid, GtkStatusS if (!load_all_dex_fields(format, gid, status)) goto gdfa_error; + if (!load_all_dex_methods(format, gid, status)) + goto gdfa_error; + if (!load_all_dex_classes(format, gid, status)) goto gdfa_error; diff --git a/plugins/dex/method.c b/plugins/dex/method.c index 5b7b30e..e5f6273 100644 --- a/plugins/dex/method.c +++ b/plugins/dex/method.c @@ -49,6 +49,10 @@ struct _GDexMethod * en place à partir du constructeur g_dex_method_new_defined(). */ +#ifndef NDEBUG + bool already_defined; /* Vérofication d'unicité */ +#endif + encoded_method info; /* Propriétés de la méthode */ bool has_body; /* Indication de présence */ code_item body; /* Corps de la méthode */ @@ -120,6 +124,9 @@ static void g_dex_method_class_init(GDexMethodClass *class) static void g_dex_method_init(GDexMethod *method) { +#ifndef NDEBUG + method->already_defined = false; +#endif } @@ -197,6 +204,11 @@ GDexMethod *g_dex_method_new_defined(GDexFormat *format, const encoded_method *s if (result == NULL) return NULL; +#ifndef NDEBUG + assert(!result->already_defined); + result->already_defined = true; +#endif + result->info = *seed; result->has_body = (seed->code_off > 0); @@ -253,17 +265,23 @@ GDexMethod *g_dex_method_new_defined(GDexFormat *format, const encoded_method *s GDexMethod *g_dex_method_new_callable(GDexFormat *format, const method_id_item *method_id) { GDexMethod *result; /* Composant à retourner */ + GDataType *ns; /* Espace d'appartenance */ const char *name; /* Nom de la routine finale */ GBinRoutine *routine; /* Routine représentée */ result = NULL; + ns = get_type_from_dex_pool(format, method_id->class_idx); + name = get_string_from_dex_pool(format, method_id->name_idx, NULL); if (name == NULL) goto gdmne_exit; routine = get_prototype_from_dex_pool(format, method_id->proto_idx); if (routine == NULL) goto gdmne_exit; + if (ns != NULL) + g_binary_routine_set_namespace(routine, ns, strdup(".")); + g_binary_routine_set_name(routine, strdup(name)); result = g_object_new(G_TYPE_DEX_METHOD, NULL); diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c index 8a421b2..75841df 100644 --- a/plugins/dex/pool.c +++ b/plugins/dex/pool.c @@ -711,6 +711,93 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) /****************************************************************************** * * +* Paramètres : format = représentation interne du format DEX à compléter. * +* gid = groupe de travail impliqué. * + status = barre de statut à tenir informée. * +* * +* Description : Charge toutes les classes listées dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_methods(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status) +{ + bool result; /* Bilan à retourner */ + guint runs_count; /* Qté d'exécutions parallèles */ + uint32_t run_size; /* Volume réparti par exécution*/ + GWorkQueue *queue; /* Gestionnaire de différés */ + activity_id_t msg; /* Message de progression */ + guint i; /* Boucle de parcours */ + uint32_t begin; /* Début de bloc de traitement */ + uint32_t end; /* Fin d'un bloc de traitement */ + GDexLoading *loading; /* Tâche de chargement à lancer*/ + + /** + * Il existe deux voies pour récupérer une méthode : + * + * - depuis 'method_id_item', qui précise classe d'appartenance, prototype + * et nom. + * + * - depuis 'encoded_method', qui contient une définition 'method_id_item', + * ainsi que des attributs propres à la méthode visée. + * + * Techniquement, il peut donc y avoir plusieurs variations d'un même + * 'method_id_item' selon différents 'encoded_method'. + * + * Dans la pratique, c'est hautement improbable : une méthode ne peut pas + * être privée et publique par exemple, ou renvoyer vers différents code. + * + * Donc on se permet d'associer une unique méthode par 'method_id_item', + * et de précharger le tout. + */ + + result = true; + + /* Préparation du réceptacle */ + + format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *)); + + /* Lancement des chargements */ + + runs_count = get_max_online_threads(); + + run_size = format->header.method_ids_size / runs_count; + + queue = get_work_queue(); + + msg = gtk_status_stack_add_activity(status, _("Loading all methods from the Dex pool..."), + format->header.method_ids_size); + + for (i = 0; i < runs_count; i++) + { + begin = i * run_size; + + if ((i + 1) == runs_count) + end = format->header.method_ids_size; + else + end = begin + run_size; + + loading = g_dex_loading_new(format, begin, end, msg, + (dex_loading_cb)get_method_from_dex_pool, &result); + + g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid); + + } + + g_work_queue_wait_for_completion(queue, gid); + + gtk_status_stack_remove_activity(status, msg); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * * * * Description : Compte le nombre de méthodes dans une table DEX. * @@ -735,7 +822,7 @@ uint32_t count_methods_in_dex_pool(const GDexFormat *format) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * -* index = index de la classe recherchée. * +* index = index de la méthode recherchée. * * * * Description : Extrait une représentation de méthode d'une table DEX. * * * @@ -748,36 +835,31 @@ uint32_t count_methods_in_dex_pool(const GDexFormat *format) GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index) { GDexMethod *result; /* Instance à retourner */ - uint32_t count; /* Nombre d'éléments présents */ 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 */ result = NULL; - count = count_methods_in_dex_pool(format); - - if (index >= count) + if (index >= format->header.method_ids_size) goto gmfdp_error; - /** - * 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. - */ + if (format->methods[index] == NULL) + { + pos = format->header.method_ids_off + index * sizeof(method_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - 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; - if (!read_dex_method_id_item(format, &addr, &method_id)) - goto gmfdp_error; + format->methods[index] = g_dex_method_new_callable(format, &method_id); - result = g_dex_method_new_callable(format, &method_id); + } + + result = format->methods[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); gmfdp_error: diff --git a/plugins/dex/pool.h b/plugins/dex/pool.h index ac7db60..dd27f94 100644 --- a/plugins/dex/pool.h +++ b/plugins/dex/pool.h @@ -71,6 +71,9 @@ uint32_t count_prototypes_in_dex_pool(const GDexFormat *); /* Extrait une représentation de routine d'une table DEX. */ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *, uint32_t); +/* Charge toutes les classes listées dans le contenu binaire. */ +bool load_all_dex_methods(GDexFormat *, wgroup_id_t, GtkStatusStack *); + /* Compte le nombre de méthodes dans une table DEX. */ uint32_t count_methods_in_dex_pool(const GDexFormat *); -- cgit v0.11.2-87-g4458