/* 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. * * Chrysalide 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. * * Chrysalide 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 . */ #include "block.h" #include /* ------------------------ 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 */ bitfield_t *domination; /* Blocs dominés de l'ensemble */ }; /* 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) { delete_bit_field(block->domination); 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. * * bits = liste des blocs dominés. * * * * 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, const bitfield_t *bits) { 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)); result->domination = dup_bit_field(bits); 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; } /****************************************************************************** * * * Paramètres : block = bloc d'instructions à consulter. * * * * Description : Indique la liste des blocs de code dominés. * * * * Retour : Champ de bits représentant des blocs. * * * * Remarques : - * * * ******************************************************************************/ const bitfield_t *g_basic_block_get_domination(const GBasicBlock *block) { return block->domination; } /* ---------------------------------------------------------------------------------- */ /* 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(const GBlockList *list, size_t index) { assert(index < list->count); return list->blocks[index]; } /****************************************************************************** * * * Paramètres : list = liste de blocs basiques à consulter. * * block = bloc d'instructions basique à considérer. * * * * Description : Fournit l'indice d'un bloc basique d'une liste de blocs. * * * * Retour : Indice de la position du bloc fourni en cas de succès. * * * * Remarques : - * * * ******************************************************************************/ size_t g_block_list_get_index(const GBlockList *list, GBasicBlock *block) { size_t result; /* Indice trouvé à retourner */ for (result = 0; result < list->count; result++) if (list->blocks[result] == block) break; return result; } /****************************************************************************** * * * 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; }