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