From 59f319d9a6961a7424c7b32f49aa7ac1045a1d4c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 20 Apr 2016 14:07:19 +0200
Subject: Protected all concurrent accesses to sources and destinations of
 instructions.

---
 plugins/libcsem/exit.c        |   3 +
 src/analysis/blocks/flow.c    |   6 ++
 src/analysis/disass/dragon.c  |  10 +++-
 src/analysis/disass/links.c   |  13 ++++-
 src/analysis/disass/loop.c    |   4 +-
 src/analysis/disass/macro.c   |   2 +
 src/analysis/disass/rank.c    |   4 ++
 src/arch/instruction-int.h    |  11 +++-
 src/arch/instruction.c        | 130 ++++++++++++++++++++++++++++++++++++++++--
 src/arch/instruction.h        |  18 ++++++
 src/gtkext/graph/nodes/flow.c |   8 +++
 src/gui/dialogs/gotox.c       |  13 ++++-
 src/gui/dialogs/gotox.h       |   2 +-
 13 files changed, 212 insertions(+), 12 deletions(-)

diff --git a/plugins/libcsem/exit.c b/plugins/libcsem/exit.c
index 1bb4edd..aa3ca18 100644
--- a/plugins/libcsem/exit.c
+++ b/plugins/libcsem/exit.c
@@ -68,6 +68,7 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c
 
     instr = g_arch_processor_find_instr_by_address(proc,  get_mrange_addr(range));
 
+    g_arch_instruction_rlock_src(instr);
     count = g_arch_instruction_get_sources(instr, &sources, &types);
 
     for (i = 0; i < count; i++)
@@ -78,6 +79,8 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c
 
     }
 
+    g_arch_instruction_runlock_src(instr);
+
     g_object_unref(G_OBJECT(proc));
 
  mokoear_done_with_sym:
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c
index 9eb9de8..bc14648 100644
--- a/src/analysis/blocks/flow.c
+++ b/src/analysis/blocks/flow.c
@@ -574,6 +574,7 @@ bool g_flow_block_is_looping_to(GFlowBlock *block, const GInstrBlock *list, GFlo
 
     result = (block == target);
 
+    g_arch_instruction_rlock_dest(block->last);
     dcount = g_arch_instruction_get_destinations(block->last, &dests, &types, NULL);
 
     for (i = 0; i < dcount && !result; i++)
@@ -598,6 +599,8 @@ bool g_flow_block_is_looping_to(GFlowBlock *block, const GInstrBlock *list, GFlo
 
         }
 
+    g_arch_instruction_runlock_dest(block->last);
+
     return result;
 
 }
@@ -634,6 +637,7 @@ bool g_flow_block_follow(GFlowBlock *block, const GInstrBlock *list, BlockFollow
     if (mask & BFP_ENTER)
         result = callback(block, BFP_ENTER, data);
 
+    g_arch_instruction_rlock_dest(block->last);
     dcount = g_arch_instruction_get_destinations(block->last, &dests, &types, NULL);
 
     for (i = 0; i < dcount && result; i++)
@@ -661,6 +665,8 @@ bool g_flow_block_follow(GFlowBlock *block, const GInstrBlock *list, BlockFollow
 
         }
 
+    g_arch_instruction_runlock_dest(block->last);
+
     if (mask & BFP_EXIT)
         result &= callback(block, BFP_EXIT, data);
 
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c
index fbdecd8..75b8bb7 100644
--- a/src/analysis/disass/dragon.c
+++ b/src/analysis/disass/dragon.c
@@ -146,8 +146,8 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_
 
         else
         {
+            g_arch_instruction_rlock_src(iter);
             scount = g_arch_instruction_get_sources(iter, NULL, &types);
-            if (scount == 0) continue;
 
             for (i = 0; i < scount; i++)
                 switch (types[i])
@@ -190,6 +190,8 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_
 
                 }
 
+            g_arch_instruction_runlock_src(iter);
+
         }
 
 
@@ -408,6 +410,7 @@ void compute_all_paths(dragon_node *nodes, size_t count)
         dragon_node *next;                  /* Noeud suivant dans le code  */
         size_t id;                          /* Indice du bit associé       */
 
+        g_arch_instruction_rlock_dest(node->last);
         dcount = g_arch_instruction_get_destinations(node->last, &dests, &types, NULL);
 
         for (i = 0; i < dcount; i++)
