diff options
Diffstat (limited to 'src/analysis/block.c')
| -rw-r--r-- | src/analysis/block.c | 837 | 
1 files changed, 777 insertions, 60 deletions
| diff --git a/src/analysis/block.c b/src/analysis/block.c index cd3ef94..14b2c0e 100644 --- a/src/analysis/block.c +++ b/src/analysis/block.c @@ -1,6 +1,6 @@  /* Chrysalide - Outil d'analyse de fichiers binaires - * block.c - encadrement des instructions par blocs + * block.h - encadrement des blocs de code   *   * Copyright (C) 2012-2017 Cyrille Bagard   * @@ -24,33 +24,86 @@  #include "block.h" +#include <assert.h> +#include <malloc.h> + +  #include "block-int.h" -/* Initialise la classe des blocs d'instructions. */ -static void g_instr_block_class_init(GInstrBlockClass *); +/* ----------------------------- BLOC DE CODE GENERIQUE ----------------------------- */ + + +/* Initialise la classe des blocs de code. */ +static void g_code_block_class_init(GCodeBlockClass *); -/* Initialise un bloc d'instructions. */ -static void g_instr_block_init(GInstrBlock *); +/* Initialise un bloc de code. */ +static void g_code_block_init(GCodeBlock *);  /* Supprime toutes les références externes. */ -static void g_instr_block_dispose(GInstrBlock *); +static void g_code_block_dispose(GCodeBlock *);  /* Procède à la libération totale de la mémoire. */ -static void g_instr_block_finalize(GInstrBlock *); +static void g_code_block_finalize(GCodeBlock *); + +/* Indique l'indice d'intégration du bloc dans une liste. */ +static void g_code_block_set_index(GCodeBlock *, size_t); + +/* Etablit les liens entre un bloc de code et ses voisins. */ +static void g_code_block_resolve_links(GCodeBlock *, const GBlockList *); + +/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ + + +/* Description d'une liste de blocs de code (instance) */ +struct _GBlockList +{ +    GObject parent;                         /* A laisser en premier        */ + +    GCodeBlock **blocks;                    /* Blocs de code rassemblés    */ +    size_t count;                           /* Quantité de ces blocs       */ + +}; + +/* Description d'une liste de blocs de code (classe) */ +struct _GBlockListClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ -/* Indique le type défini pour un bloc d'instructions. */ -G_DEFINE_TYPE(GInstrBlock, g_instr_block, G_TYPE_OBJECT); +}; + + +/* Initialise la classe des listes de blocs de code. */ +static void g_block_list_class_init(GBlockListClass *); + +/* Initialise une liste de blocs de code. */ +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 *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                               BLOC DE CODE GENERIQUE                               */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un bloc de code. */ +G_DEFINE_TYPE(GCodeBlock, g_code_block, G_TYPE_OBJECT);  /******************************************************************************  *                                                                             *  *  Paramètres  : class = classe à initialiser.                                *  *                                                                             * -*  Description : Initialise la classe des blocs d'instructions.               * +*  Description : Initialise la classe des blocs de code.                      *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -58,14 +111,14 @@ G_DEFINE_TYPE(GInstrBlock, g_instr_block, G_TYPE_OBJECT);  *                                                                             *  ******************************************************************************/ -static void g_instr_block_class_init(GInstrBlockClass *class) +static void g_code_block_class_init(GCodeBlockClass *class)  {      GObjectClass *object;                   /* Autre version de la classe  */      object = G_OBJECT_CLASS(class); -    object->dispose = (GObjectFinalizeFunc/* ! */)g_instr_block_dispose; -    object->finalize = (GObjectFinalizeFunc)g_instr_block_finalize; +    object->dispose = (GObjectFinalizeFunc/* ! */)g_code_block_dispose; +    object->finalize = (GObjectFinalizeFunc)g_code_block_finalize;  } @@ -74,7 +127,7 @@ static void g_instr_block_class_init(GInstrBlockClass *class)  *                                                                             *  *  Paramètres  : block = instance à initialiser.                              *  *                                                                             * -*  Description : Initialise un bloc d'instructions.                           * +*  Description : Initialise un bloc de code.                                  *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -82,8 +135,15 @@ static void g_instr_block_class_init(GInstrBlockClass *class)  *                                                                             *  ******************************************************************************/ -static void g_instr_block_init(GInstrBlock *block) +static void g_code_block_init(GCodeBlock *block)  { +    block->index = (size_t)-1; +    block->rank = (size_t)-1; + +    block->from = NULL; +    block->to = NULL; + +    block->view = NULL;  } @@ -100,12 +160,24 @@ static void g_instr_block_init(GInstrBlock *block)  *                                                                             *  ******************************************************************************/ -static void g_instr_block_dispose(GInstrBlock *block) +static void g_code_block_dispose(GCodeBlock *block)  { -    if (block->links_block != NULL) -        g_object_unref(G_OBJECT(block->links_block)); +#ifndef NDEBUG +    g_code_block_lock_src(block); +    assert(count_flat_array_items(block->from) == 0); +    g_code_block_unlock_src(block); +#endif + +#ifndef NDEBUG +    g_code_block_lock_dest(block); +    assert(count_flat_array_items(block->to) == 0); +    g_code_block_unlock_dest(block); +#endif -    G_OBJECT_CLASS(g_instr_block_parent_class)->dispose(G_OBJECT(block)); +    if (block->view != NULL) +        g_object_unref(G_OBJECT(block->view)); + +    G_OBJECT_CLASS(g_code_block_parent_class)->dispose(G_OBJECT(block));  } @@ -122,62 +194,512 @@ static void g_instr_block_dispose(GInstrBlock *block)  *                                                                             *  ******************************************************************************/ -static void g_instr_block_finalize(GInstrBlock *block) +static void g_code_block_finalize(GCodeBlock *block) +{ +    delete_bit_field(block->domination); + +    G_OBJECT_CLASS(g_code_block_parent_class)->finalize(G_OBJECT(block)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à consulter.                            * +*                                                                             * +*  Description : Indique la liste des blocs de code dominés.                  * +*                                                                             * +*  Retour      : Champ de bits représentant des blocs.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const bitfield_t *g_code_block_get_domination(const GCodeBlock *block) +{ +    return block->domination; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc à mettre à jour.                                * +*                index = indice valide dans la liste d'appartenance.          * +*                                                                             * +*  Description : Indique l'indice d'intégration du bloc dans une liste.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_code_block_set_index(GCodeBlock *block, size_t index) +{ +    assert(block->index == (size_t)-1); + +    block->index = index; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc à consulter.                                    * +*                                                                             * +*  Description : Indique l'indice d'intégration du bloc dans une liste.       * +*                                                                             * +*  Retour      : Indice valide dans une liste.                                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_code_block_get_index(const GCodeBlock *block) +{ +    size_t result;                          /* Indice à retourner          */ + +    assert(block->index != (size_t)-1); + +    result = block->index; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à consulter.                            * +*                addr  = localisation à comparer.                             * +*                                                                             * +*  Description : Détermine si un bloc de code débute à une adresse donnée.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_code_block_is_starting_with(const GCodeBlock *block, const vmpa2t *addr) +{ +    bool result;                            /* Bilan à retourner           */ +    GCodeBlockClass *class;                 /* Classe des blocs de code    */ + +    class = G_CODE_BLOCK_GET_CLASS(block); + +    result = class->is_starting(block, addr); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à mettre à jour.                        * +*                list  = ensemble des blocs de code à disposition.            * +*                                                                             * +*  Description : Etablit les liens entre un bloc de code et ses voisins.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_code_block_resolve_links(GCodeBlock *block, const GBlockList *list) +{ +    GCodeBlockClass *class;                 /* Classe des blocs de code    */ + +    class = G_CODE_BLOCK_GET_CLASS(block); + +    class->link(block, list); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à consulter.                            * +*                                                                             * +*  Description : Fournit le rang du bloc de code dans le flot d'exécution.    * +*                                                                             * +*  Retour      : Indice supérieur ou égal à zéro.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_code_block_get_rank(const GCodeBlock *block) +{ +    size_t result;                          /* Rang à retourner            */ + +    result = block->rank; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à mettre à jour.                        * +*                rank  = indice supérieur à zéro à prendre en compte.         * +*                                                                             * +*  Description : Définit le rang du bloc de code dans le flot d'exécution.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_code_block_set_rank(GCodeBlock *block, size_t rank) +{ +    block->rank = rank; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block       = bloc de code à manipuler.                      * +*                highlighted = gestionnaire de surbrillance pour segments.    * +*                                                                             * +*  Description : Fournit la représentation graphique d'un bloc de code.       * +*                                                                             * +*  Retour      : Vue d'un cache de lignes.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GBufferView *g_code_block_get_view(GCodeBlock *block, segcnt_list *highlighted) +{ +    GBufferView *result;                    /* Instance à retourner        */ +    GCodeBlockClass *class;                 /* Classe des blocs de code    */ + +    if (block->view == NULL) +    { +        class = G_CODE_BLOCK_GET_CLASS(block); + +        block->view = class->build(block, highlighted); + +    } + +    result = block->view; + +    g_object_ref(G_OBJECT(result)); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                     DEFINITION DE LIAISONS ENTRE BLOCS DE CODE                     */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code à mettre à jour.                        * +*                src   = sélection de l'extrémité à traiter.                  * +*                lock  = indique le sens du verrouillage à mener.             * +*                                                                             * +*  Description : Met à disposition un encadrement des accès aux liens.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_code_block_lock_unlock_links(GCodeBlock *block, bool src, bool lock) +{ +    flat_array_t **array;                   /* Choix du tableau ciblé      */ + +    array = (src ? &block->from : &block->to); + +    if (lock) +        lock_flat_array(array); +    else +        unlock_flat_array(array); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc dont les informations sont à consulter.         * +*                dest  = bloc de code visé par la liaison (côté destination). * +*                type  = type de lien à construire.                           * +*                                                                             * +*  Description : Etablit un lien entre deux blocs de code.                    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_code_block_link_with(GCodeBlock *block, GCodeBlock *dest, InstructionLinkType type) +{ +    block_link_t new_src;                   /* Nouveau lien à définir #1   */ +    block_link_t new_dst;                   /* Nouveau lien à définir #2   */ + +    /* Côté destination */ + +    new_src.linked = block; +    new_src.type = type; + +    ref_block_link((&new_src)); + +    /* Côté point de départ */ + +    new_dst.linked = dest; +    new_dst.type = type; + +    ref_block_link((&new_dst)); + +    /* Ajout dans le respect d'une cohérence globale */ + +    g_code_block_lock_src(dest); +    g_code_block_lock_dest(block); + +    add_item_to_flat_array(&dest->from, &new_src, sizeof(block_link_t)); + +    add_item_to_flat_array(&block->to, &new_dst, sizeof(block_link_t)); + +    g_code_block_unlock_dest(block); +    g_code_block_unlock_src(dest); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc de code dont les informations sont à traiter.   * +*                                                                             * +*  Description : Supprime tous les liens établis avec d'autres blocs de code. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_code_block_delete_all_links(GCodeBlock *block)  { -    G_OBJECT_CLASS(g_instr_block_parent_class)->finalize(G_OBJECT(block)); +    block_link_t *link_src;                 /* Lien à supprimer #2         */ +    GCodeBlock *other;                      /* Bloc de l'autre bout        */ +    size_t count;                           /* Quantié de liens présents   */ +    size_t i;                               /* Boucle de parcours          */ +    block_link_t *link_dst;                 /* Lien à supprimer #1         */ + +    /* Coté sources */ + +    g_code_block_lock_src(block); + +    while (count_flat_array_items(block->from) > 0) +    { +        link_src = get_flat_array_item(block->from, 0, sizeof(block_link_t)); + +        other = link_src->linked; + +        g_code_block_lock_dest(other); + +        count = count_flat_array_items(other->to); + +        for (i = 0; i < count; i++) +        { +            link_dst = get_flat_array_item(other->to, i, sizeof(block_link_t)); + +            if (link_dst->linked == block && link_dst->type == link_src->type) +            { +                unref_block_link(link_dst); + +                rem_item_from_flat_array(&other->to, i, sizeof(block_link_t)); + +                break; + +            } + +        } + +        assert(i < count); + +        g_code_block_unlock_dest(other); + +        unref_block_link(link_src); + +        rem_item_from_flat_array(&block->from, 0, sizeof(block_link_t)); + +    } + +    g_code_block_unlock_src(block); + +    /* Coté destinations */ + +    g_code_block_lock_dest(block); + +    while (count_flat_array_items(block->to) > 0) +    { +        link_dst = get_flat_array_item(block->to, 0, sizeof(block_link_t)); + +        other = link_dst->linked; + +        g_code_block_lock_src(other); + +        count = count_flat_array_items(other->from); + +        for (i = 0; i < count; i++) +        { +            link_src = get_flat_array_item(other->from, i, sizeof(block_link_t)); + +            if (link_src->linked == block && link_src->type == link_dst->type) +            { +                unref_block_link(link_src); + +                rem_item_from_flat_array(&other->from, i, sizeof(block_link_t)); + +                break; + +            } + +        } + +        assert(i < count); + +        g_code_block_unlock_src(other); + +        unref_block_link(link_dst); + +        rem_item_from_flat_array(&block->to, 0, sizeof(block_link_t)); + +    } + +    g_code_block_unlock_dest(block);  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = bloc de départ des recherches.                       * -*                addr  = ensemble de blocs à parcourir.                       * -*                final = indique si la cible ou le conteneur est renvoyée.    * +*  Paramètres  : block = bloc dont les informations sont à consulter.         *  *                                                                             * -*  Description : Recherche le bloc contenant une adresse donnée.              * +*  Description : Fournit la quantité de blocs de code pointant vers un autre. *  *                                                                             * -*  Retour      : bloc basique trouvé ou NULL en cas d'échec.                  * +*  Retour      : Nombre de ces origines.                                      *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GInstrBlock *g_instr_block_find_by_addr(const GInstrBlock *block, const vmpa2t *addr, bool final) +size_t g_code_block_count_sources(const GCodeBlock *block)  { -    return G_INSTR_BLOCK_GET_CLASS(block)->find_by_addr(block, addr, final); +    size_t result;                          /* Nombre de liens à renvoyer  */ + +    result = count_flat_array_items(block->from); + +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block    = bloc d'instructions démarrant la visite.          * -*                callback = ensemble de blocs à parcourir.                    * -*                data     = donnée utilisateur à associer au parcours.        * +*  Paramètres  : block = bloc dont les informations sont à consulter.         * +*                index = indice de l'élément à retrouver.                     *  *                                                                             * -*  Description : Parcourt tous les blocs d'instructions dans un ordre donné.  * +*  Description : Fournit les détails d'une origine d'un bloc de code donné.   *  *                                                                             * -*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*  Retour      : Lien déterminé vers un bloc de code d'origine.               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -bool g_instr_block_visit(GInstrBlock *block, instr_block_visitor_cb callback, void *data) +const block_link_t *g_code_block_get_source(GCodeBlock *block, size_t index)  { -    return G_INSTR_BLOCK_GET_CLASS(block)->visit_blocks(block, callback, data); +    block_link_t *result;                   /* Détails présents à renvoyer */ + +    result = get_flat_array_item(block->from, index, sizeof(block_link_t)); + +    ref_block_link(result); + +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = bloc d'instructions à consulter.                     * -*                list  = ensemble de blocs à compléter. [OUT]                 * -*                count = nombre de blocs au total. [OUT]                      * +*  Paramètres  : block = bloc dont les informations sont à consulter.         * +*                                                                             * +*  Description : Donne le nombre de blocs de code suivants dans le flot.      *  *                                                                             * -*  Description : Etablit la liste de tous les blocs présents.                 * +*  Retour      : Nombre de ces destinations.                                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_code_block_count_destinations(const GCodeBlock *block) +{ +    size_t result;                          /* Nombre de liens à renvoyer  */ + +    result = count_flat_array_items(block->to); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc dont les informations sont à consulter.         * +*                index = indice de l'élément à retrouver.                     * +*                                                                             * +*  Description : Fournit les détails d'une destination de bloc de code.       * +*                                                                             * +*  Retour      : Lien déterminé vers un bloc de code de destination.          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const block_link_t *g_code_block_get_destination(GCodeBlock *block, size_t index) +{ +    block_link_t *result;                   /* Détails présents à renvoyer */ + +    result = get_flat_array_item(block->to, index, sizeof(block_link_t)); + +    ref_block_link(result); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                           REGROUPEMENT EN LISTE DE BLOCS                           */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une liste de blocs de code. */ +G_DEFINE_TYPE(GBlockList, g_block_list, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : class = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des listes de blocs de code.            *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -185,20 +707,23 @@ bool g_instr_block_visit(GInstrBlock *block, instr_block_visitor_cb callback, vo  *                                                                             *  ******************************************************************************/ -void g_instr_block_list_all_blocks(const GInstrBlock *block, GInstrBlock ***list, size_t *count) +static void g_block_list_class_init(GBlockListClass *class)  { -    G_INSTR_BLOCK_GET_CLASS(block)->list_blocks(block, list, count); +    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 = bloc d'instructions à consulter.                     * -*                list  = ensemble de blocs à compléter. [OUT]                 * -*                count = nombre de blocs au total. [OUT]                      * +*  Paramètres  : block = instance à initialiser.                              *  *                                                                             * -*  Description : Etablit la liste de tous les blocs terminaux.                * +*  Description : Initialise une liste de blocs de code.                       *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -206,19 +731,19 @@ void g_instr_block_list_all_blocks(const GInstrBlock *block, GInstrBlock ***list  *                                                                             *  ******************************************************************************/ -void g_instr_block_list_leafs_blocks(const GInstrBlock *block, GInstrBlock ***list, size_t *count) +static void g_block_list_init(GBlockList *list)  { -    G_INSTR_BLOCK_GET_CLASS(block)->list_leafs(block, list, count); +    list->blocks = NULL; +    list->count = 0;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = bloc d'instructions à mettre à jour.                 * -*                links = bloc contenant les blocs liés au bloc.               * +*  Paramètres  : block = instance d'objet GLib à traiter.                     *  *                                                                             * -*  Description : Définit l'ensemble contenant les blocs liés.                 * +*  Description : Supprime toutes les références externes.                     *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -226,31 +751,223 @@ void g_instr_block_list_leafs_blocks(const GInstrBlock *block, GInstrBlock ***li  *                                                                             *  ******************************************************************************/ -void g_instr_block_set_links_block(GInstrBlock *block, GInstrBlock *links) +static void g_block_list_dispose(GBlockList *list)  { -    if (block->links_block != NULL) -        g_object_unref(G_OBJECT(block->links_block)); +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < list->count; i++) +        if (list->blocks[i] != NULL) +        { +            g_code_block_delete_all_links(list->blocks[i]); +            g_object_unref(G_OBJECT(list->blocks[i])); +        } -    g_object_ref(G_OBJECT(links)); -    block->links_block = links; +    G_OBJECT_CLASS(g_block_list_parent_class)->dispose(G_OBJECT(list));  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = bloc d'instructions à mettre à jour.                 * +*  Paramètres  : block = instance d'objet GLib à traiter.                     *  *                                                                             * -*  Description : Fournit l'ensemble contenant les blocs liés.                 * +*  Description : Procède à la libération totale de la mémoire.                *  *                                                                             * -*  Retour      : Bloc contenant les blocs liés au bloc.                       * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GInstrBlock *g_instr_block_get_links_block(const GInstrBlock *block) +static void g_block_list_finalize(GBlockList *list)  { -    return block->links_block; +    if (list->blocks != NULL) +        free(list->blocks); + +    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 de code.                             * +*                                                                             * +*  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_BLOCK_LIST, NULL); + +    result->blocks = (GCodeBlock **)calloc(count, sizeof(GCodeBlock *)); + +    result->count = count; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list = liste de blocs de code à consulter.                   * +*                                                                             * +*  Description : Compte le nombre de blocs de code représentés.               * +*                                                                             * +*  Retour      : Quantité de blocs de code rassemblés.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_block_list_count_blocks(const GBlockList *list) +{ +    size_t result;                          /* Quantité à retourner        */ + +    result = list->count; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list  = liste de blocs de code à compléter.                  * +*                block = bloc de code à intégrer.                             * +*                index = indice de la position d'insertion du bloc.           * +*                                                                             * +*  Description : Ajoute un bloc de code à une liste définie.                  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_block_list_add_block(GBlockList *list, GCodeBlock *block, size_t index) +{ +    assert(index < list->count); +    assert(list->blocks[index] == NULL); + +    list->blocks[index] = block; + +    g_code_block_set_index(block, index); + +} + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list = ensemble des blocs de code à traiter.                 * +*                                                                             * +*  Description : Etablit les liens entre les blocs de code et leurs voisins.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_block_list_resolve_links(const GBlockList *list) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < list->count; i++) +        g_code_block_resolve_links(list->blocks[i], list); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list  = liste de blocs de code à consulter.                  * +*                index = indice de la position du bloc recherché.             * +*                                                                             * +*  Description : Fournit le bloc de code correspondant à un indice de liste.  * +*                                                                             * +*  Retour      : Bloc de code trouvé, ou NULL en cas d'erreur.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GCodeBlock *g_block_list_get_block(const GBlockList *list, size_t index) +{ +    GCodeBlock *result;                     /* Bloc de code à retourner    */ + +    assert(index < list->count); + +    if (index < list->count) +        result = list->blocks[index]; +    else +        result = NULL; + +    /** +     * La liste peut être dimensionnée sans avoir été remplie... +     * Donc on fait attention avec le compteur de références. +     */ + +    if (result != NULL) +        g_object_ref(G_OBJECT(result)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : list = liste de blocs de code à consulter.                   * +*                addr = localisation à comparer.                              * +*                                                                             * +*  Description : Recherche un bloc de code débutant à une adresse donnée.     * +*                                                                             * +*  Retour      : Bloc de code trouvé ou NULL si aucun.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GCodeBlock *g_block_list_find_by_starting_instr(const GBlockList *list, const vmpa2t *addr) +{ +    GCodeBlock *result;                     /* Trouvaille à retourner      */ +    size_t i;                               /* Boucle de parcours          */ +    GCodeBlock *block;                      /* Bloc basique analysé        */ + +    result = NULL; + +    for (i = 0; i < list->count && result == NULL; i++) +    { +        block = list->blocks[i]; + +        /** +         * La liste peut être dimensionnée sans avoir été remplie... +         * Donc on fait attention. +         */ + +        assert(block != NULL); + +        if (block == NULL) +            continue; + +        if (g_code_block_is_starting_with(block, addr)) +        { +            result = block; +            g_object_ref(G_OBJECT(result)); +        } + +    } + +    return result;  } | 
