summaryrefslogtreecommitdiff
path: root/src/analysis/routine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/routine.c')
-rw-r--r--src/analysis/routine.c580
1 files changed, 580 insertions, 0 deletions
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
new file mode 100644
index 0000000..4bbd712
--- /dev/null
+++ b/src/analysis/routine.c
@@ -0,0 +1,580 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * routine.c - manipulation des prototypes de fonctions et de variables
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "routine.h"
+
+
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "../common/extstr.h"
+
+
+
+/* Représentation générique de routine (instance) */
+struct _GBinRoutine
+{
+ GObject parent; /* A laisser en premier */
+
+ vmpa_t addr; /* Position physique/mémoire */
+ off_t size; /* Taille du code associé */
+
+ RoutineType type; /* Type de routine */
+
+ variable *ret_type; /* Type retourné */
+
+ char *name; /* Désignation humaine */
+
+ variable **args_types; /* Types d'arguments */
+ size_t old_args_count; /* Nombre d'arguments */
+
+ GUnknownVariable **args; /* Arguments de la routines */
+ size_t args_count; /* Nombre d'arguments */
+
+ GUnknownVariable **locals; /* Variables locales du code */
+ size_t locals_count; /* Nombre de variables locales */
+
+};
+
+
+/* Représentation générique de routine (classe) */
+struct _GBinRoutineClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des représentation de routine. */
+static void g_bin_routine_class_init(GBinRoutineClass *);
+
+/* Initialise une instance représentation de routine. */
+static void g_bin_routine_init(GBinRoutine *);
+
+
+
+/* Indique le type définit pour une représentation de routine. */
+G_DEFINE_TYPE(GBinRoutine, g_bin_routine, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des représentation de routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bin_routine_class_init(GBinRoutineClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : line = instance à initialiser. *
+* *
+* Description : Initialise une instance représentation de routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bin_routine_init(GBinRoutine *line)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une représentation de routine. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *g_binary_routine_new(void)
+{
+ GBinRoutine *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BIN_ROUTINE, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à effacer. *
+* *
+* Description : Supprime une représentation de routine de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#if 0 /* FIXME */
+void g_binary_routine_finalize(GBinRoutine *routine)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (routine->ret_type)
+ delete_var(routine->ret_type);
+
+ if (routine->name != NULL)
+ free(routine->name);
+
+ for (i = 0; i < routine->old_args_count; i++)
+ delete_var(routine->args_types[i]);
+
+ free(routine);
+
+}
+#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison ascendante entre deux routines. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_binary_routine_compare(const GBinRoutine **a, const GBinRoutine **b)
+{
+ int result; /* Bilan à renvoyer */
+
+ if ((*a)->addr < (*b)->addr) result = -1;
+ else if((*a)->addr > (*b)->addr) result = 1;
+ else result = 0;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison descendante entre deux routines. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_binary_routine_rcompare(const GBinRoutine **a, const GBinRoutine **b)
+{
+ int result; /* Bilan à renvoyer */
+
+ if ((*a)->addr > (*b)->addr) result = -1;
+ else if((*a)->addr < (*b)->addr) result = 1;
+ else result = 0;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* addr = position mémoire ou physique déclarée. *
+* *
+* Description : Définit la position physique / en mémoire d'une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_set_address(GBinRoutine *routine, vmpa_t addr)
+{
+ routine->addr = addr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* *
+* Description : Fournit la position physique / en mémoire d'une routine. *
+* *
+* Retour : Position mémoire ou physique déclarée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+vmpa_t g_binary_routine_get_address(const GBinRoutine *routine)
+{
+ return routine->addr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* addr = taille du code associé. *
+* *
+* Description : Définit la taille du code d'une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_set_size(GBinRoutine *routine, off_t size)
+{
+ routine->size = size;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* *
+* Description : Fournit la taille du code associé à une routine. *
+* *
+* Retour : Taille du code associée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+off_t g_binary_routine_get_size(const GBinRoutine *routine)
+{
+ return routine->size;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* type = type de routine spécifié. *
+* *
+* Description : Définit le type d'une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_set_type(GBinRoutine *routine, RoutineType type)
+{
+ routine->type = type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* name = désignation humainement lisible. *
+* *
+* Description : Définit le nom humain d'une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : Le nom ne doit pas ensuite être libéré par l'appelant ! *
+* *
+******************************************************************************/
+
+void g_binary_routine_set_name(GBinRoutine *routine, char *name)
+{
+ if (routine->name != NULL)
+ free(routine->name);
+
+ routine->name = name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* *
+* 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_name(const GBinRoutine *routine)
+{
+ return routine->name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* var = variable représentant un type de retour. *
+* *
+* Description : Définit le type de retour d'une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_set_return_type(GBinRoutine *routine, variable *var)
+{
+ if (routine->ret_type != NULL)
+ delete_var(routine->ret_type);
+
+ routine->ret_type = var;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* var = variable représentant un argument supplémentaire. *
+* *
+* Description : Ajoute un argument à une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_add_arg(GBinRoutine *routine, variable *var)
+{
+ routine->old_args_count++;
+
+ routine->args_types = (variable **)realloc(routine->args_types,
+ routine->old_args_count * sizeof(variable *));
+
+ routine->args_types[routine->old_args_count - 1] = var;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* offset = position abstraite à retrouver. *
+* local = indique le type de variable à manipuler. *
+* *
+* Description : S'assure qu'une variable est bien associée à une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_routine_register_if_needed(GBinRoutine *routine, size_t offset, bool local)
+{
+ GUnknownVariable ***list; /* Liste à manipuler */
+ size_t *count; /* Taille de la liste */
+ bool found; /* Indication de présence */
+ size_t i; /* Boucle de parcours */
+ GUnknownVariable *new; /* Nouvelle variable à intégrer*/
+
+ if (local)
+ {
+ list = &routine->locals;
+ count = &routine->locals_count;
+ }
+ else
+ {
+ list = &routine->args;
+ count = &routine->args_count;
+ }
+
+ found = false;
+
+ for (i = 0; i < *count && !found; i++)
+ found = g_unknown_variable_contains_offset((*list)[i], offset);
+
+ if (!found)
+ {
+ /* Construction */
+
+ new = g_unknown_variable_new();
+
+ g_unknown_variable_set_offset(new, offset);
+
+ /* Ajout */
+
+ (*list)= (variable **)realloc(*list, ++(*count) * sizeof(GUnknownVariable *));
+ (*list)[*count - 1] = new;
+
+ qsort(*list, *count, sizeof(GUnknownVariable *), g_unknown_variable_compare);
+
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à mettre à jour. *
+* offset = position abstraite à retrouver. *
+* local = indique le type de variable à manipuler. *
+* *
+* Description : Donne l'indice d'une variable dans la liste d'une routine. *
+* *
+* Retour : Indice de la variable dans la liste adaptée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_binary_routine_get_var_index_from_offset(const GBinRoutine *routine, size_t offset, bool local)
+{
+ size_t result; /* Indice à renvoyer */
+ GUnknownVariable ***list; /* Liste à manipuler */
+ size_t *count; /* Taille de la liste */
+ size_t i; /* Boucle de parcours */
+
+ result = SIZE_MAX;
+
+ if (local)
+ {
+ list = &routine->locals;
+ count = &routine->locals_count;
+ }
+ else
+ {
+ list = &routine->args;
+ count = &routine->args_count;
+ }
+
+ for (i = 0; i < *count && result == SIZE_MAX; i++)
+ if (g_unknown_variable_contains_offset((*list)[i], offset))
+ result = i;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine à consulter. *
+* *
+* Description : Décrit le prototype de la routine sous forme de caractères. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_binary_routine_to_string(const GBinRoutine *routine)
+{
+ char *result; /* Chaîne à renvoyer */
+ size_t i; /* Boucle de parcours */
+ char *typestr; /* Stockage de nom temporaire */
+
+ /* Retour de la fonction */
+
+ switch (routine->type)
+ {
+ case RTT_CONSTRUCTOR:
+ result = strdup(routine->name);
+ result = stradd(result, "::");
+ break;
+
+ case RTT_DESTRUCTOR:
+ result = strdup(routine->name);
+ result = stradd(result, "::~");
+ break;
+
+ default: /* Pour gcc */
+ case RTT_CLASSIC:
+ if (routine->ret_type == NULL) result = strdup("??? ");
+ else
+ {
+ result = var_to_string(routine->ret_type);
+ result = stradd(result, " ");
+ }
+ break;
+
+ }
+
+ /* Nom de la routine */
+
+ result = stradd(result, routine->name);
+
+ /* Liste des arguments */
+
+ result = stradd(result, "(");
+
+ for (i = 0; i < routine->old_args_count; i++)
+ {
+ if (i > 0) result = stradd(result, ", ");
+
+ typestr = var_to_string(routine->args_types[i]);
+ result = stradd(result, typestr);
+ free(typestr);
+
+ }
+
+ result = stradd(result, ")");
+
+ return result;
+
+}