From cd54168f9877ed4ee16ee1e25c72e8338eed7928 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 21 Apr 2020 20:44:33 +0200
Subject: Redefined the interface for creating new processors from Python.

---
 plugins/arm/processor.c                   |  31 +++
 plugins/arm/v7/processor.c                |  93 ++++++-
 plugins/dalvik/processor.c                |  86 +++++-
 plugins/dalvik/v35/processor.c            |  29 +-
 plugins/pychrysalide/analysis/constants.c |   5 +
 plugins/pychrysalide/arch/processor.c     | 428 ++++++++++++++++++++++++++----
 plugins/pychrysalide/helpers.h            |   5 +-
 src/analysis/binary.c                     |   4 +-
 src/arch/processor-int.h                  |  27 +-
 src/arch/processor.c                      |  48 +++-
 src/arch/processor.h                      |   2 +-
 src/core/processors.c                     |   3 -
 12 files changed, 677 insertions(+), 84 deletions(-)

diff --git a/plugins/arm/processor.c b/plugins/arm/processor.c
index ede8674..830fa8a 100644
--- a/plugins/arm/processor.c
+++ b/plugins/arm/processor.c
@@ -40,6 +40,9 @@ static void g_arm_processor_dispose(GArmProcessor *);
 /* Procède à la libération totale de la mémoire. */
 static void g_arm_processor_finalize(GArmProcessor *);
 
+/* Indique si l'architecture possède un espace virtuel ou non. */
+static bool g_arm_processor_has_virtual_space(const GArmProcessor *);
+
 
 
 /* Indique le type défini par la GLib pour le processeur ARM. */
@@ -61,12 +64,17 @@ G_DEFINE_TYPE(GArmProcessor, g_arm_processor, G_TYPE_ARCH_PROCESSOR);
 static void g_arm_processor_class_init(GArmProcessorClass *klass)
 {
     GObjectClass *object_class;             /* Autre version de la classe  */
+    GArchProcessorClass *proc;              /* Encore une autre vision...  */
 
     object_class = G_OBJECT_CLASS(klass);
 
     object_class->dispose = (GObjectFinalizeFunc/* ! */)g_arm_processor_dispose;
     object_class->finalize = (GObjectFinalizeFunc)g_arm_processor_finalize;
 
+    proc = G_ARCH_PROCESSOR_CLASS(klass);
+
+    proc->has_vspace = (has_processor_vspace_fc)g_arm_processor_has_virtual_space;
+
 }
 
 
@@ -124,3 +132,26 @@ static void g_arm_processor_finalize(GArmProcessor *proc)
     G_OBJECT_CLASS(g_arm_processor_parent_class)->finalize(G_OBJECT(proc));
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Indique si l'architecture possède un espace virtuel ou non.  *
+*                                                                             *
+*  Retour      : true si un espace virtuel existe, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arm_processor_has_virtual_space(const GArmProcessor *proc)
+{
+    bool result;                            /* Indication à retourner      */
+
+    result = true;
+
+    return result;
+
+}
diff --git a/plugins/arm/v7/processor.c b/plugins/arm/v7/processor.c
index 078cc2d..7852284 100644
--- a/plugins/arm/v7/processor.c
+++ b/plugins/arm/v7/processor.c
@@ -66,6 +66,15 @@ static void g_armv7_processor_finalize(GArmV7Processor *);
 /* Fournit la désignation interne du processeur d'architecture. */
 static char *g_armv7_processor_get_key(const GArmV7Processor *);
 
+/* Fournit le nom humain de l'architecture visée. */
+static char *g_armv7_processor_get_desc(const GArmV7Processor *);
+
+/* Fournit la taille de l'espace mémoire d'une architecture. */
+static MemoryDataSize g_armv7_processor_get_memory_size(const GArmV7Processor *);
+
+/* Fournit la taille min. des instructions d'une architecture. */
+static MemoryDataSize g_armv7_processor_get_instruction_min_size(const GArmV7Processor *);
+
 /* Fournit un contexte pour l'exécution du processeur ARM. */
 static GArmV7Context *g_armv7_processor_get_context(const GArmV7Processor *);
 
@@ -102,16 +111,12 @@ static void g_armv7_processor_class_init(GArmV7ProcessorClass *klass)
 
     proc = G_ARCH_PROCESSOR_CLASS(klass);
 
-    proc->desc = "ARM v7";
-
-    proc->endianness = SRE_LITTLE;
-    proc->memsize = MDS_32_BITS;
-    proc->inssize = MDS_32_BITS;
-    proc->virt_space = true;
-
     proc->get_key = (get_processor_key_fc)g_armv7_processor_get_key;
-    proc->get_ctx = (get_processor_context_fc)g_armv7_processor_get_context;
+    proc->get_desc = (get_processor_desc_fc)g_armv7_processor_get_desc;
+    proc->get_memsize = (get_processor_memsize_fc)g_armv7_processor_get_memory_size;
+    proc->get_inssize = (get_processor_inssize_fc)g_armv7_processor_get_instruction_min_size;
 
