From 12b8a066d1d8dd8cbef587dc6fafed870604f49f Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 6 Mar 2017 19:48:16 +0100
Subject: Locked access to instruction operands when needed.

---
 ChangeLog                        |  22 ++++++
 plugins/androhelpers/params.c    |   8 ++-
 plugins/stackvars/stackvars.c    |  10 ++-
 src/analysis/db/items/switcher.c |  10 ++-
 src/analysis/db/items/switcher.h |   2 +-
 src/analysis/disass/links.c      |  23 ++++--
 src/arch/arm/v7/fetch.c          |  15 +++-
 src/arch/arm/v7/post.c           |  13 ++--
 src/arch/dalvik/link.c           |   8 ++-
 src/arch/instruction-int.h       |   1 +
 src/arch/instruction.c           | 147 +++++++++++++++++++++++++++------------
 src/arch/instruction.h           |  58 +++++++++++++--
 src/arch/link.c                  |  24 +++++--
 src/arch/post.c                  |   8 ++-
 src/arch/raw.c                   |   8 +++
 15 files changed, 274 insertions(+), 83 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index be4bd7e..1fd61f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+17-03-06  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/androhelpers/params.c:
+	* plugins/stackvars/stackvars.c:
+	* src/analysis/db/items/switcher.c:
+	* src/analysis/db/items/switcher.h:
+	* src/analysis/disass/links.c:
+	* src/arch/arm/v7/fetch.c:
+	* src/arch/arm/v7/post.c:
+	* src/arch/dalvik/link.c:
+	Update code.
+
+	* src/arch/instruction-int.h:
+	* src/arch/instruction.c:
+	Lock access to instruction operands when needed.
+
+	* src/arch/instruction.h:
+	* src/arch/link.c:
+	* src/arch/post.c:
+	* src/arch/raw.c:
+	Update code.
+
 17-03-05  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/operand-int.h:
diff --git a/plugins/androhelpers/params.c b/plugins/androhelpers/params.c
index 908d8c6..ea85b89 100644
--- a/plugins/androhelpers/params.c
+++ b/plugins/androhelpers/params.c
@@ -149,11 +149,13 @@ static void visit_all_method_operands(const GDexMethod *method, GArchInstruction
          iter != NULL;
          iter = g_arch_instruction_get_next_iter(instrs, iter, end))
     {
-        count = g_arch_instruction_count_operands(iter);
+        g_arch_instruction_lock_operands(iter);
+
+        count = _g_arch_instruction_count_operands(iter);
 
         for (i = 0; i < count; i++)
         {
-            operand = g_arch_instruction_get_operand(iter, i);
+            operand = _g_arch_instruction_get_operand(iter, i);
 
             if (G_IS_DALVIK_REGISTER_OPERAND(operand))
                 process_register_operand(method, operand);
@@ -163,6 +165,8 @@ static void visit_all_method_operands(const GDexMethod *method, GArchInstruction
 
         }
 
+        g_arch_instruction_unlock_operands(iter);
+
     }
 
 }
