summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-09-26 18:24:23 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-09-26 18:24:23 (GMT)
commit7972f2da7d0e363fe918992cb5661b17ee3577d7 (patch)
tree6bf42830f32315d01f90c551778b47cc62bba639
parent79f384b20e00977f8450920a8a8983b818d302f8 (diff)
Defined a proper cache for routine names with their packages.
-rw-r--r--ChangeLog15
-rw-r--r--src/analysis/routine.c179
-rw-r--r--src/analysis/routine.h10
-rw-r--r--src/analysis/type.c16
-rw-r--r--src/format/dex/class.c18
-rw-r--r--src/format/symbol.c2
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 <nocbos@gmail.com>
+ * 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 <nocbos@gmail.com>
+
* 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 <nocbos@gmail.com>
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 <assert.h>
#include <malloc.h>
@@ -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: