From 6906aa19b7ac4c14615c30d15bfb26b0b86557d5 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 13 Apr 2017 18:34:34 +0200
Subject: Simplified the way links between instructions are handled.

---
 ChangeLog                          |  24 +++
 plugins/androhelpers/switch.c      |   2 +-
 plugins/androhelpers/try_n_catch.c |   6 +-
 plugins/libcsem/exit.c             |  15 +-
 src/analysis/db/items/comment.c    |   8 +-
 src/analysis/decomp/il.c           |  16 +-
 src/analysis/disass/dragon.c       |  64 +++++---
 src/analysis/disass/links.c        |  47 ++++--
 src/analysis/disass/loop.c         |  19 ++-
 src/analysis/disass/rank.c         |  28 ++--
 src/analysis/routine.c             |  22 +--
 src/arch/instruction-int.h         |  31 ++--
 src/arch/instruction.c             | 296 +++++++++++--------------------------
 src/arch/instruction.h             |  35 ++---
 src/debug/debugger.c               |  19 ++-
 src/gtkext/graph/cluster.c         |  42 ++++--
 src/gui/dialogs/gotox.c            |  46 ++++--
 17 files changed, 349 insertions(+), 371 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5e243a0..fb22623 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+17-04-13  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/androhelpers/switch.c:
+	* plugins/androhelpers/try_n_catch.c:
+	* plugins/libcsem/exit.c:
+	* src/analysis/db/items/comment.c:
+	* src/analysis/decomp/il.c:
+	* src/analysis/disass/dragon.c:
+	* src/analysis/disass/links.c:
+	* src/analysis/disass/loop.c:
+	* src/analysis/disass/rank.c:
+	* src/analysis/routine.c:
+	Update code.
+
+	* src/arch/instruction-int.h:
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	Simplify the way links between instructions are handled.
+
+	* src/debug/debugger.c:
+	* src/gtkext/graph/cluster.c:
+	* src/gui/dialogs/gotox.c:
+	Update code.
+
 17-04-09  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/glibext/gbinportion.c:
diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c
index 275a6e7..20e6037 100644
--- a/plugins/androhelpers/switch.c
+++ b/plugins/androhelpers/switch.c
@@ -219,7 +219,7 @@ static void ensure_each_case_has_its_block(GArchInstruction *instr, GArchInstruc
     prev = g_arch_instruction_get_prev_iter(instrs, instr);
 
     if (prev != NULL
-        && !g_arch_instruction_has_destinations(prev)
+        && g_arch_instruction_count_destinations(prev) == 0
         && !(g_arch_instruction_get_flags(prev) & AIF_RETURN_POINT))
     {
         g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW);
diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c
index 9052377..5dff71e 100644
--- a/plugins/androhelpers/try_n_catch.c
+++ b/plugins/androhelpers/try_n_catch.c
@@ -135,13 +135,13 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r
 
     /* Si des détachements sont nécessaires... */
 
-    if (!g_arch_instruction_has_sources(first) && try->start_addr > 0)
+    if (g_arch_instruction_count_sources(first) == 0 && try->start_addr > 0)
     {
         prev = g_arch_instruction_get_prev_iter(instrs, first);
         g_arch_instruction_link_with(prev, first, ILT_EXEC_FLOW);
     }
 
-    if (!g_arch_instruction_has_sources(next) && (try->start_addr > 0 || try->insn_count > 0))
+    if (g_arch_instruction_count_sources(next) == 0 && (try->start_addr > 0 || try->insn_count > 0))
     {
         prev = g_arch_instruction_get_prev_iter(instrs, next);
         g_arch_instruction_link_with(prev, next, ILT_EXEC_FLOW);
@@ -155,7 +155,7 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r
              iter != NULL;
              iter = g_arch_instruction_get_next_iter(instrs, iter, end))
         {
-            if (!g_arch_instruction_has_destinations(iter))
+            if (g_arch_instruction_count_destinations(iter) == 0)
                 continue;
 
             for (i = 0; i < count; i++)
diff --git a/plugins/libcsem/exit.c b/plugins/libcsem/exit.c
index 6695787..6a21d5f 100644
--- a/plugins/libcsem/exit.c
+++ b/plugins/libcsem/exit.c
@@ -52,9 +52,9 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c
     const mrange_t *range;                  /* Emplacement du symbole      */
     GArchProcessor *proc;                   /* Architecture du binaire     */
     GArchInstruction *instr;                /* Instruction de sortie       */
-    instr_link_t *sources;                  /* Instructions diverses liées */
     size_t count;                           /* Nbre de sources affichées   */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *source;                   /* Instruction diverse liée    */
 
     format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
 
@@ -73,18 +73,21 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c
     if (instr == NULL)
         goto mokoear_not_found;
 
-    g_arch_instruction_rlock_src(instr);
-    count = g_arch_instruction_get_sources(instr, &sources);
+    g_arch_instruction_lock_src(instr);
+
+    count = g_arch_instruction_count_sources(instr);
 
     for (i = 0; i < count; i++)
     {
-        if (sources[i].type != ILT_CALL) continue;
+        source = g_arch_instruction_get_source(instr, i);
+
+        if (source->type != ILT_CALL) continue;
 
-        g_arch_instruction_set_flag(sources[i].linked, AIF_RETURN_POINT);
+        g_arch_instruction_set_flag(source->linked, AIF_RETURN_POINT);
 
     }
 
-    g_arch_instruction_runlock_src(instr);
+    g_arch_instruction_unlock_src(instr);
 
     g_object_unref(G_OBJECT(instr));
 
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
index 263f415..b43c1e6 100644
--- a/src/analysis/db/items/comment.c
+++ b/src/analysis/db/items/comment.c
@@ -581,9 +581,9 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
     size_t index;                           /* Point d'insertion           */
     GArchProcessor *proc;                   /* Propriétaire d'instructions */
     GArchInstruction *instr;                /* Instruction à traiter       */
-    instr_link_t *sources;                  /* Instructions diverses liées */
     size_t scount;                          /* Nbre de sources affichées   */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *source;                   /* Instruction diverse liée    */
     const mrange_t *range;                  /* Emplacement d'instruction   */
     size_t linked;                          /* Indice lié à traiter        */
 
@@ -631,7 +631,7 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
             instr = g_arch_processor_find_instr_by_address(proc, &comment->addr);
             assert(instr != NULL);
 
-            scount = g_arch_instruction_get_sources(instr, &sources);
+            scount = g_arch_instruction_count_sources(instr);
 
             if (apply)
             {
@@ -642,7 +642,9 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
 
             for (i = 0; i < scount && result; i++)
             {
-                range = g_arch_instruction_get_range(sources[i].linked);
+                source = g_arch_instruction_get_source(instr, i);
+
+                range = g_arch_instruction_get_range(source->linked);
 
                 /**
                  * On recherche ici une ligne potentiellement BLF_HAS_CODE ou BLF_IS_LABEL.
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index e8ca49e..f409550 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -559,6 +559,8 @@ static void build_ite_branches(GITEInstruction *decomp, GFlowBlock *block, GDecC
             g_object_unref(G_OBJECT(sub_ctx));
         }
 
+        g_object_unref(G_OBJECT(next));
+
     }
 
     /* Branche 'false' */
@@ -576,6 +578,8 @@ static void build_ite_branches(GITEInstruction *decomp, GFlowBlock *block, GDecC
             g_object_unref(G_OBJECT(sub_ctx));
         }
 
+        g_object_unref(G_OBJECT(next));
+
     }
 
     g_ite_instruction_set_branches(decomp, true_dinstr, false_dinstr);
@@ -610,9 +614,9 @@ static void close_case_decomp_instructions(GDecInstruction *case_dinstr, GInstrB
     vmpa_t common_addr;                     /* Adresse commune de suite    */
     bool is_common;                         /* Suite commune ?             */
     GArchInstruction *last;                 /* Dernière instruction de bloc*/
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t j;                               /* Boucle de parcours #2       */
+    instr_link_t *dest;                     /* Instr. visée par une autre  */
     vmpa_t addr;                            /* Adresse d'une instruction   */
     bool jump_to_case;                      /* Suite dans le cas suivant ? */
 
@@ -638,11 +642,15 @@ static void close_case_decomp_instructions(GDecInstruction *case_dinstr, GInstrB
     for (i = 0; i < lcount && is_common; i++)
     {
         g_flow_block_get_boundary(G_FLOW_BLOCK(leafs[i]), NULL, &last);
-        dcount = g_arch_instruction_get_destinations(last, &dests);
+
+        g_arch_instruction_lock_dest(last);
+        dcount = g_arch_instruction_count_destinations(last);
 
         for (j = 0; j < dcount && is_common; j++)
         {
-            g_arch_instruction_get_location(dests[j].linked, NULL, NULL, &addr);
+            dest = g_arch_instruction_get_destination(last, j);
+
+            g_arch_instruction_get_location(dest->linked, NULL, NULL, &addr);
 
             if (common_addr == VMPA_MAX)
                 common_addr = addr;
@@ -651,6 +659,8 @@ static void close_case_decomp_instructions(GDecInstruction *case_dinstr, GInstrB
 
         }
 
+        g_arch_instruction_unlock_dest(last);
+
     }
 
     /* La sortie du cas est unique ! */
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c
index b4c85c0..75ccc40 100644
--- a/src/analysis/disass/dragon.c
+++ b/src/analysis/disass/dragon.c
@@ -101,13 +101,13 @@ static dragon_node *create_dragon_nodes(GArchProcessor *proc, const instr_covera
     GArchInstruction *last;                 /* Mémorisation du passé       */
     instr_iter_t *iter;                     /* Boucle de parcours          */
     GArchInstruction *instr;                /* Instruction analysée        */
-    instr_link_t *sources;                  /* Liste des instructions liées*/
     size_t scount;                          /* Nombre de liens de source   */
     bool cut;                               /* Un découpage a été réalisé ?*/
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *source;                   /* Instruction de source liée  */
     dragon_node *new;                       /* Nouvel élément à créer      */
-    instr_link_t *dests;                    /* Liste des instructions liées*/
     size_t dcount;                          /* Nombre de liens de dest.    */
+    instr_link_t *dest;                     /* Instruction de destination  */
 
     result = NULL;
     *count = 0;
@@ -163,13 +163,16 @@ static dragon_node *create_dragon_nodes(GArchProcessor *proc, const instr_covera
         {
             /* Analyse des sources */
 
-            g_arch_instruction_rlock_src(instr);
-            scount = g_arch_instruction_get_sources(instr, &sources);
+            g_arch_instruction_lock_src(instr);
+            scount = g_arch_instruction_count_sources(instr);
 
             cut = false;
 
             for (i = 0; i < scount && !cut; i++)
-                switch (sources[i].type)
+            {
+                source = g_arch_instruction_get_source(instr, i);
+
+                switch (source->type)
                 {
                     case ILT_EXEC_FLOW:
                     case ILT_JUMP:
@@ -201,19 +204,24 @@ static dragon_node *create_dragon_nodes(GArchProcessor *proc, const instr_covera
 
                 }
 
-            g_arch_instruction_runlock_src(instr);
+            }
+
+            g_arch_instruction_unlock_src(instr);
 
         }
 
         /* Analyse des destinations */
 
-        g_arch_instruction_rlock_dest(instr);
-        dcount = g_arch_instruction_get_destinations(instr, &dests);
+        g_arch_instruction_lock_dest(instr);
+        dcount = g_arch_instruction_count_destinations(instr);
 
         cut = false;
 
         for (i = 0; i < dcount && !cut; i++)
-            switch (dests[i].type)
+        {
+            dest = g_arch_instruction_get_destination(instr, i);
+
+            switch (dest->type)
             {
                 case ILT_JUMP:
 
@@ -230,7 +238,9 @@ static dragon_node *create_dragon_nodes(GArchProcessor *proc, const instr_covera
 
             }
 
-        g_arch_instruction_runlock_dest(instr);
+        }
+
+        g_arch_instruction_unlock_dest(instr);
 
         if (!need_alloc && g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT)
         {
@@ -436,17 +446,20 @@ void compute_all_paths(dragon_node *nodes, size_t count)
 {
     void follow_flow_in_nodes(dragon_node *node)
     {
-        instr_link_t *dests;                /* Liste des instructions liées*/
         size_t dcount;                      /* Nombre de liens de dest.    */
         size_t i;                           /* Boucle de parcours          */
+        instr_link_t *dest;                 /* Instructions de destination */
         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);
+        g_arch_instruction_lock_dest(node->last);
+        dcount = g_arch_instruction_count_destinations(node->last);
 
         for (i = 0; i < dcount; i++)
-            switch (dests[i].type)
+        {
+            dest = g_arch_instruction_get_destination(node->last, i);
+
+            switch (dest->type)
             {
                 case ILT_EXEC_FLOW:
                 case ILT_JUMP:
@@ -454,7 +467,7 @@ void compute_all_paths(dragon_node *nodes, size_t count)
                 case ILT_JUMP_IF_TRUE:
                 case ILT_JUMP_IF_FALSE:
 
-                    next = find_node_for_instruction(nodes, count, false, dests[i].linked);
+                    next = find_node_for_instruction(nodes, count, false, dest->linked);
                     if (next == NULL) break;
 
                     id = get_dragon_node_index(nodes, next);
@@ -470,7 +483,9 @@ void compute_all_paths(dragon_node *nodes, size_t count)
 
             }
 
-        g_arch_instruction_runlock_dest(node->last);
+        }
+
+        g_arch_instruction_unlock_dest(node->last);
 
     }
 
@@ -518,9 +533,9 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
     size_t k;                               /* Boucle de parcours #1       */
     dragon_node *node;                      /* Noeud à traiter             */
     dragon_node *predecessor;               /* Noeud prédécesseur direct   */
-    instr_link_t *sources;                  /* Instructions d'origine      */
     size_t scount;                          /* Nombre de liens de source   */
     size_t i;                               /* Boucle de parcours #2       */
+    instr_link_t *source;                   /* Instruction d'origine       */
 
     inter = create_bit_field(count, false);
 
@@ -534,12 +549,15 @@ 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, &sources);
+            g_arch_instruction_lock_src(node->first);
+            scount = g_arch_instruction_count_sources(node->first);
             //assert(scount > 0); // un 'ret' coupe, le suivant n'a pas de source
 
             for (i = 0; i < scount; i++)
-                switch (sources[i].type)
+            {
+                source = g_arch_instruction_get_source(node->first, i);
+
+                switch (source->type)
                 {
                     case ILT_EXEC_FLOW:
                     case ILT_JUMP:
@@ -547,7 +565,7 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
                     case ILT_JUMP_IF_TRUE:
                     case ILT_JUMP_IF_FALSE:
 
-                        predecessor = find_node_for_instruction(nodes, count, true, sources[i].linked);
+                        predecessor = find_node_for_instruction(nodes, count, true, source->linked);
 
                         /*
                         printf("  -- finding pred @ 0x%08x -> 0x%08x :: %p\n",
@@ -567,7 +585,9 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
 
                 }
 
-            g_arch_instruction_runlock_src(node->first);
+            }
+
+            g_arch_instruction_unlock_src(node->first);
 
             set_in_bit_field(inter, k, 1);
 
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index d67040b..e1bc58c 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -53,9 +53,9 @@ static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat
 
 void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
 {
-    bool has_src;                           /* Présence de sources ?       */
-    instr_link_t *others;                   /* Instructions diverses liées */
     size_t count;                           /* Nbre de sources affichées   */
+    bool has_src;                           /* Présence de sources ?       */
+    instr_link_t *other;                    /* Instruction diverse liée    */
     size_t i;                               /* Boucle de parcours          */
     bool no_natural;                        /* Aucun lien naturel présent  */
     bool no_need;                           /* Pas de besoin pour ce lien  */
@@ -65,17 +65,22 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
      * on ne peut pas créer de lien plus naturel que l'existant.
      */
 
-    g_arch_instruction_rlock_src(instr);
+    g_arch_instruction_lock_src(instr);
 
-    count = g_arch_instruction_get_sources(instr, &others);
+    count = g_arch_instruction_count_sources(instr);
 
     has_src = false;
 
     for (i = 0; i < count && !has_src; i++)
-        if (others[i].type != ILT_REF)
+    {
+        other = g_arch_instruction_get_source(instr, i);
+
+        if (other->type != ILT_REF)
             has_src = true;
 
-    g_arch_instruction_runlock_src(instr);
+    }
+
+    g_arch_instruction_unlock_src(instr);
 
     if (!has_src)
         return;
@@ -96,15 +101,18 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
      * déjà en place.
      */
 
-    g_arch_instruction_rlock_dest(prev);
+    g_arch_instruction_lock_dest(prev);
 
-    count = g_arch_instruction_get_destinations(prev, &others);
+    count = g_arch_instruction_count_destinations(prev);
 
     no_natural = true;
     no_need = (count > 0);
 
     for (i = 0; i < count && no_natural; i++)
-        switch (others[i].type)
+    {
+        other = g_arch_instruction_get_destination(prev, i);
+
+        switch (other->type)
         {
             case ILT_EXEC_FLOW:
                 no_natural = false;
@@ -112,7 +120,7 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
 
             case ILT_JUMP_IF_TRUE:
             case ILT_JUMP_IF_FALSE:
-                if (others[i].linked != instr)
+                if (other->linked != instr)
                     no_need = false;
                 else
                 {
@@ -126,20 +134,25 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
 
         }
 
+    }
+
  check_done:
 
-    g_arch_instruction_runlock_dest(prev);
+    g_arch_instruction_unlock_dest(prev);
 
     if (no_natural && !no_need)
     {
         /* Vérification de la cohérence de l'ensemble */
 #ifndef NDEBUG
 
-        g_arch_instruction_rlock_src(instr);
-        count = g_arch_instruction_get_sources(instr, &others);
+        g_arch_instruction_lock_src(instr);
+        count = g_arch_instruction_count_sources(instr);
 
         for (i = 0; i < count; i++)
-            switch (others[i].type)
+        {
+            other = g_arch_instruction_get_source(instr, i);
+
+            switch (other->type)
             {
                 case ILT_EXEC_FLOW:
                     assert(false);
@@ -151,7 +164,7 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
                 case ILT_JUMP_IF_FALSE:
                 case ILT_LOOP:
                 case ILT_CATCH_EXCEPTION:
-                    assert(others[i].linked != prev);
+                    assert(other->linked != prev);
                     break;
 
                 default:
@@ -159,7 +172,9 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
 
             }
 
-        g_arch_instruction_runlock_src(instr);
+        }
+
+        g_arch_instruction_unlock_src(instr);
 
 #endif
 
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index d8ca355..b7e7ff9 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -49,9 +49,9 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
     dragon_node *node;                      /* Noeud à traiter             */
     const bitfield_t *dominators;           /* Liste de dominateurs        */
     GArchInstruction *last;                 /* Instruction finale de noeud */
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours #2       */
+    instr_link_t *dest;                     /* Instr. visée par une autre  */
     dragon_node *target;                    /* Noeud référence à tester    */
     size_t id;                              /* Indice du bit associé       */
 
@@ -63,11 +63,14 @@ 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);
+        g_arch_instruction_lock_dest(last);
+        dcount = g_arch_instruction_count_destinations(last);
 
         for (i = 0; i < dcount; i++)
-            switch (dests[i].type)
+        {
+            dest = g_arch_instruction_get_destination(last, i);
+
+            switch (dest->type)
             {
                 case ILT_EXEC_FLOW:
                 case ILT_JUMP:
@@ -75,7 +78,7 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
                 case ILT_JUMP_IF_TRUE:
                 case ILT_JUMP_IF_FALSE:
 
-                    target = find_node_for_instruction(nodes, count, false, dests[i].linked);
+                    target = find_node_for_instruction(nodes, count, false, dest->linked);
                     if (target == NULL) break;
 
                     id = get_dragon_node_index(nodes, target);
@@ -89,7 +92,7 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
                                (unsigned int)g_arch_instruction_get_range(dests[i])->addr.virtual);
                         */
 
-                        /* status = */g_arch_instruction_change_link(last, dests[i].linked, dests[i].type, ILT_LOOP);
+                        /* status = */g_arch_instruction_change_link(last, dest->linked, dest->type, ILT_LOOP);
 
 
                     }
@@ -101,7 +104,9 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
 
             }
 
-        g_arch_instruction_wunlock_dest(last);
+        }
+
+        g_arch_instruction_unlock_dest(last);
 
     }
 
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index 3f4cd9f..6ff194b 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -61,9 +61,9 @@ static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GIns
     unsigned int next;                      /* Rang suivant obtenu         */
     GInstrBlock *links;                     /* Blocs liés au bloc courant  */
     GArchInstruction *last;                 /* Dernière instruction du bloc*/
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours          */
+    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           */
@@ -77,14 +77,16 @@ static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GIns
 
     g_flow_block_get_boundary(block, NULL, &last);
 
-    g_arch_instruction_rlock_dest(last);
-    dcount = g_arch_instruction_get_destinations(last, &dests);
+    g_arch_instruction_lock_dest(last);
+    dcount = g_arch_instruction_count_destinations(last);
 
     for (i = 0; i < dcount; i++)
     {
-        range = g_arch_instruction_get_range(dests[i].linked);
+        dest = g_arch_instruction_get_destination(last, i);
 
-        switch (dests[i].type)
+        range = g_arch_instruction_get_range(dest->linked);
+
+        switch (dest->type)
         {
             case ILT_EXEC_FLOW:
             case ILT_CATCH_EXCEPTION:
@@ -175,7 +177,7 @@ static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GIns
 
     }
 
-    g_arch_instruction_runlock_dest(last);
+    g_arch_instruction_unlock_dest(last);
 
     return true;
 
@@ -304,9 +306,9 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)
 {
     unsigned int next;                      /* Rang suivant obtenu         */
     GArchInstruction *last;                 /* Dernière instruction du bloc*/
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours          */
+    instr_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           */
@@ -315,12 +317,14 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)
 
     g_basic_block_get_boundary(block, NULL, &last);
 
-    g_arch_instruction_rlock_dest(last);
-    dcount = g_arch_instruction_get_destinations(last, &dests);
+    g_arch_instruction_lock_dest(last);
+    dcount = g_arch_instruction_count_destinations(last);
 
     for (i = 0; i < dcount; i++)
     {
-        type = dests[i].type;
+        dest = g_arch_instruction_get_destination(last, i);
+
+        type = dest->type;
 
         /* La boucle de remontée n'abaisse pas les rangs */
         if (type == ILT_LOOP) continue;
@@ -337,7 +341,7 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)
             && type != ILT_JUMP_IF_FALSE)
             continue;
 
-        target = g_block_list_find_by_starting_instr(list, dests[i].linked);
+        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.
@@ -366,7 +370,7 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block)
 
     }
 
-    g_arch_instruction_runlock_dest(last);
+    g_arch_instruction_unlock_dest(last);
 
 }
 
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index f84a5fd..583e151 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -1169,9 +1169,9 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
     GBufferCache *cache;                    /* Tampon de désassemblage     */
     instr_iter_t *iter;                     /* Parcours local d'adresses   */
     GArchInstruction *instr;                /* Instruction correspondante  */
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *dest;                     /* Instr. visée par une autre  */
     const mrange_t *irange;                 /* Emplacement d'instruction   */
     size_t index;                           /* Indice de ligne à traiter   */
     GBufferLine *line;                      /* Ligne présente à l'adresse  */
@@ -1180,7 +1180,6 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
 
     result = NULL;
 
-
     config = get_main_configuration();
 
     if (!g_generic_config_get_value(config, MPK_TOOLTIP_MAX_CALLS, &max_calls))
@@ -1219,11 +1218,14 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
 
         /* Appels ? */
 
-        g_arch_instruction_rlock_dest(instr);
-        dcount = g_arch_instruction_get_destinations(instr, &dests);
+        g_arch_instruction_lock_dest(instr);
+        dcount = g_arch_instruction_count_destinations(instr);
 
         for (i = 0; i < dcount; i++)
-            switch (dests[i].type)
+        {
+            dest = g_arch_instruction_get_destination(instr, i);
+
+            switch (dest->type)
             {
                 case ILT_CALL:
 
@@ -1272,10 +1274,10 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
 
                 case ILT_REF:
 
-                    if (!G_IS_RAW_INSTRUCTION(dests[i].linked))
+                    if (!G_IS_RAW_INSTRUCTION(dest->linked))
                         continue;
 
-                    if (!g_raw_instruction_is_string(G_RAW_INSTRUCTION(dests[i].linked)))
+                    if (!g_raw_instruction_is_string(G_RAW_INSTRUCTION(dest->linked)))
                         continue;
 
                     string_count++;
@@ -1289,7 +1291,7 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
                         continue;
                     }
 
-                    irange = g_arch_instruction_get_range(dests[i].linked);
+                    irange = g_arch_instruction_get_range(dest->linked);
 
                     index = g_buffer_cache_find_index_by_addr(cache, get_mrange_addr(irange), true);
 
@@ -1326,7 +1328,9 @@ char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBi
 
             }
 
-        g_arch_instruction_runlock_dest(instr);
+        }
+
+        g_arch_instruction_unlock_dest(instr);
 
         g_object_unref(G_OBJECT(instr));
 
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index beb6b50..b7bd5f3 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -60,22 +60,13 @@ struct _GArchInstruction
     /**
      * Il existe le besoin indéniable d'un verrou pour les accès aux instructions
      * liées. Il faut par ailleurs un verrou distinct pour les sources et les
-     * destination car une même instruction peut boucler sur elle même et la
+     * destinations car une même instruction peut boucler sur elle même et la
      * fonction g_arch_instruction_change_link() pose des verrous sur les
      * deux extrémités.
      *
-     * Par ailleurs, la consommation mémoire augmente vite : GRWLock pèse 16
-     * octets et size_t mesure la taille d'un long sur 64 bits.
-     *
-     * Que ce soit avec les pointeurs (un allocateur aligne généralement les
-     * adresses retournées) ou avec les tailles (il est peu probable d'avoir
-     * 0x80000000 instructions d'origine), on dispose d'espace mémoire inutilisé
-     * adapté pour compresser la structure GArchInstruction.
-     *
-     * La GLib propose incidemment des fonctions g_bit_lock() / g_bit_unlock()...
-     *
-     * On perd au passage la distinction entre les accès en lecture et ceux en
-     * écriture, mais tant pis : la réduction de l'empreinte mémoire prime !
+     * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais
+     * sans distinction entre lectures et écritures. Tant pis : la réduction de
+     * l'empreinte mémoire prime !
      *
      * Par contre la documentation indique :
      *
@@ -83,23 +74,19 @@ struct _GArchInstruction
      * Attempting to lock on two different bits within the same integer is not supported.
      * """
      *
-     * Donc on conserve un compteur distinct pour chaque extrémité.
+     * Donc on doit bien conserver un compteur distinct pour chaque extrémité.
+     * Cela correspond de toute façon à la définition optimisée des tableaux
+     * suivante.
      */
 
-    instr_link_t *from;                     /* Origines des références     */
-    instr_link_t *to;                       /* Instructions visées         */
-    gint from_count;                        /* Nombre de ces origines      */
-    gint to_count;                          /* Nombre de ces destinations  */
+    flat_array_t *from;                     /* Origines des références     */
+    flat_array_t *to;                       /* Instructions visées         */
 
     ArchInstrFlag flags;                    /* Informations complémentaires*/
 
 };
 
 
-/* Bit de verrou pour les champs (from|to)_count */
-#define INSTR_LINK_LOCK_BIT 31
-
-
 /* Définition générique d'une instruction d'architecture (classe) */
 struct _GArchInstructionClass
 {
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 4bb2e2d..14e78dc 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -51,29 +51,6 @@ static void g_arch_instruction_finalize(GArchInstruction *);
 
 
 
-/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
-
-
-/* Dénombre les liens présents à une extrémité donnée. */
-static size_t g_arch_instruction_get_link_counter(GArchInstruction *, bool);
-
-#define g_arch_instruction_get_source_counter(ins) \
-    g_arch_instruction_get_link_counter(ins, true)
-
-#define g_arch_instruction_get_destination_counter(ins) \
-    g_arch_instruction_get_link_counter(ins, false)
-
-/* Incrémente le nombre de liens définis à une extrémité donnée. */
-static size_t g_arch_instruction_inc_link_counter(GArchInstruction *, bool);
-
-#define g_arch_instruction_inc_source_counter(ins) \
-    g_arch_instruction_inc_link_counter(ins, true)
-
-#define g_arch_instruction_inc_destination_counter(ins) \
-    g_arch_instruction_inc_link_counter(ins, false)
-
-
-
 /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
 
 
@@ -147,8 +124,8 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 {
     instr->operands = NULL;
 
-    instr->from_count = 0;
-    instr->to_count = 0;
+    instr->from = NULL;
+    instr->to = NULL;
 
 }
 
@@ -657,7 +634,6 @@ void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
 *                                                                             *
 *  Paramètres  : instr = instruction à mettre à jour.                         *
 *                src   = sélection de l'extrémité à traiter.                  *
-*                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 liens.        *
@@ -668,80 +644,16 @@ void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool write, bool lock)
+void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock)
 {
-    volatile gint *address;                 /* Choix de l'entier à traiter */
+    flat_array_t **array;                   /* Choix du tableau ciblé      */
 
-    address = (src ? &instr->from_count : &instr->to_count);
+    array = (src ? &instr->from : &instr->to);
 
     if (lock)
-        g_bit_lock(address, INSTR_LINK_LOCK_BIT);
+        lock_flat_array(array);
     else
-        g_bit_unlock(address, INSTR_LINK_LOCK_BIT);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
-*                src   = sélection de l'extrémité à traiter.                  *
-*                                                                             *
-*  Description : Dénombre les liens présents à une extrémité donnée.          *
-*                                                                             *
-*  Retour      : Quantité positive.                                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t g_arch_instruction_get_link_counter(GArchInstruction *instr, bool src)
-{
-    size_t result;                          /* Nombre de liens à renvoyer  */
-    volatile gint *address;                 /* Choix de l'entier à traiter */
-
-    address = (src ? &instr->from_count : &instr->to_count);
-
-    assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
-
-    result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
-*                src   = sélection de l'extrémité à traiter.                  *
-*                                                                             *
-*  Description : Incrémente le nombre de liens définis à une extrémité donnée.*
-*                                                                             *
-*  Retour      : Nouvelle quantité mise à jour.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t g_arch_instruction_inc_link_counter(GArchInstruction *instr, bool src)
-{
-    size_t result;                          /* Nombre de liens à renvoyer  */
-    volatile gint *address;                 /* Choix de l'entier à traiter */
-
-    address = (src ? &instr->from_count : &instr->to_count);
-
-    assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
-
-    result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
-
-    result++;
-
-    assert((result & (1 << INSTR_LINK_LOCK_BIT)) == 0);
-
-    g_atomic_int_set(address, (1 << INSTR_LINK_LOCK_BIT) | result);
-
-    return result;
+        unlock_flat_array(array);
 
 }
 
@@ -764,18 +676,23 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
     bool result;                            /* Bilan à retourner           */
     size_t count;                           /* Nombre de liens à parcourir */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *dlink;                    /* Définition de destination   */
 
     result = false;
 
-    g_arch_instruction_rlock_dest(instr);
+    g_arch_instruction_lock_dest(instr);
 
-    count = g_arch_instruction_get_destination_counter(instr);
+    count = g_arch_instruction_count_destinations(instr);
 
     for (i = 0; i < count && !result; i++)
-        if (instr->to[i].linked == dest)
-            result = true;
+    {
+        dlink = g_arch_instruction_get_destination(instr, i);
 
-    g_arch_instruction_runlock_dest(instr);
+        result = (dlink->linked == dest);
+
+    }
+
+    g_arch_instruction_unlock_dest(instr);
 
     return result;
 
@@ -798,38 +715,30 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
 
 void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
 {
-    size_t count;                           /* Raccourci pour la lecture   */
-    instr_link_t *new;                      /* Nouveau lien à définir      */
+    instr_link_t new_src;                   /* Nouveau lien à définir #1   */
+    instr_link_t new_dst;                   /* Nouveau lien à définir #2   */
 
     /* Côté destination */
 
-    g_arch_instruction_wlock_src(dest);
-
-    count = g_arch_instruction_inc_source_counter(dest);
-
-    dest->from = (instr_link_t *)realloc(dest->from, count * sizeof(instr_link_t));
-
-    new = &dest->from[count - 1];
-
-    new->linked = instr;
-    new->type = type;
-
-    g_arch_instruction_wunlock_src(dest);
+    new_src.linked = instr;
+    new_src.type = type;
 
     /* Côté point de départ */
 
-    g_arch_instruction_wlock_dest(instr);
+    new_dst.linked = dest;
+    new_dst.type = type;
 
-    count = g_arch_instruction_inc_destination_counter(instr);
+    /* Ajout dans le respect d'une cohérence globale */
 
-    instr->to = (instr_link_t *)realloc(instr->to, count * sizeof(instr_link_t));
+    g_arch_instruction_lock_src(dest);
+    g_arch_instruction_lock_dest(instr);
 
-    new = &instr->to[count - 1];
+    add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t));
 
-    new->linked = dest;
-    new->type = type;
+    add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t));
 
-    g_arch_instruction_wunlock_dest(instr);
+    g_arch_instruction_unlock_dest(instr);
+    g_arch_instruction_unlock_src(dest);
 
 }
 
@@ -845,7 +754,7 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
 *                                                                             *
 *  Retour      : true pour une mise à jour réussie, false sinon.              *
 *                                                                             *
-*  Remarques   : Le verrou doit être posé sur les destination de 'instr'.     *
+*  Remarques   : Le verrou doit être posé sur les destinations de 'instr'.    *
 *                                                                             *
 ******************************************************************************/
 
@@ -854,52 +763,56 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
     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          */
+    instr_link_t *slink;                    /* Définition de source        */
+    instr_link_t *dlink;                    /* Définition de destination   */
 
     result = false;
 
-    assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
-
-    g_arch_instruction_wlock_src(dest);
+    g_arch_instruction_lock_src(dest);
 
     /* Côté destination */
 
-    count = g_arch_instruction_get_source_counter(dest);
+    count = g_arch_instruction_count_sources(dest);
 
     for (i = 0; i < count; i++)
-        if (dest->from[i].linked == instr && dest->from[i].type == old)
+    {
+        slink = g_arch_instruction_get_source(dest, i);
+
+        if (slink->linked == instr && slink->type == old)
             break;
 
+    }
+
     if (i == count)
         goto gaicl_exit;
-    else
-        from_idx = i;
 
     /* Côté point de départ */
 
-    count = g_arch_instruction_get_destination_counter(instr);
+    count = g_arch_instruction_count_destinations(instr);
 
     for (i = 0; i < count; i++)
-        if (instr->to[i].linked == dest && instr->to[i].type == old)
+    {
+        dlink = g_arch_instruction_get_destination(instr, i);
+
+        if (dlink->linked == dest && dlink->type == old)
             break;
 
+    }
+
     if (i == count)
         goto gaicl_exit;
-    else
-        to_idx = i;
 
     /* Si les deux extrémités sont raccord... */
 
-    dest->from[from_idx].type = new;
+    slink->type = new;
 
-    instr->to[to_idx].type = new;
+    dlink->type = new;
 
     result = true;
 
  gaicl_exit:
 
-    g_arch_instruction_wunlock_src(dest);
+    g_arch_instruction_unlock_src(dest);
 
     return result;
 
@@ -910,48 +823,45 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
 *                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
 *                                                                             *
-*  Description : Indique si l'instruction a une ou plusieurs origines.        *
+*  Description : Fournit la quantité d'instructions pointant vers une autre.  *
 *                                                                             *
-*  Retour      : Bilan de la consultation.                                    *
+*  Retour      : Nombre de ces origines.                                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_arch_instruction_has_sources(GArchInstruction *instr)
+size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
 {
-    size_t count;                           /* Nombre de liens présents    */
-
-    assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
+    size_t result;                          /* Nombre de liens à renvoyer  */
 
-    count = g_arch_instruction_get_source_counter(instr);
+    result = count_flat_array_items(instr->from);
 
-    return (count > 0);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : instr   = instruction dont les informations sont à consulter.*
-*                sources = liste des liens aux instructions d'origine. [OUT]  *
+*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
+*                index = indice de l'élément à retrouver.                     *
 *                                                                             *
-*  Description : Fournit les origines d'une instruction donnée.               *
+*  Description : Fournit les détails d'une origine d'une instruction donnée.  *
 *                                                                             *
-*  Retour      : Nombre de ces origines.                                      *
+*  Retour      : Lien déterminé vers une instruction d'origine.               *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **sources)
+instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index)
 {
-    assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
+    instr_link_t *result;                   /* Détails présents à renvoyer */
 
-    if (sources != NULL)
-        *sources = instr->from;
+    result = get_flat_array_item(instr->from, index, sizeof(instr_link_t));
 
-    return g_arch_instruction_get_source_counter(instr);
+    return result;
 
 }
 
@@ -960,23 +870,21 @@ size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **so
 *                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
 *                                                                             *
-*  Description : Indique si l'instruction a une suite autre que la suivante.  *
+*  Description : Donne le nombre d'instructions non naturellement suivantes.  *
 *                                                                             *
-*  Retour      : Bilan de la consultation.                                    *
+*  Retour      : Nombre de ces destinations.                                  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_arch_instruction_has_destinations(GArchInstruction *instr)
+size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
 {
-    size_t count;                           /* Nombre de liens présents    */
-
-    assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+    size_t result;                          /* Nombre de liens à renvoyer  */
 
-    count = g_arch_instruction_get_destination_counter(instr);
+    result = count_flat_array_items(instr->to);
 
-    return (count > 0);
+    return result;
 
 }
 
@@ -984,24 +892,23 @@ bool g_arch_instruction_has_destinations(GArchInstruction *instr)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
-*                dests = liste de liens aux instructions de destination. [OUT]*
+*                index = indice de l'élément à retrouver.                     *
 *                                                                             *
-*  Description : Fournit les destinations d'une instruction donnée.           *
+*  Description : Fournit les détails d'une destination d'une instruction.     *
 *                                                                             *
-*  Retour      : Nombre de ces destinations.                                  *
+*  Retour      : Lien déterminé vers une instruction de destination.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-size_t g_arch_instruction_get_destinations(GArchInstruction *instr, instr_link_t **dests)
+instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index)
 {
-    assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+    instr_link_t *result;                   /* Détails présents à renvoyer */
 
-    if (dests != NULL)
-        *dests = instr->to;
+    result = get_flat_array_item(instr->to, index, sizeof(instr_link_t));
 
-    return g_arch_instruction_get_destination_counter(instr);
+    return result;
 
 }
 
