From 7972f2da7d0e363fe918992cb5661b17ee3577d7 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 26 Sep 2016 20:24:23 +0200 Subject: Defined a proper cache for routine names with their packages. --- ChangeLog | 15 ++++- src/analysis/routine.c | 179 +++++++++++++++++++++++++++++++++++++------------ src/analysis/routine.h | 10 +-- src/analysis/type.c | 16 +++-- src/format/dex/class.c | 18 ++++- src/format/symbol.c | 2 +- 6 files changed, 183 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b657fe..7fb2826 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,20 @@ 16-09-26 Cyrille Bagard + * src/analysis/routine.c: + * src/analysis/routine.h: + Define a proper cache for routine names with their packages. Clean the code. + + * src/analysis/type.c: + Build a namespace from types recursively. + + * src/format/dex/class.c: + * src/format/symbol.c: + Update code. + +16-09-26 Cyrille Bagard + * src/analysis/disass/disassembler.c: - Delete code sorting routines as they are already sorted. + Delete code sorting routines as they are already sorted. Clean the code. 16-09-25 Cyrille Bagard diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 559b9bf..7483bf0 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -45,13 +45,16 @@ struct _GBinRoutine GDataType *ret_type; /* Type retourné */ GDataType *namespace; /* Espace de noms / classe */ + const char *ns_sep; /* Séparateur d'éléments */ char *name; /* Désignation humaine */ GDataType *full_name; /* Désignation très complète */ - char *long_name; /* Désignation très complète ??*/ GBinVariable **args; /* Arguments de la routines */ size_t args_count; /* Nombre d'arguments */ + char *cached_decl; /* Cache pour désignation #1 */ + char *cached_full_decl; /* Cache pour désignation #2 */ + GBinVariable **locals; /* Variables locales du code */ size_t locals_count; /* Nombre de variables locales */ @@ -76,6 +79,9 @@ static void g_bin_routine_class_init(GBinRoutineClass *); /* Initialise une instance représentation de routine. */ static void g_bin_routine_init(GBinRoutine *); +/* Vide le cache des descriptions humaines. */ +static void g_binary_routine_reset_declarator(GBinRoutine *, bool); + /* Indique le type définit pour une représentation de routine. */ @@ -102,7 +108,7 @@ static void g_bin_routine_class_init(GBinRoutineClass *klass) /****************************************************************************** * * -* Paramètres : line = instance à initialiser. * +* Paramètres : routine = instance à initialiser. * * * * Description : Initialise une instance représentation de routine. * * * @@ -112,7 +118,7 @@ static void g_bin_routine_class_init(GBinRoutineClass *klass) * * ******************************************************************************/ -static void g_bin_routine_init(GBinRoutine *line) +static void g_bin_routine_init(GBinRoutine *routine) { } @@ -301,6 +307,7 @@ void g_binary_routine_set_type(GBinRoutine *routine, RoutineType type) * * * Paramètres : routine = routine à mettre à jour. * * namespace = instance d'appartenance. * +* sep = séparateur à utiliser entre les éléments. * * * * Description : Définit le groupe d'appartenance d'une routine donnée. * * * @@ -310,9 +317,12 @@ void g_binary_routine_set_type(GBinRoutine *routine, RoutineType type) * * ******************************************************************************/ -void g_binary_routine_set_namespace(GBinRoutine *routine, GDataType *namespace) +void g_binary_routine_set_namespace(GBinRoutine *routine, GDataType *namespace, const char *sep) { routine->namespace = namespace; + routine->ns_sep = sep; + + g_binary_routine_reset_declarator(routine, false); } @@ -356,6 +366,8 @@ void g_binary_routine_set_name(GBinRoutine *routine, char *name) routine->name = name; + g_binary_routine_reset_declarator(routine, true); + } @@ -371,11 +383,8 @@ void g_binary_routine_set_name(GBinRoutine *routine, char *name) * * ******************************************************************************/ -const char *g_binary_routine_get_name(GBinRoutine *routine) +const char *g_binary_routine_get_name(const GBinRoutine *routine) { - if (routine->name == NULL && routine->full_name != NULL) - g_binary_routine_set_name(routine, g_data_type_to_string(routine->full_name)); - return routine->name; } @@ -384,40 +393,6 @@ const char *g_binary_routine_get_name(GBinRoutine *routine) /****************************************************************************** * * * Paramètres : routine = routine à mettre à jour. * -* * -* Description : Fournit le nom long et humain d'une routine. * -* * -* Retour : Désignation humainement lisible ou NULL si non définie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *g_binary_routine_get_long_name(GBinRoutine *routine) -{ - if (routine->long_name == NULL) - { - if (routine->namespace != NULL) - { - routine->long_name = strdup(""); - routine->long_name = g_data_type_to_string(routine->namespace); - routine->long_name = stradd(routine->long_name, "." /* FIXME */); - } - else - routine->long_name = strdup(""); - - routine->long_name = stradd(routine->long_name, g_binary_routine_get_name(routine)); - - } - - return routine->long_name; - -} - - -/****************************************************************************** -* * -* Paramètres : routine = routine à mettre à jour. * * type = désignation complète du nom de la routine. * * * * Description : Définit de façon indirecte le nom humain d'une routine. * @@ -435,6 +410,8 @@ void g_binary_routine_set_name_from_type(GBinRoutine *routine, GDataType *type) routine->full_name = type; + g_binary_routine_reset_declarator(routine, true); + } @@ -599,6 +576,124 @@ void g_binary_routine_remove_arg(GBinRoutine *routine, size_t index) /****************************************************************************** * * * Paramètres : routine = routine à mettre à jour. * +* full = indique la portée de la réinitialisation. * +* * +* Description : Vide le cache des descriptions humaines. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_routine_reset_declarator(GBinRoutine *routine, bool full) +{ + if (full && routine->cached_decl != NULL) + { + free(routine->cached_decl); + routine->cached_decl = NULL; + } + + if (routine->cached_full_decl != NULL) + { + free(routine->cached_full_decl); + routine->cached_full_decl = NULL; + } + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* full = indique si la liste des arguments est à ajouter. * +* * +* Description : Fournit le nom humain d'une routine. * +* * +* Retour : Désignation humainement lisible ou NULL si non définie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_binary_routine_get_declarator(GBinRoutine *routine, bool full) +{ + char *new; /* Nouvelle description */ + char *namespace; /* Groupe d'appartenance */ + size_t i; /* Boucle de parcours */ + char *typestr; /* Stockage de nom temporaire */ + + if (routine->cached_decl == NULL) + { + if (routine->full_name != NULL) + new = _g_data_type_to_string(routine->full_name, false); + else + new = routine->name; + + if (routine->namespace != NULL) + { + namespace = _g_data_type_to_string(routine->namespace, false); + + new = strprep(new, routine->ns_sep); + new = strprep(new, namespace); + + free(namespace); + + } + + /* Mémorisation finale */ + + routine->cached_decl = new; + + } + + if (full && routine->cached_full_decl == NULL) + { + /* Type de retour */ + + if (routine->ret_type == NULL) + new = strdup("??? "); + else + { + new = _g_data_type_to_string(routine->ret_type, true); + if (!g_data_type_is_pointer(routine->ret_type, true)) + new = stradd(new, " "); + } + + /* Nom de la routine */ + + new = stradd(new, routine->cached_decl); + + /* Liste des arguments */ + + new = stradd(new, "("); + + for (i = 0; i < routine->args_count; i++) + { + if (i > 0) new = stradd(new, ", "); + + typestr = g_binary_variable_to_string(routine->args[i], true); + new = stradd(new, typestr); + free(typestr); + + } + + new = stradd(new, ")"); + + /* Mémorisation finale */ + + routine->cached_full_decl = new; + + } + + return (full ? routine->cached_full_decl : routine->cached_decl); + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * * offset = position abstraite à retrouver. * * local = indique le type de variable à manipuler. * * * diff --git a/src/analysis/routine.h b/src/analysis/routine.h index 9ee2c2f..38e7b32 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -113,7 +113,7 @@ void g_binary_routine_set_size(GBinRoutine *, off_t); void g_binary_routine_set_type(GBinRoutine *, RoutineType); /* Définit le groupe d'appartenance d'une routine donnée. */ -void g_binary_routine_set_namespace(GBinRoutine *, GDataType *); +void g_binary_routine_set_namespace(GBinRoutine *, GDataType *, const char *); /* Fournit le groupe d'appartenance d'une routine donnée. */ GDataType *g_binary_routine_get_namespace(const GBinRoutine *); @@ -122,10 +122,7 @@ GDataType *g_binary_routine_get_namespace(const GBinRoutine *); void g_binary_routine_set_name(GBinRoutine *, char *); /* Désignation humainement lisible ou NULL si non définie. */ -const char *g_binary_routine_get_name(GBinRoutine *); - -/* Fournit le nom long et humain d'une routine. */ -const char *g_binary_routine_get_long_name(GBinRoutine *); +const char *g_binary_routine_get_name(const GBinRoutine *); /* Définit de façon indirecte le nom humain d'une routine. */ void g_binary_routine_set_name_from_type(GBinRoutine *, GDataType *); @@ -151,6 +148,9 @@ GBinVariable *g_binary_routine_get_arg(GBinRoutine *, size_t); /* Retire un argument d'une routine. */ void g_binary_routine_remove_arg(GBinRoutine *, size_t); +/* Fournit le nom humain d'une routine. */ +const char *g_binary_routine_get_declarator(GBinRoutine *, bool); + /* S'assure qu'une variable est bien associée à une routine. */ void g_binary_routine_register_if_needed(GBinRoutine *, size_t, bool); diff --git a/src/analysis/type.c b/src/analysis/type.c index 37ad5a1..23ecc2a 100644 --- a/src/analysis/type.c +++ b/src/analysis/type.c @@ -174,20 +174,22 @@ void g_data_type_set_namespace(GDataType *type, GDataType *namespace) char *_g_data_type_to_string(const GDataType *type, bool simple) { char *result; /* Chaîne à retourner */ + const GDataType *parent; /* Espace supérieur */ char *namespace; /* Groupe d'appartenance */ result = type->to_string(type); - if (!simple && type->namespace != NULL) - { - namespace = g_data_type_to_string(type->namespace); + if (!simple) + for (parent = type->namespace; parent != NULL; parent = parent->namespace) + { + namespace = g_data_type_to_string(parent); - result = strprep(result, "." /* FIXME */); - result = strprep(result, namespace); + result = strprep(result, "." /* FIXME */); + result = strprep(result, namespace); - free(namespace); + free(namespace); - } + } if (type->qualifiers & TQF_RESTRICT) result = strprep(result, "restrict "); diff --git a/src/format/dex/class.c b/src/format/dex/class.c index a88f3f2..454cc40 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -24,6 +24,7 @@ #include "class.h" +#include #include @@ -194,6 +195,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) GDexClass *result; /* Composant à retourner */ vmpa2t addr; /* Tête de lecture générique */ class_data_item data; /* Contenu de la classe */ + GDataType *ctype; /* Type créé par la classe */ uleb128_t index; /* Conservation du dernier id */ uleb128_t i; /* Boucle de parcours */ GDexMethod *method; /* Méthode chargée */ @@ -230,6 +232,9 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) */ if (def->access_flags & ACC_ANNOTATION) goto gdcn_done; + ctype = get_type_from_dex_pool(format, def->class_idx); + assert(ctype != NULL); + index = 0; result->dmethods_count = data.direct_methods_size; @@ -246,6 +251,9 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) routine = g_dex_method_get_routine(method); + g_object_ref(G_OBJECT(ctype)); + g_binary_routine_set_namespace(routine, ctype, "."); + symbol = g_binary_symbol_new(STP_ROUTINE); g_binary_symbol_attach_routine(symbol, routine); @@ -269,6 +277,9 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) routine = g_dex_method_get_routine(method); + g_object_ref(G_OBJECT(ctype)); + g_binary_routine_set_namespace(routine, ctype, "."); + symbol = g_binary_symbol_new(STP_ROUTINE); g_binary_symbol_attach_routine(symbol, routine); @@ -276,13 +287,18 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) } + g_object_unref(G_OBJECT(ctype)); + gdcn_done: return result; - gdcn_bad_item: gdcn_bad_method: + g_object_unref(G_OBJECT(ctype)); + + gdcn_bad_item: + g_object_unref(G_OBJECT(result)); return NULL; diff --git a/src/format/symbol.c b/src/format/symbol.c index 2c2e5ad..965487d 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -329,7 +329,7 @@ const char *g_binary_symbol_get_label(const GBinSymbol *symbol) case STP_ROUTINE: case STP_ENTRY_POINT: case STP_CODE_LABEL: - result = g_binary_routine_get_name(symbol->extra.routine); + result = g_binary_routine_get_declarator(symbol->extra.routine, false); break; default: -- cgit v0.11.2-87-g4458