diff options
Diffstat (limited to 'src/analysis/routine.c')
-rw-r--r-- | src/analysis/routine.c | 580 |
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; + +} |