From e10081897750e74dfd01266606870aab3638cfbf Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 21 Jan 2019 19:49:45 +0100
Subject: Provided a way to register new available processors from Python.

---
 plugins/pychrysalide/core/Makefile.am    |   1 +
 plugins/pychrysalide/core/logs.c         |   2 +-
 plugins/pychrysalide/core/module.c       |   2 +
 plugins/pychrysalide/core/processors.c   | 248 +++++++++++++++++++++++++++++++
 plugins/pychrysalide/core/processors.h   |  39 +++++
 plugins/pychrysalide/format/executable.c |   2 +-
 plugins/ropgadgets/finder.c              |   2 +-
 src/analysis/binary.c                    |   4 +-
 src/core/core.c                          |   2 -
 src/core/processors.c                    |  68 +++------
 src/core/processors.h                    |   9 +-
 11 files changed, 319 insertions(+), 60 deletions(-)
 create mode 100644 plugins/pychrysalide/core/processors.c
 create mode 100644 plugins/pychrysalide/core/processors.h

diff --git a/plugins/pychrysalide/core/Makefile.am b/plugins/pychrysalide/core/Makefile.am
index 4018012..131e1b9 100644
--- a/plugins/pychrysalide/core/Makefile.am
+++ b/plugins/pychrysalide/core/Makefile.am
@@ -7,6 +7,7 @@ libpychrysacore_la_SOURCES =			\
 	logs.h logs.c						\
 	module.h module.c					\
 	params.h params.c					\
+	processors.h processors.c			\
 	queue.h queue.c
 
 libpychrysacore_la_LDFLAGS = 
diff --git a/plugins/pychrysalide/core/logs.c b/plugins/pychrysalide/core/logs.c
index be1f57a..afab7ab 100644
--- a/plugins/pychrysalide/core/logs.c
+++ b/plugins/pychrysalide/core/logs.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * logs.c - équivalent Python du fichier "gui/panels/logs.c"
+ * logs.c - équivalent Python du fichier "core/logs.c"
  *
  * Copyright (C) 2017 Cyrille Bagard
  *
diff --git a/plugins/pychrysalide/core/module.c b/plugins/pychrysalide/core/module.c
index 3d117a5..d954821 100644
--- a/plugins/pychrysalide/core/module.c
+++ b/plugins/pychrysalide/core/module.c
@@ -32,6 +32,7 @@
 #include "global.h"
 #include "logs.h"
 #include "params.h"
+#include "processors.h"
 #include "queue.h"
 #include "../helpers.h"
 
@@ -96,6 +97,7 @@ bool populate_core_module(void)
     if (result) result = populate_core_module_with_global();
     if (result) result = populate_core_module_with_logs();
     if (result) result = populate_core_module_with_params();
+    if (result) result = populate_core_module_with_processors();
     if (result) result = populate_core_module_with_queue();
 
     assert(result);
