From 2a6d92e2d55c0a7826137b2cc2e3148bb298abb9 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 14 Jan 2019 00:44:21 +0100
Subject: Provided uncached code block links.

---
 plugins/pychrysalide/analysis/block.c |  25 +--
 src/analysis/block-int.h              |  12 +-
 src/analysis/block.c                  | 320 ++++------------------------------
 src/analysis/block.h                  |  33 +---
 src/analysis/disass/block.c           | 114 +++++++++++-
 src/analysis/disass/rank.c            |  13 +-
 src/gtkext/graph/cluster.c            |  25 ++-
 7 files changed, 185 insertions(+), 357 deletions(-)

diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index 1456e15..c484ba6 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -25,6 +25,7 @@
 #include "block.h"
 
 
+#include <malloc.h>
 #include <pygobject.h>
 
 
@@ -151,21 +152,20 @@ static PyObject *py_code_block_get_sources(PyObject *self, void *closure)
     PyObject *result;                       /* Trouvailles à retourner     */
     GCodeBlock *block;                      /* Bloc de code à consulter    */
     size_t count;                           /* Quantité de blocs liés      */
+    block_link_t *links;                    /* Liens à traiter             */
     size_t i;                               /* Boucle de parcours          */
-    const block_link_t *link;               /* Informations conservées     */
+    block_link_t *link;                     /* Informations conservées     */
     PyObject *info;                         /* Informations à transmettre  */
 
     block = G_CODE_BLOCK(pygobject_get(self));
 
-    g_code_block_lock_src(block);
-
-    count = g_code_block_count_sources(block);
+    links = g_code_block_get_sources(block, &count);
 
     result = PyTuple_New(count);
 
     for (i = 0; i < count; i++)
     {
-        link = g_code_block_get_source(block, i);
+        link = &links[i];
 
         info = PyTuple_New(2);
 
@@ -178,7 +178,8 @@ static PyObject *py_code_block_get_sources(PyObject *self, void *closure)
 
     }
 
-    g_code_block_unlock_src(block);
+    if (links != NULL)
+        free(links);
 
     return result;
 
@@ -203,21 +204,20 @@ static PyObject *py_code_block_get_destinations(PyObject *self, void *closure)
     PyObject *result;                       /* Trouvailles à retourner     */
     GCodeBlock *block;                      /* Bloc de code à consulter    */
     size_t count;                           /* Quantité de blocs liés      */
+    block_link_t *links;                    /* Liens à traiter             */
     size_t i;                               /* Boucle de parcours          */
-    const block_link_t *link;               /* Informations conservées     */
+    block_link_t *link;                     /* Informations conservées     */
     PyObject *info;                         /* Informations à transmettre  */
 
     block = G_CODE_BLOCK(pygobject_get(self));
 
-    g_code_block_lock_dest(block);
-
-    count = g_code_block_count_destinations(block);
+    links = g_code_block_get_destinations(block, &count);
 
     result = PyTuple_New(count);
 
     for (i = 0; i < count; i++)
     {
-        link = g_code_block_get_destination(block, i);
+        link = &links[i];
 
         info = PyTuple_New(2);
 
@@ -230,7 +230,8 @@ static PyObject *py_code_block_get_destinations(PyObject *self, void *closure)
 
     }
 
-    g_code_block_unlock_dest(block);
+    if (links != NULL)
+        free(links);
 
     return result;
 
diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h
index b9b90f0..ca38703 100644
--- a/src/analysis/block-int.h
+++ b/src/analysis/block-int.h
@@ -38,8 +38,8 @@
 /* Détermine si un bloc de code débute à une adresse donnée. */
 typedef bool (* block_is_starting_fc) (const GCodeBlock *, const vmpa2t *);
 
-/* Etablit les liens entre un bloc de code et ses voisins. */
-typedef void (* block_resolve_links_fc) (GCodeBlock *, const GBlockList *);
+/* Fournit les détails des origines d'un bloc de code donné. */
+typedef block_link_t * (* block_get_links_fc) (const GCodeBlock *, const GBlockList *, size_t *);
 
 /* Fournit la représentation graphique d'un bloc de code. */
 typedef GBufferView * (* block_build_view_fc) (const GCodeBlock *, segcnt_list *);
