From db1a6171007a6641a4659392c9bcc05670396643 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 15 Dec 2016 00:30:12 +0100
Subject: Provided an iterator for instructions.

---
 ChangeLog                         |  26 ++++
 plugins/pychrysa/arch/Makefile.am |   1 +
 plugins/pychrysa/arch/instriter.c | 265 ++++++++++++++++++++++++++++++++++++++
 plugins/pychrysa/arch/instriter.h |  42 ++++++
 plugins/pychrysa/arch/module.c    |   2 +
 plugins/pychrysa/arch/processor.c |  44 ++-----
 src/arch/Makefile.am              |   1 +
 src/arch/instriter.c              | 135 +++++++++++++++++++
 src/arch/instriter.h              |  50 +++++++
 src/arch/instruction.h            |   2 +-
 src/arch/processor-int.h          |   5 +
 src/arch/processor.c              | 196 ++++++++++++++++++++++------
 src/arch/processor.h              |  18 ++-
 13 files changed, 710 insertions(+), 77 deletions(-)
 create mode 100644 plugins/pychrysa/arch/instriter.c
 create mode 100644 plugins/pychrysa/arch/instriter.h
 create mode 100644 src/arch/instriter.c
 create mode 100644 src/arch/instriter.h

diff --git a/ChangeLog b/ChangeLog
index 856c430..00d2f12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+16-12-15  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/arch/Makefile.am:
+	Add the 'instriter.[ch]' files to libpychrysaarch_la_SOURCES.
+
+	* plugins/pychrysa/arch/instriter.c:
+	* plugins/pychrysa/arch/instriter.h:
+	New entries: provide an iterator for instructions.
+
+	* plugins/pychrysa/arch/module.c:
+	* plugins/pychrysa/arch/processor.c:
+	Update code.
+
+	* src/arch/Makefile.am:
+	Add the 'instriter.[ch]' files to libarch_la_SOURCES.
+
+	* src/arch/instriter.c:
+	* src/arch/instriter.h:
+	New entries: provide an iterator for instructions.
+
+	* src/arch/instruction.h:
+	* src/arch/processor-int.h:
+	* src/arch/processor.c:
+	* src/arch/processor.h:
+	Update code.
+
 16-12-13  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/gui/editem.c:
diff --git a/plugins/pychrysa/arch/Makefile.am b/plugins/pychrysa/arch/Makefile.am
index 7607ed8..5d631bb 100644
--- a/plugins/pychrysa/arch/Makefile.am
+++ b/plugins/pychrysa/arch/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libpychrysaarch.la
 
 libpychrysaarch_la_SOURCES =			\
+	instriter.h instriter.c				\
 	instruction.h instruction.c			\
 	module.h module.c					\
 	processor.h processor.c				\
