diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-08-08 19:59:34 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-08-08 19:59:34 (GMT) |
commit | b3b515ba37ef58751e5407bfcdff2dd67932b99a (patch) | |
tree | 88dabcde3d63e87e7ac0c7509629346dde066429 /src/analysis | |
parent | 0442cf03782e65bd680449cc213ace9a21bb081b (diff) |
Defined a new kind of code blocks.
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" |