@@ -1024,53 +931,28 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins
     GArchInstruction *result;               /* Résultat à remonter         */
     size_t count;                           /* Nombre de liens à parcourir */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *dest;                     /* Destination à étudier       */
 
     result = NULL;
 
-    assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+    g_arch_instruction_lock_dest(instr);
 
-    count = g_arch_instruction_get_destination_counter(instr);
+    count = g_arch_instruction_count_destinations(instr);
 
     for (i = 0; i < count && result == NULL; i++)
-        if (instr->to[i].type == type)
-            result = instr->to[i].linked;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : iter  = membre du groupe donné en référence.                 *
-*                list  = liste des instructions à analyser.                   *
-*                count = taille de cette liste.                               *
-*                                                                             *
-*  Description : Indique la position dans les instructions identiques.        *
-*                                                                             *
-*  Retour      : Indice dans les instructions identiques du groupe.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-size_t g_arch_instruction_compute_group_index(GArchInstruction **iter, GArchInstruction **list, size_t count)
-{
-    size_t result;                          /* Valeur à retourner          */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = 0;
-
-    for (i = 0; i < count; i++)
     {
-        if ((list + i) == iter)
-            break;
+        dest = g_arch_instruction_get_destination(instr, i);
 
-        if (list[i] == *iter)
-            result++;
+        if (dest->type == type)
+        {
+            result = dest->linked;
+            g_object_ref(G_OBJECT(result));
+        }
 
     }
 
+    g_arch_instruction_unlock_dest(instr);
+
     return result;
 
 }
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index d38bb62..bb2dc94 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -215,7 +215,7 @@ typedef struct _instr_link_t
 
 
 /* Met à disposition un encadrement des accès aux liens. */
