From 4b1367d2fee7be0789744e1db35d6f9200b29163 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 27 Dec 2018 21:44:31 +0100 Subject: Updated the API in order to allow Python plugins to rely on native plugins. --- plugins/pychrysalide/plugin.c | 180 ++++++++++++++++++++++++++++++++++++++-- plugins/pychrysalide/pychrysa.c | 42 +++++++--- plugins/pychrysalide/pychrysa.h | 3 + src/plugins/pglist.c | 2 + src/plugins/pglist.h | 8 +- src/plugins/plugin-def.h | 12 ++- src/plugins/plugin-int.h | 5 ++ src/plugins/plugin.c | 42 ++++++++++ src/plugins/plugin.h | 3 + 9 files changed, 272 insertions(+), 25 deletions(-) diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index 44f518e..f232548 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -87,6 +87,15 @@ 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 *); @@ -327,14 +336,14 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) /* Localisation des différents points d'entrée déclarés */ -#define register_python_binding(inst, sym, binding) \ +#define register_python_binding(inst, pysym, sym, binding) \ ({ \ bool __result; \ - if (!has_python_method(inst, #sym)) \ + if (!has_python_method(inst, #pysym)) \ { \ log_variadic_message(LMT_ERROR, \ _("No '%s' entry in plugin candidate '%s'"), \ - #sym, G_PLUGIN_MODULE(result)->filename); \ + #pysym, G_PLUGIN_MODULE(result)->filename); \ __result = false; \ } \ else \ @@ -361,12 +370,14 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) break; case PGA_PLUGIN_INIT: - if (!register_python_binding(instance, init, (pg_management_fc)g_python_plugin_do_init)) + if (!register_python_binding(instance, init, init, + (pg_management_fc)g_python_plugin_do_init)) goto gppn_bad_plugin; break; case PGA_PLUGIN_EXIT: - if (!register_python_binding(instance, exit, (pg_management_fc)g_python_plugin_do_exit)) + if (!register_python_binding(instance, exit, exit, + (pg_management_fc)g_python_plugin_do_exit)) goto gppn_bad_plugin; break; @@ -389,7 +400,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) { case PGA_CONTENT_EXPLORER: case PGA_CONTENT_RESOLVER: - if (!register_python_binding(instance, handle_content, \ + if (!register_python_binding(instance, handle_content, handle_content, (pg_handle_content_fc)g_python_plugin_handle_binary_content)) goto gppn_bad_plugin; break; @@ -408,6 +419,27 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) switch (action) { + case PGA_FORMAT_ANALYSIS_STARTED: + 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; + 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; + 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; + break; + default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), @@ -419,7 +451,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) break; case DPS_DISASSEMBLY: - if (!register_python_binding(instance, process_disass, + if (!register_python_binding(instance, process_disassembly, process_disass, (pg_process_disassembly_fc)g_python_plugin_process_disass)) goto gppn_bad_plugin; break; @@ -668,9 +700,9 @@ 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) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *args; /* Arguments pour l'appel */ PyObject *value; /* Valeurs obtenues */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ gstate = PyGILState_Ensure(); @@ -693,6 +725,129 @@ static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, P /****************************************************************************** * * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* format = format de binaire à manipuler pendant l'opération. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * +* * +* Description : Procède à une opération liée à l'analyse d'un format. * +* * +* Retour : Bilan de l'exécution du traitement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *value; /* Valeurs obtenues */ + + gstate = PyGILState_Ensure(); + + args = PyTuple_New(4); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); + 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); + + Py_XDECREF(value); + Py_DECREF(args); + + PyGILState_Release(gstate); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* format = format de binaire à manipuler pendant l'opération. * +* info = informations à constituer en avance de phase. * +* status = barre de statut à tenir informée. * +* * +* Description : Procède à un préchargement de format de fichier. * +* * +* Retour : Bilan de l'exécution du traitement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *value; /* Valeurs obtenues */ + + gstate = PyGILState_Ensure(); + + args = PyTuple_New(4); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); + 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); + + Py_XDECREF(value); + Py_DECREF(args); + + PyGILState_Release(gstate); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* format = format de binaire à manipuler pendant l'opération. * +* * +* Description : Procède au rattachement d'éventuelles infos de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_python_plugin_attach_debug_format(const GPythonPlugin *plugin, PluginAction action, GExeFormat *format) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *value; /* Valeurs obtenues */ + + gstate = PyGILState_Ensure(); + + 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); + + Py_XDECREF(value); + Py_DECREF(args); + + PyGILState_Release(gstate); + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * * binary = binaire dont le contenu est en cours de traitement.* @@ -709,9 +864,12 @@ static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, P static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *args; /* Arguments pour l'appel */ PyObject *value; /* Valeurs obtenues */ + gstate = PyGILState_Ensure(); + args = PyTuple_New(4); PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); @@ -719,11 +877,13 @@ 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_binary_disassembly", args); + value = run_python_method(plugin->instance, "process_disassembly", args); Py_XDECREF(value); Py_DECREF(args); + PyGILState_Release(gstate); + } @@ -756,6 +916,8 @@ static bool py_plugin_module_define_constants(PyTypeObject *obj_type) result &= PyDict_AddULongMacro(obj_type, PGA_PLUGIN_INIT); result &= PyDict_AddULongMacro(obj_type, PGA_PLUGIN_EXIT); + result &= PyDict_AddULongMacro(obj_type, PGA_NATIVE_LOADED); + result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_EXPLORER); result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_RESOLVER); result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_ANALYZED); diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c index 7772592..ff36dab 100644 --- a/plugins/pychrysalide/pychrysa.c +++ b/plugins/pychrysalide/pychrysa.c @@ -64,7 +64,7 @@ DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0", - EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT)); + EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT, PGA_NATIVE_LOADED)); /* Note la nature du chargement */ @@ -93,7 +93,7 @@ static bool is_current_abi_suitable(void); static bool set_version_for_gtk_namespace(const char *); /* Charge autant de greffons composés en Python que possible. */ -static bool load_python_plugins(GPluginModule *); +static void load_python_plugins(GPluginModule *); @@ -452,13 +452,13 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) * * * Description : Charge autant de greffons composés en Python que possible. * * * -* Retour : true. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool load_python_plugins(GPluginModule *plugin) +static void load_python_plugins(GPluginModule *plugin) { char *paths; /* Emplacements de greffons */ char *save; /* Sauvegarde pour ré-entrance */ @@ -545,8 +545,6 @@ static bool load_python_plugins(GPluginModule *plugin) } - return true; - } @@ -618,11 +616,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) * En mode autonome, le shell Python remonte bien l'erreur par contre. */ - if (_chrysalide_module == NULL) - result = false; - - else - result = load_python_plugins(plugin); + result = (_chrysalide_module != NULL); _main_tstate = PyThreadState_Get(); @@ -656,6 +650,32 @@ G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin) /****************************************************************************** * * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* * +* Description : Accompagne la fin du chargement des modules natifs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +G_MODULE_EXPORT void chrysalide_plugin_on_native_loaded(GPluginModule *plugin, PluginAction action) +{ + if (!_standalone) + PyEval_AcquireLock(); + + load_python_plugins(plugin); + + if (!_standalone) + PyEval_ReleaseLock(); + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit les informations du thread principal. * diff --git a/plugins/pychrysalide/pychrysa.h b/plugins/pychrysalide/pychrysa.h index da9913b..0f844e6 100644 --- a/plugins/pychrysalide/pychrysa.h +++ b/plugins/pychrysalide/pychrysa.h @@ -48,6 +48,9 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); /* Prend acte du déchargement du greffon. */ G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *); +/* Accompagne la fin du chargement des modules natifs. */ +G_MODULE_EXPORT void chrysalide_plugin_on_native_loaded(GPluginModule *, PluginAction); + /* Fournit les informations du thread principal. */ PyThreadState *get_pychrysalide_main_tstate(void); diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index 57f7538..b7c8d1d 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -459,6 +459,8 @@ void load_remaning_plugins(void) g_rw_lock_reader_unlock(&_pg_lock); + notify_native_loaded; + } diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 0c8f6af..1306571 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -85,6 +85,11 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); while (0) +/* DPS_PG_MANAGEMENT */ + +#define notify_native_loaded \ + process_all_plugins_for(PGA_NATIVE_LOADED, g_plugin_module_notify_native_loaded, NULL) + /* DPS_SETUP */ #define include_plugin_theme(r, c) \ @@ -103,9 +108,6 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); #define handle_binary_format_analysis(a, f, g, s) \ process_all_plugins_for(a, g_plugin_module_handle_binary_format_analysis, f, g, s) -#define handle_binary_format(a, f, s) \ - process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s) - #define preload_binary_format(a, f, i, s) \ process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s) diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 96b04b1..4c59606 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -76,6 +76,7 @@ typedef uint32_t plugin_action_t; #define DPS_NONE DEFINE_PLUGIN_SUB_CATEGORY(0) #define DPS_PG_MANAGEMENT DEFINE_PLUGIN_SUB_CATEGORY(1) +#define DPS_CORE_MANAGEMENT DEFINE_PLUGIN_SUB_CATEGORY(2) /* DPC_GUI */ @@ -111,10 +112,17 @@ typedef enum _PluginAction */ /* Chargement */ - PGA_PLUGIN_INIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(0), + PGA_PLUGIN_INIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(0), /* Déchargement */ - PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), + PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), + + /** + * DPC_BASIC | DPS_CORE_MANAGEMENT + */ + + /* Fin du chargement des greffons natifs */ + PGA_NATIVE_LOADED = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(0), /** * DPC_GUI | DPS_SETUP diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 8df3527..2d98217 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -41,6 +41,9 @@ /* Prend acte du [dé]chargement du greffon. */ typedef bool (* pg_management_fc) (GPluginModule *); +/* Accompagne la fin du chargement des modules natifs. */ +typedef void (* pg_native_loaded_fc) (GPluginModule *, PluginAction); + /* Procède à une opération liée à un contenu binaire. */ typedef void (* pg_handle_content_fc) (const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *); @@ -83,6 +86,8 @@ struct _GPluginModule pg_management_fc init; /* Procédure d'initialisation */ pg_management_fc exit; /* Procédure d'extinction */ + pg_native_loaded_fc native_loaded; /* Fin des chargements natifs */ + pg_include_theme_fc include_theme; /* Extension d'un thème */ pg_handle_content_fc handle_content; /* Explorations ou résolutions */ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 1608032..a9bd9da 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -288,6 +288,27 @@ GPluginModule *g_plugin_module_new(const gchar *filename) break; + case DPS_CORE_MANAGEMENT: + + switch (action) + { + case PGA_NATIVE_LOADED: + if (!load_plugin_symbol(result->module, + "chrysalide_plugin_on_native_loaded", + &result->native_loaded)) + goto bad_plugin; + break; + + default: + log_variadic_message(LMT_WARNING, + _("Unknown action '0x%02x' in plugin '%s'..."), + result->interface->actions[i], filename); + break; + + } + + break; + default: log_variadic_message(LMT_WARNING, _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); @@ -775,6 +796,27 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag /****************************************************************************** * * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* unused = variable non utilisé pour l'usage de __VA_ARGS__. * +* * +* Description : Accompagne la fin du chargement des modules natifs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction action, void *unused) +{ + plugin->native_loaded(plugin, action); + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * * resources = liste de ressources à constituer. [OUT] * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index 86dba25..4b3b306 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -91,6 +91,9 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *, GPluginModule **, siz /* Termine le chargement du greffon préparé. */ bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t); +/* Accompagne la fin du chargement des modules natifs. */ +void g_plugin_module_notify_native_loaded(GPluginModule *, PluginAction, void *); + /* Complète une liste de resources pour thème. */ void g_plugin_module_include_theme(const GPluginModule *, PluginAction, char ***, size_t *); -- cgit v0.11.2-87-g4458