summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/arm/core.c2
-rw-r--r--plugins/dalvik/core.c2
-rw-r--r--plugins/devdbg/speed.c2
-rw-r--r--plugins/dex/core.c2
-rw-r--r--plugins/dexbnf/core.c2
-rw-r--r--plugins/dwarf/core.c2
-rw-r--r--plugins/elf/core.c2
-rw-r--r--plugins/itanium/core.c2
-rw-r--r--plugins/javadesc/core.c2
-rw-r--r--plugins/libcsem/semantic.c2
-rw-r--r--plugins/lnxsyscalls/core.c2
-rw-r--r--plugins/mobicore/core.c2
-rw-r--r--plugins/pychrysalide/Makefile.am1
-rw-r--r--plugins/pychrysalide/arch/processor.c39
-rw-r--r--plugins/pychrysalide/gui/editem.c3
-rw-r--r--plugins/pychrysalide/gui/panels/panel.c39
-rw-r--r--plugins/pychrysalide/helpers.c74
-rw-r--r--plugins/pychrysalide/helpers.h12
-rw-r--r--plugins/pychrysalide/plugin.c929
-rw-r--r--plugins/pychrysalide/pychrysa.c5
-rw-r--r--plugins/readdex/reader.c2
-rw-r--r--plugins/readelf/reader.c2
-rw-r--r--plugins/readmc/reader.c2
-rw-r--r--plugins/ropgadgets/plugin.c2
-rw-r--r--src/core/core.c5
-rw-r--r--src/plugins/Makefile.am1
-rw-r--r--src/plugins/dt.c (renamed from plugins/pychrysalide/dt.c)39
-rw-r--r--src/plugins/dt.h (renamed from plugins/pychrysalide/dt.h)16
-rw-r--r--src/plugins/plugin-def.h13
-rw-r--r--src/plugins/plugin-int.h16
-rw-r--r--src/plugins/plugin.c396
-rw-r--r--src/plugins/plugin.h12
-rw-r--r--tests/plugins/__init__.py0
-rw-r--r--tests/plugins/plugin.py223
34 files changed, 1277 insertions, 578 deletions
diff --git a/plugins/arm/core.c b/plugins/arm/core.c
index d2dd805..07b9b24 100644
--- a/plugins/arm/core.c
+++ b/plugins/arm/core.c
@@ -32,7 +32,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("arm", "Add support for the ARM architecture", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GArmPlugin", "arm", "Add support for the ARM architecture", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT));
diff --git a/plugins/dalvik/core.c b/plugins/dalvik/core.c
index 2e936b9..d7e5a04 100644
--- a/plugins/dalvik/core.c
+++ b/plugins/dalvik/core.c
@@ -35,7 +35,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("dalvik", "Add support for the Dalvik architecture", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDalvikPlugin", "dalvik", "Add support for the Dalvik architecture", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT));
diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c
index 935fbd9..77c407a 100644
--- a/plugins/devdbg/speed.c
+++ b/plugins/devdbg/speed.c
@@ -38,7 +38,7 @@
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Speed Measure", "Tracks to time spent for disassembling code", "0.1.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GSpeedPlugin", "Speed Measure", "Tracks to time spent for disassembling code", "0.1.0",
PGA_FORMAT_ANALYSIS_STARTED,PGA_FORMAT_ANALYSIS_ENDED,
PGA_FORMAT_POST_ANALYSIS_STARTED, PGA_FORMAT_POST_ANALYSIS_ENDED,
PGA_DISASSEMBLY_STARTED, PGA_DISASSEMBLY_ENDED);
diff --git a/plugins/dex/core.c b/plugins/dex/core.c
index 6bdb9d5..3e5b835 100644
--- a/plugins/dex/core.c
+++ b/plugins/dex/core.c
@@ -33,7 +33,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("dex", "Add support for the DEX format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDexPlugin", "dex", "Add support for the DEX format", "0.1.0",
RL("PyChrysalide", "dexbnf"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
diff --git a/plugins/dexbnf/core.c b/plugins/dexbnf/core.c
index 774e88e..736fa5f 100644
--- a/plugins/dexbnf/core.c
+++ b/plugins/dexbnf/core.c
@@ -33,7 +33,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("dexbnf", "Symbol demangler for Dex", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDexBnfPlugin", "dexbnf", "Symbol demangler for Dex", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
diff --git a/plugins/dwarf/core.c b/plugins/dwarf/core.c
index fa7e0ec..1e2d900 100644
--- a/plugins/dwarf/core.c
+++ b/plugins/dwarf/core.c
@@ -31,7 +31,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("dwarf", "Add support for the DWARF format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDwarfPlugin", "dwarf", "Add support for the DWARF format", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_FORMAT_ATTACH_DEBUG));
diff --git a/plugins/elf/core.c b/plugins/elf/core.c
index 6b7810e..d3d226e 100644
--- a/plugins/elf/core.c
+++ b/plugins/elf/core.c
@@ -33,7 +33,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("elf", "Add support for the ELF format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GElfPlugin", "elf", "Add support for the ELF format", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c
index ecfd7f0..71816f7 100644
--- a/plugins/itanium/core.c
+++ b/plugins/itanium/core.c
@@ -33,7 +33,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("itanium", "Symbol demangler for Itanium", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GItaniumPlugin", "itanium", "Symbol demangler for Itanium", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
diff --git a/plugins/javadesc/core.c b/plugins/javadesc/core.c
index e374749..41c4789 100644
--- a/plugins/javadesc/core.c
+++ b/plugins/javadesc/core.c
@@ -33,7 +33,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("javadesc", "Symbol demangler for Java", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GJavaDescPlugin", "javadesc", "Symbol demangler for Java", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
diff --git a/plugins/libcsem/semantic.c b/plugins/libcsem/semantic.c
index 0dc330e..de87012 100644
--- a/plugins/libcsem/semantic.c
+++ b/plugins/libcsem/semantic.c
@@ -32,7 +32,7 @@
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("LibC semantics", "Register semantic information relative to the libc", "0.1.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GCSemPlugin", "LibC semantics", "Register semantic information relative to the libc", "0.1.0",
PGA_DISASSEMBLY_HOOKED_POST);
diff --git a/plugins/lnxsyscalls/core.c b/plugins/lnxsyscalls/core.c
index f28e776..cd9fa0e 100644
--- a/plugins/lnxsyscalls/core.c
+++ b/plugins/lnxsyscalls/core.c
@@ -37,7 +37,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("Linux System Calls", "Describes each Linux system call with its arguments", \
+DEFINE_CHRYSALIDE_PLUGIN("GLnxSyscallsPlugin", "Linux System Calls", "Describes each Linux system call with its arguments", \
"0.1.0", EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_DISASSEMBLY_ENDED));
diff --git a/plugins/mobicore/core.c b/plugins/mobicore/core.c
index bc7298f..9de116d 100644
--- a/plugins/mobicore/core.c
+++ b/plugins/mobicore/core.c
@@ -32,7 +32,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("mobicore", "Support MobiCore file format for Trusted Applications", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GMobicorePlugin", "mobicore", "Support MobiCore file format for Trusted Applications", "0.1.0",
EMPTY_PG_LIST(.required), AL(PGA_CONTENT_RESOLVER));
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index 3fe13af..d9194b9 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -7,7 +7,6 @@ libdir = $(pluginslibdir)
pychrysalide_la_SOURCES = \
access.h access.c \
constval.h constval.c \
- dt.h dt.c \
helpers.h helpers.c \
plugin.h plugin.c \
pychrysa.h pychrysa.c \
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 115f980..4feaa8b 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -31,6 +31,7 @@
#include <i18n.h>
#include <arch/processor-int.h>
+#include <plugins/dt.h>
#include "context.h"
@@ -38,7 +39,6 @@
#include "instruction.h"
#include "vmpa.h"
#include "../access.h"
-#include "../dt.h"
#include "../helpers.h"
#include "../analysis/content.h"
#include "../format/executable.h"
@@ -140,18 +140,16 @@ static bool define_python_arch_processor_constants(PyTypeObject *);
static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *result; /* Objet à retourner */
- bool abstract; /* Validation du type parent */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
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 */
+ bool status; /* Bilan d'un enregistrement */
/* Validations diverses */
- abstract = (type == get_python_arch_processor_type());
+ base = get_python_arch_processor_type();
- if (abstract)
+ if (type == base)
{
result = NULL;
PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
@@ -160,30 +158,23 @@ static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObj
/* 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();
+ first_time = (g_type_from_name(type->tp_name) == 0);
- modname = PyDict_GetItemString(type->tp_dict, "__module__");
-
- module = PyObject_GetItem(sys_mod_dict, modname);
+ gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name,
+ (GClassInitFunc)py_arch_processor_init_gclass, NULL);
- dict = PyModule_GetDict(module);
+ if (first_time)
+ status = register_class_for_dynamic_pygobject(gtype, type, base);
+ else
+ status = true;
- if (!_register_class_for_pygobject(dict, gtype, type,
- &PyGObject_Type, get_python_arch_processor_type(), NULL))
+ if (!status)
{
result = NULL;
goto exit;
}
- Py_DECREF(module);
- Py_DECREF(modname);
-
- /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
result = PyType_GenericNew(type, args, kwds);
diff --git a/plugins/pychrysalide/gui/editem.c b/plugins/pychrysalide/gui/editem.c
index 986d1cb..68962ae 100644
--- a/plugins/pychrysalide/gui/editem.c
+++ b/plugins/pychrysalide/gui/editem.c
@@ -45,9 +45,6 @@
/* Réagit à un changement de contenu chargé en cours d'analyse. */
static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
-/* Réagit à un changement de contenu chargé en cours d'analyse. */
-static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
-
/* Réagit à un changement de vue du contenu en cours d'analyse. */
static void py_editor_item_change_view_wrapper(GEditorItem *, GLoadedPanel *, GLoadedPanel *);
diff --git a/plugins/pychrysalide/gui/panels/panel.c b/plugins/pychrysalide/gui/panels/panel.c
index 1df0670..d4062d3 100644
--- a/plugins/pychrysalide/gui/panels/panel.c
+++ b/plugins/pychrysalide/gui/panels/panel.c
@@ -32,11 +32,11 @@
#include <core/params.h>
#include <gui/core/panels.h>
#include <gui/panels/panel-int.h>
+#include <plugins/dt.h>
#include "../editem.h"
#include "../../access.h"
-#include "../../dt.h"
#include "../../helpers.h"
#include "../../gtkext/dockable.h"
@@ -89,18 +89,16 @@ static bool py_panel_item_define_constants(PyTypeObject *);
static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *result; /* Objet à retourner */
- bool abstract; /* Validation du type parent */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
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 */
+ bool status; /* Bilan d'un enregistrement */
/* Validations diverses */
- abstract = (type == get_python_panel_item_type());
+ base = get_python_panel_item_type();
- if (abstract)
+ if (type == base)
{
result = NULL;
PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
@@ -109,30 +107,23 @@ static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject
/* Mise en place d'un type dédié */
- gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name,
- (GClassInitFunc)py_panel_item_init_gclass);
-
- /* Enregistrement du nouveau GType dans Python */
-
- sys_mod_dict = PyImport_GetModuleDict();
+ first_time = (g_type_from_name(type->tp_name) == 0);
- modname = PyDict_GetItemString(type->tp_dict, "__module__");
-
- module = PyObject_GetItem(sys_mod_dict, modname);
+ gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name,
+ (GClassInitFunc)py_panel_item_init_gclass, NULL);
- dict = PyModule_GetDict(module);
+ if (first_time)
+ status = register_class_for_dynamic_pygobject(gtype, type, base);
+ else
+ status = true;
- if (!_register_class_for_pygobject(dict, gtype, type,
- &PyGObject_Type, get_python_panel_item_type(), NULL))
+ if (!status)
{
result = NULL;
goto exit;
}
- Py_DECREF(module);
- Py_DECREF(modname);
-
- /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
result = PyType_GenericNew(type, args, kwds);
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index ad62de4..a930097 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -701,3 +701,77 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : dict = dictionnaire où conserver une référence au type créé.*
+* gtype = type dans sa version GLib. *
+* type = type dans sa version Python. *
+* base = type de base de l'objet. *
+* *
+* Description : Enregistre un type Python dérivant d'un type GLib dynamique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTypeObject *base)
+{
+ bool result; /* Bilan à retourner */
+ PyTypeObject *legacy_parent; /* Type parent d'origine */
+ PyObject *sys_mod_dict; /* Dictionnaire des modules */
+ PyObject *modname; /* Nom du module du type */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire dudit module */
+
+ /**
+ * Lors de l'appel à pygobject_register_class(), PyGObject remplace systématiquement
+ * le type Python fourni par :
+ *
+ * Py_TYPE(type) = PyGObject_MetaType;
+ *
+ * Ce nouveau type est le suivant (cf. gi/types.py) :
+ *
+ * class _GObjectMetaBase(type):
+ * """Metaclass for automatically registering GObject classes."""
+ *
+ * D'une part, comme les enregistrements sont gérés manuellement dans le cas de
+ * types dérivés dynamiquement d'objets natifs, ce changement est inutile.
+ *
+ * D'autre part, il semble avoir un soucis de références (cf. testGarbageCollecting()
+ * du fichier de test plugins/plugin.py) :
+ *
+ * python3dm: ../Modules/gcmodule.c:379: visit_decref: Assertion `_PyGCHead_REFS(gc) != 0' failed.
+ *
+ * #3 __GI___assert_fail ()
+ * #4 visit_decref ()
+ * #5 subtype_traverse ()
+ * #6 subtract_refs ()
+ * #7 collect ()
+ * #8 collect_with_callback ()
+ * #9 gc_collect ()
+ *
+ * On restaure donc le type d'origine de l'objet Python créé dynamquement pour éviter
+ * ce genre de soucis.
+ */
+
+ legacy_parent = Py_TYPE(type);
+
+ sys_mod_dict = PyImport_GetModuleDict();
+
+ modname = PyDict_GetItemString(type->tp_dict, "__module__");
+
+ module = PyObject_GetItem(sys_mod_dict, modname);
+
+ dict = PyModule_GetDict(module);
+
+ result = _register_class_for_pygobject(dict, gtype, type, &PyGObject_Type, base, NULL);
+
+ Py_TYPE(type) = legacy_parent;
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index e080ca4..bf95e61 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -25,8 +25,9 @@
#define _PLUGINS_PYCHRYSALIDE_HELPERS_H
-#include <glib-object.h>
#include <Python.h>
+#include <assert.h>
+#include <glib-object.h>
#include <stdbool.h>
@@ -97,13 +98,8 @@ bool _register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObje
#define register_class_for_pygobject(dict, gtype, type, base) \
_register_class_for_pygobject(dict, gtype, type, base, NULL)
-
-/**
- * Quand on remplace un objet GLib dans le dos de Python, il faut
- * le remplacer de la même manière qu'on l'a obtenu !
- */
-
-#define pygobject_set(p, v) ((PyGObject *)(p))->obj = (GObject *)v
+/* Enregistre un type Python dérivant d'un type GLib dynamique. */
+bool register_class_for_dynamic_pygobject(GType, PyTypeObject *, PyTypeObject *);
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index a693d7b..22bfabb 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -32,6 +32,7 @@
#include <common/extstr.h>
+#include <plugins/dt.h>
#include <plugins/plugin-int.h>
@@ -41,6 +42,50 @@
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_plugin_module_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise la classe des greffons d'extension. */
+static void py_plugin_module_init_gclass(GPluginModuleClass *, gpointer);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds);
+
+/* Valide les fonctionnalités déclarées en actions. */
+static bool py_plugin_module_check_interface(PyObject *);
+
+/* Accompagne la fin du chargement des modules natifs. */
+static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *, PluginAction);
+
+/* Complète une liste de resources pour thème. */
+static void py_plugin_module_include_theme_wrapper(const GPluginModule *, PluginAction, char ***, size_t *);
+
+/* Procède à une opération liée à un contenu binaire. */
+static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
+
+/* Procède à une opération liée à un contenu chargé. */
+static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *, PluginAction, GLoadedContent *, wgroup_id_t, GtkStatusStack *);
+
+/* Procède à une opération liée à l'analyse d'un format. */
+static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
+/* Procède à un préchargement de format de fichier. */
+static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *);
+
+/* Procède au rattachement d'éventuelles infos de débogage. */
+static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *, PluginAction, GExeFormat *);
+
+/* Exécute une action pendant un désassemblage de binaire. */
+static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModule *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *);
+
+/* Effectue la détection d'effets d'outils externes. */
+static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *, PluginAction, const GLoadedContent *, bool, char ***, size_t *);
+
+
+
/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
@@ -75,30 +120,6 @@ static void g_python_plugin_dispose(GPythonPlugin *);
/* Description : Procède à la libération totale de la mémoire. */
static void g_python_plugin_finalize(GPythonPlugin *);
-/* Reconstruit la déclaration d'interface à partir de lectures. */
-static bool g_python_plugin_read_interface(GPythonPlugin *);
-
-/* Procède à l'initialisation du greffon. */
-static bool g_python_plugin_do_init(GPythonPlugin *);
-
-/* Procède à l'extinction du greffon. */
-static bool g_python_plugin_do_exit(GPythonPlugin *);
-
-/* Procède à une opération liée à un contenu binaire. */
-static void g_python_plugin_handle_binary_content(const GPythonPlugin *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
-
-/* Procède à une opération liée à l'analyse d'un format. */
-static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
-
-/* Procède à un préchargement de format de fichier. */
-static bool g_python_plugin_preload_binary_format(const GPythonPlugin *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *);
-
-/* Procède au rattachement d'éventuelles infos de débogage. */
-static void g_python_plugin_attach_debug_format(const GPythonPlugin *, PluginAction, GExeFormat *);
-
-/* Exécute une action pendant un désassemblage de binaire. */
-static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *);
-
/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
@@ -113,61 +134,78 @@ static bool py_plugin_module_define_constants(PyTypeObject *);
/* ---------------------------------------------------------------------------------- */
-/* INTERFACE INTERNE POUR GREFFONS PYTHON */
+/* GLUE POUR CREATION DEPUIS PYTHON */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini par la GLib pour le greffon Python. */
-G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE);
-
-
/******************************************************************************
* *
-* Paramètres : klass = classe à initialiser. *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition. *
* *
-* Description : Initialise la classe des greffons Python. *
+* Description : Accompagne la création d'une instance dérivée en Python. *
* *
-* Retour : - *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_python_plugin_class_init(GPythonPluginClass *klass)
+static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- GObjectClass *object; /* Autre version de la classe */
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
- object = G_OBJECT_CLASS(klass);
+ /* Validations diverses */
- object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
- object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
+ base = get_python_plugin_module_type();
-}
+ if (type == base)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+ goto exit;
+ }
+ /* Mise en place d'un type dédié */
-/******************************************************************************
-* *
-* Paramètres : plugin = instance à initialiser. *
-* *
-* Description : Initialise l'instance d'un greffon Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ first_time = (g_type_from_name(type->tp_name) == 0);
-static void g_python_plugin_init(GPythonPlugin *plugin)
-{
+ gtype = built_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name,
+ (GClassInitFunc)py_plugin_module_init_gclass, NULL);
+
+ if (first_time)
+ status = register_class_for_dynamic_pygobject(gtype, type, base);
+ else
+ status = true;
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
* *
-* Description : Supprime toutes les références externes. *
+* Description : Initialise la classe des greffons d'extension. *
* *
* Retour : - *
* *
@@ -175,191 +213,147 @@ static void g_python_plugin_init(GPythonPlugin *plugin)
* *
******************************************************************************/
-static void g_python_plugin_dispose(GPythonPlugin *plugin)
+static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unused)
{
- PyThreadState *tstate; /* Contexte d'environnement */
+ class->init = NULL;
+ class->exit = NULL;
- /**
- * Cf. https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
- *
- * Cependant, comme on se trouve à priori dans le thread principal de l'interpréteur,
- * PyGILState_Ensure() ne pose aucun verrou. Ce qui aboutit à la situation suivante :
- *
- * Fatal Python error: drop_gil: GIL is not locked
- *
- * On peut forcer les choses avec PyEval_AcquireLock(), mais cette fonction est marquée
- * comme dépréciée depuis Python 3.2.
- *
- * Donc on choisit les alternatives officielles.
- *
- * Cependant, PyThreadState_Get() renvoit l'erreur suivante :
- *
- * Fatal Python error: PyThreadState_Get: no current thread
- *
- * Donc on se rabat sur une sauvegarde, qui n'est initialisée que lorsque l'interpréteur
- * est intégré dans l'éditeur.
- */
+ class->native_loaded = py_plugin_module_notify_native_loaded_wrapper;
- tstate = get_pychrysalide_main_tstate();
+ class->include_theme = py_plugin_module_include_theme_wrapper;
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ class->handle_content = py_plugin_module_handle_binary_content_wrapper;
+ class->handle_loaded = py_plugin_module_handle_loaded_content_wrapper;
- Py_XDECREF(plugin->instance);
- plugin->instance = NULL;
+ class->handle_fmt_analysis = py_plugin_module_handle_binary_format_analysis_wrapper;
+ class->preload_format = py_plugin_module_preload_binary_format_wrapper;
+ class->attach_debug = py_plugin_module_attach_debug_format_wrapper;
- if (tstate != NULL)
- PyEval_SaveThread();
+ class->process_disass = py_plugin_module_process_disassembly_event_wrapper;
- G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
+ class->detect = py_plugin_module_detect_external_tools_wrapper;
}
/******************************************************************************
* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : - *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_python_plugin_finalize(GPythonPlugin *plugin)
+static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- plugin_interface *final; /* Interface finale conservée */
+ const char *name; /* Désignation humaine courte */
+ const char *desc; /* Description plus loquace */
+ const char *version; /* Version du greffon */
+ PyObject *actions_obj; /* Liste des actions offertes */
+ int ret; /* Bilan de lecture des args. */
+ PyObject *new_kwds; /* Nouveau dictionnaire épuré */
+ GPluginModule *plugin; /* Greffon à manipuler */
+ plugin_interface *iface; /* Interface à constituer */
+ size_t i; /* Boucle de parcours */
+ PyObject *action; /* Identifiant d'une action */
- Py_DECREF(plugin->module);
+ static char *kwlist[] = { "name", "desc", "version", "actions", NULL };
- final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
+ /* Récupération des paramètres */
- if (final != NULL)
- {
- assert(final->required_count == 1);
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "sssO!", kwlist,
+ &name, &desc, &version, &PyTuple_Type, &actions_obj);
+ if (!ret) return -1;
- free(final->required);
- free(final);
+ /* Initialisation d'un objet GLib */
- }
+ new_kwds = PyDict_New();
- G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
+ ret = PyGObject_Type.tp_init(self, args, new_kwds);
-}
+ Py_DECREF(new_kwds);
+ if (ret == -1) return -1;
-/******************************************************************************
-* *
-* Paramètres : modname = nom du module à charger. *
-* filename = chemin d'accès au code Python à charger. *
-* *
-* Description : Crée un greffon à partir de code Python. *
-* *
-* Retour : Adresse de la structure mise en place ou NULL si erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ /* Eléments de base */
-GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
-{
- GPythonPlugin *result; /* Structure à retourner */
- PyObject *name; /* Chemin d'accès pour Python */
- PyObject *module; /* Script Python chargé */
- PyObject *err_type; /* Type d'erreur Python */
- PyObject *err_value; /* Instance Python d'erreur */
- PyObject *err_traceback; /* Trace Python associée */
- PyObject *err_string; /* Description Python d'erreur */
- const char *err_msg; /* Représentation humaine */
- PyObject *dict; /* Dictionnaire associé */
- PyObject *class; /* Classe à instancier */
- PyObject *instance; /* Instance Python du greffon */
- size_t i; /* Boucle de parcours */
- uint32_t action; /* Identifiant d'une action */
- uint32_t category; /* Catégorie principale */
- uint32_t sub; /* Sous-catégorie visée */
+ plugin = G_PLUGIN_MODULE(pygobject_get(self));
- name = PyUnicode_FromString(modname);
- if (name == NULL) goto gppn_bad_exit;
+ iface = malloc(sizeof(plugin_interface));
+ plugin->interface = iface;
- module = PyImport_Import(name);
- Py_DECREF(name);
+ iface->name = strdup(name);
+ iface->desc = strdup(desc);
+ iface->version = strdup(version);
- if (PyErr_Occurred())
- {
- PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ iface->container = false;
- if (err_value == NULL)
- log_variadic_message(LMT_ERROR,
- _("An unknown error occured when importing '%s'..."), modname);
- else
- {
- err_string = PyObject_Str(err_value);
- err_msg = PyUnicode_AsUTF8(err_string);
+ iface->required = malloc(sizeof(char *));
+ iface->required[0] = "PyChrysalide";
+ iface->required_count = 1;
- log_variadic_message(LMT_ERROR,
- _("An error occured when importing '%s': \"%s\""), modname, err_msg);
+ iface->actions_count = PyTuple_Size(actions_obj);
+ iface->actions = malloc(iface->actions_count * sizeof(plugin_action_t));
- Py_DECREF(err_string);
- Py_DECREF(err_value);
+ for (i = 0; i < iface->actions_count; i++)
+ {
+ action = PyTuple_GetItem(actions_obj, i);
+ if (!PyLong_Check(action))
+ {
+ PyErr_SetString(PyExc_TypeError, _("invalid type for plugin action."));
+ return -1;
}
- Py_XDECREF(err_traceback);
- Py_XDECREF(err_type);
-
- Py_XDECREF(module);
+ iface->actions[i] = PyLong_AsUnsignedLong(action);
- module = NULL;
+ }
+ if (!py_plugin_module_check_interface(self))
+ {
+ PyErr_SetString(PyExc_TypeError, _("missing features for the declared actions."));
+ return -1;
}
- if (module == NULL) goto gppn_bad_exit;
+ return 0;
- dict = PyModule_GetDict(module);
- class = PyDict_GetItemString(dict, "AutoLoad");
+}
- if (class == NULL) goto gppn_no_class;
- if (!PyType_Check(class->ob_type)) goto gppn_no_class;
- instance = PyObject_CallFunction(class, NULL);
- if (instance == NULL) goto gppn_no_instance;
+/******************************************************************************
+* *
+* Paramètres : self = greffon Python en cours d'initialisation. *
+* *
+* Description : Valide les fonctionnalités déclarées en actions. *
+* *
+* Retour : true si le greffon Python est à priori utilisable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL);
+static bool py_plugin_module_check_interface(PyObject *self)
+{
+ bool result; /* Bilan à retourner */
+ GPluginModule *plugin; /* Greffon à manipuler */
+ size_t i; /* Boucle de parcours */
+ uint32_t action; /* Identifiant d'une action */
+ uint32_t category; /* Catégorie principale */
+ uint32_t sub; /* Sous-catégorie visée */
- G_PLUGIN_MODULE(result)->filename = strdup(filename);
+ result = true;
- result->module = module;
- result->instance = instance;
+ plugin = G_PLUGIN_MODULE(pygobject_get(self));
- if (!g_python_plugin_read_interface(result))
- goto gppn_interface_error;
-
- /* Localisation des différents points d'entrée déclarés */
-
-#define register_python_binding(inst, pysym, sym, binding) \
- ({ \
- bool __result; \
- if (!has_python_method(inst, #pysym)) \
- { \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- #pysym, G_PLUGIN_MODULE(result)->filename); \
- __result = false; \
- } \
- else \
- { \
- G_PLUGIN_MODULE(result)->sym = binding; \
- __result = true; \
- } \
- __result; \
- })
-
- for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++)
+ for (i = 0; i < plugin->interface->actions_count && result; i++)
{
- action = G_PLUGIN_MODULE(result)->interface->actions[i];
+ action = plugin->interface->actions[i];
category = MASK_PLUGIN_CATEGORY(action);
sub = MASK_PLUGIN_SUB_CATEGORY(action);
@@ -373,20 +367,17 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
break;
case PGA_PLUGIN_INIT:
- if (!register_python_binding(instance, init, init,
- (pg_management_fc)g_python_plugin_do_init))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "init");
break;
case PGA_PLUGIN_EXIT:
- if (!register_python_binding(instance, exit, exit,
- (pg_management_fc)g_python_plugin_do_exit))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "exit");
break;
default:
log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ _("Unknown sub-category '0x%02x' in plugin '%s'..."),
+ sub, self->ob_type->tp_name);
break;
}
@@ -402,16 +393,17 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
switch (action)
{
case PGA_CONTENT_EXPLORER:
+ result = has_python_method(self, "handle_binary_content");
+ break;
+
case PGA_CONTENT_RESOLVER:
- if (!register_python_binding(instance, handle_content, handle_content,
- (pg_handle_content_fc)g_python_plugin_handle_binary_content))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "handle_loaded_content");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- action, filename);
+ action, self->ob_type->tp_name);
break;
}
@@ -426,27 +418,21 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
case PGA_FORMAT_ANALYSIS_ENDED:
case PGA_FORMAT_POST_ANALYSIS_STARTED:
case PGA_FORMAT_POST_ANALYSIS_ENDED:
- if (!register_python_binding(instance, handle_format_analysis, handle_fmt_analysis,
- (pg_handle_format_analysis_fc)g_python_plugin_handle_binary_format_analysis))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "handle_format_analysis");
break;
case PGA_FORMAT_PRELOAD:
- if (!register_python_binding(instance, preload_format, preload_format,
- (pg_preload_format_fc)g_python_plugin_preload_binary_format))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "preload_format");
break;
case PGA_FORMAT_ATTACH_DEBUG:
- if (!register_python_binding(instance, attach_debug_format, attach_debug,
- (pg_attach_debug)g_python_plugin_attach_debug_format))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "attach_debug_format");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- action, filename);
+ action, self->ob_type->tp_name);
break;
}
@@ -454,14 +440,13 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
break;
case DPS_DISASSEMBLY:
- if (!register_python_binding(instance, process_disassembly, process_disass,
- (pg_process_disassembly_fc)g_python_plugin_process_disass))
- goto gppn_bad_plugin;
+ result = has_python_method(self, "process_disassembly");
break;
default:
log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ _("Unknown sub-category '0x%02x' in plugin '%s'..."),
+ sub, self->ob_type->tp_name);
break;
}
@@ -470,217 +455,102 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
default:
log_variadic_message(LMT_WARNING,
- _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
+ _("Unknown category '0x%02x' in plugin '%s'..."),
+ category, self->ob_type->tp_name);
break;
}
}
- /* Conclusion */
-
- return G_PLUGIN_MODULE(result);
-
- gppn_bad_plugin:
-
- gppn_interface_error:
-
- g_object_unref(G_OBJECT(result));
-
- return NULL;
-
- gppn_no_instance:
-
- gppn_no_class:
-
- Py_DECREF(module);
-
- gppn_bad_exit:
-
- return NULL;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à initialiser. *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* unused = variable non utilisé pour l'usage de __VA_ARGS__. *
* *
-* Description : Reconstruit la déclaration d'interface à partir de lectures. *
+* Description : Accompagne la fin du chargement des modules natifs. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_python_plugin_read_interface(GPythonPlugin *plugin)
+static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *plugin, PluginAction action)
{
- bool result; /* Bilan à renvoyer */
- plugin_interface interface; /* Recueil des éléments */
- PyObject *desc; /* Tableau de description */
- PyObject *str; /* Chaîne de caractères */
- PyObject *tuple; /* Liste d'éléments à traiter */
- Py_ssize_t count; /* Nombre d'éléments présents */
- Py_ssize_t i; /* Boucle de parcours */
- PyObject *action; /* Identifiant d'une action */
- plugin_interface *final; /* Interface finale conservée */
-
- result = true;
-
- desc = run_python_method(plugin->instance, "get_interface", NULL);
- if (!PyDict_Check(desc))
- {
- result = false;
- goto pgpri_end;
- }
-
- memset(&interface, 0, sizeof(interface));
-
- /* Chargements des premières chaînes */
-
-#define READ_STR_FIELD(name) \
- str = PyDict_GetItemString(desc, #name); \
- if ((result = PyUnicode_Check(str))) \
- interface.name = strdup(PyUnicode_DATA(str)); \
-
- READ_STR_FIELD(name);
- READ_STR_FIELD(desc);
- READ_STR_FIELD(version);
-
- /* Chargement des actions supportées */
-
- tuple = PyDict_GetItemString(desc, "actions");
-
- if (!PyList_Check(tuple))
- {
- result = false;
- goto pgpri_failed;
- }
-
- count = PyList_GET_SIZE(tuple);
-
- interface.actions = (plugin_action_t *)calloc(count, sizeof(plugin_action_t));
- interface.actions_count = count;
-
- for (i = 0; i < count; i++)
- {
- action = PyList_GET_ITEM(tuple, i);
-
- interface.actions[i] = PyLong_AsUnsignedLong(action);
-
- }
-
- pgpri_failed:
-
- if (result)
- {
- final = (plugin_interface *)calloc(1, sizeof(plugin_interface));
-
- memcpy(final, &interface, sizeof(interface));
-
- final->required = (const char **)malloc(sizeof(char *));
- final->required[0] = "PyChrysalide";
- final->required_count = 1;
-
- G_PLUGIN_MODULE(plugin)->interface = final;
-
- }
- else
- {
- if (interface.name != NULL) free((char *)interface.name);
- if (interface.desc != NULL) free((char *)interface.desc);
- if (interface.version != NULL) free((char *)interface.version);
-
- if (interface.actions != NULL) free(interface.actions);
-
- }
-
- pgpri_end:
-
- Py_XDECREF(desc);
-
- return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à initialiser. *
-* ref = espace de référencement global. *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* resources = liste de ressources à constituer. [OUT] *
+* count = taille de cette liste. [OUT] *
* *
-* Description : Procède à l'initialisation du greffon. *
+* Description : Complète une liste de resources pour thème. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_python_plugin_do_init(GPythonPlugin *plugin)
+static void py_plugin_module_include_theme_wrapper(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count)
{
- bool result; /* Bilan à retourner */
- PyThreadState *tstate; /* Contexte d'environnement */
- PyObject *value; /* Valeur obtenue */
-
- tstate = PyThreadState_Get();
-
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
-
- if (!has_python_method(plugin->instance, "init"))
- result = true;
-
- else
- {
- value = run_python_method(plugin->instance, "init", NULL);
-
- result = (value != NULL && PyObject_IsTrue(value));
-
- Py_XDECREF(value);
-
- }
-
- if (tstate != NULL)
- PyEval_SaveThread();
-
- return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à initialiser. *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* content = contenu binaire à traiter. *
+* wid = identifiant du groupe de traitement. *
+* status = barre de statut à tenir informée. *
* *
-* Description : Procède à l'extinction du greffon. *
+* Description : Procède à une opération liée à un contenu binaire. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_python_plugin_do_exit(GPythonPlugin *plugin)
+static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
{
- bool result; /* Bilan à retourner */
- PyObject *value; /* Valeur obtenue */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *value; /* Valeurs obtenues */
- if (!has_python_method(plugin->instance, "exit"))
- result = true;
+ gstate = PyGILState_Ensure();
- else
- {
- value = run_python_method(plugin->instance, "exit", NULL);
+ pyobj = pygobject_new(G_OBJECT(plugin));
- result = (value != NULL && PyObject_IsTrue(value));
+ assert(has_python_method(pyobj, "handle_binary_content"));
- Py_XDECREF(value);
+ args = PyTuple_New(4);
- }
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+ PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid));
+ PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
- return result;
+ value = run_python_method(pyobj, "handle_binary_content", args);
+
+ Py_XDECREF(value);
+ Py_DECREF(args);
+
+ PyGILState_Release(gstate);
}
@@ -689,11 +559,11 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin)
* *
* Paramètres : plugin = greffon à manipuler. *
* action = type d'action attendue. *
-* content = contenu binaire à traiter. *
+* content = contenu chargé à traiter. *
* wid = identifiant du groupe de traitement. *
* status = barre de statut à tenir informée. *
* *
-* Description : Procède à une opération liée à un contenu binaire. *
+* Description : Procède à une opération liée à un contenu chargé. *
* *
* Retour : - *
* *
@@ -701,14 +571,19 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin)
* *
******************************************************************************/
-static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
+static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status)
{
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *value; /* Valeurs obtenues */
gstate = PyGILState_Ensure();
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ assert(has_python_method(pyobj, "handle_loaded_content"));
+
args = PyTuple_New(4);
PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
@@ -716,7 +591,7 @@ static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, P
PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid));
PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
- value = run_python_method(plugin->instance, "handle_content", args);
+ value = run_python_method(pyobj, "handle_loaded_content", args);
Py_XDECREF(value);
Py_DECREF(args);
@@ -742,14 +617,19 @@ static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, P
* *
******************************************************************************/
-static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
{
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *value; /* Valeurs obtenues */
gstate = PyGILState_Ensure();
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ assert(has_python_method(pyobj, "handle_format_analysis"));
+
args = PyTuple_New(4);
PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
@@ -757,7 +637,7 @@ static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *p
PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid));
PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
- value = run_python_method(plugin->instance, "handle_format_analysis", args);
+ value = run_python_method(pyobj, "handle_format_analysis", args);
Py_XDECREF(value);
Py_DECREF(args);
@@ -785,14 +665,19 @@ static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *p
* *
******************************************************************************/
-static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
+static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
{
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *value; /* Valeurs obtenues */
gstate = PyGILState_Ensure();
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ assert(has_python_method(pyobj, "preload_format"));
+
args = PyTuple_New(4);
PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
@@ -800,7 +685,7 @@ static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, P
PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(info)));
PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
- value = run_python_method(plugin->instance, "preload_format", args);
+ value = run_python_method(pyobj, "preload_format", args);
Py_XDECREF(value);
Py_DECREF(args);
@@ -826,20 +711,25 @@ static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, P
* *
******************************************************************************/
-static void g_python_plugin_attach_debug_format(const GPythonPlugin *plugin, PluginAction action, GExeFormat *format)
+static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *plugin, PluginAction action, GExeFormat *format)
{
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *value; /* Valeurs obtenues */
gstate = PyGILState_Ensure();
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ assert(has_python_method(pyobj, "attach_debug_format"));
+
args = PyTuple_New(2);
PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
- value = run_python_method(plugin->instance, "attach_debug_format", args);
+ value = run_python_method(pyobj, "attach_debug_format", args);
Py_XDECREF(value);
Py_DECREF(args);
@@ -851,9 +741,9 @@ static void g_python_plugin_attach_debug_format(const GPythonPlugin *plugin, Plu
/******************************************************************************
* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* binary = binaire dont le contenu est en cours de traitement.*
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* binary = binaire dont le contenu est en cours de traitement. *
* status = barre de statut à tenir informée. *
* context = contexte de désassemblage. *
* *
@@ -865,14 +755,19 @@ static void g_python_plugin_attach_debug_format(const GPythonPlugin *plugin, Plu
* *
******************************************************************************/
-static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
+static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
{
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *value; /* Valeurs obtenues */
gstate = PyGILState_Ensure();
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ assert(has_python_method(pyobj, "process_disassembly"));
+
args = PyTuple_New(4);
PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
@@ -880,7 +775,7 @@ static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAc
PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(status)));
PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(context)));
- value = run_python_method(plugin->instance, "process_disassembly", args);
+ value = run_python_method(pyobj, "process_disassembly", args);
Py_XDECREF(value);
Py_DECREF(args);
@@ -890,6 +785,265 @@ static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAc
}
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* content = élément chargé à consulter. *
+* version = précise si les versions doivent être recherchées. *
+* names = désignations humaines correspondantes, à libérer. *
+* count = nombre de types d'obscurcissement trouvés. [OUT] *
+* *
+* Description : Effectue la détection d'effets d'outils externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count)
+{
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE INTERNE POUR GREFFONS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour le greffon Python. */
+G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des greffons Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_class_init(GPythonPluginClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser. *
+* *
+* Description : Initialise l'instance d'un greffon Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_init(GPythonPlugin *plugin)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_dispose(GPythonPlugin *plugin)
+{
+ PyThreadState *tstate; /* Contexte d'environnement */
+
+ /**
+ * Cf. https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
+ *
+ * Cependant, comme on se trouve à priori dans le thread principal de l'interpréteur,
+ * PyGILState_Ensure() ne pose aucun verrou. Ce qui aboutit à la situation suivante :
+ *
+ * Fatal Python error: drop_gil: GIL is not locked
+ *
+ * On peut forcer les choses avec PyEval_AcquireLock(), mais cette fonction est marquée
+ * comme dépréciée depuis Python 3.2.
+ *
+ * Donc on choisit les alternatives officielles.
+ *
+ * Cependant, PyThreadState_Get() renvoit l'erreur suivante :
+ *
+ * Fatal Python error: PyThreadState_Get: no current thread
+ *
+ * Donc on se rabat sur une sauvegarde, qui n'est initialisée que lorsque l'interpréteur
+ * est intégré dans l'éditeur.
+ */
+
+ tstate = get_pychrysalide_main_tstate();
+
+ if (tstate != NULL)
+ PyEval_RestoreThread(tstate);
+
+ Py_XDECREF(plugin->instance);
+ plugin->instance = NULL;
+
+ if (tstate != NULL)
+ PyEval_SaveThread();
+
+ G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_finalize(GPythonPlugin *plugin)
+{
+ plugin_interface *final; /* Interface finale conservée */
+
+ Py_XDECREF(plugin->module);
+
+ final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
+
+ if (final != NULL)
+ {
+ assert(final->required_count == 1);
+ free(final->required);
+
+ free(final);
+
+ }
+
+ G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modname = nom du module à charger. *
+* filename = chemin d'accès au code Python à charger. *
+* *
+* Description : Crée un greffon à partir de code Python. *
+* *
+* Retour : Adresse de la structure mise en place ou NULL si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
+{
+ GPythonPlugin *result; /* Structure à retourner */
+ PyObject *name; /* Chemin d'accès pour Python */
+ PyObject *module; /* Script Python chargé */
+ PyObject *err_type; /* Type d'erreur Python */
+ PyObject *err_value; /* Instance Python d'erreur */
+ PyObject *err_traceback; /* Trace Python associée */
+ PyObject *err_string; /* Description Python d'erreur */
+ const char *err_msg; /* Représentation humaine */
+ PyObject *dict; /* Dictionnaire associé */
+ PyObject *class; /* Classe à instancier */
+ PyObject *instance; /* Instance Python du greffon */
+
+ name = PyUnicode_FromString(modname);
+ if (name == NULL) goto gppn_bad_exit;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+
+ if (err_value == NULL)
+ log_variadic_message(LMT_ERROR,
+ _("An unknown error occured when importing '%s'..."), modname);
+ else
+ {
+ err_string = PyObject_Str(err_value);
+ err_msg = PyUnicode_AsUTF8(err_string);
+
+ log_variadic_message(LMT_ERROR,
+ _("An error occured when importing '%s': \"%s\""), modname, err_msg);
+
+ Py_DECREF(err_string);
+ Py_DECREF(err_value);
+
+ }
+
+ Py_XDECREF(err_traceback);
+ Py_XDECREF(err_type);
+
+ Py_XDECREF(module);
+
+ module = NULL;
+
+ }
+
+ if (module == NULL) goto gppn_bad_exit;
+
+ dict = PyModule_GetDict(module);
+ class = PyDict_GetItemString(dict, "AutoLoad");
+
+ if (class == NULL) goto gppn_no_class;
+ if (!PyType_Check(class->ob_type)) goto gppn_no_class;
+
+ instance = PyObject_CallFunction(class, NULL);
+ if (instance == NULL) goto gppn_no_instance;
+
+ result = G_PYTHON_PLUGIN(pygobject_get(instance));
+
+ G_PLUGIN_MODULE(result)->filename = strdup(filename);
+
+ result->module = module;
+ result->instance = instance;
+
+ Py_INCREF(instance);
+
+ return G_PLUGIN_MODULE(result);
+
+ gppn_no_instance:
+
+ gppn_no_class:
+
+ Py_DECREF(module);
+
+ gppn_bad_exit:
+
+ return NULL;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* MODULE PYTHON POUR LES SCRIPTS */
@@ -926,7 +1080,7 @@ static PyObject *py_plugin_module_log_message(PyObject *self, PyObject *args)
case LMT_BAD_BINARY:
case LMT_ERROR:
case LMT_EXT_ERROR:
- /*g_plugin_module_*/log_simple_message(/*G_PLUGIN_MODULE(pygobject_get(self)), */type, msg);
+ g_plugin_module_log_simple_message(G_PLUGIN_MODULE(pygobject_get(self)), type, msg);
result = Py_None;
Py_INCREF(result);
break;
@@ -1037,7 +1191,10 @@ PyTypeObject *get_python_plugin_module_type(void)
.tp_doc = "Chrysalide plugin for Python.",
.tp_methods = py_plugin_module_methods,
- .tp_getset = py_plugin_module_getseters
+ .tp_getset = py_plugin_module_getseters,
+
+ .tp_init = py_plugin_module_init,
+ .tp_new = py_plugin_module_new,
};
@@ -1072,7 +1229,7 @@ bool ensure_python_plugin_module_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_PYTHON_PLUGIN, type, &PyGObject_Type))
return false;
if (!py_plugin_module_define_constants(type))
diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c
index 8849981..502bf20 100644
--- a/plugins/pychrysalide/pychrysa.c
+++ b/plugins/pychrysalide/pychrysa.c
@@ -45,7 +45,6 @@
#include "access.h"
#include "constval.h"
-#include "dt.h"
#include "helpers.h"
#include "plugin.h"
#include "star.h"
@@ -63,7 +62,7 @@
-DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0",
+DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("GPyChrysalidePlugin", "PyChrysalide", "Provides bindings to Python", "0.1.0",
EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT, PGA_NATIVE_LOADED));
@@ -368,8 +367,6 @@ 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/plugins/readdex/reader.c b/plugins/readdex/reader.c
index 5b84a0d..2009ad6 100644
--- a/plugins/readdex/reader.c
+++ b/plugins/readdex/reader.c
@@ -34,7 +34,7 @@
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readdex", "Displays information about DEX files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GDexReaderPlugin", "readdex", "Displays information about DEX files", "0.2.0",
PGA_FORMAT_PRELOAD);
diff --git a/plugins/readelf/reader.c b/plugins/readelf/reader.c
index b137659..ba4d17a 100644
--- a/plugins/readelf/reader.c
+++ b/plugins/readelf/reader.c
@@ -35,7 +35,7 @@
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readelf", "Displays information about ELF files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GElfReaderPlugin", "readelf", "Displays information about ELF files", "0.2.0",
PGA_FORMAT_PRELOAD);
diff --git a/plugins/readmc/reader.c b/plugins/readmc/reader.c
index e10b927..e492eeb 100644
--- a/plugins/readmc/reader.c
+++ b/plugins/readmc/reader.c
@@ -36,7 +36,7 @@
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readmc", "Displays information about Mobicore files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GMCReaderPlugin", "readmc", "Displays information about Mobicore files", "0.2.0",
PGA_FORMAT_PRELOAD);
diff --git a/plugins/ropgadgets/plugin.c b/plugins/ropgadgets/plugin.c
index 1ecb7d8..d560c88 100644
--- a/plugins/ropgadgets/plugin.c
+++ b/plugins/ropgadgets/plugin.c
@@ -36,7 +36,7 @@
-DEFINE_CHRYSALIDE_PLUGIN("ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GROPPlugin", "ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0",
RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
diff --git a/src/core/core.c b/src/core/core.c
index cdcfce5..aabff62 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -44,6 +44,7 @@
#include "../common/io.h"
#include "../common/xdg.h"
#include "../glibext/linesegment.h"
+#include "../plugins/dt.h"
@@ -87,6 +88,8 @@ bool load_all_basic_components(void)
SSL_load_error_strings();
SSL_library_init();
+ result &= init_chrysalide_dynamic_types();
+
result &= load_main_config_parameters();
result &= ensure_user_has_rsa_keys();
@@ -142,6 +145,8 @@ void unload_all_basic_components(void)
unload_main_config_parameters();
+ exit_chrysalide_dynamic_types();
+
ERR_free_strings();
}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 996c418..4059e0b 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libplugins.la
libplugins_la_SOURCES = \
context-int.h \
context.h context.c \
+ dt.h dt.c \
pglist.h pglist.c \
plugin-def.h \
plugin-int.h \
diff --git a/plugins/pychrysalide/dt.c b/src/plugins/dt.c
index 0b46b45..afdba21 100644
--- a/plugins/pychrysalide/dt.c
+++ b/src/plugins/dt.c
@@ -45,6 +45,7 @@ typedef struct _type_dyn_info_t
{
GType type; /* Identifiant unique obtenu */
GClassInitFunc init; /* Définition des méthodes */
+ gconstpointer data; /* Eventuelles données utiles */
} type_dyn_info_t;
@@ -99,16 +100,16 @@ static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, G
/* Retrouve les informations concernant un type dynamique. */
static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType);
-/* Fournit un identifiant GLib pour un nouveau type Python. */
-static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc);
+/* Fournit un identifiant GLib pour un nouveau type. */
+static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer);
/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-/* Encadrement des nouveaux types Python dérivés */
-static GDynamicTypes *_python_dtypes = NULL;
+/* Encadrement des nouveaux types dérivés */
+static GDynamicTypes *_chrysalide_dtypes = NULL;
@@ -312,6 +313,7 @@ static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTyp
info->class_size = query.class_size;
info->class_init = nfo->init;
+ info->class_data = nfo->data;
info->instance_size = query.instance_size;
@@ -352,8 +354,9 @@ static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, G
* Paramètres : parent = type GLib parent. *
* name = désignation du nouveau type. *
* init = procédure d'initialisation de la classe associée. *
+* data = éventuelles données à associer à la future classe. *
* *
-* Description : Fournit un identifiant GLib pour un nouveau type Python. *
+* Description : Fournit un identifiant GLib pour un nouveau type. *
* *
* Retour : identifiant d'un nouveau type valide, ou 0. *
* *
@@ -361,7 +364,7 @@ static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, G
* *
******************************************************************************/
-static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init)
+static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init, gconstpointer data)
{
GType result; /* Identifiant à retourner */
type_dyn_info_t *new; /* Mémorisation de paramètres */
@@ -377,6 +380,7 @@ static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, c
new->type = result;
new->init = init;
+ new->data = data;
/* Inscription définitive */
@@ -401,7 +405,7 @@ static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, c
* *
* Paramètres : - *
* *
-* Description : Lance le support de dérivations de types dans Python. *
+* Description : Lance le support de dérivations de types dans Chrysalide. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -409,13 +413,13 @@ static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, c
* *
******************************************************************************/
-bool init_dynamic_python_types(void)
+bool init_chrysalide_dynamic_types(void)
{
bool result; /* Bilan à retourner */
- _python_dtypes = g_dynamic_types_new();
+ _chrysalide_dtypes = g_dynamic_types_new();
- result = (_python_dtypes != NULL);
+ result = (_chrysalide_dtypes != NULL);
return result;
@@ -426,7 +430,7 @@ bool init_dynamic_python_types(void)
* *
* Paramètres : - *
* *
-* Description : Arrête le support de dérivations de types dans Python. *
+* Description : Arrête le support de dérivations de types dans Chrysalide. *
* *
* Retour : - *
* *
@@ -434,9 +438,9 @@ bool init_dynamic_python_types(void)
* *
******************************************************************************/
-void exit_dynamic_python_types(void)
+void exit_chrysalide_dynamic_types(void)
{
- g_object_unref(G_OBJECT(_python_dtypes));
+ g_object_unref(G_OBJECT(_chrysalide_dtypes));
}
@@ -446,23 +450,24 @@ void exit_dynamic_python_types(void)
* Paramètres : parent = type GLib parent. *
* name = désignation du nouveau type. *
* init = procédure d'initialisation de la classe associée. *
+* data = éventuelles données à associer à la future classe. *
* *
-* Retour : Identifiant d'un nouveau type valide, ou 0. *
+* Description : Fournit un identifiant GLib pour un nouveau type. *
* *
-* Retour : - *
+* Retour : Identifiant d'un nouveau type valide, ou 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init)
+GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init, gconstpointer data)
{
GType result; /* Identifiant à retourner */
result = g_type_from_name(name);
if (result == 0)
- result = g_dynamic_types_register_type(_python_dtypes, parent, name, init);
+ result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, init, data);
return result;
diff --git a/plugins/pychrysalide/dt.h b/src/plugins/dt.h
index b0f16db..b9d4656 100644
--- a/plugins/pychrysalide/dt.h
+++ b/src/plugins/dt.h
@@ -21,8 +21,8 @@
*/
-#ifndef _PLUGINS_PYCHRYSALIDE_DT_H
-#define _PLUGINS_PYCHRYSALIDE_DT_H
+#ifndef _PLUGINS_DT_H
+#define _PLUGINS_DT_H
#include <glib-object.h>
@@ -33,14 +33,14 @@
/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-/* Lance le support de dérivations de types dans Python. */
-bool init_dynamic_python_types(void);
+/* Lance le support de dérivations de types dans Chrysalide. */
+bool init_chrysalide_dynamic_types(void);
-/* Arrête le support de dérivations de types dans Python. */
-void exit_dynamic_python_types(void);
+/* Arrête le support de dérivations de types dans Chrysalide. */
+void exit_chrysalide_dynamic_types(void);
-/* Fournit un identifiant GLib pour un nouveau type Python. */
-GType built_dynamic_type(GType, const char *, GClassInitFunc);
+/* Fournit un identifiant GLib pour un nouveau type. */
+GType built_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer);
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 4c59606..b8cdca8 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -45,7 +45,7 @@ typedef uint32_t plugin_abi_version_t;
#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
-#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 1, 0)
+#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 2, 0)
//#define HARD_CODE_CURRENT_ABI_VERSION const plugin_abi_version_t abi_version = CURRENT_ABI_VERSION
@@ -223,6 +223,7 @@ typedef struct _plugin_interface
uint64_t magic; /* Vérification a minima */
plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+ const char *gtp_name; /* Désignation du GType associé*/
const char *name; /* Désignation humaine courte */
const char *desc; /* Description plus loquace */
const char *version; /* Version du greffon */
@@ -253,12 +254,13 @@ typedef struct _plugin_interface
#define RL(...) BUILD_PG_LIST(.required, ((const char *[]){ __VA_ARGS__ }))
-#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, r, a) \
+#define DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, r, a) \
G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
\
.magic = CHRYSALIDE_PLUGIN_MAGIC, \
.abi_version = CURRENT_ABI_VERSION, \
\
+ .gtp_name = t, \
.name = n, \
.desc = d, \
.version = v, \
@@ -271,12 +273,13 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
\
}
-#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, r, a) \
+#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(t, n, d, v, r, a) \
G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
\
.magic = CHRYSALIDE_PLUGIN_MAGIC, \
.abi_version = CURRENT_ABI_VERSION, \
\
+ .gtp_name = t, \
.name = n, \
.desc = d, \
.version = v, \
@@ -291,8 +294,8 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
/* Interfaçage primaire avec Chrysalide */
-#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(n, d, v, ...) \
- DEFINE_CHRYSALIDE_PLUGIN(n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ ))
+#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(t, n, d, v, ...) \
+ DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ ))
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 2d98217..4746867 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -83,6 +83,14 @@ struct _GPluginModule
bitfield_t *dependencies; /* Cartographie des dépendances*/
+};
+
+
+/* Greffon pour Chrysalide (classe) */
+struct _GPluginModuleClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
pg_management_fc init; /* Procédure d'initialisation */
pg_management_fc exit; /* Procédure d'extinction */
@@ -104,14 +112,6 @@ struct _GPluginModule
};
-/* Greffon pour Chrysalide (classe) */
-struct _GPluginModuleClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
/* Présente dans le journal un message simple. */
void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index a9bd9da..ff3db31 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -35,6 +35,7 @@
#include <string.h>
+#include "dt.h"
#include "pglist.h"
#include "plugin-int.h"
@@ -52,6 +53,10 @@ static void g_plugin_module_dispose(GPluginModule *);
/* Procède à la libération totale de la mémoire. */
static void g_plugin_module_finalize(GPluginModule *);
+/* Initialise la classe des greffons d'extension. */
+static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *);
+
+
/* Indique le type défini pour un greffon. */
G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
@@ -117,6 +122,7 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
+ GPluginModuleClass *class; /* Classe de l'instance active */
pg_iface = g_plugin_module_get_interface(plugin);
@@ -145,11 +151,16 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
}
- if (plugin->exit != NULL)
- plugin->exit(plugin);
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ if (class->exit != NULL)
+ class->exit(plugin);
if (plugin->module != NULL)
+ {
g_module_close(plugin->module);
+ plugin->module = NULL;
+ }
G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin));
@@ -195,25 +206,26 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
GPluginModule *g_plugin_module_new(const gchar *filename)
{
GPluginModule *result; /* Structure à retourner */
+ GModule *module; /* Abstration de manipulation */
+ const plugin_interface *interface; /* Déclaration d'interfaçage */
plugin_abi_version_t current; /* Version de l'ABI actuelle */
+ bool valid; /* Statut de validité */
size_t i; /* Boucle de parcours */
uint32_t action; /* Identifiant d'une action */
uint32_t category; /* Catégorie principale */
uint32_t sub; /* Sous-catégorie visée */
+ GType gtype; /* Nouveau type de greffon */
- result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL);
-
- result->filename = strdup(filename);
-
- result->module = g_module_open(filename, G_MODULE_BIND_LAZY);
- if (result->module == NULL)
+ module = g_module_open(filename, G_MODULE_BIND_LAZY);
+ if (module == NULL)
{
log_variadic_message(LMT_ERROR,
_("Error while loading the plugin candidate '%s' : %s"),
filename, g_module_error());
- goto bad_plugin;
+ goto bad_module;
}
+
#define load_plugin_symbol(mod, sym, dest) \
({ \
bool __result; \
@@ -221,7 +233,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
{ \
log_variadic_message(LMT_ERROR, \
_("No '%s' entry in plugin candidate '%s'"), \
- sym, result->filename); \
+ sym, filename); \
__result = false; \
} \
else __result = true; \
@@ -231,12 +243,12 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
/* Récupération de la version d'ABI */
- if (!load_plugin_symbol(result->module, "_chrysalide_plugin", &result->interface))
+ if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface))
goto bad_plugin;
current = CURRENT_ABI_VERSION;
- if (current != result->interface->abi_version)
+ if (current != interface->abi_version)
{
log_variadic_message(LMT_ERROR,
_("ABI mismatch detected! Plugin '%s' rejected"),
@@ -247,9 +259,20 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
/* Localisation des différents points d'entrée déclarés */
- for (i = 0; i < result->interface->actions_count; i++)
+
+#define check_plugin_symbol(mod, sym) \
+ ({ \
+ bool __result; \
+ __result = g_module_symbol(mod, sym, (gpointer []) { 0 }); \
+ __result; \
+ })
+
+
+ valid = true;
+
+ for (i = 0; i < interface->actions_count && valid; i++)
{
- action = result->interface->actions[i];
+ action = interface->actions[i];
category = MASK_PLUGIN_CATEGORY(action);
sub = MASK_PLUGIN_SUB_CATEGORY(action);
@@ -267,21 +290,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
switch (action)
{
case PGA_PLUGIN_INIT:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_init", &result->init))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_init");
break;
case PGA_PLUGIN_EXIT:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_exit", &result->exit))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_exit");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- result->interface->actions[i], filename);
+ interface->actions[i], filename);
break;
}
@@ -293,16 +312,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
switch (action)
{
case PGA_NATIVE_LOADED:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_on_native_loaded",
- &result->native_loaded))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_on_native_loaded");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- result->interface->actions[i], filename);
+ interface->actions[i], filename);
break;
}
@@ -327,15 +343,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
switch (action)
{
case PGA_GUI_THEME:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_include_theme", &result->include_theme))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- result->interface->actions[i], filename);
+ interface->actions[i], filename);
break;
}
@@ -361,23 +375,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
{
case PGA_CONTENT_EXPLORER:
case PGA_CONTENT_RESOLVER:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_handle_binary_content",
- &result->handle_content))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content");
break;
case PGA_CONTENT_ANALYZED:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_handle_loaded_content",
- &result->handle_loaded))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- result->interface->actions[i], filename);
+ interface->actions[i], filename);
break;
}
@@ -392,28 +400,21 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
case PGA_FORMAT_ANALYSIS_ENDED:
case PGA_FORMAT_POST_ANALYSIS_STARTED:
case PGA_FORMAT_POST_ANALYSIS_ENDED:
- if (!load_plugin_symbol(result->module,
- "handle_binary_format_analysis",
- &result->handle_fmt_analysis))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "handle_binary_format_analysis");
break;
case PGA_FORMAT_PRELOAD:
- if (!load_plugin_symbol(result->module,
- "preload_binary_format", &result->preload_format))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "preload_binary_format");
break;
case PGA_FORMAT_ATTACH_DEBUG:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_attach_debug", &result->attach_debug))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug");
break;
default:
log_variadic_message(LMT_WARNING,
_("Unknown action '0x%02x' in plugin '%s'..."),
- result->interface->actions[i], filename);
+ interface->actions[i], filename);
break;
}
@@ -421,15 +422,11 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
break;
case DPS_DISASSEMBLY:
- if (!load_plugin_symbol(result->module,
- "process_binary_disassembly", &result->process_disass))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "process_binary_disassembly");
break;
case DPS_DETECTION:
- if (!load_plugin_symbol(result->module,
- "chrysalide_plugin_detect_external_tools", &result->detect))
- goto bad_plugin;
+ valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools");
break;
default:
@@ -450,11 +447,29 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
}
+ if (!valid)
+ goto bad_plugin;
+
+ gtype = built_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name,
+ (GClassInitFunc)g_plugin_module_init_gclass, module);
+
+ if (gtype == G_TYPE_INVALID)
+ goto bad_plugin;
+
+ result = g_object_new(gtype, NULL);
+
+ result->filename = strdup(filename);
+ result->module = module;
+
+ result->interface = interface;
+
return result;
bad_plugin:
- g_object_unref(G_OBJECT(result));
+ g_module_close(module);
+
+ bad_module:
return NULL;
@@ -463,6 +478,212 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
/******************************************************************************
* *
+* Paramètres : class = classe à initialiser. *
+* module = module représentant le greffon chargé en mémoire. *
+* *
+* Description : Initialise la classe des greffons d'extension. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module)
+{
+ const plugin_interface *interface; /* Déclaration d'interfaçage */
+ size_t i; /* Boucle de parcours */
+ uint32_t action; /* Identifiant d'une action */
+ uint32_t category; /* Catégorie principale */
+ uint32_t sub; /* Sous-catégorie visée */
+
+
+#undef load_plugin_symbol
+
+#define load_plugin_symbol(mod, sym, dest) \
+ ({ \
+ bool __result; \
+ __result = g_module_symbol(mod, sym, (gpointer *)dest); \
+ assert(__result); \
+ __result; \
+ })
+
+
+ load_plugin_symbol(module, "_chrysalide_plugin", &interface);
+
+ for (i = 0; i < interface->actions_count; i++)
+ {
+ action = interface->actions[i];
+ category = MASK_PLUGIN_CATEGORY(action);
+ sub = MASK_PLUGIN_SUB_CATEGORY(action);
+
+ switch (category)
+ {
+ case DPC_BASIC:
+
+ switch (sub)
+ {
+ case DPS_NONE:
+ break;
+
+ case DPS_PG_MANAGEMENT:
+
+ switch (action)
+ {
+ case PGA_PLUGIN_INIT:
+ load_plugin_symbol(module, "chrysalide_plugin_init", &class->init);
+ break;
+
+ case PGA_PLUGIN_EXIT:
+ load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ case DPS_CORE_MANAGEMENT:
+
+ switch (action)
+ {
+ case PGA_NATIVE_LOADED:
+ load_plugin_symbol(module, "chrysalide_plugin_on_native_loaded",
+ &class->native_loaded);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ case DPC_GUI:
+
+ switch (sub)
+ {
+ case DPS_SETUP:
+
+ switch (action)
+ {
+ case PGA_GUI_THEME:
+ load_plugin_symbol(module, "chrysalide_plugin_include_theme",
+ &class->include_theme);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ case DPC_BINARY_PROCESSING:
+
+ switch (sub)
+ {
+ case DPS_CONTENT:
+
+ switch (action)
+ {
+ case PGA_CONTENT_EXPLORER:
+ case PGA_CONTENT_RESOLVER:
+ load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content",
+ &class->handle_content);
+ break;
+
+ case PGA_CONTENT_ANALYZED:
+ load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content",
+ &class->handle_loaded);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ case DPS_FORMAT:
+
+ switch (action)
+ {
+ case PGA_FORMAT_ANALYSIS_STARTED:
+ case PGA_FORMAT_ANALYSIS_ENDED:
+ case PGA_FORMAT_POST_ANALYSIS_STARTED:
+ case PGA_FORMAT_POST_ANALYSIS_ENDED:
+ load_plugin_symbol(module, "handle_binary_format_analysis",
+ &class->handle_fmt_analysis);
+ break;
+
+ case PGA_FORMAT_PRELOAD:
+ load_plugin_symbol(module, "preload_binary_format", &class->preload_format);
+ break;
+
+ case PGA_FORMAT_ATTACH_DEBUG:
+ load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ case DPS_DISASSEMBLY:
+ load_plugin_symbol(module, "process_binary_disassembly", &class->process_disass);
+ break;
+
+ case DPS_DETECTION:
+ load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect);
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : plugin = greffon à consulter. *
* *
* Description : Indique le fichier contenant le greffon manipulé. *
@@ -654,6 +875,7 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
+ GPluginModuleClass *class; /* Classe de l'instance active */
char *dir; /* Répertoire modifiable */
/* Si un essai précédent a déjà échoué ou réussi... */
@@ -689,9 +911,11 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
if (result)
{
- if (plugin->init != NULL)
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ if (class->init != NULL)
{
- result = plugin->init(plugin);
+ result = class->init(plugin);
if (!result)
{
@@ -810,7 +1034,11 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction action, void *unused)
{
- plugin->native_loaded(plugin, action);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->native_loaded(plugin, action);
}
@@ -832,7 +1060,11 @@ void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction ac
void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count)
{
- plugin->include_theme(plugin, action, resources, count);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->include_theme(plugin, action, resources, count);
}
@@ -855,7 +1087,11 @@ void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction act
void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
{
- return plugin->handle_content(plugin, action, content, wid, status);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->handle_content(plugin, action, content, wid, status);
}
@@ -878,7 +1114,11 @@ void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAc
void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status)
{
- return plugin->handle_loaded(plugin, action, content, wid, status);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ return class->handle_loaded(plugin, action, content, wid, status);
}
@@ -901,7 +1141,11 @@ void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAc
bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
{
- return plugin->handle_fmt_analysis(plugin, action, format, gid, status);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ return class->handle_fmt_analysis(plugin, action, format, gid, status);
}
@@ -924,7 +1168,11 @@ bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin,
bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
{
- return plugin->preload_format(plugin, action, format, info, status);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ return class->preload_format(plugin, action, format, info, status);
}
@@ -945,7 +1193,11 @@ bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAc
void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginAction action, GExeFormat *format)
{
- plugin->attach_debug(plugin, action, format);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->attach_debug(plugin, action, format);
}
@@ -968,7 +1220,11 @@ void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginActi
void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
{
- plugin->process_disass(plugin, action, binary, status, context);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->process_disass(plugin, action, binary, status, context);
}
@@ -992,6 +1248,10 @@ void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, Plug
void g_plugin_module_detect_external_tools(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count)
{
- plugin->detect(plugin, action, content, version, names, count);
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ class->detect(plugin, action, content, version, names, count);
}
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 4b3b306..cccd39b 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -59,12 +59,12 @@ typedef enum _PluginStatusFlags
#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
-#define G_TYPE_PLUGIN_MODULE (g_plugin_module_get_type())
-#define G_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule))
-#define G_IS_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE))
-#define G_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
-#define G_IS_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE))
-#define G_PLUGIN_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
+#define G_TYPE_PLUGIN_MODULE (g_plugin_module_get_type())
+#define G_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule))
+#define G_IS_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE))
+#define G_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
+#define G_IS_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE))
+#define G_PLUGIN_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
/* Indique le type défini pour un greffon. */
diff --git a/tests/plugins/__init__.py b/tests/plugins/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/plugins/__init__.py
diff --git a/tests/plugins/plugin.py b/tests/plugins/plugin.py
new file mode 100644
index 0000000..6409975
--- /dev/null
+++ b/tests/plugins/plugin.py
@@ -0,0 +1,223 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide import PluginModule
+import gc
+
+
+class TestPlugin(ChrysalideTestCase):
+ """TestCase for GPluginModule."""
+
+
+ def testGarbageCollecting(self):
+ """Ensure the garbarge collector is working for plugin modules."""
+
+
+ class MyPG_1(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_1, self).__init__(**interface)
+
+
+ pg = MyPG_1()
+ self.assertIsNotNone(pg)
+
+
+ class MyPG_2(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_2, self).__init__(**interface)
+
+
+ pg = MyPG_2()
+ self.assertIsNotNone(pg)
+
+
+ class MyPG_3(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_3, self).__init__(**interface)
+
+
+ pg = MyPG_3()
+ self.assertIsNotNone(pg)
+
+
+ class MyPG_4(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_4, self).__init__(**interface)
+
+
+ pg = MyPG_4()
+ self.assertIsNotNone(pg)
+
+
+ class MyPG_5(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_5, self).__init__(**interface)
+
+
+ pg = MyPG_5()
+ self.assertIsNotNone(pg)
+
+
+ gc.collect()
+
+
+ def testCreation(self):
+ """Validate PluginModule creation from Python."""
+
+
+ class MyPG_0(PluginModule):
+ pass
+
+
+ # TypeError: Required argument 'name' (pos 1) not found
+ with self.assertRaises(TypeError):
+ pg = MyPG_0()
+
+
+ class MyPG_1(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG_1, self).__init__(**interface)
+
+
+ pg = MyPG_1()
+ self.assertIsNotNone(pg)
+
+
+ class MyPG_2(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( 'ABC', )
+ }
+
+ super(MyPG_2, self).__init__(**interface)
+
+
+ # TypeError: Invalid type for plugin action.
+ with self.assertRaises(TypeError):
+ pg = MyPG_2()
+
+
+ class MyPG_3(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, )
+ }
+
+ super(MyPG_3, self).__init__(**interface)
+
+
+ # TypeError: missing features for the declared actions.
+ with self.assertRaises(TypeError):
+ pg = MyPG_3()
+
+
+ class MyPG_4(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name4',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, )
+ }
+
+ super(MyPG_4, self).__init__(**interface)
+
+ def handle_binary_content(self, action, content, wid, status):
+ pass
+
+
+ pg = MyPG_4()
+ self.assertIsNotNone(pg)
+
+
+ def testDoubleUsage(self):
+ """Validate PluginModule double usage in Python."""
+
+
+ class MyPG(PluginModule):
+
+ def __init__(self):
+
+ interface = {
+ 'name' : 'some_name',
+ 'desc' : 'Provide some information about the useless plugin',
+ 'version' : '0.1',
+ 'actions' : ( )
+ }
+
+ super(MyPG, self).__init__(**interface)
+
+
+ pg1 = MyPG()
+ self.assertIsNotNone(pg1)
+
+ pg2 = MyPG()
+ self.assertIsNotNone(pg2)