-void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool, bool);
+void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool);
 
 /* Détermine si un lien est déjà établi entre deux instructions. */
 bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *);
@@ -226,36 +226,27 @@ 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);
 
-#define g_arch_instruction_wlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true, true)
-#define g_arch_instruction_wunlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true, false)
+#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true)
+#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false)
 
-#define g_arch_instruction_rlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false, true)
-#define g_arch_instruction_runlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false, false)
+/* Fournit la quantité d'instructions pointant vers une autre. */
+size_t g_arch_instruction_count_sources(const GArchInstruction *);
 
-/* Indique si l'instruction a une ou plusieurs origines. */
-bool g_arch_instruction_has_sources(GArchInstruction *);
+/* Fournit les détails d'une origine d'une instruction donnée. */
+instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t);
 
-/* Fournit les origines d'une instruction donnée. */
-size_t g_arch_instruction_get_sources(GArchInstruction *, instr_link_t **);
+#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true)
+#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false)
 
-#define g_arch_instruction_wlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true, true)
-#define g_arch_instruction_wunlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true, false)
+/* Donne le nombre d'instructions non naturellement suivantes. */
+size_t g_arch_instruction_count_destinations(const GArchInstruction *);
 
-#define g_arch_instruction_rlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false, true)
-#define g_arch_instruction_runlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false, false)
-
-/* Indique si l'instruction a une suite autre que la suivante. */
-bool g_arch_instruction_has_destinations(GArchInstruction *);
-
-/* Fournit les destinations d'une instruction donnée. */
-size_t g_arch_instruction_get_destinations(GArchInstruction *, instr_link_t **);
+/* Fournit les détails d'une destination d'une instruction. */
+instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t);
 
 /* Fournit la destination d'une instruction et d'un type donné. */
 GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType);
 