diff --git a/plugins/pychrysa/arch/instriter.c b/plugins/pychrysa/arch/instriter.c
new file mode 100644
index 0000000..1e5346e
--- /dev/null
+++ b/plugins/pychrysa/arch/instriter.c
@@ -0,0 +1,265 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.c - équivalent Python du fichier "arch/instriter.c"
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "instriter.h"
+
+
+#include <pygobject.h>
+
+
+#include <arch/instriter.h>
+#include <arch/processor.h>
+
+
+#include "processor.h"
+
+
+
+/* Transcription d'un itérateur en Python */
+typedef struct _PyInstrIterator
+{
+    PyObject_HEAD;                          /* A laisser en premier        */
+
+    instr_iter_t *native;                   /* Version native de l'objet   */
+
+} PyInstrIterator;
+
+
+/* Libère de la mémoire un itérateur sur des instructions. */
+static void py_instr_iterator_dealloc(PyInstrIterator *);
+
+/* Fournit l'instruction qui en suit une autre. */
+static PyObject *py_instr_iterator_next(PyInstrIterator *);
+
+/* Initialise un nouvel itérateur. */
+static int py_instr_iterator_init(PyInstrIterator *, PyObject *, PyObject *);
+
+/* Construit un nouvel itérateur. */
+static PyObject *py_instr_iterator_new(PyTypeObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = itérateur à supprimer.                                *
+*                                                                             *
+*  Description : Libère de la mémoire un itérateur sur des instructions.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_instr_iterator_dealloc(PyInstrIterator *self)
+{
+    delete_instruction_iterator(self->native);
+
+    Py_TYPE(self)->tp_free((PyObject *)self);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = itérateur à manipuler.                                *
+*                                                                             *
+*  Description : Fournit l'instruction qui en suit une autre.                 *
+*                                                                             *
+*  Retour      : Instruction suivante trouvée, ou NULL.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_instr_iterator_next(PyInstrIterator *self)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    GArchInstruction *next;                 /* Instruction suivante        */
+
+    next = get_instruction_iterator_next(self->native);
+
+    if (next != NULL)
+        result = pygobject_new(G_OBJECT(next));
+
+    else
+    {
+        PyErr_SetNone(PyExc_StopIteration);
+        result = NULL;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
+*                                                                             *
+*  Description : Initialise un nouvel itérateur.                              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_instr_iterator_init(PyInstrIterator *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+    PyObject *proc_obj;                     /* Processeur version Python   */
+    unsigned long index;                    /* Indice de première instruc. */
+    int ret;                                /* Bilan de lecture des args.  */
+    GArchProcessor *proc;                   /* Version native du processeur*/
+
+    result = -1;
+
+    ret = PyArg_ParseTuple(args, "Ok", &proc_obj, &index);
+    if (ret == 0) goto piii_exit;
+
+    ret = PyObject_IsInstance(proc_obj, (PyObject *)get_python_arch_processor_type());
+    if (!ret) goto piii_exit;
+
+    proc = G_ARCH_PROCESSOR(pygobject_get(proc_obj));
+
+    self->native = create_instruction_iterator(proc, index);
+
+    result = 0;
+
+ piii_exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type d'objet à mettre en place.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
+*                                                                             *
+*  Description : Construit un nouvel itérateur.                               *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_instr_iterator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyInstrIterator *result;                /* Nouvelle instance à renvoyer*/
+    int ret;                                /* Bilan de l'initialisation   */
+
+    result = (PyInstrIterator *)type->tp_alloc(type, 0);
+
+    if (result != NULL)
+    {
+        ret = py_instr_iterator_init(result, args, kwds);
+
+        if (ret != 0)
+        {
+            Py_DECREF(result);
+            result = NULL;
+        }
+
+    }
+
+    return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_instr_iterator_type(void)
+{
+    static PyTypeObject py_instr_iterator_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.arch.InstrIterator",
+        .tp_basicsize   = sizeof(PyInstrIterator),
+
+        .tp_dealloc     = (destructor)py_instr_iterator_dealloc,
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = "Iterator for Chrysalide instructions loaded in a given processor.",
+
+        .tp_iter        = PyObject_SelfIter,
+        .tp_iternext    = (iternextfunc)py_instr_iterator_next,
+
+        .tp_init        = (initproc)py_instr_iterator_init,
+        .tp_new         = py_instr_iterator_new,
+
+    };
+
+    return &py_instr_iterator_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.arch.InstrIterator'.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_instr_iterator(PyObject *module)
+{
+    PyTypeObject *py_instr_iterator_type;   /* Type Python 'BinContent'    */
+    int ret;                                /* Bilan d'un appel            */
+
+    py_instr_iterator_type = get_python_instr_iterator_type();
+
+    if (PyType_Ready(py_instr_iterator_type) < 0)
+        return false;
+
+    Py_INCREF(py_instr_iterator_type);
+    ret = PyModule_AddObject(module, "InstrIterator", (PyObject *)py_instr_iterator_type);
+
+    return (ret == 0);
+
+}
diff --git a/plugins/pychrysa/arch/instriter.h b/plugins/pychrysa/arch/instriter.h
new file mode 100644
index 0000000..be84dbc
--- /dev/null
+++ b/plugins/pychrysa/arch/instriter.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.h - prototypes pour l'équivalent Python du fichier "arch/instriter.h"
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_INSTRITER_H
+#define _PLUGINS_PYCHRYSALIDE_ARCH_INSTRITER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_instr_iterator_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.arch.InstrIterator'. */
+bool register_python_instr_iterator(PyObject *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ARCH_INSTRITER_H */
diff --git a/plugins/pychrysa/arch/module.c b/plugins/pychrysa/arch/module.c
index 73f8770..ce5db70 100644
--- a/plugins/pychrysa/arch/module.c
+++ b/plugins/pychrysa/arch/module.c
@@ -28,6 +28,7 @@
 #include <assert.h>
 
 
+#include "instriter.h"
 #include "instruction.h"
 #include "processor.h"
 #include "vmpa.h"
@@ -83,6 +84,7 @@ bool add_arch_module_to_python_module(PyObject *super)
 
     result &= register_python_arch_instruction(module);
     result &= register_python_arch_processor(module);
+    result &= register_python_instr_iterator(module);
     result &= register_python_vmpa(module);
     result &= register_python_mrange(module);
 
diff --git a/plugins/pychrysa/arch/processor.c b/plugins/pychrysa/arch/processor.c
index 291d788..3ef56e4 100644
--- a/plugins/pychrysa/arch/processor.c
+++ b/plugins/pychrysa/arch/processor.c
@@ -34,6 +34,7 @@
 #include <arch/processor.h>
 
 
+#include "instriter.h"
 #include "instruction.h"
 #include "vmpa.h"
 #include "../helpers.h"
@@ -62,7 +63,7 @@
 
 
 /* Fournit les instructions désassemblées pour une architecture. */
-static PyObject *py_arch_processor_get_disass_instrs(PyObject *, void *);
+static PyObject *py_arch_processor_get_instrs(PyObject *, void *);
 
 /* Recherche une instruction d'après son adresse. */
 static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *);
@@ -75,8 +76,6 @@ static PyObject *py_arch_processor_get_next_instr(PyObject *, PyObject *);
 
 
 
-
-
 /* ---------------------------------------------------------------------------------- */
 /*                    MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES                    */
 /* ---------------------------------------------------------------------------------- */
@@ -95,22 +94,19 @@ static PyObject *py_arch_processor_get_next_instr(PyObject *, PyObject *);
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_arch_processor_get_disass_instrs(PyObject *self, void *closure)
+static PyObject *py_arch_processor_get_instrs(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Instance Python à retourner */
-    GArchProcessor *proc;                   /* Architecture visée          */
-    GArchInstruction *instrs;               /* Série d'instructions liées  */
+    PyTypeObject *iterator_type;            /* Type Python de l'itérateur  */
+    PyObject *args;                         /* Liste des arguments d'appel */
 
-    proc = G_ARCH_PROCESSOR(pygobject_get(self));
-    instrs = g_arch_processor_get_disassembled_instructions(proc);
+    iterator_type = get_python_instr_iterator_type();
 
-    if (instrs != NULL)
-        result = pygobject_new(G_OBJECT(instrs));
-    else
-    {
-        result = Py_None;
-        Py_INCREF(result);
-    }
+    args = Py_BuildValue("On", self, 0);
+
+    result = PyObject_CallObject((PyObject *)iterator_type, args);
+
+    Py_DECREF(args);
 
     return result;
 
@@ -293,22 +289,6 @@ static PyObject *py_arch_processor_get_next_instr(PyObject *self, PyObject *args
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : -                                                            *
@@ -344,7 +324,7 @@ PyTypeObject *get_python_arch_processor_type(void)
 
     static PyGetSetDef py_arch_processor_getseters[] = {
         {
-            "disass_instrs", py_arch_processor_get_disass_instrs, py_arch_processor_set_disass_instrs,
+            "instrs", py_arch_processor_get_instrs, py_arch_processor_set_disass_instrs,
             "Give access to the disassembled instructions run by the current processor.", NULL
         },
         { NULL }
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 030ee87..a7ff3a2 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -6,6 +6,7 @@ libarch_la_SOURCES =					\
 	context-int.h						\
 	context.h context.c					\
 	immediate.h immediate.c				\
+	instriter.h instriter.c				\
 	instruction-int.h					\
 	instruction.h instruction.c			\
 	link.h link.c						\
diff --git a/src/arch/instriter.c b/src/arch/instriter.c
new file mode 100644
index 0000000..0f33998
--- /dev/null
+++ b/src/arch/instriter.c
@@ -0,0 +1,135 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.h - prototypes pour le parcours simplifié d'un ensemble d'instructions
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "instriter.h"
+
+
+#include <malloc.h>
+
+
+#include "processor.h"
+
+
+
+/* Suivi d'un parcours d'instructions */
+typedef struct _instr_iter_t
+{
+    GArchProcessor *proc;                   /* Conteneur associé           */
+    unsigned int stamp;                     /* Suivi d'évolutions externes */
+
+    size_t index;                           /* Instruction courante        */
+
+} instr_iter_t;
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc  = processeur recensant diverses instructions.          *
+*                index = indice de la première instruction à fournir.         *
+*                                                                             *
+*  Description : Construit un itérateur pour parcourir des instructions.      *
+*                                                                             *
+*  Retour      : Itérateur prêt à emploi.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+instr_iter_t *create_instruction_iterator(GArchProcessor *proc, size_t index)
+{
+    instr_iter_t *result;                   /* Structure à retourner       */
+
+    result = (instr_iter_t *)malloc(sizeof(instr_iter_t));
+
+    g_object_ref(G_OBJECT(proc));
+
+    result->proc = proc;
+    result->stamp = g_arch_processor_get_stamp(proc);
+
+    result->index = index;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : iter = itérateur à traiter.                                  *
+*                                                                             *
+*  Description : Détruit un itérateur mis en place.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_instruction_iterator(instr_iter_t *iter)
+{
+    g_object_unref(G_OBJECT(iter->proc));
+
+    free(iter);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : iter = itérateur à manipuler.                                *
+*                                                                             *
+*  Description : Fournit l'instruction qui en suit une autre.                 *
+*                                                                             *
+*  Retour      : Instruction suivante trouvée, ou NULL.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *get_instruction_iterator_next(instr_iter_t *iter)
+{
+    GArchInstruction *result;               /* Résultat à retourner        */
+
+    g_arch_processor_lock(iter->proc);
+
+    if (iter->stamp != g_arch_processor_get_stamp(iter->proc))
+        result = NULL;
+
+    else
+    {
+        if (iter->index < g_arch_processor_count_disassembled_instructions(iter->proc))
+            result = g_arch_processor_get_disassembled_instruction(iter->proc, iter->index);
+        else
+            result = NULL;
+
+        if (result != NULL)
+            iter->index++;
+
+    }
+
+    g_arch_processor_unlock(iter->proc);
+
+    return result;
+
+}
diff --git a/src/arch/instriter.h b/src/arch/instriter.h
new file mode 100644
index 0000000..b9c7621
--- /dev/null
+++ b/src/arch/instriter.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.h - prototypes pour le parcours simplifié d'un ensemble d'instructions
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRITER_H
+#define _ARCH_INSTRITER_H
+
+
+#include "instruction.h"
+
+
+
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
+typedef struct _GArchProcessor GArchProcessor;
+
+/* Suivi d'un parcours d'instructions */
+typedef struct _instr_iter_t instr_iter_t;
+
+
+/* Construit un itérateur pour parcourir des instructions. */
+instr_iter_t *create_instruction_iterator(GArchProcessor *, size_t);
+
+/* Détruit un itérateur mis en place. */
+void delete_instruction_iterator(instr_iter_t *);
+
+/* Fournit l'instruction qui en suit une autre. */
+GArchInstruction *get_instruction_iterator_next(instr_iter_t *);
+
+
+
+#endif  /* _ARCH_INSTRITER_H */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index d625e77..bddc2bf 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -84,7 +84,7 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *);
  * On procède donc à une seconde déclaration, en attendant éventuellement mieux.
  */
 
-/* Ligne de représentation générique (instance) */
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
 typedef struct _GArchProcessor GArchProcessor;
 
 
diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h
index 8631731..b170cad 100644
--- a/src/arch/processor-int.h
+++ b/src/arch/processor-int.h
@@ -87,6 +87,11 @@ struct _GArchProcessor
     GArchInstruction **instructions;        /* Instructions désassemblées  */
     size_t instr_allocated;                 /* Taille de la liste allouée  */
     size_t instr_count;                     /* Taille de la liste aplatie  */
+    unsigned int stamp;                     /* Marque de suivi des modifs  */
+    GMutex mutex;                           /* Verrou pour l'accès         */
+#ifndef NDEBUG
+    gint locked;                            /* Statut d'accès à la liste   */
+#endif
 
     instr_coverage *coverages;              /* Liste de couvertures        */
     size_t cov_allocated;                   /* Taille de la liste allouée  */
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 615aa86..26c7170 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -59,6 +59,12 @@ static void g_arch_processor_class_init(GArchProcessorClass *);
 /* Initialise une instance de processeur d'architecture. */
 static void g_arch_processor_init(GArchProcessor *);
 
+/* Supprime toutes les références externes. */
+static void g_arch_processor_dispose(GArchProcessor *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_processor_finalize(GArchProcessor *);
+
 
 
 
@@ -76,6 +82,9 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *, GArchInstruc
 
 
 
+
+
+
 /* Indique le type défini pour un processeur d'architecture. */
 G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT);
 
@@ -94,6 +103,12 @@ G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT);
 
 static void g_arch_processor_class_init(GArchProcessorClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_processor_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_arch_processor_finalize;
 
 }
 
@@ -112,6 +127,11 @@ static void g_arch_processor_class_init(GArchProcessorClass *klass)
 
 static void g_arch_processor_init(GArchProcessor *proc)
 {
+#ifndef DEBUG
+    g_atomic_int_set(&proc->loacked, 0);
+#endif
+    g_mutex_init(&proc->mutex);
+
     proc->coverages = NULL;
     proc->cov_allocated = 0;
     proc->cov_count = 0;
@@ -121,6 +141,46 @@ static void g_arch_processor_init(GArchProcessor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_processor_dispose(GArchProcessor *proc)
+{
+    g_mutex_clear(&proc->mutex);
+
+    G_OBJECT_CLASS(g_arch_processor_parent_class)->dispose(G_OBJECT(proc));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_processor_finalize(GArchProcessor *proc)
+{
+    G_OBJECT_CLASS(g_arch_processor_parent_class)->finalize(G_OBJECT(proc));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc = architecture visée par la procédure.                  *
 *                                                                             *
 *  Description : Fournit un contexte propre au processeur d'une architecture. *
@@ -268,6 +328,62 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *proc, GProc
 
 
 /* ---------------------------------------------------------------------------------- */
+/*                    RASSEMBLEMENT DES INSTRUCTIONS DESASSEMBLEES                    */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc  = architecture à manipuler.                            *
+*                state = nouvel état de l'accès aux instructions.             *
+*                                                                             *
+*  Description : Protège ou lève la protection de l'accès aux instructions.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_processor_lock_unlock(GArchProcessor *proc, bool state)
+{
+    if (state)
+    {
+        g_mutex_lock(&proc->mutex);
+        g_atomic_int_set(&proc->locked, 1);
+    }
+    else
+    {
+        g_atomic_int_set(&proc->locked, 0);
+        g_mutex_unlock(&proc->mutex);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture à consulter via la procédure.            *
+*                                                                             *
+*  Description : Fournit la marque de dernière modification des instructions. *
+*                                                                             *
+*  Retour      : Marque de la dernière modification de la liste d'instruct°.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+unsigned int g_arch_processor_get_stamp(const GArchProcessor *proc)
+{
+    //assert(g_atomic_int_get(&proc->locked) == 1);
+
+    return proc->stamp;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
 /*                    MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES                    */
 /* ---------------------------------------------------------------------------------- */
 
@@ -348,48 +464,6 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchIns
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : proc  = processeur recensant diverses instructions.          *
-*                addr  = position en mémoire ou physique à chercher.          *
-*                                                                             *
-*  Description : Recherche un groupe d'instruction d'après son adresse.       *
-*                                                                             *
-*  Retour      : Couverture trouvée ou NULL si aucune.                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr)
-{
-    instr_coverage *result;                 /* Trouvaille à retourner      */
-    void *ptr;                              /* Résultat des recherches     */
-
-    int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)
-    {
-        int status;                         /* Bilan d'une comparaison     */
-
-        status = cmp_mrange_with_vmpa(&c->range, a);
-
-        return status;
-
-    }
-
-    ptr = bsearch(addr, proc->coverages, proc->cov_count,
-                  sizeof(instr_coverage), (__compar_fn_t)search_for_coverage_by_addr);
-
-    result = ((instr_coverage *)ptr);
-
-    return result;
-
-}
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : proc = architecture visée par la procédure.                  *
 *                list = liste des instructions désassemblées.                 *
 *                                                                             *
@@ -519,6 +593,44 @@ size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *pr
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc  = processeur recensant diverses instructions.          *
+*                addr  = position en mémoire ou physique à chercher.          *
+*                                                                             *
+*  Description : Recherche un groupe d'instruction d'après son adresse.       *
+*                                                                             *
+*  Retour      : Couverture trouvée ou NULL si aucune.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr)
+{
+    instr_coverage *result;                 /* Trouvaille à retourner      */
+    void *ptr;                              /* Résultat des recherches     */
+
+    int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)
+    {
+        int status;                         /* Bilan d'une comparaison     */
+
+        status = cmp_mrange_with_vmpa(&c->range, a);
+
+        return status;
+
+    }
+
+    ptr = bsearch(addr, proc->coverages, proc->cov_count,
+                  sizeof(instr_coverage), (__compar_fn_t)search_for_coverage_by_addr);
+
+    result = ((instr_coverage *)ptr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc   = processeur recensant diverses instructions.         *
 *                addr   = position en mémoire ou physique à chercher.         *
 *                nearby = la recherche s'effectue-t-elle de façon stricte ?   *
diff --git a/src/arch/processor.h b/src/arch/processor.h
index f0f9b55..02b3533 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -44,10 +44,10 @@
 
 
 
-/* Ligne de représentation générique (instance) */
+/* Définition générique d'un processeur d'architecture (instance) */
 typedef struct _GArchProcessor GArchProcessor;
 
-/* Ligne de représentation générique (classe) */
+/* Définition générique d'un processeur d'architecture (classe) */
 typedef struct _GArchProcessorClass GArchProcessorClass;
 
 
@@ -74,6 +74,20 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcCont
 
 
 
+/* ------------------ RASSEMBLEMENT DES INSTRUCTIONS DESASSEMBLEES ------------------ */
+
+
+/* Protège ou lève la protection de l'accès aux instructions. */
+void g_arch_processor_lock_unlock(GArchProcessor *, bool);
+
+#define g_arch_processor_lock(p) g_arch_processor_lock_unlock(p, true)
+#define g_arch_processor_unlock(p) g_arch_processor_lock_unlock(p, false)
+
+/* Fournit la marque de dernière modification des instructions. */
+unsigned int g_arch_processor_get_stamp(const GArchProcessor *);
+
+
+
 /* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */
 
 
-- 
cgit v0.11.2-87-g4458