@@ -50,14 +50,13 @@ struct _GCodeBlock
 {
     GObject parent;                         /* A laisser en premier        */
 
+    GBlockList *list;                       /* Lien vers l'ensemble        */
+
     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   */
 
 };
@@ -68,7 +67,8 @@ struct _GCodeBlockClass
     GObjectClass parent;                    /* A laisser en premier        */
 
     block_is_starting_fc is_starting;       /* Analyse d'adresse initiale  */
-    block_resolve_links_fc link;            /* Etablissement des liens     */
+    block_get_links_fc get_src;             /* Obtention des origines      */
+    block_get_links_fc get_dest;            /* Obtention des destinations  */
     block_build_view_fc build;              /* Construction d'une vue      */
 
 };
diff --git a/src/analysis/block.c b/src/analysis/block.c
index a23634c..7003ccd 100644
--- a/src/analysis/block.c
+++ b/src/analysis/block.c
@@ -50,9 +50,6 @@ 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 ------------------------- */
@@ -137,12 +134,11 @@ static void g_code_block_class_init(GCodeBlockClass *class)
 
 static void g_code_block_init(GCodeBlock *block)
 {
+    block->list = NULL;
+
     block->index = (size_t)-1;
     block->rank = (size_t)-1;
 
-    block->from = NULL;
-    block->to = NULL;
-
     block->view = NULL;
 
 }
@@ -162,17 +158,7 @@ static void g_code_block_init(GCodeBlock *block)
 
 static void g_code_block_dispose(GCodeBlock *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_clear_object(&block->list);
 
     g_clear_object(&block->view);
 
@@ -297,30 +283,6 @@ bool g_code_block_is_starting_with(const GCodeBlock *block, const vmpa2t *addr)
 
 /******************************************************************************
 *                                                                             *
-*  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.    *
@@ -405,205 +367,36 @@ GBufferView *g_code_block_get_view(GCodeBlock *block, segcnt_list *highlighted)
 
 /******************************************************************************
 *                                                                             *
-*  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.                           *
+*                count = nombre de ces origines. [OUT]                        *
 *                                                                             *
-*  Description : Etablit un lien entre deux blocs de code.                    *
+*  Description : Fournit les détails des origines d'un bloc de code donné.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Liens déterminés vers des blocs de code d'origine.           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_code_block_link_with(GCodeBlock *block, GCodeBlock *dest, InstructionLinkType type)
+block_link_t *g_code_block_get_sources(const GCodeBlock *block, size_t *count)
 {
-    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)
-{
-    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);
+    block_link_t *result;                   /* Détails présents à renvoyer */
+    GCodeBlockClass *class;                 /* Classe des blocs de code    */
 
-    while (count_flat_array_items(block->from) > 0)
+    if (block->list == NULL)
     {
-        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));
-
+        result = NULL;
+        *count = 0;
     }
 
-    g_code_block_unlock_src(block);
-
-    /* Coté destinations */
-
-    g_code_block_lock_dest(block);
-
-    while (count_flat_array_items(block->to) > 0)
+    else
     {
-        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);
+        class = G_CODE_BLOCK_GET_CLASS(block);
 
-        rem_item_from_flat_array(&block->to, 0, sizeof(block_link_t));
+        result = class->get_src(block, block->list, count);
 
     }
 
-    g_code_block_unlock_dest(block);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : block = bloc dont les informations sont à consulter.         *
-*                                                                             *
-*  Description : Fournit la quantité de blocs de code pointant vers un autre. *
-*                                                                             *
-*  Retour      : Nombre de ces origines.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t g_code_block_count_sources(const GCodeBlock *block)
-{
-    size_t result;                          /* Nombre de liens à renvoyer  */
-
-    result = count_flat_array_items(block->from);
-
     return result;
 
 }
@@ -612,72 +405,34 @@ size_t g_code_block_count_sources(const GCodeBlock *block)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : block = bloc dont les informations sont à consulter.         *
-*                index = indice de l'élément à retrouver.                     *
+*                count = nombre de ces destinations. [OUT]                    *
 *                                                                             *