diff --git a/plugins/stackvars/stackvars.c b/plugins/stackvars/stackvars.c
index c2b4777..f3baeef 100644
--- a/plugins/stackvars/stackvars.c
+++ b/plugins/stackvars/stackvars.c
@@ -205,16 +205,18 @@ static bool replace_stack_vars_in_instruction(GArchInstruction *instr, GBinRouti
     result = false;
     new = NULL;     /* Pour GCC */
 
-    opcount = g_arch_instruction_count_operands(instr);
+    g_arch_instruction_lock_operands(instr);
+
+    opcount = _g_arch_instruction_count_operands(instr);
 
     for (i = 0; i < opcount; i++)
     {
-        operand = g_arch_instruction_get_operand(instr, i);
+        operand = _g_arch_instruction_get_operand(instr, i);
         result = replace_stack_var_in_operand(operand, routine, dryrun, &new);
 
         if (!dryrun && result)
         {
-            g_arch_instruction_replace_operand(instr, new, operand);
+            _g_arch_instruction_replace_operand(instr, new, operand);
 
             result = true;
 
@@ -222,6 +224,8 @@ static bool replace_stack_vars_in_instruction(GArchInstruction *instr, GBinRouti
 
     }
 
+    g_arch_instruction_unlock_operands(instr);
+
     return result;
 
 }
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index 01c1910..9cd2a2e 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -264,7 +264,7 @@ static void g_db_switcher_finalize(GDbSwitcher *switcher)
 *                                                                             *
 ******************************************************************************/
 
-GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmOperandDisplay display)
+GDbSwitcher *g_db_switcher_new(GArchInstruction *instr, const GImmOperand *imm, ImmOperandDisplay display)
 {
     GDbSwitcher *result;                    /* Instance à retourner        */
     size_t count;                           /* Nombre d'opérandes à visiter*/
@@ -273,12 +273,16 @@ GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand
 
     /* Recherche de la position de l'opérande */
 
-    count = g_arch_instruction_count_operands(instr);
+    g_arch_instruction_lock_operands(instr);
+
+    count = _g_arch_instruction_count_operands(instr);
 
     for (i = 0; i < count; i++)
-        if (G_ARCH_OPERAND(imm) == g_arch_instruction_get_operand(instr, i))
+        if (G_ARCH_OPERAND(imm) == _g_arch_instruction_get_operand(instr, i))
             break;
 
+    g_arch_instruction_unlock_operands(instr);
+
     if (i == count)
         return NULL;
 
diff --git a/src/analysis/db/items/switcher.h b/src/analysis/db/items/switcher.h
index d155a13..7fda6d7 100644
--- a/src/analysis/db/items/switcher.h
+++ b/src/analysis/db/items/switcher.h
@@ -57,7 +57,7 @@ typedef struct _GDbSwitcherClass GDbSwitcherClass;
 GType g_db_switcher_get_type(void);
 
 /* Crée une définition d'un signet dans une zone de texte. */
-GDbSwitcher *g_db_switcher_new(const GArchInstruction *, const GImmOperand *, ImmOperandDisplay);
+GDbSwitcher *g_db_switcher_new(GArchInstruction *, const GImmOperand *, ImmOperandDisplay);
 
 #if 0
 /* Fournit l'adresse associée à un signet. */
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index 0884dce..abe26d6 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -185,12 +185,15 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,
     vmpa2t target;                          /* Défination finale précise   */
     GArchOperand *new;                      /* Instruction de ciblage      */
 
-    op = g_arch_instruction_get_operand(instr, index);
-    if (!G_IS_IMM_OPERAND(op)) return;
+    op = _g_arch_instruction_get_operand(instr, index);
+
+    if (!G_IS_IMM_OPERAND(op))
+        goto ciit_done;
 
     imm = G_IMM_OPERAND(op);
 
-    if (g_imm_operand_get_display(imm) != IOD_HEX) return;
+    if (g_imm_operand_get_display(imm) != IOD_HEX)
+        goto ciit_done;
 
     if (g_imm_operand_to_virt_t(imm, &addr))
     {
@@ -203,12 +206,16 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,
             if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format, false))
                 g_object_unref(G_OBJECT(new));
             else
-                g_arch_instruction_replace_operand(instr, new, op);
+                _g_arch_instruction_replace_operand(instr, new, op);
 
         }
 
     }
 
+ ciit_done:
+
+    ;
+
 }
 
 
@@ -240,14 +247,16 @@ void establish_links_for_instruction(GArchInstruction *instr, GBinFormat *format
     else
         skip = false;
 
-    count = g_arch_instruction_count_operands(instr);
+    g_arch_instruction_lock_operands(instr);
+
+    count = _g_arch_instruction_count_operands(instr);
 
     for (i = 0; i < count; i++)
     {
         if (!skip)
             convert_immediate_into_target(instr, i, format);
 
-        op = g_arch_instruction_get_operand(instr, i);
+        op = _g_arch_instruction_get_operand(instr, i);
         if (!G_IS_TARGET_OPERAND(op)) continue;
 
         g_target_operand_get_addr(G_TARGET_OPERAND(op), &addr);
@@ -262,4 +271,6 @@ void establish_links_for_instruction(GArchInstruction *instr, GBinFormat *format
 
     }
 
+    g_arch_instruction_unlock_operands(instr);
+
 }
diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c
index 15707e3..6675706 100644
--- a/src/arch/arm/v7/fetch.c
+++ b/src/arch/arm/v7/fetch.c
@@ -388,13 +388,16 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
             break;
     }
 
-    op = g_arch_instruction_get_operand(instr, 1);
+    g_arch_instruction_lock_operands(instr);
+
+    op = _g_arch_instruction_get_operand(instr, 1);
     assert(G_IS_IMM_OPERAND(op));
 
     ret = g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset);
     if (!ret)
     {
         assert(0);
+        g_arch_instruction_unlock_operands(instr);
         return;
     }
 
@@ -405,6 +408,7 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
     if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &sym_addr))
     {
         assert(0);
+        g_arch_instruction_unlock_operands(instr);
         return;
     }
 
@@ -427,7 +431,11 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
     ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE /* FIXME */, &target);
     g_object_unref(G_OBJECT(content));
 
