diff options
Diffstat (limited to 'plugins/pychrysa')
| -rw-r--r-- | plugins/pychrysa/analysis/Makefile.am | 3 | ||||
| -rw-r--r-- | plugins/pychrysa/analysis/binary.c | 211 | ||||
| -rw-r--r-- | plugins/pychrysa/analysis/binary.h | 8 | ||||
| -rw-r--r-- | plugins/pychrysa/analysis/module.c | 18 | ||||
| -rw-r--r-- | plugins/pychrysa/debug/debugger.c | 11 | ||||
| -rw-r--r-- | plugins/pychrysa/plugin.c | 43 | ||||
| -rw-r--r-- | plugins/pychrysa/pychrysa.c | 47 | ||||
| -rw-r--r-- | plugins/pychrysa/pychrysa.h | 5 | 
8 files changed, 140 insertions, 206 deletions
diff --git a/plugins/pychrysa/analysis/Makefile.am b/plugins/pychrysa/analysis/Makefile.am index b18d16d..123279b 100644 --- a/plugins/pychrysa/analysis/Makefile.am +++ b/plugins/pychrysa/analysis/Makefile.am @@ -13,7 +13,8 @@ libpychrysaanalysis_la_SOURCES =		\  libpychrysaanalysis_la_LDFLAGS =  -INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) -I../../../src +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I../../../src  AM_CPPFLAGS =  diff --git a/plugins/pychrysa/analysis/binary.c b/plugins/pychrysa/analysis/binary.c index d378496..4cfb615 100644 --- a/plugins/pychrysa/analysis/binary.c +++ b/plugins/pychrysa/analysis/binary.c @@ -25,41 +25,18 @@  #include "binary.h" -#include "line.h" -#include "../format/executable.h" +#include <pygobject.h> - - -/* Classe 'analysis.binary' pour Python */ -typedef struct _py_binary -{ -    PyObject_HEAD - -    GOpenidaBinary *binary;                 /* Référence GLib              */ - -} py_binary; - - - - -/* Crée un nouvel objet Python de type 'py_binary'. */ -static PyObject *py_binary_new(PyTypeObject *, PyObject *, PyObject *); - +#include "../quirks.h" -/* Fournit le format de fichier reconnu dans le contenu binaire. */ -static PyObject *py_binary_get_format(py_binary *); - -/* Fournit les lignes de rendu associé pour Python. */ -static PyObject *py_binary_get_lines(py_binary *); - - - -/* Fournit le type d'objet 'analysis.binary' pour Python. */ -static PyTypeObject *get_analysis_binary_type(void); +/* Crée un nouvel objet Python de type 'LoadedBinary'. */ +static PyObject *py_loaded_binary_new(PyTypeObject *, PyObject *, PyObject *); +/* Fournit le fichier correspondant à l'élément binaire. */ +static PyObject *py_loaded_binary_get_filename(PyObject *self, PyObject *args); @@ -69,19 +46,28 @@ static PyTypeObject *get_analysis_binary_type(void);  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'py_binary'.             * +*  Description : Crée un nouvel objet Python de type 'LoadedBinary'.          *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Instance Python mise en place.                               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *py_loaded_binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds)  { -    py_binary *result;                      /* Instance à retourner        */ +    PyObject *result;                       /* Instance à retourner        */ +    char *filename;                         /* Nom du fichier à charger    */ +    int ret;                                /* Bilan de lecture des args.  */ +    GOpenidaBinary *binary;                 /* Version GLib du format      */ -    result = (py_binary *)type->tp_alloc(type, 0); +    ret = PyArg_ParseTuple(args, "s", &filename); +    if (!ret) return Py_None; + +    binary = g_openida_binary_new_from_file(filename); + +    result = py_loaded_binary_from_c(binary); +    g_object_unref(binary);      return (PyObject *)result; @@ -90,38 +76,28 @@ static PyObject *py_binary_new(PyTypeObject *type, PyObject *args, PyObject *kwd  /******************************************************************************  *                                                                             * -*  Paramètres  : binary = objet GLib existant à transposer.                   * +*  Paramètres  : binary = instance existante GLib.                            *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'py_binary'.             * +*  Description : Crée un nouvel objet Python de type 'LoadedBinary'.          *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Instance Python mise en place.                               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -PyObject *py_binary_new_from_existing(GOpenidaBinary *binary) +PyObject *py_loaded_binary_from_c(GOpenidaBinary *binary)  { -    py_binary *result;                      /* Instance à retourner        */ -    PyTypeObject *type;                     /* Type Python à instancier    */ - -    result = (py_binary *)g_object_get_data(G_OBJECT(binary), "python_object"); - -    if (result == NULL) -    { -        type = get_analysis_binary_type(); +    PyObject *module;                       /* Module d'appartenance       */ +    PyTypeObject *type;                     /* Type Python correspondant   */ -        result = (py_binary *)type->tp_alloc(type, 0); +    module = PyImport_ImportModule("pychrysalide.analysis"); +    type = (PyTypeObject*)PyObject_GetAttrString(module, "LoadedBinary"); +    Py_DECREF(module); -        result->binary = binary; -        g_object_ref(binary); +    pychrysalide_set_instance_data(G_OBJECT(binary), type); -        g_object_set_data(G_OBJECT(binary), "python_object", result); - -    } -    else Py_INCREF((PyObject *)result); - -    return (PyObject *)result; +    return pygobject_new(G_OBJECT(binary));  } @@ -129,52 +105,32 @@ PyObject *py_binary_new_from_existing(GOpenidaBinary *binary) -/****************************************************************************** -*                                                                             * -*  Paramètres  : self = instance manipulée à traiter.                         * -*                                                                             * -*  Description : Fournit le format de fichier reconnu dans le contenu binaire.* -*                                                                             * -*  Retour      : Nouvelle instance d'objet Python ou NULL en cas d'échec.     * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static PyObject *py_binary_get_format(py_binary *self) -{ -    PyObject *result;                       /* Liste à retourner           */ -    GExeFormat *format;                     /* Format récupéré à convertir */ - -    format = g_openida_binary_get_format(self->binary); - -    result = py_executable_convert(format); - -    return result; - -}  /******************************************************************************  *                                                                             * -*  Paramètres  : self = instance manipulée à traiter.                         * +*  Paramètres  : self = classe représentant un débogueur.                     * +*                args = arguments fournis à l'appel.                          *  *                                                                             * -*  Description : Fournit les lignes de rendu associé pour Python.             * +*  Description : Fournit le fichier correspondant à l'élément binaire.        *  *                                                                             * -*  Retour      : Nouvelle instance d'objet Python ou NULL en cas d'échec.     * +*  Retour      : Nom de fichier avec chemin absolu.                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_binary_get_lines(py_binary *self) +static PyObject *py_loaded_binary_get_filename(PyObject *self, PyObject *args)  { -    PyObject *result;                       /* Liste à retourner           */ -    GRenderingLine *lines;                  /* Liste récupérée à convertir */ +    PyObject *result;                       /* Trouvailles à retourner     */ +    GOpenidaBinary *binary;                 /* Version native              */ +    const char *filename;                   /* Fichier associé au binaire  */ + +    binary = G_OPENIDA_BINARY(pygobject_get(self)); -    lines = g_openida_binary_get_lines(self->binary); +    filename = g_openida_binary_get_filename(binary); -    result = py_line_new_from_existing(lines); +    result = PyString_FromString(filename);      return result; @@ -183,96 +139,59 @@ static PyObject *py_binary_get_lines(py_binary *self) - - - - - - - -  /******************************************************************************  *                                                                             * -*  Paramètres  : -                                                            * +*  Paramètres  : module = module dont la définition est à compléter.          *  *                                                                             * -*  Description : Fournit le type d'objet 'analysis.binary' pour Python.       * +*  Description : Prend en charge l'objet 'pychrysalide.analysis.LoadedBinary'.*  *                                                                             * -*  Retour      : Adresse du type vivant à manipuler.                          * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyTypeObject *get_analysis_binary_type(void) +bool register_python_loaded_binary(PyObject *module)  { -    static PyTypeObject *result = NULL;     /* Type pour objet à retourner */ +    PyObject *pygobj_mod;                   /* Module Python-GObject       */ +    int ret;                                /* Bilan d'un appel            */ -    static PyMethodDef py_binary_methods[] = { +    static PyMethodDef py_loaded_binary_methods[] = {          { -            "get_format", (PyCFunction)py_binary_get_format, +            "get_filename", (PyCFunction)py_loaded_binary_get_filename,              METH_NOARGS, -            "Give the file format recognized in the binary content." +            "Provide the filename of the loaded binary."          }, -        { -            "get_lines", (PyCFunction)py_binary_get_lines, -            METH_NOARGS, -            "Provide the rendering lines used by the binary." -        }, -        { NULL } -    }; - -    static PyGetSetDef py_binary_getset[] = {          { NULL }      }; -    static PyTypeObject py_binary_type = { +    static PyTypeObject py_loaded_binary_type = {          PyObject_HEAD_INIT(NULL) -        .tp_name        = "pyoida.analysis.Binary", -        .tp_basicsize   = sizeof(py_binary), +        .tp_name        = "pychrysalide.analysis.LoadedBinary", +        .tp_basicsize   = sizeof(PyGObject),          .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -        .tp_doc         = "PyOIDA loaded binary to analyse", +        .tp_doc         = "PyChrysalide loaded binary", -        .tp_methods     = py_binary_methods, -        .tp_getset      = py_binary_getset, -        .tp_new         = (newfunc)py_binary_new +        .tp_methods     = py_loaded_binary_methods, +        .tp_new         = (newfunc)py_loaded_binary_new      }; -    if (result == NULL) result = &py_binary_type; - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : module = module dont la définition est à compléter.          * -*                                                                             * -*  Description : Ajoute l'objet 'analysis.binary' au module Python.           * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool add_analysis_binary_to_python_module(PyObject *module) -{ -    PyTypeObject *py_binary_type;           /* Type défini pour Python     */ -    int ret;                                /* Bilan d'un appel            */ +    pygobj_mod = PyImport_ImportModule("gobject"); +    if (pygobj_mod == NULL) return false; -    py_binary_type = get_analysis_binary_type(); +    py_loaded_binary_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); +    Py_DECREF(pygobj_mod); -    if (PyType_Ready(py_binary_type) < 0) +    if (PyType_Ready(&py_loaded_binary_type) < 0)          return false; -    Py_INCREF(py_binary_type); -    ret = PyModule_AddObject(module, "Binary", (PyObject *)py_binary_type); +    Py_INCREF(&py_loaded_binary_type); +    ret = PyModule_AddObject(module, "LoadedBinary", (PyObject *)&py_loaded_binary_type);      return (ret == 0); diff --git a/plugins/pychrysa/analysis/binary.h b/plugins/pychrysa/analysis/binary.h index 1500a06..cc96a5b 100644 --- a/plugins/pychrysa/analysis/binary.h +++ b/plugins/pychrysa/analysis/binary.h @@ -33,11 +33,11 @@ -/* Crée un nouvel objet Python de type 'py_binary'. */ -PyObject *py_binary_new_from_existing(GOpenidaBinary *); +/* Crée un nouvel objet Python de type 'LoadedBinary'. */ +PyObject *py_loaded_binary_from_c(GOpenidaBinary *); -/* Ajoute l'objet 'analysis.binary' au module Python. */ -bool add_analysis_binary_to_python_module(PyObject *); +/* Prend en charge l'objet 'pychrysalide.analysis.LoadedBinary'. */ +bool register_python_loaded_binary(PyObject *); diff --git a/plugins/pychrysa/analysis/module.c b/plugins/pychrysa/analysis/module.c index 8f07002..42b888e 100644 --- a/plugins/pychrysa/analysis/module.c +++ b/plugins/pychrysa/analysis/module.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * module.c - intégration du répertoire analysis en tant que module   * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -26,11 +26,6 @@  #include "binary.h" -#include "exporter.h" -#include "line.h" -#include "roptions.h" - - @@ -56,20 +51,15 @@ bool add_analysis_module_to_python_module(PyObject *super)          { NULL }      }; -    module = Py_InitModule("pyoida.analysis", py_analysis_methods); +    module = Py_InitModule("pychrysalide.analysis", py_analysis_methods);      if (module == NULL) return false;      Py_INCREF(module); -    ret = PyModule_AddObject(super, "pyoida.analysis", module); +    ret = PyModule_AddObject(super, "pychrysalide.analysis", module);      result = (ret != 0); -    result &= add_analysis_binary_to_python_module(module); -    result &= add_analysis_exporter_to_python_module(module); -    result &= add_analysis_line_to_python_module(module); -    result &= add_analysis_line_iter_to_python_module(module); -    result &= add_analysis_line_riter_to_python_module(module); -    result &= add_analysis_roptions_to_python_module(module); +    result &= register_python_loaded_binary(module);      return result; diff --git a/plugins/pychrysa/debug/debugger.c b/plugins/pychrysa/debug/debugger.c index 3e42ab7..c27d30d 100644 --- a/plugins/pychrysa/debug/debugger.c +++ b/plugins/pychrysa/debug/debugger.c @@ -33,6 +33,9 @@ +/* Crée un nouvel objet Python de type 'BinaryDebugger'. */ +static PyObject *py_binary_debugger_new(PyTypeObject *, PyObject *, PyObject *); +  /*  Fournit les identifiants de tous les threads actifs. */  static PyObject *py_binary_debugger_list_all_threads(PyObject *, PyObject *); @@ -48,9 +51,9 @@ static PyObject *py_binary_debugger_get_frames_stack(PyObject *, PyObject *);  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'py_rendering_options'.  * +*  Description : Crée un nouvel objet Python de type 'BinaryDebugger'.        *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Instance Python mise en place.                               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             * @@ -82,7 +85,7 @@ static PyObject *py_binary_debugger_new(PyTypeObject *type, PyObject *args, PyOb  *                                                                             *  *  Description : Crée un nouvel objet Python de type 'BinaryDebugger'.        *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Instance Python mise en place.                               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             * @@ -93,7 +96,7 @@ PyObject *py_binary_debugger_from_c(GBinaryDebugger *debugger)      PyObject *module;                       /* Module d'appartenance       */      PyTypeObject *type;                     /* Type Python correspondant   */ -    module = PyImport_ImportModule("pyoida.debug"); +    module = PyImport_ImportModule("pychrysalide.debug");      type = (PyTypeObject*)PyObject_GetAttrString(module, "BinaryDebugger");      Py_DECREF(module); diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c index b04dd09..9dc0c29 100644 --- a/plugins/pychrysa/plugin.c +++ b/plugins/pychrysa/plugin.c @@ -72,7 +72,7 @@ static PluginAction g_python_plugin_get_action(const GPythonPlugin *);  static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *, char **, bin_t **, off_t *);  /* Exécute une action définie sur un binaire chargé. */ -static bool g_python_plugin_execute(GPythonPlugin *, GOpenidaBinary *, PluginAction); +static bool g_python_plugin_execute_on_binary(GPythonPlugin *, GOpenidaBinary *, PluginAction);  /* Exécute une action relative à un débogueur. */ @@ -247,7 +247,7 @@ static void g_python_plugin_init(GPythonPlugin *plugin)      plugin_parent = G_PLUGIN_MODULE(plugin); -    plugin_parent->exec_on_bin = (execute_action_on_binary_fc)g_python_plugin_execute; +    plugin_parent->exec_on_bin = (execute_action_on_binary_fc)g_python_plugin_execute_on_binary;      plugin_parent->handle_debugger = (execute_on_debugger_fc)g_python_plugin_handle_debugger;  } @@ -331,6 +331,9 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)      result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL); +    G_PLUGIN_MODULE(result)->name = strdup(modname); +    G_PLUGIN_MODULE(result)->name = stradd(G_PLUGIN_MODULE(result)->name, ".py"); +      G_PLUGIN_MODULE(result)->get_action = g_python_plugin_get_action;      G_PLUGIN_MODULE(result)->is_matching = g_python_plugin_is_matching; @@ -494,38 +497,25 @@ static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plu  *                                                                             *  ******************************************************************************/ -static bool g_python_plugin_execute(GPythonPlugin *plugin, GOpenidaBinary *binary, PluginAction action) +static bool g_python_plugin_execute_on_binary(GPythonPlugin *plugin, GOpenidaBinary *binary, PluginAction action)  { +    bool result;                            /* Bilan à remonter            */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *arg;                          /* Un des arguments de l'appel */ -    PyObject *value;                        /* Valeur obtenue              */ - - - -    printf("I am running !!"); - -    args = PyTuple_New(1); - +    PyObject *value;                        /* Valeurs obtenues            */ -    arg = Py_BuildValue("O&", py_binary_new_from_existing, binary); -    PyTuple_SetItem(args, 0, arg); +    args = PyTuple_New(2); +    PyTuple_SetItem(args, 0, py_loaded_binary_from_c(binary)); +    PyTuple_SetItem(args, 1, PyInt_FromLong(action)); -    value = run_python_method(plugin->module, "get_instance", args); - -    if (value != NULL) -    { -        printf("Result of call: %ld\n", PyLong_AsLong(value)); -        Py_DECREF(value); -    } +    value = run_python_method(plugin->instance, "execute_on_binary", args); +    result = (value == Py_True); +    Py_XDECREF(value);      Py_DECREF(args); - - - - +    return result;  } @@ -638,6 +628,9 @@ static bool pychrysa_plugin_define_constants(PyObject *dict)      ret = PyDict_SetItemString(dict, "PGA_DISASSEMBLE", PyInt_FromLong(PGA_DISASSEMBLE));      if (ret == -1) return false; +    ret = PyDict_SetItemString(dict, "PGA_DISASS_PROCESS", PyInt_FromLong(PGA_DISASS_PROCESS)); +    if (ret == -1) return false; +      ret = PyDict_SetItemString(dict, "PGA_CODE_PROCESS", PyInt_FromLong(PGA_CODE_PROCESS));      if (ret == -1) return false; diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c index 84400a1..7bb1e00 100644 --- a/plugins/pychrysa/pychrysa.c +++ b/plugins/pychrysa/pychrysa.c @@ -26,6 +26,7 @@  #include <dirent.h>  #include <pygobject.h> +#include <string.h>  #include <config.h> @@ -62,7 +63,27 @@ static PyMethodDef SpamMethods[] = {  /******************************************************************************  *                                                                             * -*  Paramètres  : ref = espace de référencement global.                        * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Précise le nom associé au greffon.                           * +*                                                                             * +*  Retour      : Nom à libérer de la mémoire.                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *get_plugin_name(void) +{ +    return strdup("PyChrysalide"); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : plugin = instance représentant le greffon en chargement.     * +*                ref    = espace de référencement global.                     *  *                                                                             *  *  Description : Initialise le greffon permettant l'usage de Python.          *  *                                                                             * @@ -72,7 +93,7 @@ static PyMethodDef SpamMethods[] = {  *                                                                             *  ******************************************************************************/ -bool init_plugin(GObject *ref) +bool init_plugin(GPluginModule *plugin, GObject *ref)  {      char *paths;                            /* Emplacements de greffons    */      char *path;                             /* Chemin à fouiller           */ @@ -86,7 +107,7 @@ bool init_plugin(GObject *ref) -    GPluginModule *plugin; +    GPluginModule *pyplugin; @@ -133,14 +154,18 @@ bool init_plugin(GObject *ref)              filename = stradd(filename, ".");              filename = stradd(filename, "__init__"); -            plugin = g_python_plugin_new(entry.d_name, filename); +            pyplugin = g_python_plugin_new(entry.d_name, filename); -            if (plugin == NULL) -                 printf("No suitable Python plugin found in '%s'\n", filename);  /* FIXME : LOG(...) */ +            if (pyplugin == NULL) +                g_plugin_module_log_variadic_message(plugin, LMT_ERROR,  +                                                     _("No suitable Python plugin found in '%s'"), +                                                     filename);              else              { -                printf("ok pour %s\n", filename); -                add_plugin_to_main_list(plugin); +                g_plugin_module_log_variadic_message(plugin, LMT_PROCESS,  +                                                     _("Loaded Python plugin '<b>%s</b>' from the '<b>%s</b>' directory"), +                                                     g_plugin_module_get_name(G_PLUGIN_MODULE(pyplugin)), path); +                add_plugin_to_main_list(pyplugin);              }              free(filename); @@ -202,8 +227,8 @@ PyMODINIT_FUNC PyInit_pychrysa(void)  {      static struct PyModuleDef spammodule = {          PyModuleDef_HEAD_INIT, -        "pychrysa", -        "pychrysa_doc", +        "pychrysalide", +        "pychrysalide_doc",          -1,          SpamMethods      }; @@ -233,7 +258,7 @@ PyMODINIT_FUNC initpychrysa(void)      pygobject_init(-1, -1, -1);      pychrysalide_init_quirks(); -    module = Py_InitModule("pychrysa", SpamMethods); +    module = Py_InitModule("pychrysalide", SpamMethods);      //add_analysis_roptions_to_python_module(module);      add_analysis_module_to_python_module(module); diff --git a/plugins/pychrysa/pychrysa.h b/plugins/pychrysa/pychrysa.h index e4605e5..daa0ccf 100644 --- a/plugins/pychrysa/pychrysa.h +++ b/plugins/pychrysa/pychrysa.h @@ -34,8 +34,11 @@ +/* Précise le nom associé au greffon. */ +char *get_plugin_name(void); +  /* Initialise le greffon permettant l'usage de Python. */ -bool init_plugin(GObject *); +bool init_plugin(GPluginModule *, GObject *);  /* Indique les opérations offertes par un greffon donné. */  PluginAction get_plugin_action(const GPluginModule *);  | 