diff --git a/plugins/pychrysalide/core/processors.c b/plugins/pychrysalide/core/processors.c
new file mode 100644
index 0000000..341c816
--- /dev/null
+++ b/plugins/pychrysalide/core/processors.c
@@ -0,0 +1,248 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * processors.c - équivalent Python du fichier "core/processors.c"
+ *
+ * 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 "processors.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <arch/processor.h>
+#include <core/processors.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+#include "../pychrysa.h"
+#include "../arch/processor.h"
+
+
+
+/* Enregistre un processeur pour une architecture donnée. */
+static PyObject *py_processors_register_type(PyObject *, PyObject *);
+
+/* Fournit le nom humain de l'architecture visée. */
+static PyObject *py_processors_get_description(PyObject *, PyObject *);
+
+/* Fournit le processeur d'architecture correspondant à un nom. */
+static PyObject *py_processors_get_for_name(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Enregistre un processeur pour une architecture donnée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_processors_register_type(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    const char *name;                       /* Nom technique de processeur */
+    const char *desc;                       /* description humaine liée    */
+    PyObject *type;                         /* Type d'une instance future  */
+    int ret;                                /* Bilan de lecture des args.  */
+    PyObject *new_args;                     /* Nouveaux arguments épurés   */
+    PyObject *new_kwds;                     /* Nouveau dictionnaire épuré  */
+    PyObject *dummy;                        /* Coquille vide pour analyse  */
+    GType instance;                         /* Type pour futures instances */
+    bool status;                            /* Bilan d'un enregistrement   */
+
+    ret = PyArg_ParseTuple(args, "ssO!", &name, &desc, &PyType_Type, &type);
+    if (!ret) return NULL;
+
+    ret = PyObject_IsSubclass(type, (PyObject *)get_python_arch_processor_type());;
+    if (ret == -1) return NULL;
+
+    if (ret != 1)
+    {
+        PyErr_SetString(PyExc_TypeError, _("The new processor should be a subclass of the ArchProcessor type."));
+        return NULL;
+    }
+
+    /**
+     * Comme le type GLib n'est initié et enregistré qu'à la création d'une première instance,
+     * on force sa mise en place ici, afin de ne pas contraidre l'utilisateur à le faire
+     * lui même via un appel du style :
+     *
+     *    register_processor('aaa', 'BBB CCC', type(AaaProcessor()))
+     */
+
+    new_args = PyTuple_New(0);
+    new_kwds = PyDict_New();
+
+    dummy = PyObject_Call(type, new_args, new_kwds);
+
+    Py_DECREF(new_kwds);
+    Py_DECREF(new_args);
+
+    if (dummy == NULL) return NULL;
+
+    instance = pyg_type_from_object_strict((PyObject *)Py_TYPE(dummy), TRUE);
+    assert(instance != 0 && instance != G_TYPE_ARCH_PROCESSOR);
+
+    Py_DECREF(dummy);
+
+    status = register_processor_type(name, desc, instance);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Fournit le nom humain de l'architecture visée.               *
+*                                                                             *
+*  Retour      : Désignation humaine trouvée ou NULL.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_processors_get_description(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    const char *name;                       /* Nom technique de processeur */
+    int ret;                                /* Bilan de lecture des args.  */
+    const char *desc;                       /* Description humaine obtenue */
+
+    ret = PyArg_ParseTuple(args, "s", &name);
+    if (!ret) return NULL;
+
+    desc = get_arch_processor_description(name);
+
+    if (desc != NULL)
+        result = PyUnicode_FromString(desc);
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Fournit le processeur d'architecture correspondant à un nom. *
+*                                                                             *
+*  Retour      : Processeur d'architecture trouvé.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_processors_get_for_name(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    const char *name;                       /* Nom technique de processeur */
+    int ret;                                /* Bilan de lecture des args.  */
+    GArchProcessor *proc;                   /* Instance mise en place      */
+
+    ret = PyArg_ParseTuple(args, "s", &name);
+    if (!ret) return NULL;
+
+    proc = get_arch_processor_for_name(name);
+
+    if (proc != NULL)
+    {
+        result = pygobject_new(G_OBJECT(proc));
+        g_object_unref(G_OBJECT(proc));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Définit une extension du module 'core' à compléter.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_core_module_with_processors(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Module à recompléter        */
+
+    static PyMethodDef py_processors_methods[] = {
+        {
+            "register_processor", py_processors_register_type,
+            METH_VARARGS,
+            "register_type(name, desc, cls, /)\n--\n\nRegister an an architecture processor by its name, description and class type."
+        },
+        {
+            "get_processor_description", py_processors_get_description,
+            METH_VARARGS,
+            "get_processor_description(name, /)\n--\n\nProvide the description of a given architecture processor."
+        },
+        {
+            "get_processor_for_name", py_processors_get_for_name,
+            METH_VARARGS,
+            "get_processor_for_name(name, /)\n--\n\nProvide an instance of an architecture processor for a given name."
+        },
+        { NULL }
+
+    };
+
+    module = get_access_to_python_module("pychrysalide.core");
+
+    result = register_python_module_methods(module, py_processors_methods);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/core/processors.h b/plugins/pychrysalide/core/processors.h
new file mode 100644
index 0000000..956c9e5
--- /dev/null
+++ b/plugins/pychrysalide/core/processors.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * processors.h - prototypes pour l'équivalent Python du fichier "core/processors.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_CORE_PROCESSORS_H
+#define _PLUGINS_PYCHRYSALIDE_CORE_PROCESSORS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'core' à compléter. */
+bool populate_core_module_with_processors(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_CORE_PROCESSORS_H */
diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index cc0dd33..906fae5 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -320,7 +320,7 @@ int convert_to_vmpa_using_executable(PyObject *obj, exe_cv_info_t *info)
     {
         arch = g_exe_format_get_target_machine(info->format);
 
-        conv.proc = get_arch_processor_for_type(arch);
+        conv.proc = get_arch_processor_for_name(arch);
 
         if (conv.proc != NULL)
         {
diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c
index 3e7ed1a..b9a4500 100644
--- a/plugins/ropgadgets/finder.c
+++ b/plugins/ropgadgets/finder.c
@@ -387,7 +387,7 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd
     domain.content = g_binary_format_get_content(G_BIN_FORMAT(format));
 
     target = g_exe_format_get_target_machine(format);
-    domain.proc = get_arch_processor_for_type(target);
+    domain.proc = get_arch_processor_for_name(target);
 
     bool collect_x_ranges(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused)
     {
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 8964973..7b075fd 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -1723,7 +1723,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS
     /* Architecture visée */
 
     arch = g_exe_format_get_target_machine(binary->format);
-    desc = get_arch_processor_name(arch);
+    desc = get_arch_processor_description(arch);
 
     if (desc == NULL)
     {
@@ -1734,7 +1734,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS
     else
         log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
 
-    binary->proc = get_arch_processor_for_type(arch);
+    binary->proc = get_arch_processor_for_name(arch);
 
     if (binary->proc == NULL)
     {
diff --git a/src/core/core.c b/src/core/core.c
index aabff62..5ce07d0 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -108,8 +108,6 @@ bool load_all_basic_components(void)
 
         register_arch_gtypes();
 
-        result &= load_hard_coded_processors_definitions();
-
         result &= load_hard_coded_collection_definitions();
 
     }
diff --git a/src/core/processors.c b/src/core/processors.c
index 68fd0f6..631e819 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -34,15 +34,14 @@
 #include "../arch/target.h"
 #include "../arch/undefined.h"
 #include "../arch/operands/register.h"
-//#include "../arch/jvm/processor.h"
 
 
 
 /* Caractéristiques d'un processeur */
 typedef struct _proc_t
 {
-    char *key;                              /* Clef pour un accès rapide   */
-    char *name;                             /* Désignation humaine         */
+    char *name;                             /* Clef pour un accès rapide   */
+    char *desc;                             /* Désignation humaine         */
     GType instance;                         /* Type à manipuler en interne */
 
 } proc_t;
@@ -86,8 +85,8 @@ void register_arch_gtypes(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : key      = désignation rapide et interne d'un processeur.    *
-*                name     = désignation humaine de l'architecture.            *
+*  Paramètres  : name     = désignation rapide et interne d'un processeur.    *
+*                desc     = désignation humaine de l'architecture.            *
 *                instance = type GLib représentant le type à instancier.      *
 *                                                                             *
 *  Description : Enregistre un processeur pour une architecture donnée.       *
@@ -98,14 +97,14 @@ void register_arch_gtypes(void)
 *                                                                             *
 ******************************************************************************/
 
-bool register_processor_type(const char *key, const char *name, GType instance)
+bool register_processor_type(const char *name, const char *desc, GType instance)
 {
     bool result;                            /* Bilan à retourner           */
     proc_t *new;                            /* Nouvel élément à définir    */
 
     G_LOCK(_pdef_access);
 
-    new = find_processor_by_key(key);
+    new = find_processor_by_key(name);
 
     result = (new == NULL);
 
@@ -116,8 +115,8 @@ bool register_processor_type(const char *key, const char *name, GType instance)
 
         new = &_processors_definitions[_processors_definitions_count - 1];
 
-        new->key = strdup(key);
         new->name = strdup(name);
+        new->desc = strdup(desc);
         new->instance = instance;
 
     }
@@ -133,31 +132,6 @@ bool register_processor_type(const char *key, const char *name, GType instance)
 *                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Charge les définitions de processeurs "natifs".              *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool load_hard_coded_processors_definitions(void)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = true;
-
-    //result &= register_processor_type("jvm", "Java Virtual Machine", G_TYPE_JVM_PROCESSOR);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
 *  Description : Décharge toutes les définitions de processeurs.              *
 *                                                                             *
 *  Retour      : -                                                            *
@@ -174,8 +148,8 @@ void unload_processors_definitions(void)
 
     for (i = 0; i < _processors_definitions_count; i++)
     {
-        free(_processors_definitions[i].key);
         free(_processors_definitions[i].name);
+        free(_processors_definitions[i].desc);
     }
 
     if (_processors_definitions != NULL)
@@ -191,7 +165,7 @@ void unload_processors_definitions(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : key = nom technique du processeur recherché.                 *
+*  Paramètres  : name = nom technique du processeur recherché.                *
 *                                                                             *
 *  Description : Retrouve l'enregistrement correspondant à une architecture.  *
 *                                                                             *
@@ -201,7 +175,7 @@ void unload_processors_definitions(void)
 *                                                                             *
 ******************************************************************************/
 
-static proc_t *find_processor_by_key(const char *key)
+static proc_t *find_processor_by_key(const char *name)
 {
     proc_t *result;                         /* Trouvaille à retourner      */
     size_t i;                               /* Boucle de parcours          */
@@ -212,9 +186,9 @@ static proc_t *find_processor_by_key(const char *key)
 
     result = NULL;
 
-    if (key != NULL)
+    if (name != NULL)
         for (i = 0; i < _processors_definitions_count; i++)
-            if (strcmp(_processors_definitions[i].key, key) == 0)
+            if (strcmp(_processors_definitions[i].name, name) == 0)
                 result = &_processors_definitions[i];
 
     return result;
@@ -224,7 +198,7 @@ static proc_t *find_processor_by_key(const char *key)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : key = nom technique du processeur recherché.                 *
+*  Paramètres  : name = nom technique du processeur recherché.                *
 *                                                                             *
 *  Description : Fournit le nom humain de l'architecture visée.               *
 *                                                                             *
@@ -234,20 +208,20 @@ static proc_t *find_processor_by_key(const char *key)
 *                                                                             *
 ******************************************************************************/
 
-const char *get_arch_processor_name(const char *key)
+const char *get_arch_processor_description(const char *name)
 {
     const char *result;                     /* Description à retourner     */
     proc_t *def;                            /* Définition d'architecture   */
 
     G_LOCK(_pdef_access);
 
-    def = find_processor_by_key(key);
+    def = find_processor_by_key(name);
 
     if (def == NULL)
         result = NULL;
     else
-        result = def->name;
-    
+        result = def->desc;
+
     G_UNLOCK(_pdef_access);
 
     return result;
@@ -257,9 +231,9 @@ const char *get_arch_processor_name(const char *key)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : key = nom technique du processeur recherché.                 *
+*  Paramètres  : name = nom technique du processeur recherché.                *
 *                                                                             *
-*  Description : Fournit le processeur d'architecture correspondant à un type.*
+*  Description : Fournit le processeur d'architecture correspondant à un nom. *
 *                                                                             *
 *  Retour      : Processeur d'architecture trouvé.                            *
 *                                                                             *
@@ -267,14 +241,14 @@ const char *get_arch_processor_name(const char *key)
 *                                                                             *
 ******************************************************************************/
 
-GArchProcessor *get_arch_processor_for_type(const char *key)
+GArchProcessor *get_arch_processor_for_name(const char *name)
 {
     GArchProcessor *result;                 /* Instance à retourner        */
     proc_t *def;                            /* Définition d'architecture   */
 
     G_LOCK(_pdef_access);
 
-    def = find_processor_by_key(key);
+    def = find_processor_by_key(name);
 
     if (def == NULL)
         result = NULL;
diff --git a/src/core/processors.h b/src/core/processors.h
index f202114..975c716 100644
--- a/src/core/processors.h
+++ b/src/core/processors.h
@@ -38,17 +38,14 @@ void register_arch_gtypes(void);
 /* Enregistre un processeur pour une architecture donnée. */
 bool register_processor_type(const char *, const char *, GType);
 
-/* Charge les définitions de processeurs "natifs". */
-bool load_hard_coded_processors_definitions(void);
-
 /* Décharge toutes les définitions de processeurs. */
 void unload_processors_definitions(void);
 
 /* Fournit le nom humain de l'architecture visée. */
-const char *get_arch_processor_name(const char *);
+const char *get_arch_processor_description(const char *);
 
-/* Fournit le processeur d'architecture correspondant à un type. */
-GArchProcessor *get_arch_processor_for_type(const char *);
+/* Fournit le processeur d'architecture correspondant à un nom. */
+GArchProcessor *get_arch_processor_for_name(const char *);
 
 
 
-- 
cgit v0.11.2-87-g4458