-    if (!ret) return;
+    if (!ret)
+    {
+        g_arch_instruction_unlock_operands(instr);
+        return;
+    }
 
     /* Réalise l'intégration du symbole associé */
 
@@ -480,8 +488,9 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
 
 
     new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target);
-    g_arch_instruction_replace_operand(instr, new, op);
+    _g_arch_instruction_replace_operand(instr, new, op);
 
+    g_arch_instruction_unlock_operands(instr);
 
 
 
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index 5ac3c62..6c63832 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -56,11 +56,12 @@ void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
     GBinSymbol *symbol;                     /* Nouveau symbole construit   */
 
-    op = g_arch_instruction_get_operand(instr, 1);
+    g_arch_instruction_lock_operands(instr);
 
+    op = _g_arch_instruction_get_operand(instr, 1);
 
-    if (!G_IS_IMM_OPERAND(op)) return;
-
+    if (!G_IS_IMM_OPERAND(op))
+        goto ppli_release;
 
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)
         && g_exe_format_translate_address_into_vmpa(format, addr, &target))
@@ -92,8 +93,12 @@ void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc
 
         }
 
-        g_arch_instruction_replace_operand(instr, new, op);
+        _g_arch_instruction_replace_operand(instr, new, op);
 
     }
 
+ ppli_release:
+
+    g_arch_instruction_unlock_operands(instr);
+
 }
diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c
index f92541b..d1404d0 100644
--- a/src/arch/dalvik/link.c
+++ b/src/arch/dalvik/link.c
@@ -101,9 +101,13 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
     char *int_val;                          /* Valeur en chaîne de carac.  */
     GDbComment *item;                       /* Indication sur la condition */
 
-    assert(g_arch_instruction_count_operands(instr) == 2);
+    g_arch_instruction_lock_operands(instr);
 
-    op = g_arch_instruction_get_operand(instr, 1);
+    assert(_g_arch_instruction_count_operands(instr) == 2);
+
+    op = _g_arch_instruction_get_operand(instr, 1);
+
+    g_arch_instruction_unlock_operands(instr);
 
     defined = false;
 
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 5f6758f..8dbdd18 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -56,6 +56,7 @@ struct _GArchInstruction
 
     GArchOperand **operands;                /* Liste des opérandes         */
     size_t operands_count;                  /* Nbre. d'opérandes utilisées */