+    proc->get_ctx = (get_processor_context_fc)g_armv7_processor_get_context;
     proc->disassemble = (disass_instr_fc)g_armv7_processor_disassemble;
 
 }
@@ -131,6 +136,7 @@ static void g_armv7_processor_class_init(GArmV7ProcessorClass *klass)
 
 static void g_armv7_processor_init(GArmV7Processor *proc)
 {
+    G_ARCH_PROCESSOR(proc)->endianness = SRE_LITTLE;
 
 }
 
@@ -221,6 +227,75 @@ static char *g_armv7_processor_get_key(const GArmV7Processor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit le nom humain de l'architecture visée.               *
+*                                                                             *
+*  Retour      : Désignation humaine associée au processeur.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_armv7_processor_get_desc(const GArmV7Processor *proc)
+{
+    char *result;                           /* Désignation à renvoyer      */
+
+    result = strdup("ARM v7");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille de l'espace mémoire d'une architecture.    *
+*                                                                             *
+*  Retour      : Taille de l'espace mémoire.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize g_armv7_processor_get_memory_size(const GArmV7Processor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+
+    result = MDS_32_BITS;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille min. des instructions d'une architecture.  *
+*                                                                             *
+*  Retour      : Taille d'encodage des instructions.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize g_armv7_processor_get_instruction_min_size(const GArmV7Processor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+
+    result = MDS_32_BITS;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc = architecture, spectatrice ici.                        *
 *                                                                             *
 *  Description : Fournit un contexte pour l'exécution du processeur Arm.      *
@@ -262,7 +337,7 @@ static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *pr
     uint32_t raw32;                         /* Donnée 32 bits à analyser   */
     ArmV7InstrSet iset;                     /* Type de jeu d'instructions  */
 
-    endian = G_ARCH_PROCESSOR_GET_CLASS(proc)->endianness;
+    endian = G_ARCH_PROCESSOR(proc)->endianness;
 
     iset = g_armv7_context_find_encoding(ctx, get_virt_addr(pos));
 
diff --git a/plugins/dalvik/processor.c b/plugins/dalvik/processor.c
index 38f245c..a1a211e 100644
--- a/plugins/dalvik/processor.c
+++ b/plugins/dalvik/processor.c
@@ -50,6 +50,15 @@ static void g_dalvik_processor_dispose(GDalvikProcessor *);
 /* Procède à la libération totale de la mémoire. */
 static void g_dalvik_processor_finalize(GDalvikProcessor *);
 
+/* Fournit la taille de l'espace mémoire d'une architecture. */
+static MemoryDataSize g_dalvik_processor_get_memory_size(const GDalvikProcessor *);
+
+/* Fournit la taille min. des instructions d'une architecture. */
+static MemoryDataSize g_dalvik_processor_get_instruction_min_size(const GDalvikProcessor *);
+
+/* Indique si l'architecture possède un espace virtuel ou non. */
+static bool g_dalvik_processor_has_virtual_space(const GDalvikProcessor *);
+
 /* Fournit un contexte pour l'exécution du processeur Dalvik. */
 static GDalvikContext *g_dalvik_processor_get_context(const GDalvikProcessor *);
 
@@ -83,10 +92,9 @@ static void g_dalvik_processor_class_init(GDalvikProcessorClass *klass)
 
     proc = G_ARCH_PROCESSOR_CLASS(klass);
 
-    proc->endianness = SRE_LITTLE;
-    proc->memsize = MDS_32_BITS;
-    proc->inssize = MDS_16_BITS;
-    proc->virt_space = false;
+    proc->get_memsize = (get_processor_memsize_fc)g_dalvik_processor_get_memory_size;
+    proc->get_inssize = (get_processor_inssize_fc)g_dalvik_processor_get_instruction_min_size;
+    proc->has_vspace = (has_processor_vspace_fc)g_dalvik_processor_has_virtual_space;
 
     proc->get_ctx = (get_processor_context_fc)g_dalvik_processor_get_context;
 
@@ -107,6 +115,7 @@ static void g_dalvik_processor_class_init(GDalvikProcessorClass *klass)
 
 static void g_dalvik_processor_init(GDalvikProcessor *proc)
 {
+    G_ARCH_PROCESSOR(proc)->endianness = SRE_LITTLE;
 
 }
 
@@ -151,6 +160,75 @@ static void g_dalvik_processor_finalize(GDalvikProcessor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille de l'espace mémoire d'une architecture.    *
+*                                                                             *
+*  Retour      : Taille de l'espace mémoire.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize g_dalvik_processor_get_memory_size(const GDalvikProcessor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+
+    result = MDS_32_BITS;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille min. des instructions d'une architecture.  *
+*                                                                             *
+*  Retour      : Taille d'encodage des instructions.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize g_dalvik_processor_get_instruction_min_size(const GDalvikProcessor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+
+    result = MDS_16_BITS;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Indique si l'architecture possède un espace virtuel ou non.  *
+*                                                                             *
+*  Retour      : true si un espace virtuel existe, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_dalvik_processor_has_virtual_space(const GDalvikProcessor *proc)
+{
+    bool result;                            /* Indication à retourner      */
+
+    result = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc = architecture, spectatrice ici.                        *
 *                                                                             *
 *  Description : Fournit un contexte pour l'exécution du processeur Dalvik.   *
diff --git a/plugins/dalvik/v35/processor.c b/plugins/dalvik/v35/processor.c
index 0865ee7..7e79e46 100644
--- a/plugins/dalvik/v35/processor.c
+++ b/plugins/dalvik/v35/processor.c
@@ -67,6 +67,9 @@ static void g_dalvik35_processor_finalize(GDalvik35Processor *);
 /* Fournit la désignation interne du processeur d'architecture. */
 static char *g_dalvik35_processor_get_key(const GDalvik35Processor *);
 
+/* Fournit le nom humain de l'architecture visée. */
+static char *g_dalvik35_processor_get_desc(const GDalvik35Processor *);
+
 /* Décode une instruction dans un flux de données. */
 static GArchInstruction *g_dalvik35_processor_disassemble(const GArchProcessor *, GDalvikContext *, const GBinContent *, vmpa2t *, GExeFormat *);
 
@@ -100,9 +103,8 @@ static void g_dalvik35_processor_class_init(GDalvik35ProcessorClass *klass)
 
     proc = G_ARCH_PROCESSOR_CLASS(klass);
 
-    proc->desc = "Dalvik Virtual Machine v35";
-
     proc->get_key = (get_processor_key_fc)g_dalvik35_processor_get_key;
+    proc->get_desc = (get_processor_desc_fc)g_dalvik35_processor_get_desc;
 
     proc->disassemble = (disass_instr_fc)g_dalvik35_processor_disassemble;
 
@@ -213,6 +215,29 @@ static char *g_dalvik35_processor_get_key(const GDalvik35Processor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit le nom humain de l'architecture visée.               *
+*                                                                             *
+*  Retour      : Désignation humaine associée au processeur.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_dalvik35_processor_get_desc(const GDalvik35Processor *proc)
+{
+    char *result;                           /* Désignation à renvoyer      */
+
+    result = strdup("Dalvik Virtual Machine v35");
+
+    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/plugins/pychrysalide/analysis/constants.c b/plugins/pychrysalide/analysis/constants.c
index d014fb7..87f91a3 100644
--- a/plugins/pychrysalide/analysis/constants.c
+++ b/plugins/pychrysalide/analysis/constants.c
@@ -78,6 +78,11 @@ bool define_analysis_content_constants(PyTypeObject *type)
     if (result) result = add_const_to_group(values, "_16_BITS_SIGNED", MDS_16_BITS_SIGNED);
     if (result) result = add_const_to_group(values, "_32_BITS_SIGNED", MDS_32_BITS_SIGNED);
     if (result) result = add_const_to_group(values, "_64_BITS_SIGNED", MDS_64_BITS_SIGNED);
+    if (result) result = add_const_to_group(values, "_4_BITS", MDS_4_BITS_UNSIGNED);
+    if (result) result = add_const_to_group(values, "_8_BITS", MDS_8_BITS_UNSIGNED);
+    if (result) result = add_const_to_group(values, "_16_BITS", MDS_16_BITS_UNSIGNED);
+    if (result) result = add_const_to_group(values, "_32_BITS", MDS_32_BITS_UNSIGNED);
+    if (result) result = add_const_to_group(values, "_64_BITS", MDS_64_BITS_UNSIGNED);
 
     if (!result)
     {
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index f04929e..1cfb989 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -45,6 +45,31 @@
 
 
 
+#define ARCH_PROCESSOR_DOC                                              \
+    "The ArchProcessor object aims to get subclassed to create"         \
+    " processors for new architectures.\n"                              \
+    "\n"                                                                \
+    "Several items have to be defined as class attributes in the final" \
+    " class:\n"                                                         \
+    "* *_key*: a string providing a small name used to identify the"    \
+    " architecture;\n"                                                  \
+    "* *_desc*: a string for a human readable description of the"       \
+    " new architecture;\n"                                              \
+    "* *_memory_size*: size of the memory space, as a"                  \
+    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
+    "* *_ins_min_size*: size of the smallest instruction, as a"         \
+    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
+    "* *_virtual_space*: a boolean value indicating if the architecture"\
+    " supports a virtual space.\n"                                      \
+    "\n"                                                                \
+    "Calls to the *__init__* constructor of this abstract object expect"\
+    " the following arguments as keyword parameters:\n"                 \
+    "* *endianness*: endianness to apply to the binary content to"      \
+    " disassemble, as a pychrysalide.analysis.BinContent.SourceEndian"  \
+    " value.\n"
+
+
+
 /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
 
 
@@ -63,6 +88,18 @@ static int py_arch_processor_init(PyObject *, PyObject *, PyObject *);
 /* Fournit la désignation interne du processeur d'architecture. */
 static char *py_arch_processor_get_key_wrapper(const GArchProcessor *);
 
+/* Fournit le nom humain de l'architecture visée. */
+static char *py_arch_processor_get_desc_wrapper(const GArchProcessor *);
+
+/* Fournit la taille de l'espace mémoire d'une architecture. */
+static MemoryDataSize py_arch_processor_get_memory_size_wrapper(const GArchProcessor *);
+
+/* Fournit la taille min. des instructions d'une architecture. */
+static MemoryDataSize py_arch_processor_get_instruction_min_size_wrapper(const GArchProcessor *);
+
+/* Indique si l'architecture possède un espace virtuel ou non. */
+static bool py_arch_processor_has_virtual_space_wrapper(const GArchProcessor *);
+
 /* Fournit un contexte propre au processeur d'une architecture. */
 static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *);
 
@@ -74,6 +111,12 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces
 /* ---------------------------- DEFINITION DE PROCESSEUR ---------------------------- */
 
 
+/* Fournit la désignation interne du processeur d'architecture. */
+static PyObject *py_arch_processor_get_key(PyObject *, void *);
+
+/* Fournit le nom humain de l'architecture visée. */
+static PyObject *py_arch_processor_get_desc(PyObject *, void *);
+
 /* Fournit le boustime du processeur d'une architecture. */
 static PyObject *py_arch_processor_get_endianness(PyObject *, void *);
 
@@ -81,7 +124,7 @@ static PyObject *py_arch_processor_get_endianness(PyObject *, void *);
 static PyObject *py_arch_processor_get_memory_size(PyObject *, void *);
 
 /* Fournit la taille min. des instructions d'une architecture. */
-static PyObject *py_arch_processor_get_instruction_min_size(PyObject *, void *);
+static PyObject *py_arch_processor_get_ins_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 *);
@@ -229,8 +272,12 @@ static void py_arch_processor_init_gclass(GArchProcessorClass *class, gpointer u
     }
 
     class->get_key = py_arch_processor_get_key_wrapper;
-    class->get_ctx = py_arch_processor_get_context_wrapper;
+    class->get_desc = py_arch_processor_get_desc_wrapper;
+    class->get_memsize = py_arch_processor_get_memory_size_wrapper;
+    class->get_inssize = py_arch_processor_get_instruction_min_size_wrapper;
+    class->has_vspace = py_arch_processor_has_virtual_space_wrapper;
 
+    class->get_ctx = py_arch_processor_get_context_wrapper;
     class->disassemble = py_arch_processor_disassemble_wrapper;
 
 }
@@ -271,20 +318,16 @@ static void py_arch_processor_init_ginstance(GArchProcessor *proc, GArchProcesso
 
 static int py_arch_processor_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    unsigned long endianness;               /* Boutisme du processeur      */
-    unsigned long mem_size;                 /* Taille d'adressage          */
-    unsigned long ins_min_size;             /* Taille minimale d'instruct° */
-    int vspace;                             /* Support d'un espace virtuel */
+    unsigned int endianness;                /* Boutisme du processeur      */
     int ret;                                /* Bilan de lecture des args.  */
     PyObject *new_kwds;                     /* Nouveau dictionnaire épuré  */
     GArchProcessor *proc;                   /* Processeur à manipuler      */
 
-    static char *kwlist[] = { "endianness", "mem_size", "ins_min_size", "vspace", NULL };
+    static char *kwlist[] = { "endianness", NULL };
 
     /* Récupération des paramètres */
 
-    ret = PyArg_ParseTupleAndKeywords(args, kwds, "kkkp", kwlist,
-                                      &endianness, &mem_size, &ins_min_size, &vspace);
+    ret = PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &endianness);
     if (!ret) return -1;
 
     /* Initialisation d'un objet GLib */
@@ -301,14 +344,9 @@ static int py_arch_processor_init(PyObject *self, PyObject *args, PyObject *kwds
 
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
 
-    /*
     proc->endianness = endianness;
-    proc->memsize = mem_size;
-    proc->inssize = ins_min_size;
-    proc->virt_space = vspace;
-    */
 
-    register_dynamic_type_pattern(G_OBJECT(proc));
+    //register_dynamic_type_pattern(G_OBJECT(proc));
 
     return 0;
 
@@ -334,8 +372,6 @@ static char *py_arch_processor_get_key_wrapper(const GArchProcessor *proc)
     PyObject *pyobj;                        /* Objet Python concerné       */
     PyObject *pykey;                        /* Clef en objet Python        */
     int ret;                                /* Bilan d'une conversion      */
-    GArchProcessorClass *class;             /* Classe de l'objet courant   */
-    GArchProcessorClass *parent;            /* Classe parente              */
 
     result = NULL;
 
@@ -343,9 +379,9 @@ static char *py_arch_processor_get_key_wrapper(const GArchProcessor *proc)
 
     pyobj = pygobject_new(G_OBJECT(proc));
 
-    if (has_python_method(pyobj, "_get_key"))
+    if (PyObject_HasAttrString(pyobj, "_key"))
     {
-        pykey = run_python_method(pyobj, "_get_key", NULL);
+        pykey = PyObject_GetAttrString(pyobj, "_key");
 
         if (pykey != NULL)
         {
@@ -360,13 +396,203 @@ static char *py_arch_processor_get_key_wrapper(const GArchProcessor *proc)
 
     }
 
-    else
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit le nom humain de l'architecture visée.               *
+*                                                                             *
+*  Retour      : Désignation humaine associée au processeur.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *py_arch_processor_get_desc_wrapper(const GArchProcessor *proc)
+{
+    char *result;                           /* Désignation à renvoyer      */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pydesc;                       /* Description en objet Python */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = NULL;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(proc));
+
+    if (PyObject_HasAttrString(pyobj, "_desc"))
     {
-        class = G_ARCH_PROCESSOR_GET_CLASS(proc);
-        parent = g_type_class_peek_parent(class);
+        pydesc = PyObject_GetAttrString(pyobj, "_desc");
+
+        if (pydesc != NULL)
+        {
+            ret = PyUnicode_Check(pydesc);
+
+            if (ret)
+                result = strdup(PyUnicode_AsUTF8(pydesc));
+
+            Py_DECREF(pydesc);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille de l'espace mémoire d'une architecture.    *
+*                                                                             *
+*  Retour      : Taille de l'espace mémoire.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize py_arch_processor_get_memory_size_wrapper(const GArchProcessor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pysize;                       /* Taille en objet Python      */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(proc));
+
+    if (PyObject_HasAttrString(pyobj, "_memory_size"))
+    {
+        pysize = PyObject_GetAttrString(pyobj, "_memory_size");
+
+        if (pysize != NULL)
+        {
+            ret = PyLong_Check(pysize);
+
+            if (ret)
+                result = PyLong_AsUnsignedLong(pysize);
+
+            Py_DECREF(pysize);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Fournit la taille min. des instructions d'une architecture.  *
+*                                                                             *
+*  Retour      : Taille d'encodage des instructions.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MemoryDataSize py_arch_processor_get_instruction_min_size_wrapper(const GArchProcessor *proc)
+{
+    MemoryDataSize result;                  /* Taille  à retourner         */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pysize;                       /* Taille en objet Python      */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(proc));
 
-        if (parent->get_key != NULL)
-            result = parent->get_key(proc);
+    if (PyObject_HasAttrString(pyobj, "_ins_min_size"))
+    {
+        pysize = PyObject_GetAttrString(pyobj, "_ins_min_size");
+
+        if (pysize != NULL)
+        {
+            ret = PyLong_Check(pysize);
+
+            if (ret)
+                result = PyLong_AsUnsignedLong(pysize);
+
+            Py_DECREF(pysize);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = processeur d'architecture à consulter.                *
+*                                                                             *
+*  Description : Indique si l'architecture possède un espace virtuel ou non.  *
+*                                                                             *
+*  Retour      : true si un espace virtuel existe, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_arch_processor_has_virtual_space_wrapper(const GArchProcessor *proc)
+{
+    bool result;                            /* Indication à retourner      */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pyhas;                        /* Présence en objet Python    */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(proc));
+
+    if (PyObject_HasAttrString(pyobj, "_virtual_space"))
+    {
+        pyhas = PyObject_GetAttrString(pyobj, "_virtual_space");
+
+        if (pyhas != NULL)
+        {
+            ret = PyBool_Check(pyhas);
+
+            if (ret)
+                result = (pyhas == Py_True);
+
+            Py_DECREF(pyhas);
+
+        }
 
     }
 
@@ -535,6 +761,100 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
+*  Description : Fournit la désignation interne du processeur d'architecture. *
+*                                                                             *
+*  Retour      : Simple chaîne de caractères.                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_processor_get_key(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GArchProcessor *proc;                   /* Version GLib de l'opérande  */
+    char *key;                              /* Désignation du processeur   */
+
+#define ARCH_PROCESSOR_KEY_ATTRIB PYTHON_GET_DEF_FULL           \
+(                                                               \
+    key, py_arch_processor,                                     \
+    "Provide the small name used to identify the architecture," \
+    " as a code string."                                        \
+)
+
+    proc = G_ARCH_PROCESSOR(pygobject_get(self));
+    assert(proc != NULL);
+
+    key = g_arch_processor_get_key(proc);
+
+    if (key != NULL)
+    {
+        result = PyUnicode_FromString(key);
+        free(key);
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le nom humain de l'architecture visée.               *
+*                                                                             *
+*  Retour      : Désignation humaine associée au processeur.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_processor_get_desc(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GArchProcessor *proc;                   /* Version GLib de l'opérande  */
+    char *desc;                              /* Désignation du processeur   */
+
+#define ARCH_PROCESSOR_DESC_ATTRIB PYTHON_GET_DEF_FULL      \
+(                                                           \
+    desc, py_arch_processor,                                \
+    "Provide a a human readable description of the new"     \
+    " architecture, as a simple string."                    \
+)
+
+    proc = G_ARCH_PROCESSOR(pygobject_get(self));
+    assert(proc != NULL);
+
+    desc = g_arch_processor_get_desc(proc);
+
+    if (desc != NULL)
+    {
+        result = PyUnicode_FromString(desc);
+        free(desc);
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
 *  Description : Fournit le boustime du processeur d'une architecture.        *
 *                                                                             *
 *  Retour      : Boutisme associé au processeur.                              *
@@ -549,12 +869,19 @@ static PyObject *py_arch_processor_get_endianness(PyObject *self, void *closure)
     GArchProcessor *proc;                   /* Version GLib de l'opérande  */
     SourceEndian endianness;                /* Boutisme du processeur      */
 
+#define ARCH_PROCESSOR_ENDIANNESS_ATTRIB PYTHON_GET_DEF_FULL    \
+(                                                               \
+    endianness, py_arch_processor,                              \
+    "Provide the processor endianness, as a"                    \
+    " pychrysalide.analysis.BinContent.SourceEndian value."     \
+)
+
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
     assert(proc != NULL);
 
     endianness = g_arch_processor_get_endianness(proc);
 
-    result = Py_BuildValue("I", endianness);
+    result = cast_with_constants_group_from_type(get_python_binary_content_type(), "SourceEndian", endianness);
 
     return result;
 
@@ -580,12 +907,19 @@ static PyObject *py_arch_processor_get_memory_size(PyObject *self, void *closure
     GArchProcessor *proc;                   /* Version GLib de l'opérande  */
     MemoryDataSize size;                    /* Type de donnée représentée  */
 
+#define ARCH_PROCESSOR_MEMORY_SIZE_ATTRIB PYTHON_GET_DEF_FULL       \
+(                                                                   \
+    memory_size, py_arch_processor,                                 \
+    "Provide the size of the architecture memory address space,"    \
+    " as a pychrysalide.analysis.BinContent.MemoryDataSize value."  \
+)
+
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
     assert(proc != NULL);
 
     size = g_arch_processor_get_memory_size(proc);
 
-    result = Py_BuildValue("I", size);
+    result = cast_with_constants_group_from_type(get_python_binary_content_type(), "MemoryDataSize", size);
 
     return result;
 
@@ -605,18 +939,25 @@ static PyObject *py_arch_processor_get_memory_size(PyObject *self, void *closure
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_arch_processor_get_instruction_min_size(PyObject *self, void *closure)
+static PyObject *py_arch_processor_get_ins_min_size(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Instance Python à retourner */
     GArchProcessor *proc;                   /* Version GLib de l'opérande  */
     MemoryDataSize size;                    /* Type de donnée représentée  */
 
+#define ARCH_PROCESSOR_INS_MIN_SIZE_ATTRIB PYTHON_GET_DEF_FULL      \
+(                                                                   \
+    ins_min_size, py_arch_processor,                                \
+    "Provide the minimal size of one processor instruction, as a"   \
+    " pychrysalide.analysis.BinContent.MemoryDataSize value."       \
+)
+
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
     assert(proc != NULL);
 
     size = g_arch_processor_get_instruction_min_size(proc);
 
-    result = Py_BuildValue("I", size);
+    result = cast_with_constants_group_from_type(get_python_binary_content_type(), "MemoryDataSize", size);
 
     return result;
 
@@ -642,6 +983,13 @@ static PyObject *py_arch_processor_has_virtual_space(PyObject *self, void *closu
     GArchProcessor *proc;                   /* Architecture visée          */
     bool status;                            /* Bilan de consultation       */
 
+#define ARCH_PROCESSOR_VIRTUAL_SPACE_ATTRIB PYTHON_HAS_DEF_FULL     \
+(                                                                   \
+    virtual_space, py_arch_processor,                               \
+    "Tell if the processor provides a virtual address space. This"  \
+    " status is a boolean value."                                   \
+)
+
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
 
     status = g_arch_processor_has_virtual_space(proc);
@@ -1066,22 +1414,12 @@ PyTypeObject *get_python_arch_processor_type(void)
     };
 
     static PyGetSetDef py_arch_processor_getseters[] = {
-        {
-            "endianness", py_arch_processor_get_endianness, NULL,
-            "Provide the processor endianness.", NULL
-        },
-        {
-            "mem_size", py_arch_processor_get_memory_size, NULL,
-            "Provide the size of memory addresses for the given architecture.", NULL
-        },
-        {
-            "ins_min_size", py_arch_processor_get_instruction_min_size, NULL,
-            "Provide the minimal size of one processor instruction.", NULL
-        },
-        {
-            "virtual_space", py_arch_processor_has_virtual_space, NULL,
-            "Tell if the processor provides a virtual address space.", NULL
-        },
+        ARCH_PROCESSOR_KEY_ATTRIB,
+        ARCH_PROCESSOR_DESC_ATTRIB,
+        ARCH_PROCESSOR_ENDIANNESS_ATTRIB,
+        ARCH_PROCESSOR_MEMORY_SIZE_ATTRIB,
+        ARCH_PROCESSOR_INS_MIN_SIZE_ATTRIB,
+        ARCH_PROCESSOR_VIRTUAL_SPACE_ATTRIB,
         {
             "errors", py_arch_processor_get_errors, NULL,
             "List of all detected errors which occurred during the disassembling process.", NULL
@@ -1102,7 +1440,7 @@ PyTypeObject *get_python_arch_processor_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
 
-        .tp_doc         = "PyChrysalide processor for a given architecture.",
+        .tp_doc         = ARCH_PROCESSOR_DOC,
 
         .tp_methods     = py_arch_processor_methods,
         .tp_getset      = py_arch_processor_getseters,
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index 924ba02..fe13f84 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -97,9 +97,12 @@ bool register_python_module_object(PyObject *, PyTypeObject *);
         closure                                         \
     }
 
-#define PYTHON_IS_DEF_FULL(name, base, doc)            \
+#define PYTHON_IS_DEF_FULL(name, base, doc)             \
     PYTHON_GETSET_DEF("is_" #name, base ## _is_ ## name, NULL, doc, NULL)
 
+#define PYTHON_HAS_DEF_FULL(name, base, doc)            \
+    PYTHON_GETSET_DEF(#name, base ## _has_ ## name, NULL, doc, NULL)
+
 #define PYTHON_GET_DEF_FULL(name, base, doc)            \
     PYTHON_GETSET_DEF(#name, base ## _get_ ## name, NULL, doc, NULL)
 
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index e875679..0f7b096 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -1647,7 +1647,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, bool connect, bool ca
     bool result;                            /* Bilan à retourner           */
     GBinFormat *format;                     /* Format lié au binaire       */
     const char *arch;                       /* Architecture d'exécution    */
-    const char *desc;                       /* Description humaine associée*/
+    char *desc;                             /* Description humaine associée*/
     bool has_virt;                          /* Présence de virtuel ?       */
     GProcContext *context;                  /* Contexte de suivi dédié     */
     GWidthTracker *tracker;                 /* Gestionnaire de largeur     */
@@ -1690,6 +1690,8 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, bool connect, bool ca
 
     log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
 
+    free(desc);
+
     g_signal_connect(binary->proc, "changed", G_CALLBACK(on_binary_processor_changed), binary);
 
     has_virt = g_arch_processor_has_virtual_space(binary->proc);
diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h
index 34ba66a..6187ff0 100644
--- a/src/arch/processor-int.h
+++ b/src/arch/processor-int.h
@@ -36,6 +36,18 @@
 /* Fournit la désignation interne du processeur d'architecture. */
 typedef char * (* get_processor_key_fc) (const GArchProcessor *);
 
+/* Fournit le nom humain de l'architecture visée. */
+typedef char * (* get_processor_desc_fc) (const GArchProcessor *);
+
+/* Fournit la taille de l'espace mémoire d'une architecture. */
+typedef MemoryDataSize (* get_processor_memsize_fc) (const GArchProcessor *);
+
+/* Fournit la taille min. des instructions d'une architecture. */
+typedef MemoryDataSize (* get_processor_inssize_fc) (const GArchProcessor *);
+
+/* Indique si l'architecture possède un espace virtuel ou non. */
+typedef bool (* has_processor_vspace_fc) (const GArchProcessor *);
+
 /* Fournit un contexte propre au processeur d'une architecture. */
 typedef GProcContext * (* get_processor_context_fc) (const GArchProcessor *);
 
@@ -69,6 +81,8 @@ struct _GArchProcessor
 {
     GObject parent;                         /* A laisser en premier        */
 
+    SourceEndian endianness;                /* Boutisme de l'architecture  */
+
     GArchInstruction **instructions;        /* Instructions désassemblées  */
     size_t instr_count;                     /* Taille de la liste aplatie  */
     unsigned int stamp;                     /* Marque de suivi des modifs  */
@@ -95,16 +109,13 @@ struct _GArchProcessorClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    const char *desc;                       /* Description humaine liée    */
-
-    SourceEndian endianness;                /* Boutisme de l'architecture  */
-    MemoryDataSize memsize;                 /* Taille de l'espace mémoire  */
-    MemoryDataSize inssize;                 /* Taille min. d'encodage      */
-    bool virt_space;                        /* Présence d'espace virtuel ? */
-
     get_processor_key_fc get_key;           /* Code représentant la classe */
-    get_processor_context_fc get_ctx;       /* Obtention d'un contexte     */
+    get_processor_desc_fc get_desc;         /* Description humaine         */
+    get_processor_memsize_fc get_memsize;   /* Taille d'un mot classique   */
+    get_processor_inssize_fc get_inssize;   /* Taille minimale d'instruct° */
+    has_processor_vspace_fc has_vspace;     /* Présence d'un espace virtuel*/
 
+    get_processor_context_fc get_ctx;       /* Obtention d'un contexte     */
     disass_instr_fc disassemble;            /* Traduction en instructions  */
 
     /* Signaux */
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 7dbd8eb..59af6cd 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -290,7 +290,10 @@ char *g_arch_processor_get_key(const GArchProcessor *proc)
     class = G_ARCH_PROCESSOR_GET_CLASS(proc);
 
     if (class->get_key == NULL)
+    {
+        assert(false);
         result = NULL;
+    }
 
     else
         result = class->get_key(proc);
@@ -312,14 +315,21 @@ char *g_arch_processor_get_key(const GArchProcessor *proc)
 *                                                                             *
 ******************************************************************************/
 
-const char *g_arch_processor_get_desc(const GArchProcessor *proc)
+char *g_arch_processor_get_desc(const GArchProcessor *proc)
 {
-    const char *result;                     /* Désignation à renvoyer      */
+    char *result;                           /* Désignation à renvoyer      */
     GArchProcessorClass *class;             /* Classe de l'instance        */
 
     class = G_ARCH_PROCESSOR_GET_CLASS(proc);
 
-    result = class->desc;
+    if (class->get_desc == NULL)
+    {
+        assert(false);
+        result = NULL;
+    }
+
+    else
+        result = class->get_desc(proc);
 
     return result;
 
@@ -341,11 +351,8 @@ const char *g_arch_processor_get_desc(const GArchProcessor *proc)
 SourceEndian g_arch_processor_get_endianness(const GArchProcessor *proc)
 {
     SourceEndian result;                    /* Boutisme à retourner        */
-    GArchProcessorClass *class;             /* Classe de l'instance        */
 
-    class = G_ARCH_PROCESSOR_GET_CLASS(proc);
-
-    result = class->endianness;
+    result = proc->endianness;
 
     return result;
 
@@ -371,7 +378,14 @@ MemoryDataSize g_arch_processor_get_memory_size(const GArchProcessor *proc)
 
     class = G_ARCH_PROCESSOR_GET_CLASS(proc);
 
-    result = class->memsize;
+    if (class->get_memsize == NULL)
+    {
+        assert(false);
+        result = MDS_UNDEFINED;
+    }
+
+    else
+        result = class->get_memsize(proc);
 
     return result;
 
@@ -397,7 +411,14 @@ MemoryDataSize g_arch_processor_get_instruction_min_size(const GArchProcessor *p
 
     class = G_ARCH_PROCESSOR_GET_CLASS(proc);
 
-    result = class->inssize;
+    if (class->get_inssize == NULL)
+    {
+        assert(false);
+        result = MDS_UNDEFINED;
+    }
+
+    else
+        result = class->get_inssize(proc);
 
     return result;
 
@@ -423,7 +444,14 @@ bool g_arch_processor_has_virtual_space(const GArchProcessor *proc)
 
     class = G_ARCH_PROCESSOR_GET_CLASS(proc);
 
-    result = class->virt_space;
+    if (class->has_vspace == NULL)
+    {
+        assert(false);
+        result = false;
+    }
+
+    else
+        result = class->has_vspace(proc);
 
     return result;
 
diff --git a/src/arch/processor.h b/src/arch/processor.h
index 7edf341..b88fa6f 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -59,7 +59,7 @@ GType g_arch_processor_get_type(void);
 char *g_arch_processor_get_key(const GArchProcessor *);
 
 /* Fournit le nom humain de l'architecture visée. */
-const char *g_arch_processor_get_desc(const GArchProcessor *);
+char *g_arch_processor_get_desc(const GArchProcessor *);
 
 /* Fournit le boustime du processeur d'une architecture. */
 SourceEndian g_arch_processor_get_endianness(const GArchProcessor *);
diff --git a/src/core/processors.c b/src/core/processors.c
index 7234365..48e2cd2 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -108,9 +108,6 @@ bool register_processor_type(GType type)
     key = g_arch_processor_get_key(proc);
     if (key == NULL) goto done;
 
-    result = (key != NULL);
-
-
     G_LOCK(_pdef_access);
 
     new = find_processor_by_key(key);
-- 
cgit v0.11.2-87-g4458