summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-01-12 14:23:01 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-01-12 14:23:01 (GMT)
commitbaa854bfcc969022a00617b58a661e37f345cab5 (patch)
tree093d3ace4c2e1ad8fa37ce5e08723f768fffbada /src
parent0fdba5bd3e2c9ed913619990dbda7925867e46c5 (diff)
Rewrite the plugin system.
Diffstat (limited to 'src')
-rw-r--r--src/common/compiler.h16
-rw-r--r--src/common/cpp.h8
-rw-r--r--src/plugins/Makefile.am16
-rw-r--r--src/plugins/dt.c2
-rw-r--r--src/plugins/manager-int.h54
-rw-r--r--src/plugins/manager.c113
-rw-r--r--src/plugins/manager.h61
-rw-r--r--src/plugins/native-int.h62
-rw-r--r--src/plugins/native.c278
-rw-r--r--src/plugins/native.h39
-rw-r--r--src/plugins/pglist.c355
-rw-r--r--src/plugins/pglist.h63
-rw-r--r--src/plugins/plugin-def.h16
-rw-r--r--src/plugins/plugin-int.h88
-rw-r--r--src/plugins/plugin.c970
-rw-r--r--src/plugins/plugin.h41
-rw-r--r--src/plugins/self.h99
17 files changed, 1235 insertions, 1046 deletions
diff --git a/src/common/compiler.h b/src/common/compiler.h
index 2585e47..65df8a4 100644
--- a/src/common/compiler.h
+++ b/src/common/compiler.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* compiler.h - prototypes pour le regroupement d'astuces à destination du compilateur
*
- * Copyright (C) 2024 Cyrille Bagard
+ * Copyright (C) 2024-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,5 +34,19 @@
#define __weak __attribute__((weak))
+/**
+ * Contournement des avertissements de la forme suivante :
+ *
+ * assignment to 'const char * const*' from incompatible pointer type 'char **' [-Wincompatible-pointer-types]
+ *
+ * Références :
+ * - https://www.reddit.com/r/C_Programming/comments/qa2231/const_char_const_and_char_are_incompatible/
+ * - https://stackoverflow.com/questions/78125/why-cant-i-convert-char-to-a-const-char-const-in-c
+ * - https://c-faq.com/ansi/constmismatch.html
+ */
+
+#define CONST_ARRAY_CAST(a, tp) (const tp **)a
+
+
#endif /* _COMMON_COMPILER_H */
diff --git a/src/common/cpp.h b/src/common/cpp.h
index 39e7676..2644281 100644
--- a/src/common/cpp.h
+++ b/src/common/cpp.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* cpp.h - prototypes pour avoir à disposition un langage C plus plus mieux
*
- * Copyright (C) 2010-2020 Cyrille Bagard
+ * Copyright (C) 2010-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -31,6 +31,12 @@
/**
+ * Fournit la taille d'une chaîne statique.
+ */
+#define STATIC_STR_SIZE(s) (sizeof(s) - 1)
+
+
+/**
* Fournit la taille d'un tableau statique.
*/
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index dd191fa..555c449 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,12 +1,16 @@
noinst_LTLIBRARIES = libplugins.la
-libplugins_la_SOURCES = \
- dt.h dt.c \
- pglist.h pglist.c \
- plugin-def.h \
- plugin-int.h \
- plugin.h plugin.c \
+libplugins_la_SOURCES = \
+ dt.h dt.c \
+ manager-int.h \
+ manager.h manager.c \
+ native-int.h \
+ native.h native.c \
+ pglist.h pglist.c \
+ plugin-def.h \
+ plugin-int.h \
+ plugin.h plugin.c \
self.h
libplugins_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/plugins/dt.c b/src/plugins/dt.c
index 2899845..9de0553 100644
--- a/src/plugins/dt.c
+++ b/src/plugins/dt.c
@@ -550,7 +550,7 @@ gpointer create_object_from_type(GType type)
result = NULL;
if (g_dynamic_types_find(_chrysalide_dtypes, type) != NULL)
- result = build_type_instance(type);
+ result = NULL;//build_type_instance(type);
else
result = g_object_new(type, NULL);
diff --git a/src/plugins/manager-int.h b/src/plugins/manager-int.h
new file mode 100644
index 0000000..5ccc8f8
--- /dev/null
+++ b/src/plugins/manager-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * singleton-int.h - définitions internes propres aux interventions dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_CONTAINER_INT_H
+#define _PLUGINS_CONTAINER_INT_H
+
+
+#include "manager.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+typedef void (* handle_native_plugins_cb) (GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+typedef void (* handle_all_plugins_cb) (GPluginManager *);
+
+
+/* Instance d'objet visant à être unique (interface) */
+struct _GPluginManagerInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ handle_native_plugins_cb handle_native; /* Greffons natifs chargés */
+ handle_all_plugins_cb handle_all; /* Ensemble des greffons chargé*/
+
+};
+
+
+
+#endif /* _PLUGINS_CONTAINER_INT_H */
diff --git a/src/plugins/manager.c b/src/plugins/manager.c
new file mode 100644
index 0000000..381fbc1
--- /dev/null
+++ b/src/plugins/manager.c
@@ -0,0 +1,113 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.c - intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "manager.h"
+
+
+#include "manager-int.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Procède à l'initialisation de l'interface de gestion. */
+static void g_plugin_manager_default_init(GPluginManagerInterface *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERVENTION DANS LA GESTION DE GREFFONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */
+G_DEFINE_INTERFACE(GPluginManager, g_plugin_manager, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de gestion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plugin_manager_default_init(GPluginManagerInterface *iface)
+{
+ iface->handle_native = NULL;
+ iface->handle_all = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Accompagne la fin du chargement des modules natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_native != NULL)
+ iface->handle_native(manager);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Prend acte du chargement de l'ensemble des greffons. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_all != NULL)
+ iface->handle_all(manager);
+
+}
diff --git a/src/plugins/manager.h b/src/plugins/manager.h
new file mode 100644
index 0000000..2eb90a8
--- /dev/null
+++ b/src/plugins/manager.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour l'intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_MANAGER_H
+#define _PLUGINS_MANAGER_H
+
+
+#include "../glibext/helpers.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+#define G_TYPE_PLUGIN_MANAGER (g_plugin_manager_get_type())
+
+DECLARE_INTERFACE(GPluginManager, g_plugin_manager, G, PLUGIN_MANAGER);
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *);
+
+
+
+/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */
+
+
+#define notify_native_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_native_plugins_loaded_event)
+
+#define notify_all_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_all_plugins_loaded_event)
+
+
+
+#endif /* _PLUGINS_MANAGER_H */
diff --git a/src/plugins/native-int.h b/src/plugins/native-int.h
new file mode 100644
index 0000000..8b8e0eb
--- /dev/null
+++ b/src/plugins/native-int.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native-int.h - prototypes pour les structures internes des greffons natifs
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_NATIVE_INT_H
+#define _PLUGINS_NATIVE_INT_H
+
+
+#include "native.h"
+
+
+#include "plugin-int.h"
+
+
+
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Greffon natif pour Chrysalide (instance) */
+struct _GNativePlugin
+{
+ GPluginModule parent; /* A laisser en premier */
+
+ GModule *module; /* Abstration de manipulation */
+
+};
+
+
+/* Greffon natif pour Chrysalide (classe) */
+struct _GNativePluginClass
+{
+ GPluginModuleClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un greffon natif. */
+bool g_native_plugin_create(GNativePlugin *, const char *, const char *, const char *, const char *, const char * const *, size_t, GModule *);
+
+
+
+#endif /* _PLUGINS_NATIVE_INT_H */
diff --git a/src/plugins/native.c b/src/plugins/native.c
new file mode 100644
index 0000000..fedccbe
--- /dev/null
+++ b/src/plugins/native.c
@@ -0,0 +1,278 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.c - interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "native.h"
+
+
+#include "native-int.h"
+#include "../common/cpp.h"
+
+
+
+/* ------------------------- COMPOSITION DE NOUVEAU GREFFON ------------------------- */
+
+
+/* Initialise la classe des greffons natifs. */
+static void g_native_plugin_class_init(GNativePluginClass *);
+
+/* Initialise une instance de greffon natif. */
+static void g_native_plugin_init(GNativePlugin *);
+
+/* Supprime toutes les références externes. */
+static void g_native_plugin_dispose(GNativePlugin *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_native_plugin_finalize(GNativePlugin *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Pointe le fichier contenant le greffon manipulé. */
+static char *g_native_plugin_get_filename(const GNativePlugin *);
+
+/* Fournit le nom brut associé au greffon. */
+static char *g_native_plugin_get_modname(const GNativePlugin *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COMPOSITION DE NOUVEAU GREFFON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un greffon Python. */
+G_DEFINE_TYPE(GNativePlugin, g_native_plugin, G_TYPE_PLUGIN_MODULE);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des greffons natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_class_init(GNativePluginClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GPluginModuleClass *plugin; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_native_plugin_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_native_plugin_finalize;
+
+ plugin = G_PLUGIN_MODULE_CLASS(class);
+
+ plugin->get_filename = (get_plugin_filename_fc)g_native_plugin_get_filename;
+ plugin->get_modname = (get_plugin_modname_fc)g_native_plugin_get_modname;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser. *
+* *
+* Description : Initialise une instance de greffon natif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_init(GNativePlugin *plugin)
+{
+ plugin->module = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_dispose(GNativePlugin *plugin)
+{
+ if (plugin->module != NULL)
+ {
+ g_module_close(plugin->module);
+ plugin->module = NULL;
+ }
+
+ G_OBJECT_CLASS(g_native_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_native_plugin_finalize(GNativePlugin *plugin)
+{
+ G_OBJECT_CLASS(g_native_plugin_parent_class)->finalize(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
+* module = extension vue du système. *
+* *
+* Description : Met en place un greffon natif. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : Le transfert de propriétée du module est total. *
+* *
+******************************************************************************/
+
+bool g_native_plugin_create(GNativePlugin *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count, GModule *module)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_plugin_module_create(G_PLUGIN_MODULE(plugin), name, desc, version, url, required, count);
+
+ if (result)
+ plugin->module = module;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Pointe le fichier contenant le greffon manipulé. *
+* *
+* Retour : Chemin d'accès au greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_filename(const GNativePlugin *plugin)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+
+ result = strdup(g_module_name(plugin->module));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à valider. *
+* *
+* Description : Fournit le nom brut associé au greffon. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_modname(const GNativePlugin *plugin)
+{
+ char *result; /* Désignation brute à renvoyer*/
+ char *path; /* Chemin à traiter */
+ char *filename; /* Nom de bibliothèque partagée*/
+ size_t length; /* Taille du nom */
+ int ret; /* Bilan d'une comparaison */
+
+ path = g_native_plugin_get_filename(plugin);
+
+ filename = basename(path);
+
+ if (strncmp(filename, "lib", 3) == 0)
+ filename += 3;
+
+ length = strlen(filename);
+
+#ifdef _WIN32
+# define SHARED_SUFFIX ".dll"
+#else
+# define SHARED_SUFFIX ".so"
+#endif
+
+ if (length >= STATIC_STR_SIZE(SHARED_SUFFIX))
+ {
+ ret = strncmp(&filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)],
+ SHARED_SUFFIX,
+ STATIC_STR_SIZE(SHARED_SUFFIX));
+
+ if (ret == 0)
+ filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)] = '\0';
+
+ }
+
+ result = strdup(filename);
+
+ free(path);
+
+ return result;
+
+}
diff --git a/src/plugins/native.h b/src/plugins/native.h
new file mode 100644
index 0000000..205342c
--- /dev/null
+++ b/src/plugins/native.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.h - prototypes pour les interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_NATIVE_H
+#define _PLUGINS_NATIVE_H
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define G_TYPE_NATIVE_PLUGIN (g_native_plugin_get_type())
+
+DECLARE_GTYPE(GNativePlugin, g_native_plugin, G, NATIVE_PLUGIN);
+
+
+
+#endif /* _PLUGINS_NATIVE_H */
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index e4cb825..083f11f 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -30,20 +30,29 @@
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <i18n.h>
#include "dt.h"
+#include "manager.h"
#include "plugin-int.h"
-#include "../common/extstr.h"
+#include "../common/cpp.h"
+#include "../common/extstr.h" // REMME ?
#include "../core/logs.h"
#include "../core/nox.h"
#include "../core/paths.h"
+/**
+ * Prototype de la fonction de création, à garder synchronisé avec
+ * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h).
+ */
+typedef GPluginModule * (* get_plugin_instance_cb) (GModule *);
+
/* Liste de l'ensemble des greffons */
static GPluginModule **_pg_list = NULL;
static size_t _pg_count = 0;
@@ -129,6 +138,10 @@ bool init_all_plugins(bool load)
void exit_all_plugins(void)
{
+
+#if 0 //////
+
+
size_t i; /* Boucle de parcours */
const plugin_interface *pg_iface; /* Définition du greffon */
@@ -188,6 +201,10 @@ void exit_all_plugins(void)
exit_chrysalide_dynamic_types();
+
+
+#endif
+
}
@@ -244,83 +261,95 @@ static int filter_dirs_or_mods(const struct dirent *entry)
* *
* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Part à la recherche de greffons sous forme de modules. *
+* Description : Indique la version (NOX/UI) associée à un nom de fichier. *
* *
-* Retour : - *
+* Retour : true si la version complémentaire existe ou false. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void browse_directory_for_plugins(const char *dir)
+static bool check_for_plugin_versions(const char *dir, const char *filename, bool *is_nox, bool *is_ui)
{
- struct dirent **namelist; /* Eléments trouvés */
- int ret; /* Bilan du parcours */
- bool nox; /* Absence de support graphique*/
- char *filename; /* Elément à ausculter */
- GPluginModule *plugin; /* Greffon à intégrer ou pas */
-
- ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
- if (ret < 0)
- {
- LOG_ERROR_N("scandir");
- return;
- }
-
- nox = run_in_nox_mode();
+ bool result; /* Bilan à renvoyer */
+ size_t length; /* Taille du nom de fichier */
+ char *alt_path; /* Autre chemin complet testé */
+ int ret; /* Bilan d'une impression */
- while (ret--)
- {
-
- if (nox)
- {
#ifdef _WIN32
-# define UI_SHARED_SUFFIX "-ui.dll"
+# define SHARED_SUFFIX ".dll"
#else
-# define UI_SHARED_SUFFIX "-ui.so"
+# define SHARED_SUFFIX ".so"
#endif
+#define UI_SHARED_SUFFIX "ui" SHARED_SUFFIX
- if (strstr(namelist[ret]->d_name, UI_SHARED_SUFFIX) != NULL)
- {
- log_variadic_message(LMT_ERROR, _("Skipping unsuitable file: %s"), namelist[ret]->d_name);
- continue;
- }
+ result = false;
- }
+ /* Propriétés du fichier courant */
- filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char));
+ length = strlen(filename);
- strcpy(filename, dir);
- strcat(filename, G_DIR_SEPARATOR_S);
- strcat(filename, namelist[ret]->d_name);
+ if (length < STATIC_STR_SIZE(UI_SHARED_SUFFIX))
+ *is_ui = false;
- if (namelist[ret]->d_type == DT_DIR)
- browse_directory_for_plugins(filename);
+ else
+ *is_ui = (strcmp(filename + length - STATIC_STR_SIZE(UI_SHARED_SUFFIX), UI_SHARED_SUFFIX) == 0);
+
+ if (*is_ui)
+ *is_nox = false;
+
+ else
+ {
+ if (length < STATIC_STR_SIZE(SHARED_SUFFIX))
+ *is_nox = false;
else
- {
- plugin = g_plugin_module_new(filename);
+ *is_nox = (strcmp(filename + length - STATIC_STR_SIZE(SHARED_SUFFIX), SHARED_SUFFIX) == 0);
- if (plugin != NULL)
- register_plugin(plugin);
+ }
+
+ /* Recherche d'une version alternative */
+ if (*is_nox || *is_ui)
+ {
+
+ if (*is_nox)
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ UI_SHARED_SUFFIX);
+ else
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ SHARED_SUFFIX);
+
+ if (ret <= 0)
+ {
+ LOG_ERROR_N("asprintf");
+ goto exit;
}
- free(filename);
- free(namelist[ret]);
+ ret = access(alt_path, R_OK | X_OK);
+
+ result = (ret == 0);
+
+ free(alt_path);
}
- free(namelist);
+ exit:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à ajouter aux autres disponibles. *
+* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Ajoute un greffon à la liste principale de greffons. *
+* Description : Part à la recherche de greffons sous forme de modules. *
* *
* Retour : - *
* *
@@ -328,52 +357,117 @@ static void browse_directory_for_plugins(const char *dir)
* *
******************************************************************************/
-void _register_plugin(GPluginModule *plugin)
+static void browse_directory_for_plugins(const char *dir)
{
- size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Informations à consulter */
- const char *name; /* Désignation du greffon */
-
- /**
- * L'appel sans verrou n'est fourni que pour les greffons
- * mettant en place des greffons en interne !
- */
-
- /* Recherche d'un éventuel doublon */
+ struct dirent **namelist; /* Eléments trouvés */
+ int ret; /* Bilan d'un appel */
+ int k; /* Boucle de parcours */
+ bool nox_mode; /* Absence de support graphique*/
+ char *filename; /* Elément à ausculter */
+ bool is_nox; /* Chemin de version basique ? */
+ bool is_ui; /* Chemin de version graphique */
+ bool has_alt; /* Existence d'une alternative */
+ GModule *module; /* Abstration de manipulation */
+ get_plugin_instance_cb get_instance; /* Point d'entrée exporté */
+ GPluginModule *plugin; /* Greffon à intégrer ou pas */
- pg_iface = g_plugin_module_get_interface(plugin);
+ ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
+ if (ret < 0)
+ {
+ LOG_ERROR_N("scandir");
+ return;
+ }
- name = pg_iface->name;
+ nox_mode = run_in_nox_mode();
- for (i = 0; i < _pg_count; i++)
+ for (k = ret; k--; )
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ ret = asprintf(&filename, "%s%s%s", dir, G_DIR_SEPARATOR_S, namelist[k]->d_name);
+ if (ret <= 0)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ if (namelist[k]->d_type == DT_DIR)
+ browse_directory_for_plugins(filename);
- if (strcmp(name, pg_iface->name) == 0)
+ else
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' already registered!"), name);
- break;
+ printf("// Candidate // %s\n", filename);
- }
+ has_alt = check_for_plugin_versions(dir, namelist[k]->d_name, &is_nox, &is_ui);
- }
+ printf(" -> nox=%d ui=%d -> alt? %d\n", is_nox, is_ui, has_alt);
- /* Ajout du greffon à la liste */
- if (i == _pg_count)
- {
- _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+ if ((nox_mode && is_nox) || (!nox_mode && ((is_nox && !has_alt) || is_ui)))
+ {
+
+
+ printf(" ---> load!\n");
- _pg_list[_pg_count - 1] = plugin;
- g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, 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 next_file;
+ }
+
+
+ printf(" (main) module=%p '%s'\n", module, g_module_name(module));
+
+
+ if (!g_module_symbol(module, "get_chrysalide_plugin_instance", (gpointer *)&get_instance))
+ {
+ log_variadic_message(LMT_ERROR,
+ _("No '%s' entry in plugin candidate '%s'"),
+ "<sym>", filename);
+
+
+
+ }
+
+
+ if (get_instance == NULL)
+ plugin = NULL;
+ else
+ plugin = get_instance(module);
+
+
+
+ printf(" ===> plugin: %p\n", plugin);
+
+
+
+ if (plugin != NULL)
+ {
+ register_plugin(plugin);
+ unref_object(plugin);
+ }
+
+ else
+ g_module_close(module);
+
+ }
+ else
+ log_variadic_message(LMT_INFO, _("Skipping unsuitable file for plugin: %s"), filename);
+
+ }
+
+ next_file:
+
+ free(filename);
+ free(namelist[k]);
}
- else
- /* FIXME : leak(plugin); */;
+ free(namelist);
}
@@ -394,7 +488,7 @@ void _register_plugin(GPluginModule *plugin)
static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last)
{
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *name; /* Désignation du greffon */
size_t index; /* Indice du greffon */
GPluginModule *same; /* Juste pour la récupération */
@@ -402,16 +496,17 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
{
assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE);
- pg_iface = g_plugin_module_get_interface(plugin);
+ name = g_plugin_module_get_name(plugin);
- same = get_plugin_by_name(pg_iface->name, &index);
+ same = get_plugin_by_name(name, &index);
assert(same != NULL);
+ assert(same == plugin);
- _pg_list[index] = NULL;
+ g_clear_object(&_pg_list[index]);
- g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL);
- g_object_unref(G_OBJECT(same));
+ unref_object(same);
}
@@ -432,9 +527,40 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
void register_plugin(GPluginModule *plugin)
{
+ size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du greffon */
+ const char *existing; /* Nom d'un greffon en place */
+
g_rw_lock_writer_lock(&_pg_lock);
- _register_plugin(plugin);
+ /* Recherche d'un éventuel doublon */
+
+ name = g_plugin_module_get_name(plugin);
+
+ for (i = 0; i < _pg_count; i++)
+ {
+ existing = g_plugin_module_get_name(_pg_list[i]);
+
+ if (strcmp(name, existing) == 0)
+ {
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' already registered!"), name);
+ break;
+ }
+
+ }
+
+ /* Ajout du greffon à la liste */
+
+ if (i == _pg_count)
+ {
+ _pg_list = realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+
+ _pg_list[_pg_count - 1] = plugin;
+ ref_object(plugin);
+
+ g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ }
g_rw_lock_writer_unlock(&_pg_lock);
@@ -543,7 +669,7 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
{
GPluginModule *result; /* Greffon trouvé à renvoyer */
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *current; /* Nom du greffon courant */
result = NULL;
@@ -557,11 +683,12 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/* Si on est en train de procéder à un nettoyage... */
if (_pg_list[i] == NULL) continue;
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ current = g_plugin_module_get_name(_pg_list[i]);
- if (strcmp(pg_iface->name, name) == 0)
+ if (strcmp(current, name) == 0)
{
result = _pg_list[i];
+ ref_object(result);
if (index != NULL)
*index = i;
@@ -570,9 +697,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
}
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
return result;
}
@@ -603,60 +727,7 @@ GPluginModule **get_all_plugins(size_t *count)
for (i = 0; i < _pg_count; i++)
{
result[i] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
- }
-
- g_rw_lock_reader_unlock(&_pg_lock);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : action = fonctionnalité recherchée. *
-* count = nombre de greffons trouvés. [OUT] *
-* *
-* Description : Fournit les greffons offrant le service demandé. *
-* *
-* Retour : Liste de greffons correspondants issue d'un tri interne. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
-{
- GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours #1 */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t j; /* Boucle de parcours #2 */
-
- result = NULL;
- *count = 0;
-
- g_rw_lock_reader_lock(&_pg_lock);
-
- for (i = 0; i < _pg_count; i++)
- {
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- for (j = 0; j < pg_iface->actions_count; j++)
- {
- if (pg_iface->actions[j] == action)
- {
- result = realloc(result, ++(*count) * sizeof(GPluginModule *));
-
- result[*count - 1] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
-
- break;
-
- }
-
- }
-
+ ref_object(result[i]);
}
g_rw_lock_reader_unlock(&_pg_lock);
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 83e9091..5541493 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -52,9 +52,6 @@ void _lock_unlock_plugin_list_for_reading(bool lock);
#define unlock_plugin_list_for_reading() _lock_unlock_plugin_list_for_reading(false)
/* Ajoute un greffon à la liste principale de greffons. */
-void _register_plugin(GPluginModule *);
-
-/* Ajoute un greffon à la liste principale de greffons. */
void register_plugin(GPluginModule *);
/* Charge tous les greffons restant à charger. */
@@ -66,16 +63,39 @@ GPluginModule *get_plugin_by_name(const char *, size_t *);
/* Fournit la liste de l'ensemble des greffons. */
GPluginModule **get_all_plugins(size_t *);
-/* Fournit les greffons offrant le service demandé. */
-GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
-
/**
* Définitions des opérations appliquables à une catégories de greffons.
*/
-#define process_all_plugins_for(a, f, ...) \
+#define process_all_plugins_for(tp, cst, fc) \
+ do \
+ { \
+ size_t __count; \
+ GPluginModule **__list; \
+ size_t __i; \
+ __list = get_all_plugins(&__count); \
+ for (__i = 0; __i < __count; __i++) \
+ { \
+ if (G_TYPE_CHECK_INSTANCE_TYPE(__list[__i], tp)) \
+ fc(cst(__list[__i])); \
+ unref_object(__list[__i]); \
+ } \
+ if (__list != NULL) \
+ free(__list); \
+ } \
+ while (0)
+
+
+
+
+
+#if 0
+
+// TODO : REMME
+
+#define process_all_plugins_for_old__(a, f, ...) \
do \
{ \
size_t __count; \
@@ -114,11 +134,13 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_PG_MANAGEMENT */
+/*
#define notify_native_plugins_loaded() \
- process_all_plugins_for(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
#define notify_all_plugins_loaded() \
- process_all_plugins_for(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+*/
#define build_type_instance(t) \
process_plugins_while_null(PGA_TYPE_BUILDING, g_plugin_module_build_type_instance, t)
@@ -126,44 +148,47 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_SETUP */
#define include_plugin_theme(d, r, c) \
- process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
+ process_all_plugins_for_old__(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
/* DPS_RUNNING */
#define notify_panel_creation(i) \
- process_all_plugins_for(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
+ process_all_plugins_for_old__(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
#define notify_panel_docking(i, d) \
- process_all_plugins_for(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
+ process_all_plugins_for_old__(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
/* DPS_CONTENT */
#define handle_binary_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_binary_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_binary_content, c, i, s)
#define handle_loaded_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_loaded_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_loaded_content, c, i, s)
/* DPS_FORMAT */
#define handle_known_format_analysis(a, f, g, s) \
- process_all_plugins_for(a, g_plugin_module_handle_known_format_analysis, f, g, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_known_format_analysis, f, g, s)
#define preload_binary_format(a, f, i, s) \
- process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_preload_binary_format, f, i, s)
#define attach_debug_format(f) \
- process_all_plugins_for(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
+ process_all_plugins_for_old__(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
/* DPS_DISASSEMBLY */
#define process_disassembly_event(a, b, s, c) \
- process_all_plugins_for(a, g_plugin_module_process_disassembly_event, b, s, c)
+ process_all_plugins_for_old__(a, g_plugin_module_process_disassembly_event, b, s, c)
/* DPS_DETECTION */
#define detect_external_tools(a, cnt, v, n, c) \
- process_all_plugins_for(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+ process_all_plugins_for_old__(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+
+
+#endif
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 1118140..b5e0b51 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -35,18 +35,6 @@
/* ------------------------ IDENTIFICATION DE COMPATIBILITES ------------------------ */
-/* Version identifiant les définitions courantes */
-typedef uint32_t plugin_abi_version_t;
-
-#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
- (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
-
-#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
-#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, 3, 0)
-
/* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
@@ -232,14 +220,14 @@ typedef enum _PluginAction
/* ------------------------ PREMIER INTERFACAGE PROTOCOLAIRE ------------------------ */
-#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
+//#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
/* Définition d'un greffon */
typedef struct _plugin_interface
{
uint64_t magic; /* Vérification a minima */
- plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+ uint32_t /*plugin_abi_version_t*/ abi_version; /* Version du protocole utilisé*/
/**
* Les champs suivants ne sont généralement pas alloués dynamiquement,
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 3ba19dc..07b455a 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -37,21 +37,28 @@
#include "../common/bits.h"
-/* Transfert de la conscience de soi. */
-typedef void (* pg_set_self_fc) (GPluginModule *);
-/* Prend acte du [dé]chargement du greffon. */
+/* Pointe le fichier contenant le greffon manipulé. */
+typedef char * (* get_plugin_filename_fc) (const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+typedef char * (* get_plugin_modname_fc) (const GPluginModule *);
+
+/* Prend acte de (l'|la dés)activation du greffon. */
typedef bool (* pg_management_fc) (GPluginModule *);
+
+
+
+/* Transfert de la conscience de soi. */
+typedef void (* pg_set_self_fc) (GPluginModule *);
+
/* Accompagne la fin du chargement des modules natifs. */
typedef void (* pg_plugins_loaded_fc) (GPluginModule *, PluginAction);
/* Crée une instance à partir d'un type dynamique externe. */
typedef gpointer (* pg_build_instance_fc) (GPluginModule *, PluginAction, GType);
-/* Fournit le nom brut associé au greffon. */
-typedef char * (* pg_get_modname_fc) (const GPluginModule *);
-
#if 0
/* Procède à une opération liée à un contenu binaire. */
@@ -90,22 +97,47 @@ typedef void (* pg_detect_tools_fc) (const GPluginModule *, PluginAction, const
#endif
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Version identifiant les définitions courantes */
+typedef uint32_t plugin_abi_version_t;
+
+#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
+ (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
+
+#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
+#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
+#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
+
+/**
+ * 0.3.0 : dernière version avec actions et fonctions associées
+ * 1.0.0 (04/01/25) : bascule en chargement d'objet et interfaces
+ */
+#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(1, 0, 0)
+
+
/* Greffon pour Chrysalide (instance) */
struct _GPluginModule
{
GObject parent; /* A laisser en premier */
- char *filename; /* Fichier associé au greffon */
- GModule *module; /* Abstration de manipulation */
+ uint32_t magic; /* Vérification a minima */
+ plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+
+ char *name; /* Désignation humaine courte */
+ char *desc; /* Description plus loquace */
+ char *version; /* Version du greffon */
+ char *url; /* Site Web associé */
- const plugin_interface *interface; /* Déclaration d'interfaçage */
+ char **required; /* Pré-chargements requis */
+ size_t required_count; /* Quantité de ces dépendances */
PluginStatusFlags flags; /* Fanion pour l'état courant */
bitfield_t *dependencies; /* Cartographie des dépendances*/
- //GGenConfig *config; /* Configuration dédiée */
-
};
@@ -114,6 +146,18 @@ struct _GPluginModuleClass
{
GObjectClass parent; /* A laisser en premier */
+ get_plugin_filename_fc get_filename; /* Obtention du chemin */
+ get_plugin_modname_fc get_modname; /* Fourniture du nom brut */
+
+ pg_management_fc enable; /* Procédure d'activation */
+ pg_management_fc disable; /* Procédure d'extinction */
+
+
+
+ /////////////////////////////////////////////
+
+#if 0
+
pg_management_fc init; /* Procédure d'initialisation */
pg_management_fc manage; /* Etape dans la vie du greffon*/
pg_management_fc exit; /* Procédure d'extinction */
@@ -121,8 +165,6 @@ struct _GPluginModuleClass
pg_plugins_loaded_fc plugins_loaded; /* Fin des chargements */
pg_build_instance_fc build_instance; /* Création d'objets */
- pg_get_modname_fc get_modname; /* Fourniture du nom brut */
-
#if 0
#ifdef INCLUDE_GTK_SUPPORT
pg_include_theme_fc include_theme; /* Extension d'un thème */
@@ -141,12 +183,28 @@ struct _GPluginModuleClass
pg_detect_tools_fc detect; /* Lancement de détections */
#endif
+#endif
+
+ /////////////////////////////////////////////
+
};
-/* Met en place la configuration dédiée au greffon. */
-void g_plugin_module_create_config(GPluginModule *);
+
+#define STORE_PLUGIN_ABI(p) \
+ do \
+ { \
+ GPluginModule *_p; \
+ _p = G_PLUGIN_MODULE(p); \
+ _p->magic = CHRYSALIDE_PLUGIN_MAGIC; \
+ _p->abi_version = CURRENT_ABI_VERSION; \
+ } \
+ while (0);
+
+
+/* Met en place un greffon. */
+bool g_plugin_module_create(GPluginModule *, const char *, const char *, const char *, const char *, const char * const *, size_t);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 75cf4e0..c537bc3 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -30,7 +30,6 @@
#include <libgen.h>
#include <malloc.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -38,6 +37,7 @@
#include "dt.h"
#include "pglist.h"
#include "plugin-int.h"
+#include "../common/compiler.h"
#include "../common/extstr.h"
#include "../common/pathname.h"
#include "../common/xdg.h"
@@ -56,19 +56,12 @@ 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 *);
-
-/* Fournit le nom brut associé au greffon. */
-static char *_g_plugin_module_get_modname(const GPluginModule *);
-
/* Indique le type défini pour un greffon. */
G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
-
/******************************************************************************
* *
* Paramètres : class = classe à initialiser. *
@@ -84,16 +77,17 @@ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
static void g_plugin_module_class_init(GPluginModuleClass *class)
{
GObjectClass *object; /* Autre version de la classe */
- GPluginModuleClass *plugin; /* Version parente de la classe*/
object = G_OBJECT_CLASS(class);
object->dispose = (GObjectFinalizeFunc/* ! */)g_plugin_module_dispose;
object->finalize = (GObjectFinalizeFunc)g_plugin_module_finalize;
- plugin = G_PLUGIN_MODULE_CLASS(class);
+ class->get_filename = NULL;
+ class->get_modname = NULL;
- plugin->get_modname = (pg_get_modname_fc)_g_plugin_module_get_modname;
+ class->enable = NULL;
+ class->disable = NULL;
}
@@ -112,7 +106,17 @@ static void g_plugin_module_class_init(GPluginModuleClass *class)
static void g_plugin_module_init(GPluginModule *plugin)
{
- //plugin->config = NULL;
+ plugin->name = NULL;
+ plugin->desc = NULL;
+ plugin->version = NULL;
+ plugin->url = NULL;
+
+ plugin->required = NULL;
+ plugin->required_count = 0;
+
+ plugin->flags = PSF_NONE;
+
+ plugin->dependencies = NULL;
}
@@ -131,58 +135,35 @@ static void g_plugin_module_init(GPluginModule *plugin)
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);
+ lock_plugin_list_for_reading();
- if (pg_iface != NULL)
+ for (i = 0; i < plugin->required_count; i++)
{
- lock_plugin_list_for_reading();
+ dependency = get_plugin_by_name(plugin->required[i], NULL);
- for (i = 0; i < pg_iface->required_count; i++)
+ /* Si le chargement a bien été complet avant la sortie... */
+ if (dependency != NULL)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ /* Un coup pour l'appel à get_plugin_by_name(). */
+ unref_object(dependency);
- /* Si le chargement a bien été complet avant la sortie... */
- if (dependency != NULL)
- {
- /* Un coup pour l'appel à get_plugin_by_name(). */
- g_object_unref(G_OBJECT(dependency));
-
- /* Un coup pour la dépendance */
- g_object_unref(G_OBJECT(dependency));
-
- }
+ /* Un coup pour la dépendance */
+ unref_object(dependency);
}
- unlock_plugin_list_for_reading();
-
}
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+ unlock_plugin_list_for_reading();
- if (class->exit != NULL)
- class->exit(plugin);
-
- /*
- if (plugin->config != NULL)
- {
- g_generic_config_write(plugin->config);
-
- g_clear_object(&plugin->config);
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- }
- */
-
- if (plugin->module != NULL)
- {
- g_module_close(plugin->module);
- plugin->module = NULL;
- }
+ if (class->disable != NULL)
+ class->disable(plugin);
G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin));
@@ -203,7 +184,25 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
static void g_plugin_module_finalize(GPluginModule *plugin)
{
- free(plugin->filename);
+ size_t i; /* Boucle de parcours */
+
+ if (plugin->name != NULL)
+ free(plugin->name);
+
+ if (plugin->desc != NULL)
+ free(plugin->desc);
+
+ if (plugin->version != NULL)
+ free(plugin->version);
+
+ if (plugin->url != NULL)
+ free(plugin->url);
+
+ for (i = 0; i < plugin->required_count; i++)
+ free(plugin->required[i]);
+
+ if (plugin->required != NULL)
+ free(plugin->required);
if (plugin->dependencies != NULL)
delete_bit_field(plugin->dependencies);
@@ -215,627 +214,173 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : filename = nom du fichier à charger. *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
* *
-* Description : Crée un module pour un greffon donné. *
+* Description : Met en place un greffon. *
* *
-* Retour : Adresse de la structure mise en place. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule *g_plugin_module_new(const gchar *filename)
+bool g_plugin_module_create(GPluginModule *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count)
{
- GPluginModule *result; /* Structure à retourner */
- GModule *module; /* Abstration de manipulation */
- pg_set_self_fc set_self; /* Copie du greffon */
- 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 */
-
- 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_module;
- }
-
-
-#define load_plugin_symbol(mod, sym, dest) \
- ({ \
- bool __result; \
- if (!g_module_symbol(mod, sym, (gpointer *)dest)) \
- { \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result = false; \
- } \
- else __result = true; \
- __result; \
- })
-
-
- /* Récupération de la version d'ABI */
-
- if (!load_plugin_symbol(module, "chrysalide_plugin_set_self", &set_self))
- goto no_self_setter;
-
- if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface))
- goto no_interface;
-
- current = CURRENT_ABI_VERSION;
-
- if (current != interface->abi_version)
- goto wrong_abi;
-
- /* Localisation des différents points d'entrée déclarés */
-
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ size_t k; /* Boucle de parcours #2 */
-#define check_plugin_symbol(mod, sym) \
- ({ \
- bool __result; \
- __result = g_module_symbol(mod, sym, (gpointer []) { NULL }); \
- if (!__result) \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result; \
- })
+ /* Validations préalables */
+ assert(name != NULL);
- valid = true;
+ result = (name != NULL);
- for (i = 0; i < interface->actions_count && valid; i++)
+ if (result && plugin->abi_version != CURRENT_ABI_VERSION)
{
- 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:
- valid = check_plugin_symbol(module, "chrysalide_plugin_init");
- break;
-
- case PGA_PLUGIN_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_manage");
- break;
-
- case PGA_PLUGIN_EXIT:
- valid = check_plugin_symbol(module, "chrysalide_plugin_exit");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_CORE_MANAGEMENT:
-
- switch (action)
- {
- case PGA_NATIVE_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded");
- break;
-
- case PGA_TYPE_BUILDING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_build_type_instance");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
-#if 0
-
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
- valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_creation");
- break;
-
- case PGA_PANEL_DOCKING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_docking");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
- case DPC_BINARY_PROCESSING:
-
- switch (sub)
- {
- case DPS_CONTENT:
-
- switch (action)
- {
- case PGA_CONTENT_EXPLORER:
- case PGA_CONTENT_RESOLVER:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content");
- break;
+ result = false;
- case PGA_CONTENT_ANALYZED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content");
- break;
+ log_variadic_message(LMT_ERROR, _("ABI mismatch detected: %08x (plugin) vs %08x (core)"),
+ plugin->abi_version, CURRENT_ABI_VERSION);
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- 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:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis");
- break;
-
- case PGA_FORMAT_PRELOAD:
- valid = check_plugin_symbol(module, "chrysalide_plugin_preload_binary_format");
- break;
+ }
- case PGA_FORMAT_ATTACH_DEBUG:
- valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug");
- break;
+ /* Mémorisation des informations */
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
+ if (result)
+ {
+ plugin->name = strdup(name);
- }
+ if (desc != NULL)
+ plugin->desc = strdup(desc);
- break;
+ if (version != NULL)
+ plugin->version = strdup(version);
- case DPS_DISASSEMBLY:
- valid = check_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event");
- break;
+ if (url != NULL)
+ plugin->url = strdup(url);
- case DPS_DETECTION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools");
- break;
+ if (count > 0)
+ {
+ plugin->required = malloc(count * sizeof(char *));
+ plugin->required_count = 0;
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ for (i = 0; i < count; i++)
+ {
+ for (k = 0; k < plugin->required_count; k++)
+ if (strcmp(required[i], plugin->required[k]) == 0)
break;
- }
+ if (k < plugin->required_count)
+ continue;
-#endif
+ plugin->required[plugin->required_count++] = strdup(required[i]);
- break;
+ }
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
- break;
+ plugin->required = realloc(plugin->required, plugin->required_count * sizeof(char *));
}
}
- if (!valid)
- goto missing_feature;
-
- gtype = build_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name,
- (GClassInitFunc)g_plugin_module_init_gclass, module, NULL);
-
- if (gtype == G_TYPE_INVALID)
- goto no_instance;
-
- result = g_object_new(gtype, NULL);
-
- result->filename = strdup(filename);
- result->module = module;
-
- result->interface = interface;
-
- set_self(result);
-
return result;
- no_self_setter:
-
- log_variadic_message(LMT_ERROR, _("Self pointer setter is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_interface:
-
- log_variadic_message(LMT_ERROR, _("Main interface is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- wrong_abi:
-
- log_variadic_message(LMT_ERROR, _("ABI mismatch detected! Plugin '%s' rejected"), filename);
- goto bad_plugin;
-
- missing_feature:
-
- log_variadic_message(LMT_ERROR, _("An expected feature is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_instance:
-
- log_variadic_message(LMT_ERROR, _("Unabled to create an instance of plugin '%s'"), filename);
-
- bad_plugin:
-
- g_module_close(module);
-
- bad_module:
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : class = classe à initialiser. *
-* module = module représentant le greffon chargé en mémoire. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Initialise la classe des greffons d'extension. *
+* Description : Indique le nom associé à un greffon. *
* *
-* Retour : - *
+* Retour : Désignation interne de l'extension, pour référence(s). *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module)
+const char *g_plugin_module_get_name(const GPluginModule *plugin)
{
- 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_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_manage", &class->manage);
- 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_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded",
- &class->plugins_loaded);
- break;
-
- case PGA_TYPE_BUILDING:
- load_plugin_symbol(module, "chrysalide_plugin_build_type_instance",
- &class->build_instance);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-#if 0
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_include_theme",
- &class->include_theme);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_creation",
- &class->notify_panel);
-#endif
- break;
-
- case PGA_PANEL_DOCKING:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_docking",
- &class->notify_docking);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
+ const char *result; /* Valeur finale à renvoyer */
- 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:
+ result = plugin->name;
- 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, "chrysalide_plugin_handle_binary_format_analysis",
- &class->handle_fmt_analysis);
- break;
-
- case PGA_FORMAT_PRELOAD:
- load_plugin_symbol(module, "chrysalide_plugin_preload_binary_format", &class->preload_format);
- break;
-
- case PGA_FORMAT_ATTACH_DEBUG:
- load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug);
- break;
+ return result;
- default:
- assert(false);
- break;
+}
- }
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit une description fonctionnelle d'un greffon. *
+* *
+* Retour : Description textuelle associée à une extension ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- case DPS_DISASSEMBLY:
- load_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event", &class->process_disass);
- break;
+const char *g_plugin_module_get_desc(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- case DPS_DETECTION:
- load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect);
- break;
+ result = plugin->desc;
- default:
- assert(false);
- break;
+ return result;
- }
+}
-#endif
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit la version d'un greffon et de ses fonctionnalités. *
+* *
+* Retour : Version sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- default:
- assert(false);
- break;
+const char *g_plugin_module_get_version(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- }
+ result = plugin->version;
- }
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit l'URL des ressources en ligne liées à un greffon. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : URL de renvoi associée à une extension ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_plugin_module_get_modname(const GPluginModule *plugin)
+const char *g_plugin_module_get_url(const GPluginModule *plugin)
{
- char *result; /* Désignation brute à renvoyer*/
- GPluginModuleClass *class; /* Classe de l'instance active */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- result = class->get_modname(plugin);
+ const char *result; /* Valeur finale à renvoyer */
- /**
- * Tente une opération de la dernière chance.
- *
- * Dans le cas d'un module Python, la fonction de classe peut ne pas
- * trouver de support si l'extension Python n'est pas au point.
- */
- if (result == NULL && class->get_modname != _g_plugin_module_get_modname)
- result = _g_plugin_module_get_modname(plugin);
+ result = plugin->url;
return result;
@@ -844,41 +389,24 @@ char *g_plugin_module_get_modname(const GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
+* count = taille de la liste fournie. [OUT] *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit la liste des dépendances d'un greffon donné. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : Liste des noms d'extensions requises pour une extension. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
+const char * const *g_plugin_module_get_requirements(const GPluginModule *plugin, size_t *count)
{
- char *result; /* Désignation brute à renvoyer*/
- char *path; /* Chemin à traiter */
- char *filename; /* Nom de bibliothèque partagée*/
- size_t length; /* Taille du nom */
-
- path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin)));
-
- filename = basename(path);
-
- if (strncmp(filename, "lib", 3) == 0)
- filename += 3;
-
- length = strlen(filename);
-
- if (length >= 3)
- {
- if (strncmp(&filename[length - 3], ".so", 3) == 0)
- filename[length - 3] = '\0';
- }
+ const char * const *result; /* Valeur finale à renvoyer */
- result = strdup(filename);
+ result = CONST_ARRAY_CAST(plugin->required, char);
- free(path);
+ *count = plugin->required_count;
return result;
@@ -889,7 +417,7 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Indique le fichier contenant le greffon manipulé. *
+* Description : Pointe le fichier contenant le greffon manipulé. *
* *
* Retour : Chemin d'accès au greffon. *
* *
@@ -897,28 +425,42 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
******************************************************************************/
-const char *g_plugin_module_get_filename(const GPluginModule *plugin)
+char *g_plugin_module_get_filename(const GPluginModule *plugin)
{
- return plugin->filename;
+ char *result; /* Chemin d'accès à renvoyer */
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_filename(plugin);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à consulter. *
+* Paramètres : plugin = greffon à valider. *
* *
-* Description : Fournit la description du greffon dans son intégralité. *
+* Description : Fournit le nom brut associé au greffon. *
* *
-* Retour : Interfaçage renseigné. *
+* Retour : Désignation brute du greffon. *
* *
* Remarques : - *
* *
******************************************************************************/
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin)
+char *g_plugin_module_get_modname(const GPluginModule *plugin)
{
- return plugin->interface;
+ char *result; /* Désignation brute à renvoyer*/
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_modname(plugin);
+
+ return result;
}
@@ -979,7 +521,6 @@ void g_plugin_module_override_flags(GPluginModule *plugin, PluginStatusFlags fla
bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count)
{
bool result; /* Bilan à faire remonter */
- const plugin_interface *pg_iface; /* Définition du greffon */
bitfield_t *new; /* Nouvelle définition */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
@@ -997,15 +538,13 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) == 0)
{
- pg_iface = g_plugin_module_get_interface(plugin);
-
/* Collecte des dépendances */
new = dup_bit_field(plugin->dependencies);
- for (i = 0; i < pg_iface->required_count; i++)
+ for (i = 0; i < plugin->required_count; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], &index);
+ dependency = get_plugin_by_name(plugin->required[i], &index);
if (dependency == NULL)
plugin->flags |= PSF_UNKNOW_DEP;
@@ -1023,7 +562,7 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
*/
if (test_in_bit_field(plugin->dependencies, index))
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1041,13 +580,14 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
/* Vérification sanitaire */
- dependency = get_plugin_by_name(pg_iface->name, &index);
+ dependency = get_plugin_by_name(plugin->name, &index);
assert(dependency != NULL);
+ assert(dependency == plugin);
if (test_in_bit_field(plugin->dependencies, index))
plugin->flags |= PSF_DEP_LOOP;
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1075,12 +615,12 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
{
bool result; /* Bilan à retourner */
PluginStatusFlags flags; /* Fanions de greffon */
- const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
+ char *filename; /* Chemin d'accès au greffon */
GPluginModuleClass *class; /* Classe de l'instance active */
- //GGenConfig *config; /* Configuration à charger */
- char *dir; /* Répertoire modifiable */
+ char *tmp; /* Chaîne modifiable */
+ char *dir; /* Pointeur vers répertoire */
/* Si un essai précédent a déjà échoué ou réussi... */
@@ -1092,40 +632,41 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
/* Chargement des dépendances */
- pg_iface = g_plugin_module_get_interface(plugin);
-
result = true;
- for (i = 0; i < pg_iface->required_count && result; i++)
+ filename = g_plugin_module_get_filename(plugin);
+
+ for (i = 0; i < plugin->required_count && result; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ dependency = get_plugin_by_name(plugin->required[i], NULL);
assert(dependency != NULL);
result = g_plugin_module_load(dependency, list, count);
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Some dependencies failed to load for plugin '%s'"), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Some dependencies failed to load for plugin '%s'"), filename);
+
+ plugin->flags |= PSF_FAILURE;
goto failure;
+
}
/* Chargement du greffon courant */
class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- if (class->init != NULL)
+ if (class->enable != NULL)
{
- result = class->init(plugin);
+ result = class->enable(plugin);
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to load itself..."), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' failed to load itself..."), filename);
plugin->flags |= PSF_FAILURE;
goto failure;
@@ -1134,39 +675,23 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
}
- g_plugin_module_create_config(plugin);
-
- result = g_plugin_module_manage(plugin, PGA_PLUGIN_LOADED);
+ /* Message de bilan */
- if (!result)
- {
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to complete loading..."), plugin->filename);
-
- plugin->flags |= PSF_FAILURE;
- goto failure;
-
- }
-
- /*
- config = g_plugin_module_get_config(plugin);
- g_generic_config_read(config);
- g_object_unref(G_OBJECT(config));
- */
-
- dir = strdup(plugin->filename);
- dir = dirname(dir);
+ tmp = strdup(filename);
+ dir = dirname(tmp);
log_variadic_message(LMT_PROCESS,
_("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"),
- strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir);
+ strrchr(filename, G_DIR_SEPARATOR) + 1, dir);
- free(dir);
+ free(tmp);
plugin->flags |= PSF_LOADED;
failure:
+ free(filename);
+
return result;
}
@@ -1227,31 +752,6 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c
/******************************************************************************
* *
-* Paramètres : plugin = greffon à compléter. *
-* *
-* Description : Met en place la configuration dédiée au greffon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_plugin_module_create_config(GPluginModule *plugin)
-{
- char *filename; /* Chemin d'accès particulier */
-
- filename = g_plugin_module_build_config_filename(plugin, "config.xml", false);
-
- //plugin->config = g_generic_config_new_from_file(filename);
-
- free(filename);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : plugin = greffon à consulter. *
* *
* Description : Fournit la configuration mise en place pour le greffon. *
@@ -1295,11 +795,11 @@ void g_plugin_module_log_simple_message(const GPluginModule *plugin, LogMessageT
size_t len; /* Taille tampon disponible */
char *buffer; /* Tampon du msg reconstitué */
- len = 4 + strlen(plugin->interface->name) + 6 + strlen(msg) + 1;
+ len = 4 + strlen(plugin->name) + 6 + strlen(msg) + 1;
buffer = calloc(len, sizeof(char));
strcpy(buffer, "<i>[");
- strcat(buffer, plugin->interface->name);
+ strcat(buffer, plugin->name);
strcat(buffer, "]</i> ");
strcat(buffer, msg);
@@ -1345,80 +845,12 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
}
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* *
-* Description : Encadre une étape de la vie d'un greffon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_plugin_module_manage(GPluginModule *plugin, PluginAction action)
-{
- bool result; /* Bilan à faire remonter */
- GPluginModuleClass *class; /* Classe de l'instance active */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool handle_action; /* Action supportée ? */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- if (class->manage == NULL)
- result = true;
-
- else
- {
- handle_action = false;
-
- pg_iface = g_plugin_module_get_interface(plugin);
-
- for (i = 0; i < pg_iface->actions_count; i++)
- if (pg_iface->actions[i] == PGA_PLUGIN_LOADED)
- {
- handle_action = true;
- break;
- }
-
- if (handle_action)
- result = class->manage(plugin/*, action*/);
- else
- result = true;
-
- }
-
- return result;
-
-}
-/******************************************************************************
-* *
-* 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. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_plugin_module_notify_plugins_loaded(GPluginModule *plugin, PluginAction action, void *unused)
-{
- GPluginModuleClass *class; /* Classe de l'instance active */
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- class->plugins_loaded(plugin, action);
-}
+#if 0
/******************************************************************************
@@ -1450,8 +882,6 @@ gpointer g_plugin_module_build_type_instance(GPluginModule *plugin, PluginAction
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 5c473b2..a4cc388 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -52,6 +52,27 @@
DECLARE_GTYPE(GPluginModule, g_plugin_module, G, PLUGIN_MODULE);
+/* Indique le nom associé à un greffon. */
+const char *g_plugin_module_get_name(const GPluginModule *);
+
+/* Fournit une description fonctionnelle d'un greffon. */
+const char *g_plugin_module_get_desc(const GPluginModule *);
+
+/* Fournit la version d'un greffon et de ses fonctionnalités. */
+const char *g_plugin_module_get_version(const GPluginModule *);
+
+/* Fournit l'URL des ressources en ligne liées à un greffon. */
+const char *g_plugin_module_get_url(const GPluginModule *);
+
+/* Fournit la liste des dépendances d'un greffon donné. */
+const char * const *g_plugin_module_get_requirements(const GPluginModule *, size_t *);
+
+/* Pointe le fichier contenant le greffon manipulé. */
+char *g_plugin_module_get_filename(const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+char *g_plugin_module_get_modname(const GPluginModule *);
+
/* Fanions indiquant le statut du greffon */
typedef enum _PluginStatusFlags
{
@@ -66,19 +87,6 @@ typedef enum _PluginStatusFlags
#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
-
-/* Crée un module pour un greffon donné. */
-GPluginModule *g_plugin_module_new(const gchar *);
-
-/* Fournit le nom brut associé au greffon. */
-char *g_plugin_module_get_modname(const GPluginModule *);
-
-/* Indique le fichier contenant le greffon manipulé. */
-const char *g_plugin_module_get_filename(const GPluginModule *);
-
-/* Fournit la description du greffon dans son intégralité. */
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);
-
/* Fournit des indications sur l'état du greffon. */
PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *);
@@ -103,17 +111,12 @@ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, c
/* Présente dans le journal un message complexe. */
void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, const char *, ...);
-/* Encadre une étape de la vie d'un greffon. */
-bool g_plugin_module_manage(GPluginModule *, PluginAction);
-/* Accompagne la fin du chargement des modules natifs. */
-void g_plugin_module_notify_plugins_loaded(GPluginModule *, PluginAction, void *);
+#if 0
/* Crée une instance à partir d'un type dynamique externe. */
gpointer g_plugin_module_build_type_instance(GPluginModule *, PluginAction, GType);
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
/* Complète une liste de resources pour thème. */
diff --git a/src/plugins/self.h b/src/plugins/self.h
index 4d5ddb0..78a3fe6 100644
--- a/src/plugins/self.h
+++ b/src/plugins/self.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * self.h - définitions pour inclusion dans les différents greffons
+ * self.h - définitions de fonctionnalités facilitant la mise en place d'extensions natives
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,72 +26,55 @@
#define _PLUGINS_SELF_H
-#ifndef _PLUGINS_PLUGIN_H
-# include "plugin.h"
-#endif
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "plugin.h"
#include "../common/compiler.h"
-/* Facilitations de déclarations */
+/* Symboles principaux */
+
+#define PLUGIN_CORE_SELF \
+static GPluginModule *_this_plugin = NULL; \
+static void chrysalide_plugin_set_self(GPluginModule *); \
+static void chrysalide_plugin_set_self(GPluginModule *plugin) \
+{ \
+ assert(_this_plugin == NULL); \
+ _this_plugin = plugin; \
+}; \
+__private GPluginModule *_chrysalide_plugin_get_self(void); \
+__private GPluginModule *_chrysalide_plugin_get_self(void) \
+{ \
+ return _this_plugin; \
+};
+
+#define NATIVE_PLUGIN_ENTRYPOINT(fc) \
+PLUGIN_CORE_SELF; \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *); \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *module) \
+{ \
+ GPluginModule *result; /* Instance à retourner */ \
+ result = fc(module); \
+ chrysalide_plugin_set_self(result); \
+ return result; \
+}
+
+
+/* Spécifications */
#define CHRYSALIDE_WEBSITE(p) "https://www.chrysalide.re/" p
-#define EMPTY_PG_LIST(name) \
- name = NULL, \
- name ## _count = 0 \
-
-#define BUILD_PG_LIST(name, lst) \
- name = lst, \
- name ## _count = sizeof(lst) / sizeof(lst[0]) \
-
-#define AL(...) BUILD_PG_LIST(.actions, ((plugin_action_t []){ __VA_ARGS__ }))
-
-#define RL(...) BUILD_PG_LIST(.required, ((char *[]){ __VA_ARGS__ }))
-
-#define NO_REQ EMPTY_PG_LIST(.required)
-
-
-/* Composants d'interface */
-
-#define PLUGIN_CORE_SELF \
-static GPluginModule *_this_plugin = NULL; \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p); \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p) { _this_plugin = p; }; \
-__private GPluginModule *_chrysalide_plugin_get_self(void); \
-__private GPluginModule *_chrysalide_plugin_get_self(void) { return _this_plugin; };
-
-#define PLUGIN_CORE_PROPS(n, d, v, u, c) \
- \
- .magic = CHRYSALIDE_PLUGIN_MAGIC, \
- .abi_version = CURRENT_ABI_VERSION, \
- \
- .gtp_name = "G" n "Plugin", \
- .name = n, \
- .desc = d, \
- .version = v, \
- .url = u, \
- \
- .container = c
-
-#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, false), \
- r, \
- a, \
-}
+#define NO_REQ NULL, 0
-#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, true), \
- r, \
- a, \
-}
+#define BUILD_PG_LIST(lst) lst, sizeof(lst) / sizeof(lst[0])
+
+#define REQ_LIST(...) BUILD_PG_LIST((const char *[]){ __VA_ARGS__ })
-/* Manipulations accélérées */
+/* Journalisation */
__private GPluginModule *_chrysalide_plugin_get_self(void);