-/* Indique la position dans les instructions identiques. */
-size_t g_arch_instruction_compute_group_index(GArchInstruction **, GArchInstruction **, size_t);
-
 
 
 /* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */
diff --git a/src/debug/debugger.c b/src/debug/debugger.c
index 0dfe315..85ca241 100644
--- a/src/debug/debugger.c
+++ b/src/debug/debugger.c
@@ -1037,9 +1037,9 @@ virt_t *g_binary_debugger_get_next_pcs(GBinaryDebugger *debugger, virt_t pc, boo
     instr_iter_t *iter;                     /* Parcours local d'adresses   */
     GArchInstruction *instr;                /* Instruction correspondante  */
     virt_t ret;                             /* Adresse de retour d'appel   */
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *dest;                     /* Instr. visée par une autre  */
     const mrange_t *range;                  /* Emplacement d'instruction   */
 
     result = NULL;
@@ -1071,12 +1071,15 @@ virt_t *g_binary_debugger_get_next_pcs(GBinaryDebugger *debugger, virt_t pc, boo
         /* Sinon on se penche sur ses destinations */
         else
         {
-            g_arch_instruction_rlock_dest(instr);
+            g_arch_instruction_lock_dest(instr);
 
-            dcount = g_arch_instruction_get_destinations(instr, &dests);
+            dcount = g_arch_instruction_count_destinations(instr);
 
             for (i = 0; i < dcount; i++)
-                switch (dests[i].type)
+            {
+                dest = g_arch_instruction_get_destination(instr, i);
+
+                switch (dest->type)
                 {
                     case ILT_EXEC_FLOW:
                     case ILT_JUMP:
@@ -1088,7 +1091,7 @@ virt_t *g_binary_debugger_get_next_pcs(GBinaryDebugger *debugger, virt_t pc, boo
                         (*count)++;
                         result = (virt_t *)realloc(result, *count * sizeof(virt_t));
 
-                        range = g_arch_instruction_get_range(dests[i].linked);
+                        range = g_arch_instruction_get_range(dest->linked);
 
                         result[*count - 1] = get_virt_addr(get_mrange_addr(range));
                         break;
@@ -1100,7 +1103,7 @@ virt_t *g_binary_debugger_get_next_pcs(GBinaryDebugger *debugger, virt_t pc, boo
                             (*count)++;
                             result = (virt_t *)realloc(result, *count * sizeof(virt_t));
 
-                            range = g_arch_instruction_get_range(dests[i].linked);
+                            range = g_arch_instruction_get_range(dest->linked);
 
                             result[*count - 1] = get_virt_addr(get_mrange_addr(range));
 
@@ -1113,7 +1116,9 @@ virt_t *g_binary_debugger_get_next_pcs(GBinaryDebugger *debugger, virt_t pc, boo
 
                 }
 
-            g_arch_instruction_runlock_dest(instr);
+            }
+
+            g_arch_instruction_unlock_dest(instr);
 
             /* Si tout ça ne donne rien, on se rabat sur l'instruction suivante par défaut */
             if (*count == 0)
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index 9aee82c..413af86 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -904,9 +904,9 @@ 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*/
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours #1       */
+    instr_link_t *dest;                     /* Instr. visée 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é          */
@@ -920,11 +920,14 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 
     g_basic_block_get_boundary(cluster->block, NULL, &last);
 
-    g_arch_instruction_rlock_dest(last);
-    dcount = g_arch_instruction_get_destinations(last, &dests);
+    g_arch_instruction_lock_dest(last);
+    dcount = g_arch_instruction_count_destinations(last);
 
     for (i = 0; i < dcount; i++)
-        switch (dests[i].type)
+    {
+        dest = g_arch_instruction_get_destination(last, i);
+
+        switch (dest->type)
         {
             case ILT_EXEC_FLOW:
             case ILT_JUMP:
@@ -932,7 +935,7 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
             case ILT_JUMP_IF_TRUE:
             case ILT_JUMP_IF_FALSE:
 
-                target = G_GRAPH_CLUSTER(g_hash_table_lookup(all, dests[i].linked));
+                target = G_GRAPH_CLUSTER(g_hash_table_lookup(all, dest->linked));
                 assert(target != NULL);
 
                 /* Point de départ */
@@ -982,7 +985,7 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 
                 leaving->index = cluster->ba_count - 1;
 
-                incoming->type = dests[i].type;
+                incoming->type = dest->type;
 
                 if (incoming->type == ILT_JUMP_IF_TRUE)
                     incoming->edge = g_graph_edge_new_true(&leaving->start, &incoming->y, &incoming->end);
@@ -1027,7 +1030,9 @@ static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all
 
         }
 
-    g_arch_instruction_runlock_dest(last);
+    }
+
+    g_arch_instruction_unlock_dest(last);
 
 
 
@@ -1508,9 +1513,9 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
 #ifndef NDEBUG
     gboolean new;                           /* Bloc déjà traité ?          */
 #endif
-    instr_link_t *dests;                    /* Instr. visées par une autre */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours #1       */
+    instr_link_t *dest;                     /* Instr. visée par une autre  */
     GBasicBlock *target;                    /* Bloc ciblé par un lien      */
     size_t j;                               /* Boucle de parcours #2       */
     bool changed;                           /* Un ajout a été effectué ?   */
@@ -1533,11 +1538,14 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
 
     /* Détermination des blocs suivants */
 
-    g_arch_instruction_rlock_dest(last);
-    dcount = g_arch_instruction_get_destinations(last, &dests);
+    g_arch_instruction_lock_dest(last);
+    dcount = g_arch_instruction_count_destinations(last);
 
     for (i = 0; i < dcount; i++)
-        switch (dests[i].type)
+    {
+        dest = g_arch_instruction_get_destination(last, i);
+
+        switch (dest->type)
         {
             case ILT_EXEC_FLOW:
             case ILT_JUMP:
@@ -1545,7 +1553,7 @@ 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, dests[i].linked);
+                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.
@@ -1558,7 +1566,7 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
                  *
                  */
 
-                printf(" NEW BLK :: %d -> %p\n", dests[i].type, target);
+                printf(" NEW BLK :: %d -> %p\n", dest->type, target);
 
                 if (target != NULL)
                 {
@@ -1588,11 +1596,11 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
                          * la table globale.
                          */
 
-                        if (!g_hash_table_contains(all, dests[i].linked))
+                        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", dests[i].type, target);
+                            printf(" --push-- %d -> %p\n", dest->type, target);
                         }
 
                     }
@@ -1618,7 +1626,9 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
 
         }
 
-    g_arch_instruction_runlock_dest(last);
+    }
+
+    g_arch_instruction_unlock_dest(last);
 
     /* Intégration de tous les blocs en attente */
 
diff --git a/src/gui/dialogs/gotox.c b/src/gui/dialogs/gotox.c
index e467f8e..00ad356 100644
--- a/src/gui/dialogs/gotox.c
+++ b/src/gui/dialogs/gotox.c
@@ -276,9 +276,9 @@ GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBi
 {
     GtkWidget *result;                      /* Fenêtre à renvoyer          */
     GtkTreeStore *store;                    /* Modèle de gestion           */
-    instr_link_t *list;                     /* Liste d'instructions        */
     size_t count;                           /* Nombre d'éléments présents  */
     size_t i;                               /* Boucle de parcours          */
+    instr_link_t *item;                     /* Instruction diverse liée    */
     const vmpa2t *addr;                     /* Adresse à considérer        */
 
     /* Mise en place de la boîte de dialogue */
@@ -294,27 +294,43 @@ GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBi
 
     if (back)
     {
-        g_arch_instruction_rlock_src(instr);
-        count = g_arch_instruction_get_sources(instr, &list);
+        g_arch_instruction_lock_src(instr);
+
+        count = g_arch_instruction_count_sources(instr);
+
+        for (i = 0; i < count; i++)
+        {
+            item = g_arch_instruction_get_source(instr, i);
+
+            addr = get_mrange_addr(g_arch_instruction_get_range(item->linked));
+
+            add_new_location_to_list(store, binary, addr, NULL);
+
+        }
+
+        g_arch_instruction_unlock_src(instr);
+
     }
+
     else
     {
-        g_arch_instruction_rlock_dest(instr);
-        count = g_arch_instruction_get_destinations(instr, &list);
-    }
+        g_arch_instruction_lock_dest(instr);
 
-    for (i = 0; i < count; i++)
-    {
-        addr = get_mrange_addr(g_arch_instruction_get_range(list[i].linked));
+        count = g_arch_instruction_count_destinations(instr);
 
-        add_new_location_to_list(store, binary, addr, NULL);
+        for (i = 0; i < count; i++)
+        {
+            item = g_arch_instruction_get_destination(instr, i);
 
-    }
+            addr = get_mrange_addr(g_arch_instruction_get_range(item->linked));
 
-    if (back)
-        g_arch_instruction_runlock_src(instr);
-    else
-        g_arch_instruction_runlock_dest(instr);
+            add_new_location_to_list(store, binary, addr, NULL);
+
+        }
+
+        g_arch_instruction_unlock_dest(instr);
+
+    }
 
     g_object_unref(G_OBJECT(store));
 
-- 
cgit v0.11.2-87-g4458