+    gint operands_lock;                     /* Verrouillage des accès      */
 
     /**
      * Il existe le besoin indéniable d'un verrou pour les accès aux instructions
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 7df72bf..339364f 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -145,6 +145,8 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass)
 
 static void g_arch_instruction_init(GArchInstruction *instr)
 {
+    instr->operands_lock = 0;
+
     instr->from_count = 0;
     instr->to_count = 0;
 
@@ -409,6 +411,91 @@ void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offse
 }
 
 
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr  = instruction à consulter.                            *
+*                rregs  = liste des rgistres lus. [OUT]                       *
+*                rcount = nombre de registres lus. [OUT]                      *
+*                wregs  = liste des rgistres écrits. [OUT]                    *
+*                wcount = nombre de registres écrits. [OUT]                   *
+*                                                                             *
+*  Description : Liste les registres lus et écrits par l'instruction.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Les compteurs de références sont à décrémenter après usage ! *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
+{
+#if 0
+
+    size_t i;                               /* Boucle de parcours          */
+
+    *rregs = NULL;
+    *rcount = 0;
+    *wregs = NULL;
+    *wcount = 0;
+
+    instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
+
+    for (i = 0; i < *rcount; i++)
+        g_object_ref(G_OBJECT((*rregs)[i]));
+
+    for (i = 0; i < *wcount; i++)
+        g_object_ref(G_OBJECT((*wregs)[i]));
+
+#endif
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                             MANIPULATION DES OPERANDES                             */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction à mettre à jour.                         *
+*                                                                             *
+*  Description : Verrouille les accès la liste des opérandes.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_lock_operands(GArchInstruction *instr)
+{
+    g_bit_lock(&instr->operands_lock, 0);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction à mettre à jour.                         *
+*                                                                             *
+*  Description : Déverrouille les accès la liste des opérandes.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_unlock_operands(GArchInstruction *instr)
+{
+    g_bit_unlock(&instr->operands_lock, 0);
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr     = instance à mettre à jour.                        *
@@ -424,11 +511,15 @@ void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offse
 
 void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
 {
+    g_arch_instruction_lock_operands(instr);
+
     instr->operands_count++;
     instr->operands = (GArchOperand **)realloc(instr->operands, instr->operands_count * sizeof(GArchOperand *));
 
     instr->operands[instr->operands_count - 1] = operand;
 
+    g_arch_instruction_unlock_operands(instr);
+
 }
 
 
@@ -444,8 +535,10 @@ void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOpera
 *                                                                             *
 ******************************************************************************/
 
-size_t g_arch_instruction_count_operands(const GArchInstruction *instr)
+size_t _g_arch_instruction_count_operands(const GArchInstruction *instr)
 {
+    assert(instr->operands_lock != 0);
+
     return instr->operands_count;
 
 }
@@ -464,10 +557,12 @@ size_t g_arch_instruction_count_operands(const GArchInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
+GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
 {
     GArchOperand *result;                   /* Opérande à retourner        */
 
+    assert(instr->operands_lock != 0);
+
     if (index >= instr->operands_count) result = NULL;
     else result = instr->operands[index];
 
@@ -492,10 +587,12 @@ GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *new, const GArchOperand *old)
+void _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *new, const GArchOperand *old)
 {
     size_t i;                               /* Boucle de parcours          */
 
+    assert(instr->operands_lock != 0);
+
     for (i = 0; i < instr->operands_count; i++)
         if (instr->operands[i] == old)
             break;
@@ -522,10 +619,12 @@ void g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *n
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *operand)
+void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *operand)
 {
     size_t i;                               /* Boucle de parcours          */
 
+    assert(instr->operands_lock != 0);
+
     for (i = 0; i < instr->operands_count; i++)
         if (instr->operands[i] == operand)
             break;
@@ -540,46 +639,6 @@ void g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *op
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr  = instruction à consulter.                            *
-*                rregs  = liste des rgistres lus. [OUT]                       *
-*                rcount = nombre de registres lus. [OUT]                      *
-*                wregs  = liste des rgistres écrits. [OUT]                    *
-*                wcount = nombre de registres écrits. [OUT]                   *
-*                                                                             *
-*  Description : Liste les registres lus et écrits par l'instruction.         *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : Les compteurs de références sont à décrémenter après usage ! *
-*                                                                             *
-******************************************************************************/
-
-void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
-{
-#if 0
-
-    size_t i;                               /* Boucle de parcours          */
-
-    *rregs = NULL;
-    *rcount = 0;
-    *wregs = NULL;
-    *wcount = 0;
-
-    instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
-
-    for (i = 0; i < *rcount; i++)
-        g_object_ref(G_OBJECT((*rregs)[i]));
-
-    for (i = 0; i < *wcount; i++)
-        g_object_ref(G_OBJECT((*wregs)[i]));
-
-#endif
-
-}
-
-
 
 /* ---------------------------------------------------------------------------------- */
 /*                     DEFINITION DES LIAISONS ENTRE INSTRUCTIONS                     */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 6388f94..fad6c72 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -123,23 +123,67 @@ void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *,
 
 
 
+/* Liste les registres lus et écrits par l'instruction. */
+void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated));
+
+
+
+/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
+
+
+/* Verrouille les accès la liste des opérandes. */
+void g_arch_instruction_lock_operands(GArchInstruction *);
+
+/* Déverrouille les accès la liste des opérandes. */
+void g_arch_instruction_unlock_operands(GArchInstruction *);
+
 /* Attache un opérande supplémentaire à une instruction. */
 void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *);
 
 /* Indique la quantité d'opérandes présents dans l'instruction. */
-size_t g_arch_instruction_count_operands(const GArchInstruction *);
+size_t _g_arch_instruction_count_operands(const GArchInstruction *);
 
 /* Fournit un opérande donné d'une instruction. */
-GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *, size_t);
+GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t);
 
 /* Remplace un opérande d'une instruction par un autre. */
-void g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, const GArchOperand *);
+void _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, const GArchOperand *);
 
 /* Détache un opérande liée d'une instruction. */
-void g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
-
-/* Liste les registres lus et écrits par l'instruction. */
-void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated));
+void _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
+
+
+#define g_arch_instruction_count_operands(ins)                  \
+    ({                                                          \
+        size_t __result;                                        \
+        g_arch_instruction_lock_operands(ins);                  \
+        __result = _g_arch_instruction_count_operands(ins);     \
+        g_arch_instruction_unlock_operands(ins);                \
+        __result;                                               \
+    })
+
+#define g_arch_instruction_get_operand(ins, idx)                \
+    ({                                                          \
+        GArchOperand *__result;                                 \
+        g_arch_instruction_lock_operands(ins);                  \
+        __result = _g_arch_instruction_get_operand(ins, idx);   \
+        g_arch_instruction_unlock_operands(ins);                \
+        __result;                                               \
+    })
+
+#define g_arch_instruction_replace_operand(ins, n, o)           \
+    ({                                                          \
+        g_arch_instruction_lock_operands(ins);                  \
+        _g_arch_instruction_replace_operand(ins, n, o);         \
+        g_arch_instruction_unlock_operands(ins);                \
+    })
+
+#define g_arch_instruction_detach_operand(ins, o)               \
+    ({                                                          \
+        g_arch_instruction_lock_operands(ins);                  \
+        _g_arch_instruction_detach_operand(ins, o);             \
+        g_arch_instruction_unlock_operands(ins);                \
+    })
 
 
 
