From c0af4cc392a246b05d41b7b7c05bbcd8b0cfb39e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 7 Dec 2018 21:33:21 +0100
Subject: Relied on GObject introspection and dynamic gtypes to inherit in
 Python.

---
 plugins/pychrysalide/Makefile.am         |   1 +
 plugins/pychrysalide/analysis/content.c  |  45 +++
 plugins/pychrysalide/analysis/content.h  |   3 +
 plugins/pychrysalide/arch/Makefile.am    |   1 +
 plugins/pychrysalide/arch/context.c      | 163 +++++++++++
 plugins/pychrysalide/arch/context.h      |  45 +++
 plugins/pychrysalide/arch/instruction.c  |  45 +++
 plugins/pychrysalide/arch/instruction.h  |   3 +
 plugins/pychrysalide/arch/module.c       |   2 +
 plugins/pychrysalide/arch/processor.c    | 359 ++++++++++++++++++++++++
 plugins/pychrysalide/dt.c                | 462 +++++++++++++++++++++++++++++++
 plugins/pychrysalide/dt.h                |  47 ++++
 plugins/pychrysalide/format/executable.c |  46 +++
 plugins/pychrysalide/format/executable.h |   3 +
 plugins/pychrysalide/helpers.c           |  29 +-
 plugins/pychrysalide/pychrysa.c          |   3 +
 src/arch/processor.c                     |  49 +++-
 src/arch/processor.h                     |   6 +-
 tests/arch/processor.py                  |  52 ++++
 19 files changed, 1334 insertions(+), 30 deletions(-)
 create mode 100644 plugins/pychrysalide/arch/context.c
 create mode 100644 plugins/pychrysalide/arch/context.h
 create mode 100644 plugins/pychrysalide/dt.c
 create mode 100644 plugins/pychrysalide/dt.h
 create mode 100644 tests/arch/processor.py

diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index cfd5f81..0483b2a 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -6,6 +6,7 @@ libdir = $(pluginslibdir)
 
 pychrysalide_la_SOURCES =				\
 	access.h access.c					\
+	dt.h dt.c							\
 	helpers.h helpers.c					\
 	plugin.h plugin.c					\
 	pychrysa.h pychrysa.c				\
diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c
index f590f82..26e7654 100644
--- a/plugins/pychrysalide/analysis/content.c
+++ b/plugins/pychrysalide/analysis/content.c
@@ -583,3 +583,48 @@ bool ensure_python_binary_content_is_registered(void)
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en contenu binaire.                       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_binary_content(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_binary_content_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to binary content");
+            break;
+
+        case 1:
+            *((GBinContent **)dst) = G_BIN_CONTENT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/content.h b/plugins/pychrysalide/analysis/content.h
index b433828..61b82b3 100644
--- a/plugins/pychrysalide/analysis/content.h
+++ b/plugins/pychrysalide/analysis/content.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_binary_content_type(void);
 /* Prend en charge l'objet 'pychrysalide.analysis.BinContent'. */
 bool ensure_python_binary_content_is_registered(void);
 
+/* Tente de convertir en contenu binaire. */
+int convert_to_binary_content(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_CONTENT_H */
diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am
index 6210ed3..0145db2 100644
--- a/plugins/pychrysalide/arch/Makefile.am
+++ b/plugins/pychrysalide/arch/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libpychrysaarch.la
 
 libpychrysaarch_la_SOURCES =			\
+	context.h context.c					\
 	feeder.h feeder.c					\
 	immediate.h immediate.c				\
 	instriter.h instriter.c				\
diff --git a/plugins/pychrysalide/arch/context.c b/plugins/pychrysalide/arch/context.c
new file mode 100644
index 0000000..4428075
--- /dev/null
+++ b/plugins/pychrysalide/arch/context.c
@@ -0,0 +1,163 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - équivalent Python du fichier "arch/context.h"
+ *
+ * Copyright (C) 2018 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 "context.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <arch/context.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_proc_context_type(void)
+{
+    static PyMethodDef py_proc_context_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_proc_context_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_proc_context_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.arch.ProcContext",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = "PyChrysalide disassembly context.",
+
+        .tp_methods     = py_proc_context_methods,
+        .tp_getset      = py_proc_context_getseters,
+
+    };
+
+    return &py_proc_context_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.arch.ArchContext'.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_proc_context_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'ArchContext'   */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_proc_context_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        APPLY_ABSTRACT_FLAG(type);
+
+        module = get_access_to_python_module("pychrysalide.arch");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_PROC_CONTEXT, type, &PyGObject_Type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en contexte de désassemblage.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_proc_context(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_proc_context_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to disassembly context");
+            break;
+
+        case 1:
+            *((GProcContext **)dst) = G_PROC_CONTEXT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/arch/context.h b/plugins/pychrysalide/arch/context.h
new file mode 100644
index 0000000..eb5f0c1
--- /dev/null
+++ b/plugins/pychrysalide/arch/context.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour l'équivalent Python du fichier "arch/context.h"
+ *
+ * Copyright (C) 2018 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_CONTEXT_H
+#define _PLUGINS_PYCHRYSALIDE_ARCH_CONTEXT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_proc_context_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.arch.ProcContext'. */
+bool ensure_python_proc_context_is_registered(void);
+
+/* Tente de convertir en contexte de désassemblage. */
+int convert_to_proc_context(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ARCH_CONTEXT_H */
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 4202625..6399d63 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -568,3 +568,48 @@ bool ensure_python_arch_instruction_is_registered(void)
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en instruction d'architecture.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_arch_instruction(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_arch_instruction_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to arch instruction");
+            break;
+
+        case 1:
+            *((GArchInstruction **)dst) = G_ARCH_INSTRUCTION(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/arch/instruction.h b/plugins/pychrysalide/arch/instruction.h
index 5433222..fea329f 100644
--- a/plugins/pychrysalide/arch/instruction.h
+++ b/plugins/pychrysalide/arch/instruction.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_arch_instruction_type(void);
 /* Prend en charge l'objet 'pychrysalide.arch.ArchInstruction'. */
 bool ensure_python_arch_instruction_is_registered(void);
 
+/* Tente de convertir en instruction d'architecture. */
+int convert_to_arch_instruction(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ARCH_INSTRUCTION_H */
diff --git a/plugins/pychrysalide/arch/module.c b/plugins/pychrysalide/arch/module.c
index 8bd6df6..db514ef 100644
--- a/plugins/pychrysalide/arch/module.c
+++ b/plugins/pychrysalide/arch/module.c
@@ -32,6 +32,7 @@
 #include <common/endianness.h>
 
 
+#include "context.h"
 #include "feeder.h"
 #include "immediate.h"
 #include "instriter.h"
@@ -163,6 +164,7 @@ bool populate_arch_module(void)
 
     result = true;
 
+    if (result) result = ensure_python_proc_context_is_registered();
     if (result) result = ensure_python_proxy_feeder_is_registered();
     if (result) result = ensure_python_imm_operand_is_registered();
     if (result) result = ensure_python_instr_iterator_is_registered();
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 7ff374b..2ecf6b8 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -30,19 +30,35 @@
 
 
 #include <i18n.h>
+#include <arch/processor-int.h>
 
 
+#include "context.h"
 #include "instriter.h"
 #include "instruction.h"
 #include "vmpa.h"
 #include "../access.h"
+#include "../dt.h"
 #include "../helpers.h"
+#include "../analysis/content.h"
+#include "../format/executable.h"
 
 
 
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
 
 
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_arch_processor_new(PyTypeObject *, PyObject *, PyObject *);
 
+/* Initialise la classe des descriptions de fichier binaire. */
+static void py_arch_processor_init_gclass(GArchProcessorClass *, gpointer);
+
+/* Fournit un contexte propre au processeur d'une architecture. */
+static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *);
+
+/* Désassemble une instruction dans un flux de données. */
+static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProcessor *, GProcContext *, const GBinContent *, vmpa2t *, GExeFormat *);
 
 
 
@@ -61,6 +77,11 @@ static PyObject *py_arch_processor_get_instruction_min_size(PyObject *, void *);
 /* Indique si l'architecture possède un espace virtuel ou non. */
 static PyObject *py_arch_processor_has_virtual_space(PyObject *, void *);
 
+/* Fournit un contexte propre au processeur d'une architecture. */
+static PyObject *py_arch_processor_get_context(PyObject *, PyObject *);
+
+/* Désassemble une instruction dans un flux de données. */
+static PyObject *py_arch_processor_disassemble(PyObject *, PyObject *);
 
 
 
@@ -89,6 +110,7 @@ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *);
 
 
 
+/* ---------------------------- DEFINITION DE PROCESSEUR ---------------------------- */
 
 
 /* Définit les constantes pour les types d'erreurs. */
@@ -96,7 +118,239 @@ static bool define_python_arch_processor_constants(PyTypeObject *);
 
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                          GLUE POUR CREATION DEPUIS PYTHON                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type du nouvel objet à mettre en place.               *
+*                args = éventuelle liste d'arguments.                         *
+*                kwds = éventuel dictionnaire de valeurs mises à disposition. *
+*                                                                             *
+*  Description : Accompagne la création d'une instance dérivée en Python.     *
+*                                                                             *
+*  Retour      : Nouvel objet Python mis en place ou NULL en cas d'échec.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;                       /* Objet à retourner           */
+    bool abstract;                          /* Validation du type parent   */
+    GType gtype;                            /* Nouveau type de processeur  */
+    PyObject *sys_mod_dict;                 /* Dictionnaire des modules    */
+    PyObject *modname;                      /* Nom du module du type       */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire dudit module   */
+
+    /* Validations diverses */
+
+    abstract = (type == get_python_arch_processor_type());
+
+    if (abstract)
+    {
+        result = NULL;
+        PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+        goto exit;
+    }
+
+    /* Mise en place d'un type dédié */
+
+    gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name,
+                               (GClassInitFunc)py_arch_processor_init_gclass);
+
+    /* Enregistrement du nouveau GType dans Python */
+
+    sys_mod_dict = PyImport_GetModuleDict();
+
+    modname = PyDict_GetItemString(type->tp_dict, "__module__");
+
+    module = PyObject_GetItem(sys_mod_dict, modname);
+
+    dict = PyModule_GetDict(module);
+
+    if (!_register_class_for_pygobject(dict, gtype, type,
+                                       &PyGObject_Type, get_python_arch_processor_type(), NULL))
+    {
+        result = NULL;
+        goto exit;
+    }
+
+    Py_DECREF(module);
+    Py_DECREF(modname);
+
+    /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+    result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                unused = données non utilisées ici.                          *
+*                                                                             *
+*  Description : Initialise la classe des descriptions de fichier binaire.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_arch_processor_init_gclass(GArchProcessorClass *class, gpointer unused)
+{
+    class->get_ctx = py_arch_processor_get_context_wrapper;
+
+    class->disassemble = py_arch_processor_disassemble_wrapper;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture visée par la procédure.                  *
+*                                                                             *
+*  Description : Fournit un contexte propre au processeur d'une architecture. *
+*                                                                             *
+*  Retour      : Nouveau contexte mis à disposition.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *proc)
+{
+    GProcContext *result;                   /* Instance à retourner        */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pyctx;                        /* Contexte en objet Python    */
+    int ret;                                /* Bilan d'une conversion      */
+    GArchProcessorClass *class;             /* Classe de l'objet courant   */
+    GArchProcessorClass *parent;            /* Classe parente              */
+
+    pyobj = pygobject_new(G_OBJECT(proc));
+
+    if (has_python_method(pyobj, "_get_context"))
+    {
+        pyctx = run_python_method(pyobj, "_get_context", NULL);
+
+        if (pyctx == NULL)
+            result = NULL;
+
+        else
+        {
+            ret = convert_to_proc_context(pyctx, &result);
+
+            if (ret == 1)
+                g_object_ref(G_OBJECT(result));
+            else
+            {
+                PyErr_Clear();
+                result = NULL;
+            }
 
+            Py_DECREF(pyctx);
+
+        }
+
+    }
+
+    else
+    {
+        class = G_ARCH_PROCESSOR_GET_CLASS(proc);
+        parent = g_type_class_peek_parent(class);
+
+        result = parent->get_ctx(proc);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc    = architecture visée par la procédure.               *
+*                ctx     = contexte lié à l'exécution du processeur.          *
+*                content = flux de données à analyser.                        *
+*                pos     = position courante dans ce flux. [OUT]              *
+*                format  = format du fichier contenant le code.               *
+*                                                                             *
+*  Description : Désassemble une instruction dans un flux de données.         *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, vmpa2t *pos, GExeFormat *format)
+{
+    GArchInstruction *result;               /* Instance à retourner        */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pypos;                        /* Position en objet Python    */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *pyins;                        /* Instruction en objet Python */
+    int ret;                                /* Bilan d'une conversion      */
+
+    pyobj = pygobject_new(G_OBJECT(proc));
+
+    if (has_python_method(pyobj, "_disassemble"))
+    {
+        pypos = build_from_internal_vmpa(pos);
+        Py_INCREF(pypos);
+
+        args = PyTuple_New(4);
+        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+        PyTuple_SetItem(args, 2, pypos);
+        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(format)));
+
+        pyins = run_python_method(pyobj, "_disassemble", args);
+
+        Py_DECREF(args);
+
+        if (pyins == NULL)
+            result = NULL;
+
+        else
+        {
+            ret = convert_to_arch_instruction(pyins, &result);
+
+            if (ret == 1)
+                g_object_ref(G_OBJECT(result));
+            else
+            {
+                PyErr_Clear();
+                result = NULL;
+            }
+
+            Py_DECREF(pyins);
+
+            copy_vmpa(pos, get_internal_vmpa(pypos));
+
+        }
+
+        Py_DECREF(pypos);
+
+    }
+
+    else
+        result = NULL;
+
+    return result;
+
+}
 
 
 
@@ -229,7 +483,100 @@ static PyObject *py_arch_processor_has_virtual_space(PyObject *self, void *closu
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = architecture concernée par la procédure.              *
+*                args = instruction représentant le point de départ.          *
+*                                                                             *
+*  Description : Fournit un contexte propre au processeur d'une architecture. *
+*                                                                             *
+*  Retour      : Nouveau contexte mis à disposition.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static PyObject *py_arch_processor_get_context(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GArchProcessor *proc;                   /* Processeur manipulé         */
+    GProcContext *ctx;                      /* Nouveau contexte en place   */
+
+    proc = G_ARCH_PROCESSOR(pygobject_get(self));
+
+    ctx = g_arch_processor_get_context(proc);
+
+    if (ctx != NULL)
+    {
+        result = pygobject_new(G_OBJECT(ctx));
+        g_object_unref(G_OBJECT(ctx));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = architecture concernée par la procédure.              *
+*                args = instruction représentant le point de départ.          *
+*                                                                             *
+*  Description : Désassemble une instruction dans un flux de données.         *
+*                                                                             *
+*  Retour      : Instruction mise en place ou None en cas d'échec.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_processor_disassemble(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GProcContext *ctx;                      /* Contexte de désassemblage   */
+    GBinContent *content;                   /* Contenu binaire à parcourir */
+    PyObject *pypos;                        /* Position en objet Python    */
+    GExeFormat *format;                     /* Format de fichier associé   */
+    int ret;                                /* Bilan de lecture des args.  */
+    vmpa2t pos;                             /* Position d'analyse courante */
+    GArchProcessor *proc;                   /* Processeur manipulé         */
+    GArchInstruction *instr;                /* Instruction mise en place   */
+
+    ret = PyArg_ParseTuple(args, "O&O&OO&",
+                           convert_to_proc_context, &ctx,
+                           convert_to_binary_content, &content,
+                           &pypos,
+                           convert_to_executable_format, &format);
+    if (!ret) return NULL;
+
+    ret = convert_any_to_vmpa(pypos, &pos);
+    if (ret != 1) return NULL;
+
+    proc = G_ARCH_PROCESSOR(pygobject_get(self));
+
+    instr = g_arch_processor_disassemble(proc, ctx, content, &pos, format);
+
+    copy_vmpa(get_internal_vmpa(pypos), &pos);
+
+    if (instr != NULL)
+    {
+        result = pygobject_new(G_OBJECT(instr));
+        g_object_unref(G_OBJECT(instr));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
 
 
 
@@ -527,6 +874,16 @@ PyTypeObject *get_python_arch_processor_type(void)
 {
     static PyMethodDef py_arch_processor_methods[] = {
         {
+            "get_context", py_arch_processor_get_context,
+            METH_NOARGS,
+            "get_context($self, /)\n--\n\nProvide a new disassembly context."
+        },
+        {
+            "disassemble", py_arch_processor_disassemble,
+            METH_VARARGS,
+            "disassemble($self, context, content, pos, format, /)\n--\n\nDisassemble a portion of binary content into one instruction."
+        },
+        {
             "add_error", py_arch_processor_add_error,
             METH_VARARGS,
             "add_error($self, type, addr, desc, /)\n--\n\nExtend the list of detected disassembling errors."
@@ -581,6 +938,8 @@ PyTypeObject *get_python_arch_processor_type(void)
         .tp_methods     = py_arch_processor_methods,
         .tp_getset      = py_arch_processor_getseters,
 
+        .tp_new         = py_arch_processor_new,
+
     };
 
     return &py_arch_processor_type;
diff --git a/plugins/pychrysalide/dt.c b/plugins/pychrysalide/dt.c
new file mode 100644
index 0000000..edfc032
--- /dev/null
+++ b/plugins/pychrysalide/dt.c
@@ -0,0 +1,462 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.c - possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dt.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
+
+
+#define G_TYPE_DYNAMIC_TYPES            g_dynamic_types_get_type()
+#define G_DYNAMIC_TYPES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
+#define G_IS_DYNAMIC_TYPES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+
+
+/* Mémorisation des caractéristiques de type */
+typedef struct _type_dyn_info_t
+{
+    GType type;                             /* Identifiant unique obtenu   */
+    GClassInitFunc init;                    /* Définition des méthodes     */
+
+} type_dyn_info_t;
+
+/* Description de fichier binaire (instance) */
+typedef struct _GDynamicTypes
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    type_dyn_info_t **info;                 /* Liste d'informations utiles */
+    size_t count;                           /* Taille de cette liste       */
+
+} GDynamicTypes;
+
+/* Description de fichier binaire (classe) */
+typedef struct _GDynamicTypesClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+} GDynamicTypesClass;
+
+
+/* Indique le type défini pour une gestion de types dynamique. */
+static GType g_dynamic_types_get_type(void);
+
+/* Initialise la classe de gestion de types dynamique. */
+static void g_dynamic_types_class_init(GDynamicTypesClass *);
+
+/* Initialise une gestion de types dynamique. */
+static void g_dynamic_types_init(GDynamicTypes *);
+
+/* Procède à l'initialisation de l'interface de typage nouveau. */
+static void g_dynamic_types_interface_init(GTypePluginClass *);
+
+/* Supprime toutes les références externes. */
+static void g_dynamic_types_dispose(GDynamicTypes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dynamic_types_finalize(GDynamicTypes *);
+
+/* Crée un nouveau gestionnaire de nouveaux types. */
+static GDynamicTypes *g_dynamic_types_new(void);
+
+/* Marque une augmentation des utilisations. */
+static void g_dynamic_types_use(GDynamicTypes *);
+
+/* Marque une diminution des utilisations. */
+static void g_dynamic_types_unuse(GDynamicTypes *);
+
+/* Complète la définition d'un type dynamiquement. */
+static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
+
+/* Retrouve les informations concernant un type dynamique. */
+static type_dyn_info_t *g_dynamic_types_find(GDynamicTypes *, GType);
+
+/* Fournit un identifiant GLib pour un nouveau type Python. */
+static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc);
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Encadrement des nouveaux types Python dérivés */
+static GDynamicTypes *_python_dtypes = NULL;
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           MODULE DE GESTION DES NOUVEAUX                           */
+/* ---------------------------------------------------------------------------------- */
+
+/* Indique le type défini pour une gestion de types dynamique. */
+G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe de gestion de types dynamique.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une gestion de types dynamique.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_init(GDynamicTypes *types)
+{
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de typage nouveau. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_interface_init(GTypePluginClass *iface)
+{
+    iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
+    iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
+    iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_dispose(GDynamicTypes *types)
+{
+    G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_finalize(GDynamicTypes *types)
+{
+    G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un nouveau gestionnaire de nouveaux types.              *
+*                                                                             *
+*  Retour      : Instance mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDynamicTypes *g_dynamic_types_new(void)
+{
+    GDynamicTypes *result;                  /* Adresse à retourner         */
+
+    result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                                                                             *
+*  Description : Marque une augmentation des utilisations.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_use(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                                                                             *
+*  Description : Marque une diminution des utilisations.                      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_unuse(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                type  = nouveau type GLib à traiter.                         *
+*                info  = information concernant ce type à constituer. [OUT]   *
+*                table = table de valeur à éventuellement initialiser. [OUT]  *
+*                                                                             *
+*  Description : Complète la définition d'un type dynamiquement.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
+{
+    type_dyn_info_t *nfo;                   /* Source d'inspiration        */
+    GType parent;                           /* Type parent du type         */
+    GTypeQuery query;                       /* Informations complémentaires*/
+
+    /* Consultation */
+
+    nfo = g_dynamic_types_find(types, type);
+    assert(nfo != NULL);
+
+    parent = g_type_parent(type);
+    g_type_query(parent, &query);
+
+    /* Définition */
+
+    info->class_size = query.class_size;
+    info->class_init = nfo->init;
+
+    info->instance_size = query.instance_size;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                type   = identifiant du type GLib à considérer.              *
+*                                                                             *
+*  Description : Retrouve les informations concernant un type dynamique.      *
+*                                                                             *
+*  Retour      : Structure contenant les informations associées au type.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static type_dyn_info_t *g_dynamic_types_find(GDynamicTypes *types, GType target)
+{
+
+    return types->info[0];
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                name   = désignation du nouveau type.                        *
+*                init   = procédure d'initialisation de la classe associée.   *
+*                                                                             *
+*  Description : Fournit un identifiant GLib pour un nouveau type Python.     *
+*                                                                             *
+*  Retour      : identifiant d'un nouveau type valide, ou 0.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init)
+{
+    GType result;                           /* Identifiant à retourner     */
+    type_dyn_info_t *new;                   /* Mémorisation de paramètres  */
+
+    /* Création d'un nouveau type adapté */
+
+    result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
+
+    if (result == 0)
+        goto exit;
+
+    new = malloc(sizeof(type_dyn_info_t));
+
+    new->type = result;
+    new->init = init;
+
+    /* Inscription définitive */
+
+    types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
+
+    types->info[types->count - 1] = new;
+
+ exit:
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         ACCOMPAGNEMENTS DES NOUVEAUX TYPES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Lance le support de dérivations de types dans Python.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool init_dynamic_python_types(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    _python_dtypes = g_dynamic_types_new();
+
+    result = (_python_dtypes != NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Arrête le support de dérivations de types dans Python.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_dynamic_python_types(void)
+{
+    g_object_unref(G_OBJECT(_python_dtypes));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                name   = désignation du nouveau type.                        *
+*                init   = procédure d'initialisation de la classe associée.   *
+*                                                                             *
+*  Retour      : Identifiant d'un nouveau type valide, ou 0.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init)
+{
+    GType result;                           /* Identifiant à retourner     */
+
+    result = g_type_from_name(name);
+
+    if (result == 0)
+        result = g_dynamic_types_register_type(_python_dtypes, parent, name, init);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/dt.h b/plugins/pychrysalide/dt.h
new file mode 100644
index 0000000..b0f16db
--- /dev/null
+++ b/plugins/pychrysalide/dt.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_DT_H
+#define _PLUGINS_PYCHRYSALIDE_DT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Lance le support de dérivations de types dans Python. */
+bool init_dynamic_python_types(void);
+
+/* Arrête le support de dérivations de types dans Python. */
+void exit_dynamic_python_types(void);
+
+/* Fournit un identifiant GLib pour un nouveau type Python. */
+GType built_dynamic_type(GType, const char *, GClassInitFunc);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index 0346ecb..cc0dd33 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -25,6 +25,7 @@
 #include "executable.h"
 
 
+#include <assert.h>
 #include <pygobject.h>
 
 
@@ -236,6 +237,51 @@ bool ensure_python_executable_format_is_registered(void)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en format exécutable.                     *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_executable_format(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_executable_format_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to executable format");
+            break;
+
+        case 1:
+            *((GExeFormat **)dst) = G_EXE_FORMAT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                              TRADUCTION D'EMPLACEMENT                              */
diff --git a/plugins/pychrysalide/format/executable.h b/plugins/pychrysalide/format/executable.h
index d2308e0..f94058d 100644
--- a/plugins/pychrysalide/format/executable.h
+++ b/plugins/pychrysalide/format/executable.h
@@ -43,6 +43,9 @@ PyTypeObject *get_python_executable_format_type(void);
 /* Prend en charge l'objet 'pychrysalide.format.ExeFormat'. */
 bool ensure_python_executable_format_is_registered(void);
 
+/* Tente de convertir en format exécutable. */
+int convert_to_executable_format(PyObject *, void *);
+
 
 
 /* ---------------------------- TRADUCTION D'EMPLACEMENT ---------------------------- */
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 4ada405..51c2f31 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -112,12 +112,18 @@ bool has_python_method(PyObject *module, const char *method)
     bool result;                            /* Bilan à retourner           */
     PyObject *func;                         /* Fonction visée              */
 
-    func = PyObject_GetAttrString(module, method);
-    if (func == NULL) return false;
+    result = (PyObject_HasAttrString(module, method) == 1);
 
-    result = PyCallable_Check(func);
+    if (result)
+    {
+        func = PyObject_GetAttrString(module, method);
+        assert(func != NULL);
 
-    Py_DECREF(func);
+        result = PyCallable_Check(func);
+
+        Py_DECREF(func);
+
+    }
 
     return result;
 
@@ -503,20 +509,15 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
 
     va_end(ap);
 
-
+    /**
+     * les renseignements suivants ne semblent pas nécessaires...
+     */
 
     /*
-#0  0x000055555565aad4 in insertdict (mp=0x7fffe7c2c8a8, key='GenConfig', hash=262970853803706525, value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:801
-#1  0x000055555565bf62 in PyDict_SetItem (op={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key='GenConfig', value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:1227
-#2  0x00005555556610b0 in PyDict_SetItemString (v={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key=0x7ffff69cd0bd "GenConfig", item=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:2870
-#3  0x00007ffff69b3d12 in _register_class_for_pygobject (dict={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, gtype=93824998785328, type=0x7ffff6bd9ce0 <py_generic_config_type>, base=0x7fffe80e72a0 <PyGObject_Type>) at helpers.c:320
+    type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
+    type->tp_dictoffset = offsetof(PyGObject, inst_dict);
     */
 
-
-
-    //type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
-    //type->tp_dictoffset = offsetof(PyGObject, inst_dict);
-
     pygobject_register_class(dict, NULL, gtype, type, static_bases);
 
     if (PyErr_Occurred() == NULL)
diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c
index 50d2f92..785481b 100644
--- a/plugins/pychrysalide/pychrysa.c
+++ b/plugins/pychrysalide/pychrysa.c
@@ -44,6 +44,7 @@
 
 
 #include "access.h"
+#include "dt.h"
 #include "helpers.h"
 #include "plugin.h"
 #include "struct.h"
@@ -362,6 +363,8 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
 
     /* Mise en place des fonctionnalités offertes */
 
+    init_dynamic_python_types();
+
     result = PyModule_Create(&py_chrysalide_module);
 
     register_access_to_python_module(py_chrysalide_module.m_name, result);
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 4450208..4d7bacc 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -69,6 +69,8 @@ static void g_arch_processor_dispose(GArchProcessor *);
 /* Procède à la libération totale de la mémoire. */
 static void g_arch_processor_finalize(GArchProcessor *);
 
+/* Fournit un contexte générique pour l'exécution du processeur. */
+static GProcContext *_g_arch_processor_get_context(const GArchProcessor *);
 
 
 
@@ -125,6 +127,8 @@ static void g_arch_processor_class_init(GArchProcessorClass *klass)
     object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_processor_dispose;
     object->finalize = (GObjectFinalizeFunc)g_arch_processor_finalize;
 
+    klass->get_ctx = _g_arch_processor_get_context;
+
     g_signal_new("changed",
                  G_TYPE_ARCH_PROCESSOR,
                  G_SIGNAL_RUN_LAST,
@@ -225,28 +229,21 @@ static void g_arch_processor_finalize(GArchProcessor *proc)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : proc = architecture visée par la procédure.                  *
+*  Paramètres  : proc = architecture, spectatrice ici.                        *
 *                                                                             *
-*  Description : Fournit un contexte propre au processeur d'une architecture. *
+*  Description : Fournit un contexte générique pour l'exécution du processeur.*
 *                                                                             *
-*  Retour      : Nouveau contexte mis à disposition.                          *
+*  Retour      : Contexte mis en place.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GProcContext *g_arch_processor_get_context(const GArchProcessor *proc)
+static GProcContext *_g_arch_processor_get_context(const GArchProcessor *proc)
 {
-    GProcContext *result;                   /* Contexte à retourner        */
-    GArchProcessorClass *class;             /* Classe de l'instance active */
+    GProcContext *result;                   /* Instance à retourner        */
 
-    class = G_ARCH_PROCESSOR_GET_CLASS(proc);
-
-    if (class->get_ctx != NULL)
-        result = class->get_ctx(proc);
-
-    else
-        result = NULL;
+    result = g_object_new(G_TYPE_PROC_CONTEXT, NULL);
 
     return result;
 
@@ -331,6 +328,32 @@ bool g_arch_processor_has_virtual_space(const GArchProcessor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = architecture visée par la procédure.                  *
+*                                                                             *
+*  Description : Fournit un contexte propre au processeur d'une architecture. *
+*                                                                             *
+*  Retour      : Nouveau contexte mis à disposition.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GProcContext *g_arch_processor_get_context(const GArchProcessor *proc)
+{
+    GProcContext *result;                   /* Contexte à retourner        */
+    GArchProcessorClass *class;             /* Classe de l'instance active */
+
+    class = G_ARCH_PROCESSOR_GET_CLASS(proc);
+
+    result = class->get_ctx(proc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc    = architecture visée par la procédure.               *
 *                ctx     = contexte lié à l'exécution du processeur.          *
 *                content = flux de données à analyser.                        *
diff --git a/src/arch/processor.h b/src/arch/processor.h
index 24d9287..26eddb1 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -55,9 +55,6 @@ typedef struct _GArchProcessorClass GArchProcessorClass;
 /* Indique le type défini pour un processeur d'architecture. */
 GType g_arch_processor_get_type(void);
 
-/* Fournit un contexte propre au processeur d'une architecture. */
-GProcContext *g_arch_processor_get_context(const GArchProcessor *);
-
 /* Fournit le boustime du processeur d'une architecture. */
 SourceEndian g_arch_processor_get_endianness(const GArchProcessor *);
 
@@ -70,6 +67,9 @@ MemoryDataSize g_arch_processor_get_instruction_min_size(const GArchProcessor *)
 /* Indique si l'architecture possède un espace virtuel ou non. */
 bool g_arch_processor_has_virtual_space(const GArchProcessor *);
 
+/* Fournit un contexte propre au processeur d'une architecture. */
+GProcContext *g_arch_processor_get_context(const GArchProcessor *);
+
 /* Désassemble une instruction dans un flux de données. */
 GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcContext *, const GBinContent *, vmpa2t *, GExeFormat *);
 
diff --git a/tests/arch/processor.py b/tests/arch/processor.py
new file mode 100644
index 0000000..5ad6490
--- /dev/null
+++ b/tests/arch/processor.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+import pychrysalide
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.arch import ArchProcessor
+from pychrysalide.arch import ProcContext
+from pychrysalide.arch import vmpa
+from pychrysalide.format import FlatFormat
+
+
+
+class TestProcessor(ChrysalideTestCase):
+    """TestCase for arch.ArchProcessor."""
+
+
+
+    def testGI(self):
+        """Validate the GObject introspection."""
+
+        with self.assertRaises(RuntimeError):
+            np = ArchProcessor()
+
+
+        class NewContext(ProcContext):
+            pass
+
+        class NewProc(ArchProcessor):
+
+            def _get_context(self):
+                return NewContext()
+
+            def _disassemble(self, ctx, content, pos, format):
+                return None
+
+
+        np = NewProc()
+
+        data  = b'\x01\x02\x03\x04'
+        cnt = MemoryContent(data)
+        fmt = FlatFormat(cnt)
+
+        ctx = np.get_context()
+        self.assertTrue(type(ctx) == NewContext)
+
+        pos = vmpa(0)
+
+        ins = np.disassemble(ctx, cnt, pos, fmt)
+
+        self.assertIsNone(ins)
-- 
cgit v0.11.2-87-g4458