From b3b515ba37ef58751e5407bfcdff2dd67932b99a Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 8 Aug 2018 21:59:34 +0200 Subject: Defined a new kind of code blocks. --- plugins/pychrysalide/analysis/block.c | 39 +- src/analysis/binary.c | 6 +- src/analysis/block-int.h | 49 +- src/analysis/block.c | 837 +++++++++++++++++++++++++++++++--- src/analysis/block.h | 143 ++++-- src/analysis/disass/block.c | 453 +++++------------- src/analysis/disass/block.h | 57 +-- src/analysis/disass/disassembler.c | 25 +- src/analysis/disass/dragon.c | 10 +- src/analysis/disass/dragon.h | 5 +- src/analysis/disass/rank.c | 318 +------------ src/analysis/disass/routines.c | 23 +- src/analysis/disass/routines.h | 6 +- src/analysis/routine.h | 2 +- src/gtkext/graph/cluster.c | 273 +++-------- src/gtkext/graph/cluster.h | 4 +- src/gtkext/gtkblockdisplay.c | 42 +- src/gtkext/gtkblockdisplay.h | 5 +- src/gtkext/gtkbufferdisplay.c | 27 +- src/gtkext/gtkbufferdisplay.h | 3 - src/gtkext/gtkdisplaypanel-int.h | 4 - src/gtkext/gtkdisplaypanel.c | 3 - 22 files changed, 1189 insertions(+), 1145 deletions(-) diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c index edd364d..e646ba8 100644 --- a/plugins/pychrysalide/analysis/block.c +++ b/plugins/pychrysalide/analysis/block.c @@ -34,6 +34,9 @@ #include "../helpers.h" +////////////////////////////////////////////////////////// +#if 0 + /* Permet la jonction entre C et Python lors des visites */ typedef struct _py_block_vdata @@ -163,31 +166,7 @@ static PyObject *py_instructions_block_get_links_block(PyObject *self, PyObject } -/****************************************************************************** -* * -* Paramètres : obj_type = type dont le dictionnaire est à compléter. * -* * -* Description : Définit les constantes pour les blocs basiques. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_instructions_block_define_constants(PyTypeObject *obj_type) -{ - bool result; /* Bilan à retourner */ - - result = true; - - result &= PyDict_AddIntMacro(obj_type, BVO_IN); - result &= PyDict_AddIntMacro(obj_type, BVO_PENDING); - result &= PyDict_AddIntMacro(obj_type, BVO_OUT); - - return result; - -} +#endif /****************************************************************************** @@ -205,16 +184,13 @@ static bool py_instructions_block_define_constants(PyTypeObject *obj_type) PyTypeObject *get_python_instr_block_type(void) { static PyMethodDef py_instr_block_methods[] = { - { - "visit", (PyCFunction)py_instructions_block_visit, - METH_VARARGS, - "visit($self, cb, data, /)\n--\n\nVisit all the basic blocks, starting at the provided one." - }, +#if 0 { "get_links_block", (PyCFunction)py_instructions_block_get_links_block, METH_VARARGS, "get_links_block($self, /)\n--\n\nGet the block containing all blocks linked to the caller." }, +#endif { NULL } }; @@ -256,6 +232,7 @@ PyTypeObject *get_python_instr_block_type(void) bool register_python_instr_block(PyObject *module) { +#if 0 PyTypeObject *py_instr_block_type; /* Type Python 'InstrBlock' */ PyObject *dict; /* Dictionnaire du module */ @@ -268,7 +245,7 @@ bool register_python_instr_block(PyObject *module) if (!py_instructions_block_define_constants(py_instr_block_type)) return false; - +#endif return true; } 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 +#include + + #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 +#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 +#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 : + * .... + * 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 +#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 +#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 -#include - - -#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 : - * .... - * 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 /* 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 : - * .... - * 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" diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index a156bfa..8e33671 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -34,7 +34,6 @@ #include "../gtkbufferdisplay.h" #include "../gtkdisplaypanel.h" #include "../../common/sort.h" -#include "../../glibext/gbinarycursor.h" // REMME #include "../../glibext/gloadedpanel.h" @@ -75,7 +74,7 @@ typedef struct _hspace_booking /* Découpage vertical */ typedef struct _graph_rank { - unsigned int level; /* Niveau des blocs */ + size_t level; /* Niveau des blocs */ hspace_booking **right2left; /* Réservations de D -> G */ size_t r2l_count; /* Quantité de ces réservations*/ @@ -105,7 +104,7 @@ struct _GGraphCluster incoming_edge **top_anchors; /* Accroches supérieures */ size_t ta_count; /* Quantité de ces accroches */ - GBasicBlock *block; /* Bloc d'origine représenté */ + GCodeBlock *block; /* Bloc d'origine représenté */ GtkWidget *display; /* Vue graphique associée */ GtkAllocation alloc; /* Emplacement final du bloc */ @@ -113,7 +112,7 @@ struct _GGraphCluster size_t ba_count; /* Quantité de ces accroches */ bool has_straight; /* Présence d'une ligne droite */ - unsigned int straight_level; /* Rang atteint en ligne droite*/ + size_t straight_level; /* Rang atteint en ligne droite*/ size_t straight_index; /* Indice du lien vertical */ graph_rank *ranks; /* Répartition verticale */ @@ -152,7 +151,7 @@ static void g_graph_cluster_dispose(GGraphCluster *); static void g_graph_cluster_finalize(GGraphCluster *); /* Complète un graphique avec un sous-ensemble de blocs. */ -static void g_graph_cluster_add_sub(GGraphCluster *, GGraphCluster *, GBasicBlock *); +static void g_graph_cluster_add_sub(GGraphCluster *, GGraphCluster *, GCodeBlock *); /* Organisation la disposition d'un ensemble de blocs basiques. */ static void g_graph_cluster_dispatch_x(GGraphCluster *); @@ -285,12 +284,11 @@ static void g_graph_cluster_finalize(GGraphCluster *cluster) /****************************************************************************** * * -* Paramètres : binary = binaire charger dont le code est à représenter.* -* list = ensemble de blocs basiques à manipuler. * -* index = indice du bloc principal à mettre en place. * +* Paramètres : block = premier bloc du groupe. * * highlighted = gestionnaire de surbrillance pour segments. * +* binary = binaire charger dont le code est à représenter.* * * -* Description : Construit un graphique à partir de blocs basiques. * +* Description : * * * * Retour : Adresse de la structure mise en place. * * * @@ -298,14 +296,9 @@ static void g_graph_cluster_finalize(GGraphCluster *cluster) * * ******************************************************************************/ -GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted) +GGraphCluster *g_graph_cluster_new(GCodeBlock *block, segcnt_list *highlighted, GLoadedBinary *binary) { GGraphCluster *result; /* Structure à retourner */ - vmpa2t first; /* Début d'un groupe de lignes */ - vmpa2t last; /* Fin d'un groupe de lignes */ - GLineCursor *___tmp_first; - GLineCursor *___tmp_last; - GBufferCache *cache; /* Tampon brut à découper */ GBufferView *view; /* Partie affichée du tampon */ GtkRequisition requisition; /* Taille à l'écran actuelle */ @@ -313,10 +306,12 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list /* Encapsulation du bloc d'entrée */ - result->block = g_block_list_get_block(list, index); - g_object_ref(G_OBJECT(result->block)); + result->block = block; + g_object_ref(G_OBJECT(block)); - result->display = gtk_block_display_new(); + view = g_code_block_get_view(result->block, highlighted); + + result->display = gtk_block_display_new(view); gtk_widget_show(result->display); g_loaded_panel_set_content(G_LOADED_PANEL(result->display), G_LOADED_CONTENT(binary)); @@ -325,25 +320,6 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result->display), true); - /* Restriction au bloc basique */ - - g_basic_block_get_boundary_addresses(result->block, &first, &last); - - - /////////////////////// - ___tmp_first = g_binary_cursor_new(); - g_binary_cursor_update(G_BINARY_CURSOR(___tmp_first), &first); - ___tmp_last = g_binary_cursor_new(); - g_binary_cursor_update(G_BINARY_CURSOR(___tmp_last), &last); - /////////////////////// - - - cache = g_loaded_binary_get_disassembled_cache(binary); - - view = g_buffer_view_new(cache, highlighted); - g_buffer_view_restrict(view, ___tmp_first, ___tmp_last); - gtk_buffer_display_set_view(GTK_BUFFER_DISPLAY(result->display), view); - /* Détermination d'une position initiale centrée */ gtk_widget_get_preferred_size(result->display, NULL, &requisition); @@ -375,14 +351,14 @@ GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list * * ******************************************************************************/ -static void g_graph_cluster_add_sub(GGraphCluster *cluster, GGraphCluster *sub, GBasicBlock *block) +static void g_graph_cluster_add_sub(GGraphCluster *cluster, GGraphCluster *sub, GCodeBlock *block) { - unsigned int level; /* Niveau du nouvel ensemble */ + size_t level; /* Niveau du nouvel ensemble */ size_t i; /* Boucle de parcours */ graph_rank new; /* Nouvel étage à insérer */ graph_rank *rank; /* Nouvel étage à compléter */ - level = g_basic_block_get_rank(block); + level = g_code_block_get_rank(block); for (i = 0; i < cluster->ranks_count; i++) if (cluster->ranks[i].level == level) @@ -917,30 +893,27 @@ static GGraphCluster *g_graph_cluster_find_lower_dest_cluster(const GGraphCluste static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all) { - unsigned int level; /* Niveau du nouvel ensemble */ - GArchInstruction *last; /* Dernière instruction du bloc*/ + size_t level; /* Niveau du nouvel ensemble */ size_t dcount; /* Nombre de liens de dest. */ size_t i; /* Boucle de parcours #1 */ - const instr_link_t *dest; /* Instr. visée par une autre */ + const block_link_t *dest; /* Bloc visé par une autre */ GGraphCluster *target; /* Bloc ciblé par un lien */ leaving_edge *leaving; /* Point de départ d'un lien */ - unsigned int target_level; /* Rang du bloc ciblé */ + size_t target_level; /* Rang du bloc ciblé */ size_t j; /* Boucle de parcours #2 */ size_t k; /* Boucle de parcours #3 */ incoming_edge *incoming; /* Définitions d'arrivée */ /* Au niveau du bloc courant */ - level = g_basic_block_get_rank(cluster->block); + level = g_code_block_get_rank(cluster->block); - g_basic_block_get_boundary(cluster->block, NULL, &last); - - g_arch_instruction_lock_dest(last); - dcount = g_arch_instruction_count_destinations(last); + g_code_block_lock_dest(cluster->block); + dcount = g_code_block_count_destinations(cluster->block); for (i = 0; i < dcount; i++) { - dest = g_arch_instruction_get_destination(last, i); + dest = g_code_block_get_destination(cluster->block, i); switch (dest->type) { @@ -1045,11 +1018,11 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all } - unref_instr_link(dest); + unref_block_link(dest); } - g_arch_instruction_unlock_dest(last); + g_code_block_unlock_dest(cluster->block); @@ -1489,7 +1462,7 @@ static void g_graph_cluster_resolve_links(const GGraphCluster *cluster) typedef struct _pending_blocks { size_t count; /* Taille de la liste */ - GBasicBlock *list[0]; /* Liste de blocs à traiter */ + GCodeBlock *list[0]; /* Liste de blocs à traiter */ } pending_blocks; @@ -1524,43 +1497,38 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *, const GBlockList *, static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted, pending_blocks *pending, GHashTable *all) { GGraphCluster *result; /* Instance nouvelle à renvoyer*/ - GBasicBlock *block; /* Bloc à manipuler */ - GArchInstruction *first; /* Première instruction du bloc*/ - GArchInstruction *last; /* Dernière instruction du bloc*/ + GCodeBlock *block; /* Bloc à manipuler */ #ifndef NDEBUG gboolean new; /* Bloc déjà traité ? */ #endif size_t dcount; /* Nombre de liens de dest. */ size_t i; /* Boucle de parcours #1 */ - const instr_link_t *dest; /* Instr. visée par une autre */ - GBasicBlock *target; /* Bloc ciblé par un lien */ + const block_link_t *dest; /* Bloc visé par une autre */ size_t j; /* Boucle de parcours #2 */ bool changed; /* Un ajout a été effectué ? */ const bitfield_t *dominators; /* Blocs dominant ce même bloc */ size_t next; /* Indice du prochain bloc */ GGraphCluster *sub; /* Sous-ensemble à intégrer */ - result = g_graph_cluster_new(binary, list, index, highlighted); - block = g_block_list_get_block(list, index); - g_basic_block_get_boundary(block, &first, &last); + result = g_graph_cluster_new(block, highlighted, binary); #ifndef NDEBUG - new = g_hash_table_insert(all, first, result); + new = g_hash_table_insert(all, block, result); assert(new); #else - g_hash_table_insert(all, first, result); + g_hash_table_insert(all, block, result); #endif /* Détermination des blocs suivants */ - 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); switch (dest->type) { @@ -1570,69 +1538,40 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi case ILT_JUMP_IF_TRUE: case ILT_JUMP_IF_FALSE: - target = g_block_list_find_by_starting_instr(list, dest->linked); - - /** - * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. - * Par exemple sous ARM : - * - * 00008358 : - * .... - * 8362: f7ff bfcf b.w 8304 <_init+0x38> - * .... - * - */ - - printf(" NEW BLK :: %d -> %p\n", dest->type, target); + for (j = 0; j < pending->count; j++) + if (pending->list[j] == dest->linked) + break; - if (target != NULL) + if (j == pending->count) { - for (j = 0; j < pending->count; j++) - if (pending->list[j] == target) - break; - - if (j == pending->count) + /** + * Il faut vérifier ici si la destination n'a pas déjà été + * empruntée, sauf peine de faire réagir l'assertion plus + * haut au moment de l'insertion. + * + * Le type de code à problème est le suivant : + * + * ... + * if (...) + * ... + * ... + * + * Le code suivant le bloc conditionnel a deux origines, + * qui vont chacune poursuivre le traitement vers ce code + * commun. + * + * Et comme les origines ne sont pas dominantes, on utilise + * la table globale. + */ + + if (!g_hash_table_contains(all, dest->linked)) { - /** - * Il faut vérifier ici si la destination n'a pas déjà été - * empruntée, sauf peine de faire réagir l'assertion plus - * haut au moment de l'insertion. - * - * Le type de code à problème est le suivant : - * - * ... - * if (...) - * ... - * ... - * - * Le code suivant le bloc conditionnel a deux origines, - * qui vont chacune poursuivre le traitement vers ce code - * commun. - * - * Et comme les origines ne sont pas dominantes, on utilise - * la table globale. - */ - - if (!g_hash_table_contains(all, dest->linked)) - { - assert((pending->count + 1) < g_block_list_count_blocks(list)); - pending->list[pending->count++] = target; - printf(" --push-- %d -> %p\n", dest->type, target); - } + g_object_ref(G_OBJECT(dest->linked)); - } + assert((pending->count + 1) < g_block_list_count_blocks(list)); + pending->list[pending->count++] = dest->linked; - do - { - size_t k; - printf(" --stack-- "); - for (k = 0; k < pending->count; k++) - printf("%p ", pending->list[k]); - printf("\n"); } - while (0); - - } @@ -1643,11 +1582,13 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi } - unref_instr_link(dest); + unref_block_link(dest); } - g_arch_instruction_unlock_dest(last); + g_code_block_unlock_dest(block); + + g_object_unref(G_OBJECT(block)); /* Intégration de tous les blocs en attente */ @@ -1658,7 +1599,7 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi for (i = 0; i < pending->count && !changed; i++) { block = pending->list[i]; - dominators = g_basic_block_get_domination(block); + dominators = g_code_block_get_domination(block); if (test_in_bit_field(dominators, index)) { @@ -1668,23 +1609,23 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi if ((i + 1) < pending->count) memmove(&pending->list[i], &pending->list[i + 1], - (pending->count - i - 1) * sizeof(GBasicBlock *)); + (pending->count - i - 1) * sizeof(GCodeBlock *)); pending->count--; /* Intégration */ - next = g_block_list_get_index(list, block); + next = g_code_block_get_index(block); assert(next < g_block_list_count_blocks(list)); - printf(" --pop-- block=%p index=%zu\n", block, next); - sub = setup_graph_clusters(binary, list, next, highlighted, pending, all); g_graph_cluster_add_sub(result, sub, block); } + g_object_ref(G_OBJECT(block)); + } } @@ -1725,77 +1666,7 @@ GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList * count = g_block_list_count_blocks(list); - pending = (pending_blocks *)calloc(1, sizeof(pending_blocks) + count * sizeof(GBasicBlock *)); - - - -#if 0 - do - { - size_t i; - GBasicBlock *block; - const bitfield_t *domination; - GArchInstruction *first; /* Première instruction du bloc*/ - GArchInstruction *last; /* Dernière instruction du bloc*/ - - - printf("DBG // count : %zu\n", count); - - for (i = 0; i < count; i++) - { - block = g_block_list_get_block(list, i); - domination = g_basic_block_get_domination(block); - - g_basic_block_get_boundary(block, &first, &last); - - printf("DBG // block [%zu] @ 0x%08x : 0x%08lx -- rank = %u\n", - i, - (unsigned int)first->range.addr.virtual, - gfw(domination), g_basic_block_get_rank(block)); - - } - - fflush(NULL); - - } - while (0); - - - - void show_tree(GGraphCluster *cluster, int depth) - { - int i; - GArchInstruction *first; - size_t j; - size_t k; - - printf("TREE | "); - - for (i = 0; i < depth; i++) - printf(" "); - - g_basic_block_get_boundary(cluster->block, &first, NULL); - - printf("cluster @ 0x%08x\n", (unsigned int)first->range.addr.virtual); - - for (j = 0; j < cluster->ranks_count; j++) - { - printf("TREE | "); - - for (i = 0; i < depth; i++) - printf(" "); - - printf(" + rank %u +\n", cluster->ranks[j].level); - - for (k = 0; k < cluster->ranks[j].count; k++) - show_tree(cluster->ranks[j].clusters[k], depth + 1); - - } - - - } -#endif - + pending = (pending_blocks *)calloc(1, sizeof(pending_blocks) + count * sizeof(GCodeBlock *)); result = setup_graph_clusters(binary, list, 0, highlighted, pending, all); diff --git a/src/gtkext/graph/cluster.h b/src/gtkext/graph/cluster.h index 70e1608..abd8a87 100644 --- a/src/gtkext/graph/cluster.h +++ b/src/gtkext/graph/cluster.h @@ -50,8 +50,8 @@ typedef struct _GGraphClusterClass GGraphClusterClass; /* Indique le type définit par la GLib pour les mises en disposition graphique. */ GType g_graph_cluster_get_type(void); -/* Construit un graphique à partir de blocs basiques. */ -GGraphCluster *g_graph_cluster_new(GLoadedBinary *, const GBlockList *, size_t, segcnt_list *); +/* Construit un graphique à partir de blocs de code. */ +GGraphCluster *g_graph_cluster_new(GCodeBlock *, segcnt_list *, GLoadedBinary *); /* Détermine l'emplacement requis d'un ensemble de blocs. */ void g_graph_cluster_compute_needed_alloc(const GGraphCluster *, GtkAllocation *); diff --git a/src/gtkext/gtkblockdisplay.c b/src/gtkext/gtkblockdisplay.c index bc189a2..a6f16a5 100644 --- a/src/gtkext/gtkblockdisplay.c +++ b/src/gtkext/gtkblockdisplay.c @@ -72,9 +72,6 @@ static gboolean gtk_block_display_query_tooltip(GtkWidget *, gint, gint, gboolea /* Redessine l'affichage suite à un changement visuel. */ static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *, GBufferView *); -/* Prend acte de l'association d'un binaire chargé. */ -static void gtk_block_display_attach_binary(GtkBlockDisplay *, GLoadedBinary *); - /* Fournit le position courante dans un panneau de chargement. */ static GLineCursor *gtk_block_display_get_cursor(const GtkBlockDisplay *); @@ -121,7 +118,6 @@ static void gtk_block_display_class_init(GtkBlockDisplayClass *class) panel_class = GTK_DISPLAY_PANEL_CLASS(class); - panel_class->attach = (attach_binary_fc)gtk_block_display_attach_binary; panel_class->get_cursor = (get_cursor_fc)gtk_block_display_get_cursor; panel_class->set_cursor = (set_cursor_fc)gtk_block_display_set_cursor; @@ -205,7 +201,7 @@ static void gtk_block_display_finalize(GtkBlockDisplay *display) /****************************************************************************** * * -* Paramètres : - * +* Paramètres : view = représentation à afficher dans le composant. * * * * Description : Crée un nouveau composant pour l'affichage de bloc en ASM. * * * @@ -215,12 +211,17 @@ static void gtk_block_display_finalize(GtkBlockDisplay *display) * * ******************************************************************************/ -GtkWidget *gtk_block_display_new(void) +GtkWidget *gtk_block_display_new(GBufferView *view) { GtkBlockDisplay *result; /* Composant à retourner */ result = g_object_new(GTK_TYPE_BLOCK_DISPLAY, NULL); + GTK_BUFFER_DISPLAY(result)->view = view; + + g_signal_connect_swapped(G_OBJECT(view), "need-redraw", + G_CALLBACK(gtk_block_display_need_redraw), result); + return GTK_WIDGET(result); } @@ -366,35 +367,6 @@ static gboolean gtk_block_display_need_redraw(GtkBlockDisplay *display, GBufferV /****************************************************************************** * * -* Paramètres : display = composant GTK à mettre à jour. * -* binary = binaire associé à intégrer. * -* * -* Description : Prend acte de l'association d'un binaire chargé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_display_attach_binary(GtkBlockDisplay *display, GLoadedBinary *binary) -{ - GBufferCache *cache; /* Tampon par défaut */ - GBufferView *view; /* Vue sur ce même tampon */ - - cache = g_loaded_binary_get_disassembled_cache(binary); - view = g_buffer_view_new(cache, NULL); - - gtk_buffer_display_set_view(GTK_BUFFER_DISPLAY(display), view); - - g_signal_connect_swapped(G_OBJECT(view), "need-redraw", - G_CALLBACK(gtk_block_display_need_redraw), display); - -} - - -/****************************************************************************** -* * * Paramètres : display = composant GTK à consulter. * * * * Description : Fournit le position courante dans un panneau de chargement. * diff --git a/src/gtkext/gtkblockdisplay.h b/src/gtkext/gtkblockdisplay.h index 3f7267d..b250e35 100644 --- a/src/gtkext/gtkblockdisplay.h +++ b/src/gtkext/gtkblockdisplay.h @@ -29,6 +29,9 @@ #include +#include "../glibext/gbufferview.h" + + #define GTK_TYPE_BLOCK_DISPLAY (gtk_block_display_get_type()) #define GTK_BLOCK_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_BLOCK_DISPLAY, GtkBlockDisplay)) @@ -49,7 +52,7 @@ typedef struct _GtkBlockDisplayClass GtkBlockDisplayClass; GType gtk_block_display_get_type(void); /* Crée un nouveau composant pour l'affichage de bloc en ASM. */ -GtkWidget *gtk_block_display_new(void); +GtkWidget *gtk_block_display_new(GBufferView *); /* Force un type de vue pour les options de rendu. */ void gtk_block_display_override_view_index(GtkBlockDisplay *, unsigned int); diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c index ea391bb..fccea38 100644 --- a/src/gtkext/gtkbufferdisplay.c +++ b/src/gtkext/gtkbufferdisplay.c @@ -205,8 +205,7 @@ static void gtk_buffer_display_init(GtkBufferDisplay *display) static void gtk_buffer_display_dispose(GtkBufferDisplay *display) { - if (display->view != NULL) - g_object_unref(G_OBJECT(display->view)); + g_object_unref(G_OBJECT(display->view)); G_OBJECT_CLASS(gtk_buffer_display_parent_class)->dispose(G_OBJECT(display)); @@ -773,30 +772,6 @@ static void gtk_buffer_display_cache_glance(GtkBufferDisplay *display, cairo_t * /****************************************************************************** * * -* Paramètres : display = instance d'objet Gtk à actualiser. * -* view = nouvelle vue à associer au composant. * -* * -* Description : Lie une vue au composant d'affichage de tampon. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_buffer_display_set_view(GtkBufferDisplay *display, GBufferView *view) -{ - if (display->view != NULL) - g_object_unref(G_OBJECT(display->view)); - - display->view = view; - g_object_ref(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * * Paramètres : display = composant GTK à consulter. * * * * Description : Fournit la vue associée au tampon de lignes courant. * diff --git a/src/gtkext/gtkbufferdisplay.h b/src/gtkext/gtkbufferdisplay.h index 9998b43..dc2e4ff 100644 --- a/src/gtkext/gtkbufferdisplay.h +++ b/src/gtkext/gtkbufferdisplay.h @@ -51,9 +51,6 @@ typedef struct _GtkBufferDisplayClass GtkBufferDisplayClass; /* Détermine le type du composant d'affichage de tampon de lignes. */ GType gtk_buffer_display_get_type(void); -/* Lie une vue au composant d'affichage de tampon. */ -void gtk_buffer_display_set_view(GtkBufferDisplay *, GBufferView *); - /* Fournit la vue associée au tampon de lignes courant. */ GBufferView *gtk_buffer_display_get_view(const GtkBufferDisplay *); diff --git a/src/gtkext/gtkdisplaypanel-int.h b/src/gtkext/gtkdisplaypanel-int.h index 9fdb702..b1a96e9 100644 --- a/src/gtkext/gtkdisplaypanel-int.h +++ b/src/gtkext/gtkdisplaypanel-int.h @@ -37,9 +37,6 @@ -/* Prend acte de l'association d'un binaire chargé. */ -typedef void (* attach_binary_fc) (GtkDisplayPanel *, GLoadedBinary *); - /* Indique les dimensions de travail du composant d'affichage. */ typedef void (* compute_requested_size_fc) (GtkDisplayPanel *, gint *, gint *); @@ -101,7 +98,6 @@ struct _GtkDisplayPanelClass { GtkFixedClass parent; /* A laisser en premier */ - attach_binary_fc attach; /* Association avec un binaire */ compute_requested_size_fc compute_size; /* Calcul de la taille requise */ compute_scroll_inc_fc compute_inc; /* Calcul des bonds */ adjust_scroll_value_fc adjust; /* Réaction à un défilement */ diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c index 97a4276..0c3a6b9 100644 --- a/src/gtkext/gtkdisplaypanel.c +++ b/src/gtkext/gtkdisplaypanel.c @@ -1062,9 +1062,6 @@ static void gtk_display_panel_set_content(GtkDisplayPanel *panel, GLoadedContent panel->binary = G_LOADED_BINARY(content); - if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach != NULL) /* REMME */ - GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach(panel, panel->binary); - g_signal_connect(panel->options, "value-changed", G_CALLBACK(on_display_panel_option_change), panel); } -- cgit v0.11.2-87-g4458