@@ -435,6 +438,8 @@ void compute_all_paths(dragon_node *nodes, size_t count)
 
             }
 
+        g_arch_instruction_runlock_dest(node->last);
+
     }
 
     follow_flow_in_nodes(&nodes[0]);
@@ -498,6 +503,7 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
 
             set_all_in_bit_field(inter);
 
+            g_arch_instruction_rlock_src(node->first);
             scount = g_arch_instruction_get_sources(node->first, &srcs, &types);
             //assert(scount > 0); // un 'ret' coupe, le suivant n'a pas de source
 
@@ -530,6 +536,8 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
 
                 }
 
+            g_arch_instruction_runlock_src(node->first);
+
             set_in_bit_field(inter, k, 1);
 
             if (!is_bit_field_equal_to(node->bits, inter))
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index 86663cc..f52029b 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -51,6 +51,7 @@ static void convert_immediate_into_target(GArchInstruction *, size_t, const GBin
 
 void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
 {
+    bool has_src;                           /* Présence de sources ?       */
     GArchInstruction **others;              /* Instructions diverses liées */
     InstructionLinkType *types;             /* Types de lien existants     */
     size_t count;                           /* Nbre de sources affichées   */
@@ -61,7 +62,11 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
      * on ne peut pas créer de lien plus naturel que l'existant.
      */
 
-    if (!g_arch_instruction_has_sources(instr))
+    g_arch_instruction_rlock_src(instr);
+    has_src = g_arch_instruction_has_sources(instr);
+    g_arch_instruction_runlock_src(instr);
+
+    if (!has_src)
         return;
 
     /**
@@ -79,6 +84,7 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
      * On s'assure que le lien naturel est valide.
      */
 
+    g_arch_instruction_rlock_dest(prev);
     count = g_arch_instruction_get_destinations(prev, &others, &types, NULL);
 
     for (i = 0; i < count; i++)
@@ -89,12 +95,15 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
         if (types[i] == ILT_LOOP) break;
     }
 
+    g_arch_instruction_runlock_dest(prev);
+
     if (count > 0 && i < count) return;
 
     /**
      * On vérifie que le lien n'existe pas déjà avant d'en créer un...
      */
 
+    g_arch_instruction_rlock_src(instr);
     count = g_arch_instruction_get_sources(instr, &others, &types);
 
     for (i = 0; i < count; i++)
@@ -103,6 +112,8 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
         if (others[i] == prev && types[i] == ILT_JUMP_IF_FALSE) break;
     }
 
+    g_arch_instruction_runlock_src(instr);
+
     if (i == count)
         g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW);
 
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index e7dbbd7..89a4bc9 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -64,8 +64,8 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
 
         get_dragon_node_bounding_instructions(node, NULL, &last);
 
+        g_arch_instruction_wlock_dest(last);
         dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
-        if (dcount == 0) continue;
 
         for (i = 0; i < dcount; i++)
             switch (types[i])
@@ -102,6 +102,8 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
 
             }
 
+        g_arch_instruction_wunlock_dest(last);
+
     }
 
 }
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index d9d20ee..6ac1fb2 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -227,6 +227,7 @@ static GInstrBlock *build_instruction_blocks(GArchProcessor *proc, const dragon_
 
         others = NULL;
 
+        g_arch_instruction_rlock_dest(last);
         dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
 
         for (i = 0; i < dcount && others == NULL; i++)
@@ -283,6 +284,7 @@ static GInstrBlock *build_instruction_blocks(GArchProcessor *proc, const dragon_
 
             }
 
+        g_arch_instruction_runlock_dest(last);
 
         if (others != NULL)
         {
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index 9b9f29e..85d9e66 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -73,6 +73,8 @@ static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GIns
     links = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
 
     g_flow_block_get_boundary(block, NULL, &last);
+
+    g_arch_instruction_rlock_dest(last);
     dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
 
     for (i = 0; i < dcount; i++)
@@ -170,6 +172,8 @@ static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GIns
 
     }
 
+    g_arch_instruction_runlock_dest(last);
+
     return true;
 
 }
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index eca2807..69cdc8a 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -80,10 +80,19 @@ struct _GArchInstruction
     GArchInstruction **from;                /* Origines des références     */
     InstructionLinkType *from_types;        /* Type des liens de dest.     */
     size_t from_count;                      /* Nombre de ces origines      */
