diff options
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/binary.c | 6 | ||||
| -rw-r--r-- | src/analysis/block-int.h | 49 | ||||
| -rw-r--r-- | src/analysis/block.c | 837 | ||||
| -rw-r--r-- | src/analysis/block.h | 143 | ||||
| -rw-r--r-- | src/analysis/disass/block.c | 453 | ||||
| -rw-r--r-- | src/analysis/disass/block.h | 57 | ||||
| -rw-r--r-- | src/analysis/disass/disassembler.c | 25 | ||||
| -rw-r--r-- | src/analysis/disass/dragon.c | 10 | ||||
| -rw-r--r-- | src/analysis/disass/dragon.h | 5 | ||||
| -rw-r--r-- | src/analysis/disass/rank.c | 318 | ||||
| -rw-r--r-- | src/analysis/disass/routines.c | 23 | ||||
| -rw-r--r-- | src/analysis/disass/routines.h | 6 | ||||
| -rw-r--r-- | src/analysis/routine.h | 2 | 
13 files changed, 1095 insertions, 839 deletions
| diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 1c6393a..fd0dd3b 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1766,12 +1766,16 @@ static const char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, un  static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *binary, unsigned int index)  {      GtkWidget *result;                      /* Support à retourner         */ +    GBufferCache *cache;                    /* Tampon par défaut           */ +    GBufferView *view;                      /* Vue sur ce même tampon      */      GtkWidget *display;                     /* Composant d'affichage       */      switch (index)      {          case BVW_BLOCK: -            display = gtk_block_display_new(); +            cache = g_loaded_binary_get_disassembled_cache(binary); +            view = g_buffer_view_new(cache, NULL); +            display = gtk_block_display_new(view);              break;          case BVW_GRAPH: diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h index fdf6549..b9b90f0 100644 --- a/src/analysis/block-int.h +++ b/src/analysis/block-int.h @@ -1,6 +1,6 @@  /* Chrysalide - Outil d'analyse de fichiers binaires - * block-int.h - prototypes pour la définition interne des blocs d'instructions + * block-int.h - prototypes pour la définition interne des blocs de code   *   * Copyright (C) 2012-2017 Cyrille Bagard   * @@ -28,49 +28,54 @@  #include "block.h" +#include "../common/array.h" -/* Recherche le bloc contenant une adresse donnée. */ -typedef GInstrBlock * (* find_by_addr_fc) (const GInstrBlock *, const vmpa2t *, bool); -/* Parcourt tous les blocs d'instructions dans un ordre donné. */ -typedef bool (* visit_all_blocks_fc) (GInstrBlock *, instr_block_visitor_cb, void *); -/* Etablit la liste de tous les blocs présents. */ -typedef void (* list_all_blocks_fc) (const GInstrBlock *, GInstrBlock ***, size_t *); +/* ----------------------------- BLOC DE CODE GENERIQUE ----------------------------- */ -/* Etablit la liste de tous les blocs terminaux. */ -typedef void (* list_leafs_blocks_fc) (const GInstrBlock *, GInstrBlock ***, size_t *); +/* Détermine si un bloc de code débute à une adresse donnée. */ +typedef bool (* block_is_starting_fc) (const GCodeBlock *, const vmpa2t *); -/* Fournit les différents accès aux registres. */ -//typedef const reg_access * (* list_regs_accesses_fc) (const GInstrBlock *, size_t *); +/* Etablit les liens entre un bloc de code et ses voisins. */ +typedef void (* block_resolve_links_fc) (GCodeBlock *, const GBlockList *); +/* Fournit la représentation graphique d'un bloc de code. */ +typedef GBufferView * (* block_build_view_fc) (const GCodeBlock *, segcnt_list *); -/* Description d'un bloc d'instructions (instance) */ -struct _GInstrBlock +/* Description d'un bloc de code (instance) */ +struct _GCodeBlock  {      GObject parent;                         /* A laisser en premier        */ -    GInstrBlock *links_block;               /* Lieu des blocs attachés     */ +    bitfield_t *domination;                 /* Blocs dominés de l'ensemble */ + +    size_t index;                           /* Indice dans une liste       */ +    size_t rank;                            /* Rang dans l'exécution       */ + +    flat_array_t *from;                     /* Origines des références     */ +    flat_array_t *to;                       /* Instructions visées         */ + +    GBufferView *view;                      /* Représentation construite   */  }; -/* Description d'un bloc d'instructions (classe) */ -struct _GInstrBlockClass +/* Description d'un bloc de code (classe) */ +struct _GCodeBlockClass  {      GObjectClass parent;                    /* A laisser en premier        */ -    find_by_addr_fc find_by_addr;           /* Recherche par adresse       */ -    visit_all_blocks_fc visit_blocks;       /* Visite des différents blocs */ -    list_all_blocks_fc list_blocks;         /* Liste de tous les blocs     */ -    list_leafs_blocks_fc list_leafs;        /* Liste des blocs terminaux   */ -    //list_regs_accesses_fc list_regs;        /* Liste des accès registres   */ +    block_is_starting_fc is_starting;       /* Analyse d'adresse initiale  */ +    block_resolve_links_fc link;            /* Etablissement des liens     */ +    block_build_view_fc build;              /* Construction d'une vue      */  }; - +/* Détermine si un bloc de code débute à une adresse donnée. */ +bool g_code_block_is_starting_with(const GCodeBlock *, const vmpa2t *); 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;  } diff --git a/src/analysis/block.h b/src/analysis/block.h index 20b018d..9087abf 100644 --- a/src/analysis/block.h +++ b/src/analysis/block.h @@ -1,6 +1,6 @@  /* Chrysalide - Outil d'analyse de fichiers binaires - * block.h - prototypes pour l'encadrement des instructions par blocs + * block.h - prototypes pour l'encadrement des blocs de code   *   * Copyright (C) 2012-2017 Cyrille Bagard   * @@ -30,58 +30,135 @@  #include <stdbool.h> +#include "../arch/instruction.h"  #include "../arch/vmpa.h" +#include "../common/bits.h" +#include "../glibext/gbufferview.h" +#include "../glibext/linesegment.h" -#define G_TYPE_INSTR_BLOCK               g_instr_block_get_type() -#define G_INSTR_BLOCK(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_instr_block_get_type(), GInstrBlock)) -#define G_IS_INSTR_BLOCK(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_instr_block_get_type())) -#define G_INSTR_BLOCK_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_INSTR_BLOCK, GInstrBlockClass)) -#define G_IS_INSTR_BLOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_INSTR_BLOCK)) -#define G_INSTR_BLOCK_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_INSTR_BLOCK, GInstrBlockClass)) +/* ----------------------------- BLOC DE CODE GENERIQUE ----------------------------- */ -/* Description d'un bloc d'instructions (instance) */ -typedef struct _GInstrBlock GInstrBlock; +#define G_TYPE_CODE_BLOCK            g_code_block_get_type() +#define G_CODE_BLOCK(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CODE_BLOCK, GCodeBlock)) +#define G_IS_CODE_BLOCK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CODE_BLOCK)) +#define G_CODE_BLOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CODE_BLOCK, GCodeBlockClass)) +#define G_IS_CODE_BLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CODE_BLOCK)) +#define G_CODE_BLOCK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CODE_BLOCK, GCodeBlockClass)) -/* Description d'un bloc d'instructions (classe) */ -typedef struct _GInstrBlockClass GInstrBlockClass; +/* Description d'un bloc de code (instance) */ +typedef struct _GCodeBlock GCodeBlock; -/* Position au cours d'une visite */ -typedef enum _BlockVisitOrder +/* Description d'un bloc de code (classe) */ +typedef struct _GCodeBlockClass GCodeBlockClass; + + +/* Indique le type défini pour un bloc de code. */ +GType g_code_block_get_type(void); + +/* Indique la liste des blocs de code dominés. */ +const bitfield_t *g_code_block_get_domination(const GCodeBlock *); + +/* Indique l'indice d'intégration du bloc dans une liste. */ +size_t g_code_block_get_index(const GCodeBlock *); + +/* Fournit le rang du bloc de code dans le flot d'exécution. */ +size_t g_code_block_get_rank(const GCodeBlock *); + +/* Définit le rang du bloc de code dans le flot d'exécution. */ +void g_code_block_set_rank(GCodeBlock *, size_t); + +/* Fournit la représentation graphique d'un bloc de code. */ +GBufferView *g_code_block_get_view(GCodeBlock *, segcnt_list *); + + + +/* ------------------- DEFINITION DE LIAISONS ENTRE BLOCS DE CODE ------------------- */ + + +/* Déscription d'une liaison entre deux blocs */ +typedef struct _block_link_t  { -    BVO_IN,                                 /* Entrée dans un gros bloc    */ -    BVO_PENDING,                            /* Visite d'un bloc simple     */ -    BVO_OUT                                 /* Sortie d'un gros bloc       */ +    GCodeBlock *linked;                     /* Autre bloc de code lié      */ +    InstructionLinkType type;               /* Type de liaison             */ + +} block_link_t; + + +#define ref_block_link(l) g_object_ref(G_OBJECT(l->linked)); +#define unref_block_link(l) g_object_unref(G_OBJECT(l->linked)); + + +/* Met à disposition un encadrement des accès aux liens. */ +void g_code_block_lock_unlock_links(GCodeBlock *, bool, bool); + +/* Etablit un lien entre deux blocs de code. */ +void g_code_block_link_with(GCodeBlock *, GCodeBlock *, InstructionLinkType); + +/* Supprime tous les liens établis avec d'autres blocs de code. */ +void g_code_block_delete_all_links(GCodeBlock *block); + +#define g_code_block_lock_src(blk) g_code_block_lock_unlock_links(blk, true, true) +#define g_code_block_unlock_src(blk) g_code_block_lock_unlock_links(blk, true, false) + +/* Fournit la quantité de blocs de code pointant vers un autre. */ +size_t g_code_block_count_sources(const GCodeBlock *); + +/* Fournit les détails d'une origine d'un bloc de code donné. */ +const block_link_t *g_code_block_get_source(GCodeBlock *, size_t); + +#define g_code_block_lock_dest(blk) g_code_block_lock_unlock_links(blk, false, true) +#define g_code_block_unlock_dest(blk) g_code_block_lock_unlock_links(blk, false, false) + +/* Donne le nombre de blocs de code suivants dans le flot. */ +size_t g_code_block_count_destinations(const GCodeBlock *); + +/* Fournit les détails d'une destination de bloc de code. */ +const block_link_t *g_code_block_get_destination(GCodeBlock *, size_t); + + + +/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ + + +#define G_TYPE_BLOCK_LIST            g_block_list_get_type() +#define G_BLOCK_LIST(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BLOCK_LIST, GBlockList)) +#define G_IS_BLOCK_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BLOCK_LIST)) +#define G_BLOCK_LIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BLOCK_LIST, GBlockListClass)) +#define G_IS_BLOCK_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BLOCK_LIST)) +#define G_BLOCK_LIST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BLOCK_LIST, GBlockListClass)) + -} BlockVisitOrder; +/* Description d'une liste de blocs de code (instance) */ +typedef struct _GBlockList GBlockList; -/* Rappel à chaque bloc visité */ -typedef bool (* instr_block_visitor_cb) (GInstrBlock *, BlockVisitOrder, void *); +/* Description d'une liste de blocs de code (classe) */ +typedef struct _GBlockListClass GBlockListClass; -/* Indique le type défini pour un bloc d'instructions. */ -GType g_instr_block_get_type(void); +/* Indique le type défini pour une liste de blocs de code. */ +GType g_block_list_get_type(void); -/* Recherche le bloc contenant une adresse donnée. */ -GInstrBlock *g_instr_block_find_by_addr(const GInstrBlock *, const vmpa2t *, bool); +/* Crée une liste de blocs de code. */ +GBlockList *g_block_list_new(size_t); -/* Parcourt tous les blocs d'instructions dans un ordre donné. */ -bool g_instr_block_visit(GInstrBlock *, instr_block_visitor_cb, void *); +/* Compte le nombre de blocs de code représentés. */ +size_t g_block_list_count_blocks(const GBlockList *); -/* Etablit la liste de tous les blocs présents. */ -void g_instr_block_list_all_blocks(const GInstrBlock *, GInstrBlock ***, size_t *); +/* Ajoute un bloc de code à une liste définie. */ +void g_block_list_add_block(GBlockList *, GCodeBlock *, size_t); -/* Etablit la liste de tous les blocs terminaux. */ -void g_instr_block_list_leafs_blocks(const GInstrBlock *, GInstrBlock ***, size_t *); +/* Etablit les liens entre les blocs de code et leurs voisins. */ +void g_block_list_resolve_links(const GBlockList *); -/* Définit l'ensemble contenant les blocs liés. */ -void g_instr_block_set_links_block(GInstrBlock *, GInstrBlock *); +/* Fournit le bloc de code correspondant à un indice de liste. */ +GCodeBlock *g_block_list_get_block(const GBlockList *, size_t); -/* Fournit l'ensemble contenant les blocs liés. */ -GInstrBlock *g_instr_block_get_links_block(const GInstrBlock *); +/* Recherche un bloc de code débutant à une adresse donnée. */ +GCodeBlock *g_block_list_find_by_starting_instr(const GBlockList *, const vmpa2t *); diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c index 2d01d5d..5c97358 100644 --- a/src/analysis/disass/block.c +++ b/src/analysis/disass/block.c @@ -27,6 +27,10 @@  #include <assert.h> +#include "../block-int.h" +#include "../../glibext/gbinarycursor.h" + +  /* ------------------------ MISE EN PLACE DES BLOCS BASIQUES ------------------------ */ @@ -34,21 +38,19 @@  /* Description d'un bloc basique d'instructions (instance) */  struct _GBasicBlock  { -    GObject parent;                         /* A laisser en premier        */ +    GCodeBlock parent;                      /* A laisser en premier        */ + +    GLoadedBinary *binary;                  /* Binaire chargé et associé   */      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        */ +    GCodeBlockClass parent;                 /* A laisser en premier        */  }; @@ -65,40 +67,14 @@ static void g_basic_block_dispose(GBasicBlock *);  /* Procède à la libération totale de la mémoire. */  static void g_basic_block_finalize(GBasicBlock *); +/* Détermine si un bloc de code débute à une adresse donnée. */ +static bool g_basic_block_is_starting_with(const GBasicBlock *, const vmpa2t *); +/* Etablit les liens entre un bloc de code et ses voisins. */ +static void g_basic_block_resolve_links(GBasicBlock *, const GBlockList *); -/* ------------------------- 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 *); +/* Fournit la représentation graphique d'un bloc de code. */ +static GBufferView *g_basic_block_build_view(const GBasicBlock *, segcnt_list *); @@ -108,7 +84,7 @@ static void g_block_list_finalize(GBlockList *);  /* Indique le type défini pour un bloc d'instructions basique. */ -G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_OBJECT); +G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_CODE_BLOCK);  /****************************************************************************** @@ -126,12 +102,19 @@ G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_OBJECT);  static void g_basic_block_class_init(GBasicBlockClass *class)  {      GObjectClass *object;                   /* Autre version de la classe  */ +    GCodeBlockClass *block;                 /* Version parente de la classe*/      object = G_OBJECT_CLASS(class);      object->dispose = (GObjectFinalizeFunc/* ! */)g_basic_block_dispose;      object->finalize = (GObjectFinalizeFunc)g_basic_block_finalize; +    block = G_CODE_BLOCK_CLASS(class); + +    block->is_starting = (block_is_starting_fc)g_basic_block_is_starting_with; +    block->link = (block_resolve_links_fc)g_basic_block_resolve_links; +    block->build = (block_build_view_fc)g_basic_block_build_view; +  } @@ -149,7 +132,6 @@ static void g_basic_block_class_init(GBasicBlockClass *class)  static void g_basic_block_init(GBasicBlock *block)  { -    block->rank = -1;  } @@ -168,8 +150,10 @@ static void g_basic_block_init(GBasicBlock *block)  static void g_basic_block_dispose(GBasicBlock *block)  { -    g_object_ref(G_OBJECT(block->first)); -    g_object_ref(G_OBJECT(block->last)); +    g_object_unref(G_OBJECT(block->binary)); + +    g_object_unref(G_OBJECT(block->first)); +    g_object_unref(G_OBJECT(block->last));      G_OBJECT_CLASS(g_basic_block_parent_class)->dispose(G_OBJECT(block)); @@ -190,8 +174,6 @@ static void g_basic_block_dispose(GBasicBlock *block)  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));  } @@ -199,9 +181,10 @@ static void g_basic_block_finalize(GBasicBlock *block)  /******************************************************************************  *                                                                             * -*  Paramètres  : first = première instruction du bloc.                        * -*                last  = dernière instruction du bloc.                        * -*                bits  = liste des blocs dominés.                             * +*  Paramètres  : binary = binaire chargé contenant les instructions.          * +*                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.             *  *                                                                             * @@ -211,57 +194,37 @@ static void g_basic_block_finalize(GBasicBlock *block)  *                                                                             *  ******************************************************************************/ -GBasicBlock *g_basic_block_new(GArchInstruction *first, GArchInstruction *last, const bitfield_t *bits) +GCodeBlock *g_basic_block_new(GLoadedBinary *binary, GArchInstruction *first, GArchInstruction *last, const bitfield_t *bits)  { -    GBasicBlock *result;                     /* Structure à retourner       */ +    GBasicBlock *result;                    /* Structure à retourner       */ +    GCodeBlock *parent;                     /* Version parente d'instance  */      result = g_object_new(G_TYPE_BASIC_BLOCK, NULL); +    result->binary = binary; +    g_object_ref(G_OBJECT(binary)); +      result->first = first;      result->last = last; -    g_object_ref(G_OBJECT(result->first)); -    g_object_ref(G_OBJECT(result->last)); +    g_object_ref(G_OBJECT(first)); +    g_object_ref(G_OBJECT(last)); -    result->domination = dup_bit_field(bits); +    parent = G_CODE_BLOCK(result); -    return result; - -} +    parent->domination = dup_bit_field(bits); - -/****************************************************************************** -*                                                                             * -*  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; +    return parent;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = bloc d'instructions à consulter.                     * -*                start = adresse de départ du bloc. [OUT]                     * -*                end   = dernière adresse du bloc. [OUT]                      * +*  Paramètres  : block = bloc de code à consulter.                            * +*                addr  = localisation à comparer.                             *  *                                                                             * -*  Description : Fournit les adresses limites d'un bloc basique.              * +*  Description : Détermine si un bloc de code débute à une adresse donnée.    *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -269,140 +232,26 @@ void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **fir  *                                                                             *  ******************************************************************************/ -void g_basic_block_get_boundary_addresses(const GBasicBlock *block, vmpa2t *start, vmpa2t *end) +static bool g_basic_block_is_starting_with(const GBasicBlock *block, const vmpa2t *addr)  { +    bool result;                            /* Bilan à retourner           */      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)); -    } +    range = g_arch_instruction_get_range(block->first); -    if (end != NULL) -    { -        range = g_arch_instruction_get_range(block->last); -        copy_vmpa(end, get_mrange_addr(range)); -    } +    result = (cmp_vmpa(addr, get_mrange_addr(range)) == 0); -} - - -/****************************************************************************** -*                                                                             * -*  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) -{ +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : block = instance d'objet GLib à traiter.                     * +*  Paramètres  : block = bloc de code à mettre à jour.                        * +*                list  = ensemble des blocs de code à disposition.            *  *                                                                             * -*  Description : Supprime toutes les références externes.                     * +*  Description : Etablit les liens entre un bloc de code et ses voisins.      *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -410,150 +259,87 @@ static void g_block_list_init(GBlockList *list)  *                                                                             *  ******************************************************************************/ -static void g_block_list_dispose(GBlockList *list) +static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *list)  { +    size_t dcount;                          /* Nombre de liens de dest.    */      size_t i;                               /* Boucle de parcours          */ +    const instr_link_t *dest;               /* Instr. visée par une autre  */ +    const mrange_t *range;                  /* Couverture d'instruction    */ +    GCodeBlock *target;                     /* Bloc ciblé par un lien      */ -    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; - -} +    g_arch_instruction_lock_dest(block->last); +    dcount = g_arch_instruction_count_destinations(block->last); +    for (i = 0; i < dcount; i++) +    { +        dest = g_arch_instruction_get_destination(block->last, i); -/****************************************************************************** -*                                                                             * -*  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   : -                                                            * -*                                                                             * -******************************************************************************/ +        range = g_arch_instruction_get_range(dest->linked); -size_t g_block_list_count_blocks(const GBlockList *list) -{ -    return list->count; +        target = g_block_list_find_by_starting_instr(list, get_mrange_addr(range)); -} +        /** +         * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. +         * Par exemple sous ARM : +         * +         *    00008358 <call_gmon_start>: +         *        .... +         *        8362:       f7ff bfcf       b.w     8304 <_init+0x38> +         *        .... +         * +         */ +        if (target != NULL) +        { +            g_code_block_link_with(G_CODE_BLOCK(block), target, dest->type); +            g_object_unref(G_OBJECT(target)); +        } -/****************************************************************************** -*                                                                             * -*  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   : -                                                            * -*                                                                             * -******************************************************************************/ +        unref_instr_link(dest); -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; +    g_arch_instruction_unlock_dest(block->last);  }  /******************************************************************************  *                                                                             * -*  Paramètres  : list  = liste de blocs basiques à consulter.                 * -*                index = indice de la position du bloc recherché.             * +*  Paramètres  : block       = bloc de code à manipuler.                      * +*                highlighted = gestionnaire de surbrillance pour segments.    *  *                                                                             * -*  Description : Fournit un bloc basique à d'une liste définie.               * +*  Description : Fournit la représentation graphique d'un bloc de code.       *  *                                                                             * -*  Retour      : Bloc d'instructions basique trouvé.                          * +*  Retour      : Vue d'un cache de lignes.                                    *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GBasicBlock *g_block_list_get_block(const GBlockList *list, size_t index) +static GBufferView *g_basic_block_build_view(const GBasicBlock *block, segcnt_list *highlighted)  { -    assert(index < list->count); +    GBufferView *result;                    /* Instance à retourner        */ +    const mrange_t *first_range;            /* Couverture d'instruction #1 */ +    const mrange_t *last_range;             /* Couverture d'instruction #2 */ +    GLineCursor *start;                     /* Départ de zone couverture   */ +    GLineCursor *end;                       /* Fin de zone couverture      */ +    GBufferCache *cache;                    /* Tampon brut à découper      */ -    return list->blocks[index]; +    first_range = g_arch_instruction_get_range(block->first); +    last_range = g_arch_instruction_get_range(block->last); -} +    start = g_binary_cursor_new(); +    g_binary_cursor_update(G_BINARY_CURSOR(start), get_mrange_addr(first_range)); +    end = g_binary_cursor_new(); +    g_binary_cursor_update(G_BINARY_CURSOR(end), get_mrange_addr(last_range)); -/****************************************************************************** -*                                                                             * -*  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   : -                                                            * -*                                                                             * -******************************************************************************/ +    cache = g_loaded_binary_get_disassembled_cache(block->binary); -size_t g_block_list_get_index(const GBlockList *list, GBasicBlock *block) -{ -    size_t result;                          /* Indice trouvé à retourner   */ +    result = g_buffer_view_new(cache, highlighted); -    for (result = 0; result < list->count; result++) -        if (list->blocks[result] == block) -            break; +    g_buffer_view_restrict(result, start, end);      return result; @@ -562,37 +348,30 @@ size_t g_block_list_get_index(const GBlockList *list, GBasicBlock *block)  /******************************************************************************  *                                                                             * -*  Paramètres  : list  = liste de blocs basiques à consulter.                 * -*                instr = instruction de début de bloc recherchée.             * +*  Paramètres  : block = bloc d'instructions à consulter.                     * +*                first = instruction de départ du bloc. [OUT]                 * +*                last  = dernière instruction du bloc. [OUT]                  *  *                                                                             * -*  Description : Recherche un bloc basique selon une première instruction.    * +*  Description : Fournit les instructions limites d'un bloc basique.          *  *                                                                             * -*  Retour      : Bloc basique trouvé ou NULL si aucun.                        * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GBasicBlock *g_block_list_find_by_starting_instr(const GBlockList *list, GArchInstruction *instr) +void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **first, GArchInstruction **last)  { -    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++) +    if (first != NULL)      { -        block = list->blocks[i]; - -        g_basic_block_get_boundary(block, &first, NULL); - -        if (instr == first) -            result = block; - +        *first = block->first; +        g_object_ref(G_OBJECT(*first));      } -    return result; +    if (last != NULL) +    { +        *last = block->last; +        g_object_ref(G_OBJECT(*last)); +    }  } diff --git a/src/analysis/disass/block.h b/src/analysis/disass/block.h index 68cade7..eab0b27 100644 --- a/src/analysis/disass/block.h +++ b/src/analysis/disass/block.h @@ -28,6 +28,8 @@  #include <glib-object.h> +#include "../binary.h" +#include "../block.h"  #include "../../arch/instruction.h"  #include "../../common/bits.h" @@ -55,64 +57,11 @@ typedef struct _GBasicBlockClass GBasicBlockClass;  GType g_basic_block_get_type(void);  /* Crée un bloc basique d'exécution d'instructions. */ -GBasicBlock *g_basic_block_new(GArchInstruction *, GArchInstruction *, const bitfield_t *); +GCodeBlock *g_basic_block_new(GLoadedBinary *, GArchInstruction *, GArchInstruction *, const bitfield_t *);  /* Fournit les instructions limites d'un bloc basique. */  void g_basic_block_get_boundary(const GBasicBlock *, GArchInstruction **, GArchInstruction **); -/* Fournit les adresses limites d'un bloc basique. */ -void g_basic_block_get_boundary_addresses(const GBasicBlock *, vmpa2t *, vmpa2t *); - -/* Fournit le rang du bloc basique dans le flot d'exécution. */ -unsigned int g_basic_block_get_rank(const GBasicBlock *); - -/* Définit le rang du bloc basique dans le flot d'exécution. */ -void g_basic_block_set_rank(GBasicBlock *, unsigned int); - -/* Indique la liste des blocs de code dominés. */ -const bitfield_t *g_basic_block_get_domination(const GBasicBlock *); - - - -/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ - - -#define G_TYPE_BLOCK_LIST               g_block_list_get_type() -#define G_BLOCK_LIST(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_block_list_get_type(), GBlockList)) -#define G_IS_BLOCK_LIST(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_block_list_get_type())) -#define G_BLOCK_LIST_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BLOCK_LIST, GBlockListClass)) -#define G_IS_BLOCK_LIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BLOCK_LIST)) -#define G_BLOCK_LIST_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BLOCK_LIST, GBlockListClass)) - - -/* Description d'une liste de blocs basiques (instance) */ -typedef struct _GBlockList GBlockList; - -/* Description d'une liste de blocs basiques (classe) */ -typedef struct _GBlockListClass GBlockListClass; - - -/* Indique le type défini pour une liste de blocs basiques. */ -GType g_block_list_get_type(void); - -/* Crée une liste de blocs basiques. */ -GBlockList *g_block_list_new(size_t); - -/* Compte le nombre de blocs basiques représentés. */ -size_t g_block_list_count_blocks(const GBlockList *); - -/* Ajoute un bloc basique à une liste définie. */ -void g_block_list_add_block(GBlockList *, GBasicBlock *, size_t); - -/* Fournit un bloc basique à d'une liste définie. */ -GBasicBlock *g_block_list_get_block(const GBlockList *, size_t ); - -/* Fournit l'indice d'un bloc basique d'une liste de blocs. */ -size_t g_block_list_get_index(const GBlockList *, GBasicBlock *); - -/* Recherche un bloc basique selon une première instruction. */ -GBasicBlock *g_block_list_find_by_starting_instr(const GBlockList *, GArchInstruction *); -  #endif  /* _ANALYSIS_DISASS_BLOCK_H */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 6e71ed6..f229af3 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -52,7 +52,7 @@  static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *);  /* Opère sur toutes les routines. */ -static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GBinFormat *); +static void process_all_routines(GLoadedBinary *, wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb);  /* Réalise un désassemblage effectif. */  static void compute_disassembly(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *); @@ -127,12 +127,11 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co  /******************************************************************************  *                                                                             * -*  Paramètres  : gid      = groupe de travail impliqué.                       * +*  Paramètres  : binary   = binaire chargé comprenant les routines à traiter. * +*                gid      = groupe de travail impliqué.                       *                   status   = barre de statut à tenir informée.                 *  *                msg      = message à faire paraître pour la patience.        *  *                fallback = routine de traitements particuliers.              * -*                proc     = ensemble d'instructions désassemblées.            * -*                format   = accès aux données du binaire d'origine.           *  *                                                                             *  *  Description : Opère sur toutes les routines.                               *  *                                                                             * @@ -142,8 +141,9 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co  *                                                                             *  ******************************************************************************/ -static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GBinFormat *format) +static void process_all_routines(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback)  { +    GBinFormat *format;                     /* Format associé au binaire   */      GBinPortion *portions;                  /* Couche première de portions */      size_t sym_count;                       /* Nombre de ces symboles      */      guint runs_count;                       /* Qté d'exécutions parallèles */ @@ -155,6 +155,8 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const      size_t end;                             /* Fin d'un bloc de traitement */      GRoutinesStudy *study;                  /* Tâche d'étude à programmer  */ +    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); +      portions = g_exe_format_get_portions(G_EXE_FORMAT(format));      g_binary_format_lock_symbols_rd(format); @@ -178,8 +180,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const          else              end = begin + run_size; -        study = g_routines_study_new(proc, format, portions, -                                     begin, end, id, fallback); +        study = g_routines_study_new(binary, portions, begin, end, id, fallback);          g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); @@ -193,6 +194,8 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const      g_object_unref(G_OBJECT(portions)); +    g_object_unref(G_OBJECT(format)); +  } @@ -293,9 +296,9 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg       * Quatrième étape : établissement des couvertures de routines restantes.       */ -    process_all_routines(gid, status, +    process_all_routines(binary, gid, status,                           _("Finding remaining limits..."), -                         g_routines_study_compute_limits, proc, G_BIN_FORMAT(format)); +                         g_routines_study_compute_limits);      process_disassembly_event(PGA_DISASSEMBLY_LIMITED, binary, status, context); @@ -317,9 +320,9 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg       * Sixième étape : regroupement en blocs basiques.       */ -    process_all_routines(gid, status, +    process_all_routines(binary, gid, status,                           _("Control-flow analysis for routines..."), -                         g_routines_study_handle_blocks, proc, G_BIN_FORMAT(format)); +                         g_routines_study_handle_blocks);      process_disassembly_event(PGA_DISASSEMBLY_GROUPED, binary, status, context); diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c index 04f5190..ad20b24 100644 --- a/src/analysis/disass/dragon.c +++ b/src/analysis/disass/dragon.c @@ -28,6 +28,9 @@  #include <malloc.h> +#include "block.h" + +  /* ---------------------------- ENCAPSULATION DES NOEUDS ---------------------------- */ @@ -801,6 +804,7 @@ dragon_node *find_knight_node_for_instruction(const dragon_knight *knight, bool  /******************************************************************************  *                                                                             *  *  Paramètres  : knight = rassemblement des complexités de code.              * +*                binary = binaire contenant l'ensemble des instructions.      *  *                                                                             *  *  Description : Traduit une complexité de noeuds en liste de blocs basiques. *  *                                                                             * @@ -810,7 +814,7 @@ dragon_node *find_knight_node_for_instruction(const dragon_knight *knight, bool  *                                                                             *  ******************************************************************************/ -GBlockList *translate_dragon_knight(const dragon_knight *knight) +GBlockList *translate_dragon_knight(const dragon_knight *knight, GLoadedBinary *binary)  {      GBlockList *result;                     /* Liste à retourner           */      dragon_node *nodes;                     /* Liste des noeuds détectés   */ @@ -819,7 +823,7 @@ GBlockList *translate_dragon_knight(const dragon_knight *knight)      dragon_node *node;                      /* Noeud à traiter             */      GArchInstruction *first;                /* Première instruction        */      GArchInstruction *last;                 /* Dernière instruction        */ -    GBasicBlock *block;                     /* Nouveau bloc basique        */ +    GCodeBlock *block;                      /* Nouveau bloc basique        */      get_dragon_knight_content(knight, &nodes, &count); @@ -831,7 +835,7 @@ GBlockList *translate_dragon_knight(const dragon_knight *knight)          get_dragon_node_bounding_instructions(node, &first, &last); -        block = g_basic_block_new(first, last, node->bits); +        block = g_basic_block_new(binary, first, last, node->bits);          g_block_list_add_block(result, block, i); diff --git a/src/analysis/disass/dragon.h b/src/analysis/disass/dragon.h index dfef39f..584f43a 100644 --- a/src/analysis/disass/dragon.h +++ b/src/analysis/disass/dragon.h @@ -25,7 +25,8 @@  #define _ANALYSIS_DISASS_DRAGON_H -#include "block.h" +#include "../binary.h" +#include "../block.h"  #include "../../arch/processor.h"  #include "../../common/bits.h" @@ -90,7 +91,7 @@ size_t get_dragon_knight_node_index(const dragon_knight *, dragon_node *);  dragon_node *find_knight_node_for_instruction(const dragon_knight *, bool, const GArchInstruction *);  /* Traduit une complexité de noeuds en liste de blocs basiques. */ -GBlockList *translate_dragon_knight(const dragon_knight *); +GBlockList *translate_dragon_knight(const dragon_knight *, GLoadedBinary *); diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c index 6e737a5..b4a8f92 100644 --- a/src/analysis/disass/rank.c +++ b/src/analysis/disass/rank.c @@ -24,270 +24,12 @@  #include "rank.h" - - -#if 0 - -#include <assert.h> -#include <sys/param.h> - - -#include "../blocks/flow.h" -#include "../blocks/virtual.h" - - - -/* Classe le contenu d'un bloc d'instructions exécutées. */ -static bool rank_flow_block(GFlowBlock *, BlockVisitOrder, const GInstrBlock *); - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = bloc d'instructions concerné par la visite.          * -*                order = indication quant au sens de visite.                  * -*                list  = ensemble des blocs basiques à parcourir.             * -*                                                                             * -*  Description : Classe le contenu d'un bloc d'instructions exécutées.        * -*                                                                             * -*  Retour      : true pour continuer la visite.                               * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GInstrBlock *list) -{ -    unsigned int next;                      /* Rang suivant obtenu         */ -    GInstrBlock *links;                     /* Blocs liés au bloc courant  */ -    GArchInstruction *last;                 /* Dernière instruction du bloc*/ -    size_t dcount;                          /* Nombre de liens de dest.    */ -    size_t i;                               /* Boucle de parcours          */ -    const instr_link_t *dest;               /* Instr. visée par une autre  */ -    const mrange_t *range;                  /* Emplacement d'une cible     */ -    GFlowBlock *target;                     /* Bloc ciblé par un lien      */ -    unsigned int rank;                      /* Rang à constituer           */ - -    /* Si le bloc visité n'est pas basique... */ -    if (order != BVO_PENDING) return true; - -    next = g_flow_block_get_rank(block) + 1; - -    links = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); - -    g_flow_block_get_boundary(block, NULL, &last); - -    g_arch_instruction_lock_dest(last); -    dcount = g_arch_instruction_count_destinations(last); - -    for (i = 0; i < dcount; i++) -    { -        dest = g_arch_instruction_get_destination(last, i); - -        range = g_arch_instruction_get_range(dest->linked); - -        switch (dest->type) -        { -            case ILT_EXEC_FLOW: -            case ILT_CATCH_EXCEPTION: -                target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); -                //assert(target != NULL); -                break; - -            case ILT_JUMP: -                target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); - -                /** -                 * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. -                 * Par exemple sous ARM : -                 * -                 *    00008358 <call_gmon_start>: -                 *        .... -                 *        8362:       f7ff bfcf       b.w     8304 <_init+0x38> -                 *        .... -                 * -                 */ -                /* assert(target != NULL);*/ - -                break; - -            case ILT_CASE_JUMP: -                target = G_FLOW_BLOCK(g_instr_block_find_by_addr(links, get_mrange_addr(range), true)); -                //assert(target != NULL); -                break; - -            case ILT_JUMP_IF_TRUE: -            case ILT_JUMP_IF_FALSE: - -                /** -                 * Même dans les branches if/then/else, il n'y a pas forcément de groupe de blocs -                 * associé. C'est par exemple le cas dans des constructions telles que celle de -                 * la fonction __libc_csu_init() : -                 * -                 *    if (...) -                 *       do -                 *       { -                 *          ... -                 *       } -                 *       while (...) -                 * -                 *    ... -                 * -                 * Le code final est étiquetté comme étant le 'else' de la première condition, -                 * donc au niveau de la condition de bouclage, il appartient déjà à un autre -                 * et n'est donc pas réattribué une seconde fois. -                 * -                 */ - -                if (links != NULL) -                    target = G_FLOW_BLOCK(g_instr_block_find_by_addr(links, get_mrange_addr(range), true)); -                else -                    target = NULL; - -                /** -                 * Le bloc visé ne se trouve pas toujours dans les blocs attachés : -                 * -                 * { bloc IF } -                 *    { bloc THEN } -                 * { block NEXT } -                 * -                 * Le bloc NEXT est ici à rechercher dans la liste globale. -                 */ - -                if (target == NULL) -                    target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); - -                //assert(target != NULL); - -                break; - -            default: -                target = NULL; -                break; - -        } - -        unref_instr_link(dest); - -        if (target != NULL) -        { -            rank = MAX(next, g_flow_block_get_rank(target)); - -            g_flow_block_set_rank(target, rank); - -        } - -    } - -    g_arch_instruction_unlock_dest(last); - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : routine = routine regroupant les blocs à traiter.            * -*                                                                             * -*  Description : Classe les blocs des routines.                               * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void rank_routine_blocks(GBinRoutine *routine) -{ -    GInstrBlock *main_block;                /* Ensemble des blocs d'instr. */ - -    main_block = g_binary_routine_get_basic_blocks(routine); - - -    if (main_block == NULL) return; - - -    g_instr_block_visit(main_block, (instr_block_visitor_cb)rank_flow_block, main_block); - - -#if 0 - -    printf("===== BLOCK(S) xXXx ======\n"); - - -        bool visit_ranked_block(GInstrBlock *blk, BlockVisitOrder order, int *indent) -        { -            int i; - -            switch (order) -            { -                case BVO_IN: -                case BVO_PENDING: - -                    for (i = 0; i < *indent; i++) -                        printf("   "); - -                    printf("%p '%s'", blk, G_OBJECT_TYPE_NAME(blk)); - -                    if (G_IS_FLOW_BLOCK(blk)) -                    { -                        vmpa2t start; -                        vmpa2t end; - -                        g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end); - -                        printf("  0x%08x -> 0x%08x (rank = %u)", -                               (unsigned int)start.virtual, -                               (unsigned int)end.virtual, -                               g_flow_block_get_rank(G_FLOW_BLOCK(blk))); - -                    } - -                    printf("\n"); - -                    if (order == BVO_IN) (*indent)++; -                    break; - -                case BVO_OUT: -                    (*indent)--; -                    break; - -            } - -            return true; - -        } - -        g_instr_block_visit(main_block, (instr_block_visitor_cb)visit_ranked_block, (int []){ 0 }); - -        printf("\n"); - - -#endif - - - - -} - - - -#endif - - - - - - -  #include <assert.h>  /* Classe les blocs basiques d'une routine. */ -void rank_routine_block(const GBlockList *, GBasicBlock *); - +void rank_routine_block(const GBlockList *, GCodeBlock *); @@ -304,27 +46,23 @@ void rank_routine_block(const GBlockList *, GBasicBlock *);  *                                                                             *  ******************************************************************************/ -void rank_routine_block(const GBlockList *list, GBasicBlock *block) +void rank_routine_block(const GBlockList *list, GCodeBlock *block)  { -    unsigned int next;                      /* Rang suivant obtenu         */ -    GArchInstruction *last;                 /* Dernière instruction du bloc*/ +    size_t next;                            /* Rang suivant obtenu         */      size_t dcount;                          /* Nombre de liens de dest.    */      size_t i;                               /* Boucle de parcours          */ -    const instr_link_t *dest;               /* Instr. visée par une autre  */ +    const block_link_t *dest;               /* Instr. visée par une autre  */      InstructionLinkType type;               /* Raccourci pour confort      */ -    GBasicBlock *target;                    /* Bloc ciblé par un lien      */      unsigned int rank;                      /* Rang à constituer           */ -    next = g_basic_block_get_rank(block) + 1; - -    g_basic_block_get_boundary(block, NULL, &last); +    next = g_code_block_get_rank(block) + 1; -    g_arch_instruction_lock_dest(last); -    dcount = g_arch_instruction_count_destinations(last); +    g_code_block_lock_dest(block); +    dcount = g_code_block_count_destinations(block);      for (i = 0; i < dcount; i++)      { -        dest = g_arch_instruction_get_destination(last, i); +        dest = g_code_block_get_destination(block, i);          type = dest->type; @@ -343,30 +81,13 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)              && type != ILT_JUMP_IF_FALSE)              goto next_dest; -        target = g_block_list_find_by_starting_instr(list, dest->linked); +        rank = g_code_block_get_rank(dest->linked); -        /** -         * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. -         * Par exemple sous ARM : -         * -         *    00008358 <call_gmon_start>: -         *        .... -         *        8362:       f7ff bfcf       b.w     8304 <_init+0x38> -         *        .... -         * -         */ - -        if (target != NULL) +        if (next > rank || rank == -1)          { -            rank = g_basic_block_get_rank(target); - -            if (next > rank || rank == -1) -            { -                g_basic_block_set_rank(target, next); +            g_code_block_set_rank(dest->linked, next); -                rank_routine_block(list, target); - -            } +            rank_routine_block(list, dest->linked);          } @@ -376,7 +97,7 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)      } -    g_arch_instruction_unlock_dest(last); +    g_code_block_unlock_dest(block);  } @@ -396,22 +117,17 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)  void rank_routine_blocks(GBinRoutine *routine)  {      GBlockList *blocks;                     /* Ensemble des blocs d'instr. */ -    GBasicBlock *start;                     /* Bloc basique de départ      */ +    GCodeBlock *start;                      /* Bloc basique de départ      */      blocks = g_binary_routine_get_basic_blocks(routine); -    start = g_block_list_get_block(blocks, 0 /* FIXME */); +    start = g_block_list_get_block(blocks, 0);      assert(start != NULL); - -    g_basic_block_set_rank(start, 0); - +    g_code_block_set_rank(start, 0);      rank_routine_block(blocks, start); - - - - +    g_object_unref(G_OBJECT(start));  } diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index f04611f..4e65b77 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -41,6 +41,8 @@ struct _GRoutinesStudy  {      GDelayedWork parent;                    /* A laisser en premier        */ +    GLoadedBinary *binary;                  /* Binaire en cours d'analyse  */ +      GArchProcessor *proc;                   /* Processeur avec ses instr.  */      GBinFormat *format;                     /* Format de fichier manipulé  */      GBinPortion *portions;                  /* Couches de binaire bornées  */ @@ -155,6 +157,8 @@ static void g_routines_study_dispose(GRoutinesStudy *study)      g_object_unref(G_OBJECT(study->format));      g_object_unref(G_OBJECT(study->proc)); +    g_object_unref(G_OBJECT(study->binary)); +      G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study));  } @@ -181,8 +185,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study)  /******************************************************************************  *                                                                             * -*  Paramètres  : proc     = ensemble d'instructions désassemblées.            * -*                format   = format de fichier à manipuler.                    * +*  Paramètres  : binary   = binaire chargé comprenant les routines à traiter. *  *                portions = ensemble de couches binaires bornées.             *  *                begin    = point de départ du parcours de liste.             *  *                end      = point d'arrivée exclu du parcours.                * @@ -197,24 +200,24 @@ static void g_routines_study_finalize(GRoutinesStudy *study)  *                                                                             *  ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinFormat *format, GBinPortion *portions, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) +GRoutinesStudy *g_routines_study_new(GLoadedBinary *binary, GBinPortion *portions, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback)  {      GRoutinesStudy *result;                /* Tâche à retourner           */      result = g_object_new(G_TYPE_ROUTINES_STUDY, NULL); -    result->proc = proc; -    g_object_ref(G_OBJECT(proc)); +    result->binary = binary; +    g_object_ref(G_OBJECT(binary)); -    result->format = format; -    g_object_ref(G_OBJECT(format)); +    result->proc = g_loaded_binary_get_processor(binary); +    result->format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));      result->portions = portions;      g_object_ref(G_OBJECT(portions)); -    g_binary_format_lock_symbols_rd(format); +    g_binary_format_lock_symbols_rd(result->format); -    result->count = g_binary_format_count_symbols(format); +    result->count = g_binary_format_count_symbols(result->format);      result->fallback = fallback;      result->begin = begin; @@ -397,7 +400,7 @@ void g_routines_study_handle_blocks(GRoutinesStudy *study, GBinRoutine *routine,      detect_loops_in_code(knight); -    blocks = translate_dragon_knight(knight); +    blocks = translate_dragon_knight(knight, study->binary);      g_binary_routine_set_basic_blocks(routine, blocks); diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index d6fd76b..ce44fec 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -25,10 +25,8 @@  #define _ANALYSIS_DISASS_ROUTINES_H +#include "../binary.h"  #include "../routine.h" -#include "../../arch/processor.h" -#include "../../format/executable.h" -#include "../../format/format.h"  #include "../../gtkext/gtkstatusstack.h" @@ -53,7 +51,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, GBinRoutine *, size_t);  /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinFormat *, GBinPortion *, size_t, size_t, activity_id_t, rtn_fallback_cb); +GRoutinesStudy *g_routines_study_new(GLoadedBinary *, GBinPortion *, size_t, size_t, activity_id_t, rtn_fallback_cb);  /* Détermine si besoin est les bornes des routines. */  void g_routines_study_compute_limits(GRoutinesStudy *, GBinRoutine *, size_t); diff --git a/src/analysis/routine.h b/src/analysis/routine.h index 35480c2..6f0d645 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -32,7 +32,7 @@  #include "binary.h"  #include "variable.h" -#include "disass/block.h" +#include "block.h"  #include "../arch/processor.h" | 