diff --git a/src/arch/link.c b/src/arch/link.c
index dfc2bd5..fbcd391 100644
--- a/src/arch/link.c
+++ b/src/arch/link.c
@@ -53,9 +53,13 @@ void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon
     vmpa2t addr;                            /* Adresse de destination      */
     GArchInstruction *target;               /* Ligne visée par la référence*/
 
-    assert(g_arch_instruction_count_operands(instr) > 0);
+    g_arch_instruction_lock_operands(instr);
 
-    op = g_arch_instruction_get_operand(instr, 0);
+    assert(_g_arch_instruction_count_operands(instr) > 0);
+
+    op = _g_arch_instruction_get_operand(instr, 0);
+
+    g_arch_instruction_unlock_operands(instr);
 
     if (!G_IS_IMM_OPERAND(op)) return;
 
@@ -102,9 +106,13 @@ void handle_branch_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcC
     const mrange_t *range;                  /* Emplacement d'instruction   */
     vmpa2t next;                            /* Position suivante           */
 
-    assert(g_arch_instruction_count_operands(instr) > index);
+    g_arch_instruction_lock_operands(instr);
+
+    assert(_g_arch_instruction_count_operands(instr) > index);
 
-    op = g_arch_instruction_get_operand(instr, index);
+    op = _g_arch_instruction_get_operand(instr, index);
+
+    g_arch_instruction_unlock_operands(instr);
 
     defined = false;
 
@@ -175,9 +183,13 @@ void handle_call_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon
     vmpa2t addr;                            /* Adresse de destination      */
     GArchInstruction *target;               /* Ligne visée par la référence*/
 
-    assert(g_arch_instruction_count_operands(instr) > 0);
+    g_arch_instruction_lock_operands(instr);
+
+    assert(_g_arch_instruction_count_operands(instr) > 0);
+
+    op = _g_arch_instruction_get_operand(instr, 0);
 
-    op = g_arch_instruction_get_operand(instr, 0);
+    g_arch_instruction_unlock_operands(instr);
 
     if (!G_IS_IMM_OPERAND(op)) return;
 
diff --git a/src/arch/post.c b/src/arch/post.c
index 59ed40e..babe6a9 100644
--- a/src/arch/post.c
+++ b/src/arch/post.c
@@ -63,7 +63,9 @@ void post_process_target_resolution(GArchInstruction *instr, GArchProcessor *pro
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
     GBinSymbol *symbol;                     /* Nouveau symbole construit   */
 
-    op = g_arch_instruction_get_operand(instr, index);
+    g_arch_instruction_lock_operands(instr);
+
+    op = _g_arch_instruction_get_operand(instr, index);
     assert(G_IS_IMM_OPERAND(op));
 
     if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr)
@@ -109,8 +111,10 @@ void post_process_target_resolution(GArchInstruction *instr, GArchProcessor *pro
 
         }
 
-        g_arch_instruction_replace_operand(instr, new, op);
+        _g_arch_instruction_replace_operand(instr, new, op);
 
     }
 
+    g_arch_instruction_unlock_operands(instr);
+
 }
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 63dadab..f22645f 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -512,6 +512,8 @@ static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, s
 
         first = true;
 
+        g_arch_instruction_lock_operands(base);
+
         for (i = 0; i < base->operands_count; i++)
         {
             status = g_imm_operand_get_value(G_IMM_OPERAND(base->operands[i]), MDS_8_BITS, &byte);
@@ -558,6 +560,8 @@ static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, s
 
         }
 
+        g_arch_instruction_unlock_operands(base);
+
         /* Si une chaîne reste encore */
         if (iter > 1)
         {
@@ -581,6 +585,8 @@ static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, s
 
     else
     {
+        g_arch_instruction_lock_operands(base);
+
         if (base->operands_count > 0)
         {
             g_arch_operand_print(base->operands[0], line, 0/*syntax*/);
@@ -596,6 +602,8 @@ static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, s
 
         }
 
+        g_arch_instruction_unlock_operands(base);
+
     }
 
 }
-- 
cgit v0.11.2-87-g4458