-*  Description : Fournit les détails d'une origine d'un bloc de code donné.   *
+*  Description : Fournit les détails des destinations de bloc de code.        *
 *                                                                             *
-*  Retour      : Lien déterminé vers un bloc de code d'origine.               *
+*  Retour      : Liens déterminés vers des blocs de code de destination.      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const block_link_t *g_code_block_get_source(GCodeBlock *block, size_t index)
+block_link_t *g_code_block_get_destinations(const GCodeBlock *block, size_t *count)
 {
     block_link_t *result;                   /* Détails présents à renvoyer */
+    GCodeBlockClass *class;                 /* Classe des blocs de code    */
 
-    result = get_flat_array_item(block->from, index, sizeof(block_link_t));
-
-    ref_block_link(result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : block = bloc dont les informations sont à consulter.         *
-*                                                                             *
-*  Description : Donne le nombre de blocs de code suivants dans le flot.      *
-*                                                                             *
-*  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   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    if (block->list == NULL)
+    {
+        result = NULL;
+        *count = 0;
+    }
 
-const block_link_t *g_code_block_get_destination(GCodeBlock *block, size_t index)
-{
-    block_link_t *result;                   /* Détails présents à renvoyer */
+    else
+    {
+        class = G_CODE_BLOCK_GET_CLASS(block);
 
-    result = get_flat_array_item(block->to, index, sizeof(block_link_t));
+        result = class->get_dest(block, block->list, count);
 
-    ref_block_link(result);
+    }
 
     return result;
 
@@ -755,11 +510,7 @@ static void g_block_list_dispose(GBlockList *list)
     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_clear_object(&list->blocks[i]);
-        }
+        g_clear_object(&list->blocks[i]);
 
     G_OBJECT_CLASS(g_block_list_parent_class)->dispose(G_OBJECT(list));
 
@@ -806,7 +557,7 @@ GBlockList *g_block_list_new(size_t count)
 
     result = g_object_new(G_TYPE_BLOCK_LIST, NULL);
 
-    result->blocks = (GCodeBlock **)calloc(count, sizeof(GCodeBlock *));
+    result->blocks = calloc(count, sizeof(GCodeBlock *));
 
     result->count = count;
 
@@ -859,6 +610,9 @@ void g_block_list_add_block(GBlockList *list, GCodeBlock *block, size_t index)
 
     list->blocks[index] = block;
 
+    block->list = list;
+    g_object_ref(G_OBJECT(list));
+
     g_code_block_set_index(block, index);
 
 }
@@ -879,10 +633,6 @@ void g_block_list_add_block(GBlockList *list, GCodeBlock *block, size_t index)
 
 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);
 
 }
 
diff --git a/src/analysis/block.h b/src/analysis/block.h
index 21eaaa5..23637d7 100644
--- a/src/analysis/block.h
+++ b/src/analysis/block.h
@@ -88,36 +88,15 @@ typedef struct _block_link_t
 } 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));
+#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);
+/* Fournit les détails des origines d'un bloc de code donné. */
+block_link_t *g_code_block_get_sources(const GCodeBlock *, size_t *);
 
-/* 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);
+/* Fournit les détails des destinations de bloc de code. */
+block_link_t *g_code_block_get_destinations(const GCodeBlock *, size_t *);
 
 
 
diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c
index 6cf7c17..23393f6 100644
--- a/src/analysis/disass/block.c
+++ b/src/analysis/disass/block.c
@@ -25,6 +25,7 @@
 
 
 #include <assert.h>
+#include <malloc.h>
 
 
 #include "../block-int.h"
@@ -70,8 +71,11 @@ 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 *);
+/* Fournit les détails des origines d'un bloc de code donné. */
+static block_link_t *g_basic_block_get_sources(const GBasicBlock *, const GBlockList *, size_t *);
+
+/* Fournit les détails des destinations de bloc de code. */
+static block_link_t *g_basic_block_get_destinations(const GBasicBlock *, const GBlockList *, size_t *);
 
 /* Fournit la représentation graphique d'un bloc de code. */
 static GBufferView *g_basic_block_build_view(const GBasicBlock *, segcnt_list *);