+    GRWLock from_access;                    /* Verrou de protection        */
+#ifndef NDEBUG
+    gint hold_from_access;                  /* Suivi des verrouillages     */
+#endif
+
     GArchInstruction **to;                  /* Eventuelles lignes visées   */
     InstructionLinkType *to_types;          /* Type des liens de dest.     */
     link_extra_info *links_info;            /* Informations complémentaires*/
     size_t to_count;                        /* Nombre de ces destinations  */
+    GRWLock to_access;                      /* Verrou de protection        */
+#ifndef NDEBUG
+    gint hold_to_access;                    /* Suivi des verrouillages     */
+#endif
 
     get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés    */
     //print_instruction_fc print;             /* Imprime l'ensemble          */
@@ -91,7 +100,7 @@ struct _GArchInstruction
     //is_instruction_return_fc is_return;     /* Retour de fonction ou pas ? */
     decomp_instr_fc decomp;                 /* Procédure de décompilation  */
 
-    bool is_return;                         /* Retour de fonction ou pas ? */
+    bool is_return;                         /* Retour de fonction ou pas ? */   // FIXME : à virer
 
 };
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 46f533e..4de70b7 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -107,6 +107,12 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 
     instr->is_return = false;
 
+    g_rw_lock_init(&instr->from_access);
+    g_atomic_int_set(&instr->hold_from_access, 0);
+
+    g_rw_lock_init(&instr->to_access);
+    g_atomic_int_set(&instr->hold_to_access, 0);
+
 }
 
 
@@ -143,6 +149,9 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
 
 static void g_arch_instruction_finalize(GArchInstruction *instr)
 {
+    g_rw_lock_clear(&instr->from_access);
+    g_rw_lock_clear(&instr->to_access);
+
     G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
 
 }
@@ -558,6 +567,8 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
 
     /* Côté destination */
 
