diff options
Diffstat (limited to 'src/analysis/disass/block.c')
-rw-r--r-- | src/analysis/disass/block.c | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c new file mode 100644 index 0000000..ff780e6 --- /dev/null +++ b/src/analysis/disass/block.c @@ -0,0 +1,546 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * block.c - encadrement des instructions par blocs + * + * Copyright (C) 2012-2013 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 "block.h" + + +#include <assert.h> + + + +/* ------------------------ MISE EN PLACE DES BLOCS BASIQUES ------------------------ */ + + +/* Description d'un bloc basique d'instructions (instance) */ +struct _GBasicBlock +{ + GObject parent; /* A laisser en premier */ + + GArchInstruction *first; /* Première instruction */ + GArchInstruction *last; /* Dernière instruction */ + + unsigned int rank; /* Rang dans l'exécution */ + +}; + +/* Description d'un bloc basique d'instructions (classe) */ +struct _GBasicBlockClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des blocs d'instructions basique. */ +static void g_basic_block_class_init(GBasicBlockClass *); + +/* Initialise un bloc d'instructions basique. */ +static void g_basic_block_init(GBasicBlock *); + +/* Supprime toutes les références externes. */ +static void g_basic_block_dispose(GBasicBlock *); + +/* Procède à la libération totale de la mémoire. */ +static void g_basic_block_finalize(GBasicBlock *); + + + +/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ + + +/* Description d'une liste de blocs basiques (instance) */ +struct _GBlockList +{ + GObject parent; /* A laisser en premier */ + + GBasicBlock **blocks; /* Blocs basiques rassemblés */ + size_t count; /* Quantité de ces blocs */ + +}; + +/* Description d'une liste de blocs basiques (classe) */ +struct _GBlockListClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des listes de blocs basiques. */ +static void g_block_list_class_init(GBlockListClass *); + +/* Initialise une liste de blocs basiques. */ +static void g_block_list_init(GBlockList *); + +/* Supprime toutes les références externes. */ +static void g_block_list_dispose(GBlockList *); + +/* Procède à la libération totale de la mémoire. */ +static void g_block_list_finalize(GBlockList *); + + + +/* ---------------------------------------------------------------------------------- */ +/* MISE EN PLACE DES BLOCS BASIQUES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un bloc d'instructions basique. */ +G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* * +* Description : Initialise la classe des blocs d'instructions basique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_basic_block_class_init(GBasicBlockClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_basic_block_dispose; + object->finalize = (GObjectFinalizeFunc)g_basic_block_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance à initialiser. * +* * +* Description : Initialise un bloc d'instructions basique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_basic_block_init(GBasicBlock *block) +{ + block->rank = -1; + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_basic_block_dispose(GBasicBlock *block) +{ + g_object_ref(G_OBJECT(block->first)); + g_object_ref(G_OBJECT(block->last)); + + G_OBJECT_CLASS(g_basic_block_parent_class)->dispose(G_OBJECT(block)); + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_basic_block_finalize(GBasicBlock *block) +{ + G_OBJECT_CLASS(g_basic_block_parent_class)->finalize(G_OBJECT(block)); + +} + + +/****************************************************************************** +* * +* Paramètres : first = première instruction du bloc. * +* last = dernière instruction du bloc. * +* * +* Description : Crée un bloc basique d'exécution d'instructions. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBasicBlock *g_basic_block_new(GArchInstruction *first, GArchInstruction *last) +{ + GBasicBlock *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BASIC_BLOCK, NULL); + + result->first = first; + result->last = last; + + g_object_ref(G_OBJECT(result->first)); + g_object_ref(G_OBJECT(result->last)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions à consulter. * +* first = instruction de départ du bloc. [OUT] * +* last = dernière instruction du bloc. [OUT] * +* * +* Description : Fournit les instructions limites d'un bloc basique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **first, GArchInstruction **last) +{ + if (first != NULL) + *first = block->first; + + if (last != NULL) + *last = block->last; + +} + + +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions à consulter. * +* start = adresse de départ du bloc. [OUT] * +* end = dernière adresse du bloc. [OUT] * +* * +* Description : Fournit les adresses limites d'un bloc basique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_basic_block_get_boundary_addresses(const GBasicBlock *block, vmpa2t *start, vmpa2t *end) +{ + const mrange_t *range; /* Couverture d'instruction */ + + if (start != NULL) + { + range = g_arch_instruction_get_range(block->first); + copy_vmpa(start, get_mrange_addr(range)); + } + + if (end != NULL) + { + range = g_arch_instruction_get_range(block->last); + copy_vmpa(end, get_mrange_addr(range)); + } + +} + + +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions à consulter. * +* * +* Description : Fournit le rang du bloc basique dans le flot d'exécution. * +* * +* Retour : Indice supérieur ou égal à zéro. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int g_basic_block_get_rank(const GBasicBlock *block) +{ + return block->rank; + +} + + +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions à consulter. * +* rank = Indice supérieur à zéro à prendre en compte. * +* * +* Description : Définit le rang du bloc basique dans le flot d'exécution. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_basic_block_set_rank(GBasicBlock *block, unsigned int rank) +{ + block->rank = rank; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* REGROUPEMENT EN LISTE DE BLOCS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une liste de blocs basiques. */ +G_DEFINE_TYPE(GBlockList, g_block_list, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* * +* Description : Initialise la classe des listes de blocs basiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_block_list_class_init(GBlockListClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_block_list_dispose; + object->finalize = (GObjectFinalizeFunc)g_block_list_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance à initialiser. * +* * +* Description : Initialise une liste de blocs basiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_block_list_init(GBlockList *list) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_block_list_dispose(GBlockList *list) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < list->count; i++) + if (list->blocks[i] != NULL) + g_object_unref(G_OBJECT(list->blocks[i])); + + G_OBJECT_CLASS(g_block_list_parent_class)->dispose(G_OBJECT(list)); + +} + + +/****************************************************************************** +* * +* Paramètres : block = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_block_list_finalize(GBlockList *list) +{ + G_OBJECT_CLASS(g_block_list_parent_class)->finalize(G_OBJECT(list)); + +} + + +/****************************************************************************** +* * +* Paramètres : count = quantité finale de blocs présentie. * +* * +* Description : Crée une liste de blocs basiques. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBlockList *g_block_list_new(size_t count) +{ + GBlockList *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BASIC_BLOCK, NULL); + + result->blocks = (GBasicBlock **)calloc(count, sizeof(GBasicBlock *)); + + result->count = count; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de blocs basiques à consulter. * +* * +* Description : Compte le nombre de blocs basiques représentés. * +* * +* Retour : Quantité de blocs basiques rassemblés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_block_list_count_blocks(const GBlockList *list) +{ + return list->count; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de blocs basiques à compléter. * +* block = bloc d'instructions basique à intégrer. * +* index = indice de la position d'insertion du bloc. * +* * +* Description : Ajoute un bloc basique à une liste définie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_block_list_add_block(GBlockList *list, GBasicBlock *block, size_t index) +{ + assert(index < list->count); + assert(list->blocks[index] == NULL); + + list->blocks[index] = block; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de blocs basiques à consulter. * +* index = indice de la position du bloc recherché. * +* * +* Description : Fournit un bloc basique à d'une liste définie. * +* * +* Retour : Bloc d'instructions basique trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBasicBlock *g_block_list_get_block(GBlockList *list, size_t index) +{ + assert(index < list->count); + + return list->blocks[index]; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de blocs basiques à consulter. * +* instr = instruction de début de bloc recherchée. * +* * +* Description : Recherche un bloc basique selon une première instruction. * +* * +* Retour : Bloc basique trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBasicBlock *g_block_list_find_by_starting_instr(const GBlockList *list, GArchInstruction *instr) +{ + GBasicBlock *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + GBasicBlock *block; /* Bloc basique analysé */ + GArchInstruction *first; /* Première instruction du bloc*/ + + result = NULL; + + for (i = 0; i < list->count && result == NULL; i++) + { + block = list->blocks[i]; + + g_basic_block_get_boundary(block, &first, NULL); + + if (instr == first) + result = block; + + } + + return result; + +} |