@@ -112,7 +116,8 @@ static void g_basic_block_class_init(GBasicBlockClass *class)
     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->get_src = (block_get_links_fc)g_basic_block_get_sources;
+    block->get_dest = (block_get_links_fc)g_basic_block_get_destinations;
     block->build = (block_build_view_fc)g_basic_block_build_view;
 
 }
@@ -248,24 +253,102 @@ static bool g_basic_block_is_starting_with(const GBasicBlock *block, const vmpa2
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : block = bloc de code à mettre à jour.                        *
+*  Paramètres  : block = bloc dont les informations sont à consulter.         *
 *                list  = ensemble des blocs de code à disposition.            *
+*                count = nombre de ces origines. [OUT]                        *
 *                                                                             *
-*  Description : Etablit les liens entre un bloc de code et ses voisins.      *
+*  Description : Fournit les détails des origines d'un bloc de code donné.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Liens déterminés vers des blocs de code d'origine.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static block_link_t *g_basic_block_get_sources(const GBasicBlock *block, const GBlockList *list, size_t *count)
+{
+    block_link_t *result;                   /* Détails présents à renvoyer */
+    size_t scount;                          /* Nombre de liens d'origine   */
+    size_t i;                               /* Boucle de parcours          */
+    const instr_link_t *src;                /* Instr. visée par une autre  */
+    const mrange_t *range;                  /* Couverture d'instruction    */
+    GCodeBlock *target;                     /* Bloc ciblé par un lien      */
+    block_link_t *new;                      /* Nouvelle entrée à définir   */
+
+    result = NULL;
+    *count = 0;
+
+    g_arch_instruction_lock_src(block->first);
+    scount = g_arch_instruction_count_sources(block->first);
+
+    for (i = 0; i < scount; i++)
+    {
+        src = g_arch_instruction_get_source(block->first, i);
+
+        range = g_arch_instruction_get_range(src->linked);
+
+        target = g_block_list_find_by_starting_addr(list, get_mrange_addr(range));
+
+        /**
+         * Les liens ne sont pas toujours internes !
+         */
+
+        if (target != NULL)
+        {
+            result = realloc(result, ++(*count) * sizeof(block_link_t));
+
+            new = &result[*count - 1];
+
+            new->linked = target;
+            new->type = src->type;
+
+            /**
+             * On pourrait par optimisation retirer les deux lignes suivantes...
+             */
+
+            ref_block_link(new);
+
+            g_object_unref(G_OBJECT(target));
+
+        }
+
+        unref_instr_link(src);
+
+    }
+
+    g_arch_instruction_unlock_src(block->first);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc dont les informations sont à consulter.         *
+*                list  = ensemble des blocs de code à disposition.            *
+*                count = nombre de ces destinations. [OUT]                    *
+*                                                                             *
+*  Description : Fournit les détails des destinations de bloc de code.        *
+*                                                                             *
+*  Retour      : Liens déterminés vers des blocs de code de destination.      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *list)
+static block_link_t *g_basic_block_get_destinations(const GBasicBlock *block, const GBlockList *list, size_t *count)
 {
+    block_link_t *result;                   /* Détails présents à renvoyer */
     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      */
+    block_link_t *new;                      /* Nouvelle entrée à définir   */
+
+    result = NULL;
+    *count = 0;
 
     g_arch_instruction_lock_dest(block->last);
     dcount = g_arch_instruction_count_destinations(block->last);
@@ -291,8 +374,21 @@ static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *li
 
         if (target != NULL)
         {
-            g_code_block_link_with(G_CODE_BLOCK(block), target, dest->type);
+            result = realloc(result, ++(*count) * sizeof(block_link_t));
+
+            new = &result[*count - 1];
+
+            new->linked = target;
+            new->type = dest->type;
+
+            /**
+             * On pourrait par optimisation retirer les deux lignes suivantes...
+             */
+
+            ref_block_link(new);
+
             g_object_unref(G_OBJECT(target));
+
         }
 
         unref_instr_link(dest);
@@ -301,6 +397,8 @@ static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *li
 
     g_arch_instruction_unlock_dest(block->last);
 
+    return result;
+
 }
 
 
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index b6eb4c5..d703aee 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -50,19 +50,19 @@ void rank_routine_block(const GBlockList *list, GCodeBlock *block)
 {
     size_t next;                            /* Rang suivant obtenu         */
     size_t dcount;                          /* Nombre de liens de dest.    */
+    block_link_t *links;                    /* Liens associés au bloc      */
     size_t i;                               /* Boucle de parcours          */
-    const block_link_t *dest;               /* Instr. visée par une autre  */
+    block_link_t *dest;                     /* Bloc visé par un autre      */
     InstructionLinkType type;               /* Raccourci pour confort      */
     unsigned int rank;                      /* Rang à constituer           */
 
     next = g_code_block_get_rank(block) + 1;
 
-    g_code_block_lock_dest(block);
-    dcount = g_code_block_count_destinations(block);
+    links = g_code_block_get_destinations(block, &dcount);
 
     for (i = 0; i < dcount; i++)
     {
-        dest = g_code_block_get_destination(block, i);
+        dest = &links[i];
 
         type = dest->type;
 
@@ -93,11 +93,12 @@ void rank_routine_block(const GBlockList *list, GCodeBlock *block)
 
  next_dest:
 
-        unref_instr_link(dest);
+        unref_block_link(dest);
 
     }
 
-    g_code_block_unlock_dest(block);
+    if (links != NULL)
+        free(links);
 
 }
 
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index 70d58fa..bc8f9dd 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -1712,8 +1712,9 @@ static void g_graph_cluster_add_sub(GGraphCluster *cluster, GGraphCluster *sub)
 static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all)
 {
     size_t dcount;                          /* Nombre de liens de dest.    */
+    block_link_t *links;                    /* Liens associés au bloc      */
     size_t i;                               /* Boucle de parcours #1       */
-    const block_link_t *dest;               /* Bloc visé par une autre     */
+    block_link_t *dest;                     /* Bloc visé par un autre      */
     GGraphCluster *target;                  /* Bloc ciblé par un lien      */
     leaving_link_t *leaving;                /* Point de départ d'un lien   */
     incoming_link_t *incoming;              /* Définitions d'arrivée       */
@@ -1722,12 +1723,11 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 
     /* Au niveau du bloc courant */
 
-    g_code_block_lock_dest(cluster->block);
-    dcount = g_code_block_count_destinations(cluster->block);
+    links = g_code_block_get_destinations(cluster->block, &dcount);
 
     for (i = 0; i < dcount; i++)
     {
-        dest = g_code_block_get_destination(cluster->block, i);
+        dest = &links[i];
 
         switch (dest->type)
         {
@@ -1783,7 +1783,6 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
                 /* Point d'arrivée */
 
                 midpts = malloc(2 * sizeof(GdkPoint));
-                midpts = calloc(2, sizeof(GdkPoint));//////////////// REMME
 
                 incoming = create_incoming_loop_link(target, midpts, leaving);
 
@@ -1813,9 +1812,8 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 
     }
 
-    g_code_block_unlock_dest(cluster->block);
-
-
+    if (links != NULL)
+        free(links);
 
     /* Doit-on forcer un lien strictement vertical ? */
 
@@ -2634,8 +2632,9 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
     gboolean new;                           /* Bloc déjà traité ?          */
 #endif
     size_t dcount;                          /* Nombre de liens de dest.    */
+    block_link_t *links;                    /* Liens associés au bloc      */
     size_t i;                               /* Boucle de parcours #1       */
-    const block_link_t *dest;               /* Bloc visé par une autre     */
+    block_link_t *dest;                     /* Bloc visé par un 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 */
@@ -2655,12 +2654,11 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
 
     /* Détermination des blocs suivants */
 
-    g_code_block_lock_dest(block);
-    dcount = g_code_block_count_destinations(block);
+    links = g_code_block_get_destinations(block, &dcount);
 
     for (i = 0; i < dcount; i++)
     {
-        dest = g_code_block_get_destination(block, i);
+        dest = &links[i];
 
         switch (dest->type)
         {
@@ -2718,7 +2716,8 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
 
     }
 
-    g_code_block_unlock_dest(block);
+    if (links != NULL)
+        free(links);
 
     g_object_unref(G_OBJECT(block));
 
-- 
cgit v0.11.2-87-g4458