+    g_arch_instruction_wlock_src(dest);
+
     count = ++dest->from_count;
 
     dest->from = (GArchInstruction **)realloc(dest->from,
@@ -568,8 +579,12 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
     dest->from[count - 1] = instr;
     dest->from_types[count - 1] = type;
 
+    g_arch_instruction_wunlock_src(dest);
+
     /* Côté point de départ */
 
+    g_arch_instruction_wlock_dest(instr);
+
     count = ++instr->to_count;
 
     instr->to = (GArchInstruction **)realloc(instr->to,
@@ -595,6 +610,8 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
 
     va_end(ap);
 
+    g_arch_instruction_wunlock_dest(instr);
+
 }
 
 
@@ -609,17 +626,24 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
 *                                                                             *
 *  Retour      : true pour une mise à jour réussie, false sinon.              *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : Le verrou doit être posé sur les destination de 'instr'.     *
 *                                                                             *
 ******************************************************************************/
 
 bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
 {
+    bool result;                            /* Bilan à retourner           */
     size_t count;                           /* Raccourci pour la lecture   */
     size_t i;                               /* Boucle de parcours          */
     size_t from_idx;                        /* Indice côté destination     */
     size_t to_idx;                          /* Indice côté source          */
 
+    result = false;
+
+    assert(g_atomic_int_get(&instr->hold_to_access) > 0);
+
+    g_arch_instruction_wlock_src(dest);
+
     /* Côté destination */
 
     count = dest->from_count;
@@ -629,7 +653,7 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
             break;
 
     if (i == count)
-        return false;
+        goto gaicl_exit;
     else
         from_idx = i;
 
@@ -642,7 +666,7 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
             break;
 
     if (i == count)
-        return false;
+        goto gaicl_exit;
     else
         to_idx = i;
 
@@ -652,7 +676,13 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
 
     instr->to_types[to_idx] = new;
 
-    return true;
+    result = true;
+
+ gaicl_exit:
+
+    g_arch_instruction_wunlock_src(dest);
+
+    return result;
 
 
     /* TODO : si les informations complémentaires restent en place, compléter ! */
@@ -662,6 +692,46 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : collec = collection à mettre à jour.                         *
+*                write  = précise le type d'accès prévu (lecture/écriture).   *
+*                lock   = indique le sens du verrouillage à mener.            *
+*                                                                             *
+*  Description : Met à disposition un encadrement des accès aux sources.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_lock_unlock_sources(GArchInstruction *instr, bool write, bool lock)
+{
+#ifndef NDEBUG
+    if (!lock)
+        g_atomic_int_dec_and_test(&instr->hold_from_access);
+#endif
+
+    if (write)
+    {
+        if (lock) g_rw_lock_writer_lock(&instr->from_access);
+        else g_rw_lock_writer_unlock(&instr->from_access);
+    }
+    else
+    {
+        if (lock) g_rw_lock_reader_lock(&instr->from_access);
+        else g_rw_lock_reader_unlock(&instr->from_access);
+    }
+
+#ifndef NDEBUG
+    if (lock)
+        g_atomic_int_inc(&instr->hold_from_access);
+#endif
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
 *                                                                             *
 *  Description : Indique si l'instruction a une ou plusieurs origines.        *
@@ -674,6 +744,8 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
 
 bool g_arch_instruction_has_sources(const GArchInstruction *instr)
 {
+    assert(g_atomic_int_get(&instr->hold_from_access) > 0);
+
     return (instr->from_count > 0);
 
 }
@@ -695,6 +767,8 @@ bool g_arch_instruction_has_sources(const GArchInstruction *instr)
 
 size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstruction ***srcs, InstructionLinkType **types)
 {
+    assert(g_atomic_int_get(&instr->hold_from_access) > 0);
+
     if (srcs != NULL)
         *srcs = instr->from;
 
@@ -708,6 +782,46 @@ size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstru
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : collec = collection à mettre à jour.                         *
+*                write  = précise le type d'accès prévu (lecture/écriture).   *
+*                lock   = indique le sens du verrouillage à mener.            *
+*                                                                             *
+*  Description : Met à disposition un encadrement des accès aux destinations. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_lock_unlock_destinations(GArchInstruction *instr, bool write, bool lock)
+{
+#ifndef NDEBUG
+    if (!lock)
+        g_atomic_int_dec_and_test(&instr->hold_to_access);
+#endif
+
+    if (write)
+    {
+        if (lock) g_rw_lock_writer_lock(&instr->to_access);
+        else g_rw_lock_writer_unlock(&instr->to_access);
+    }
+    else
+    {
+        if (lock) g_rw_lock_reader_lock(&instr->to_access);
+        else g_rw_lock_reader_unlock(&instr->to_access);
+    }
+
+#ifndef NDEBUG
+    if (lock)
+        g_atomic_int_inc(&instr->hold_to_access);
+#endif
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
 *                                                                             *
 *  Description : Indique si l'instruction a une suite autre que la suivante.  *
@@ -720,8 +834,8 @@ size_t g_arch_instruction_get_sources(const GArchInstruction *instr, GArchInstru
 
 bool g_arch_instruction_has_destinations(const GArchInstruction *instr)
 {
-    /* FIXME !? */
-    //return (instr->to_count > 1 || (instr->to_count == 1 && instr->to_types[0] != ILT_CALL));
+    assert(g_atomic_int_get(&instr->hold_to_access) > 0);
+
     return (instr->to_count > 0);
 
 }
@@ -744,6 +858,8 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *instr)
 
 size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchInstruction ***dests, InstructionLinkType **types, link_extra_info **info)
 {
+    assert(g_atomic_int_get(&instr->hold_to_access) > 0);
+
     if (dests != NULL)
         *dests = instr->to;
 
@@ -778,6 +894,8 @@ GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstructio
 
     result = NULL;
 
+    assert(g_atomic_int_get(&instr->hold_to_access) > 0);
+
     for (i = 0; i < instr->to_count && result == NULL; i++)
         if (instr->to_types[i] == type)
             result = instr->to[i];
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 95d2e22..f26a240 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -189,12 +189,30 @@ void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, Instru
 /* Change la nature d'un lien entre deux instructions. */
 bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
 
+/* Met à disposition un encadrement des accès aux sources. */
+void g_arch_instruction_lock_unlock_sources(GArchInstruction *, bool, bool);
+
+#define g_arch_instruction_wlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, true, true)
+#define g_arch_instruction_wunlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, true, false)
+
+#define g_arch_instruction_rlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, false, true)
+#define g_arch_instruction_runlock_src(ins) g_arch_instruction_lock_unlock_sources(ins, false, false)
+
 /* Indique si l'instruction a une ou plusieurs origines. */
 bool g_arch_instruction_has_sources(const GArchInstruction *);
 
 /* Fournit les origines d'une instruction donnée. */
 size_t g_arch_instruction_get_sources(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **);
 
+/* Met à disposition un encadrement des accès aux destinations. */
+void g_arch_instruction_lock_unlock_destinations(GArchInstruction *, bool, bool);
+
+#define g_arch_instruction_wlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, true, true)
+#define g_arch_instruction_wunlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, true, false)
+
+#define g_arch_instruction_rlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, false, true)
+#define g_arch_instruction_runlock_dest(ins) g_arch_instruction_lock_unlock_destinations(ins, false, false)
+
 /* Indique si l'instruction a une suite autre que la suivante. */
 bool g_arch_instruction_has_destinations(const GArchInstruction *);
 
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index 343f916..e19cacb 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -827,6 +827,8 @@ static void g_flow_node_setup_entry_slots(GFlowNode *node)
     size_t used;                            /* Nombre de liens utilisés    */
 
     g_flow_block_get_boundary(node->block, &first, NULL);
+
+    g_arch_instruction_rlock_src(first);
     icount = g_arch_instruction_get_sources(first, &instrs, &types);
 
     usable = 0;
@@ -892,6 +894,8 @@ static void g_flow_node_setup_entry_slots(GFlowNode *node)
 
     assert(used == usable);
 
+    g_arch_instruction_runlock_src(first);
+
 }
 
 
@@ -918,6 +922,8 @@ static void g_flow_node_setup_exit_slots(GFlowNode *node)
     size_t used;                            /* Nombre de liens utilisés    */
 
     g_flow_block_get_boundary(node->block, NULL, &last);
+
+    g_arch_instruction_rlock_dest(last);
     icount = g_arch_instruction_get_destinations(last, &instrs, &types, NULL);
 
     usable = 0;
@@ -983,6 +989,8 @@ static void g_flow_node_setup_exit_slots(GFlowNode *node)
 
     assert(used == usable);
 
+    g_arch_instruction_runlock_dest(last);
+
 }
 
 
diff --git a/src/gui/dialogs/gotox.c b/src/gui/dialogs/gotox.c
index fd05100..5d19fee 100644
--- a/src/gui/dialogs/gotox.c
+++ b/src/gui/dialogs/gotox.c
@@ -269,7 +269,7 @@ GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *parent, GLoadedBinary
 *                                                                             *
 ******************************************************************************/
 
-GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBinary *binary, const GArchInstruction *instr, bool back)
+GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBinary *binary, GArchInstruction *instr, bool back)
 {
     GtkWidget *result;                      /* Fenêtre à renvoyer          */
     GtkTreeStore *store;                    /* Modèle de gestion           */
@@ -290,9 +290,15 @@ GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBi
     /* Affichage de toutes les instructions référencées */
 
     if (back)
+    {
+        g_arch_instruction_rlock_src(instr);
         count = g_arch_instruction_get_sources(instr, &list, NULL);
+    }
     else
+    {
+        g_arch_instruction_rlock_dest(instr);
         count = g_arch_instruction_get_destinations(instr, &list, NULL, NULL);
+    }
 
     for (i = 0; i < count; i++)
     {
@@ -302,6 +308,11 @@ GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBi
 
     }
 
+    if (back)
+        g_arch_instruction_runlock_src(instr);
+    else
+        g_arch_instruction_runlock_dest(instr);
+
     g_object_unref(G_OBJECT(store));
 
     gtk_dialog_set_response_sensitive(GTK_DIALOG(result), GTK_RESPONSE_OK, count > 0);
diff --git a/src/gui/dialogs/gotox.h b/src/gui/dialogs/gotox.h
index ab17d42..4284ae8 100644
--- a/src/gui/dialogs/gotox.h
+++ b/src/gui/dialogs/gotox.h
@@ -37,7 +37,7 @@
 GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *, GLoadedBinary *);
 
 /* Construit la fenêtre de sélection des références croisées. */
-GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *, GLoadedBinary *, const GArchInstruction *, bool);
+GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *, GLoadedBinary *, GArchInstruction *, bool);
 
 /* Fournit l'adresse obtenue par la saisie de l'utilisateur. */
 vmpa2t *get_address_from_gotox_dialog(GtkWidget *);
-- 
cgit v0.11.2-87-g4458