diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2019-01-03 23:36:47 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2019-01-03 23:36:47 (GMT) |
commit | 55ccf25e0c6666436f0ecd222e60208ebf6ab30e (patch) | |
tree | 21c1ecc9e6d6ae50d0cfb0ffa4eaf61bf78a45a2 /src/plugins | |
parent | 28bfc34862513acb8fe9fcd02afca493c2411c02 (diff) |
Defined a dynamic type for each plugin.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/Makefile.am | 1 | ||||
-rw-r--r-- | src/plugins/dt.c | 474 | ||||
-rw-r--r-- | src/plugins/dt.h | 47 | ||||
-rw-r--r-- | src/plugins/plugin-def.h | 13 | ||||
-rw-r--r-- | src/plugins/plugin-int.h | 16 | ||||
-rw-r--r-- | src/plugins/plugin.c | 396 | ||||
-rw-r--r-- | src/plugins/plugin.h | 12 |
7 files changed, 872 insertions, 87 deletions
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 996c418..4059e0b 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libplugins.la libplugins_la_SOURCES = \ context-int.h \ context.h context.c \ + dt.h dt.c \ pglist.h pglist.c \ plugin-def.h \ plugin-int.h \ diff --git a/src/plugins/dt.c b/src/plugins/dt.c new file mode 100644 index 0000000..afdba21 --- /dev/null +++ b/src/plugins/dt.c @@ -0,0 +1,474 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * dt.c - possibilité de créer de nouveaux types de façon dynamique + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "dt.h" + + +#include <assert.h> +#include <malloc.h> + + + +/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */ + + +#define G_TYPE_DYNAMIC_TYPES g_dynamic_types_get_type() +#define G_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes)) +#define G_IS_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES)) +#define G_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass)) +#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES)) +#define G_DYNAMIC_TYPES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass)) + + +/* Mémorisation des caractéristiques de type */ +typedef struct _type_dyn_info_t +{ + GType type; /* Identifiant unique obtenu */ + GClassInitFunc init; /* Définition des méthodes */ + gconstpointer data; /* Eventuelles données utiles */ + +} type_dyn_info_t; + +/* Description de fichier binaire (instance) */ +typedef struct _GDynamicTypes +{ + GObject parent; /* A laisser en premier */ + + type_dyn_info_t **info; /* Liste d'informations utiles */ + size_t count; /* Taille de cette liste */ + +} GDynamicTypes; + +/* Description de fichier binaire (classe) */ +typedef struct _GDynamicTypesClass +{ + GObjectClass parent; /* A laisser en premier */ + +} GDynamicTypesClass; + + +/* Indique le type défini pour une gestion de types dynamique. */ +static GType g_dynamic_types_get_type(void); + +/* Initialise la classe de gestion de types dynamique. */ +static void g_dynamic_types_class_init(GDynamicTypesClass *); + +/* Initialise une gestion de types dynamique. */ +static void g_dynamic_types_init(GDynamicTypes *); + +/* Procède à l'initialisation de l'interface de typage nouveau. */ +static void g_dynamic_types_interface_init(GTypePluginClass *); + +/* Supprime toutes les références externes. */ +static void g_dynamic_types_dispose(GDynamicTypes *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dynamic_types_finalize(GDynamicTypes *); + +/* Crée un nouveau gestionnaire de nouveaux types. */ +static GDynamicTypes *g_dynamic_types_new(void); + +/* Marque une augmentation des utilisations. */ +static void g_dynamic_types_use(GDynamicTypes *); + +/* Marque une diminution des utilisations. */ +static void g_dynamic_types_unuse(GDynamicTypes *); + +/* Complète la définition d'un type dynamiquement. */ +static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *); + +/* Retrouve les informations concernant un type dynamique. */ +static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType); + +/* Fournit un identifiant GLib pour un nouveau type. */ +static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer); + + + +/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */ + + +/* Encadrement des nouveaux types dérivés */ +static GDynamicTypes *_chrysalide_dtypes = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/* MODULE DE GESTION DES NOUVEAUX */ +/* ---------------------------------------------------------------------------------- */ + +/* Indique le type défini pour une gestion de types dynamique. */ +G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe de gestion de types dynamique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_class_init(GDynamicTypesClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose; + object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : types = instance à initialiser. * +* * +* Description : Initialise une gestion de types dynamique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_init(GDynamicTypes *types) +{ + +} + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de typage nouveau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_interface_init(GTypePluginClass *iface) +{ + iface->use_plugin = (GTypePluginUse)g_dynamic_types_use; + iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse; + iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type; + +} + +/****************************************************************************** +* * +* Paramètres : types = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_dispose(GDynamicTypes *types) +{ + G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types)); + +} + + +/****************************************************************************** +* * +* Paramètres : types = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_finalize(GDynamicTypes *types) +{ + G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau gestionnaire de nouveaux types. * +* * +* Retour : Instance mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDynamicTypes *g_dynamic_types_new(void) +{ + GDynamicTypes *result; /* Adresse à retourner */ + + result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : types = gestionnaire de types courant. * +* * +* Description : Marque une augmentation des utilisations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_use(GDynamicTypes *types) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : types = gestionnaire de types courant. * +* * +* Description : Marque une diminution des utilisations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_unuse(GDynamicTypes *types) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : types = gestionnaire de types courant. * +* type = nouveau type GLib à traiter. * +* info = information concernant ce type à constituer. [OUT] * +* table = table de valeur à éventuellement initialiser. [OUT] * +* * +* Description : Complète la définition d'un type dynamiquement. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table) +{ + const type_dyn_info_t *nfo; /* Source d'inspiration */ + GType parent; /* Type parent du type */ + GTypeQuery query; /* Informations complémentaires*/ + + /* Consultation */ + + nfo = g_dynamic_types_find(types, type); + assert(nfo != NULL); + + parent = g_type_parent(type); + g_type_query(parent, &query); + + /* Définition */ + + info->class_size = query.class_size; + info->class_init = nfo->init; + info->class_data = nfo->data; + + info->instance_size = query.instance_size; + +} + + +/****************************************************************************** +* * +* Paramètres : parent = type GLib parent. * +* type = identifiant du type GLib à considérer. * +* * +* Description : Retrouve les informations concernant un type dynamique. * +* * +* Retour : Structure contenant les informations associées au type. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target) +{ + type_dyn_info_t *result; /* Informations à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < types->count && result == NULL; i++) + if (types->info[i]->type == target) + result = types->info[i]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : parent = type GLib parent. * +* name = désignation du nouveau type. * +* init = procédure d'initialisation de la classe associée. * +* data = éventuelles données à associer à la future classe. * +* * +* Description : Fournit un identifiant GLib pour un nouveau type. * +* * +* Retour : identifiant d'un nouveau type valide, ou 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init, gconstpointer data) +{ + GType result; /* Identifiant à retourner */ + type_dyn_info_t *new; /* Mémorisation de paramètres */ + + /* Création d'un nouveau type adapté */ + + result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0); + + if (result == 0) + goto exit; + + new = malloc(sizeof(type_dyn_info_t)); + + new->type = result; + new->init = init; + new->data = data; + + /* Inscription définitive */ + + types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *)); + + types->info[types->count - 1] = new; + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* ACCOMPAGNEMENTS DES NOUVEAUX TYPES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Lance le support de dérivations de types dans Chrysalide. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_chrysalide_dynamic_types(void) +{ + bool result; /* Bilan à retourner */ + + _chrysalide_dtypes = g_dynamic_types_new(); + + result = (_chrysalide_dtypes != NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Arrête le support de dérivations de types dans Chrysalide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_chrysalide_dynamic_types(void) +{ + g_object_unref(G_OBJECT(_chrysalide_dtypes)); + +} + + +/****************************************************************************** +* * +* Paramètres : parent = type GLib parent. * +* name = désignation du nouveau type. * +* init = procédure d'initialisation de la classe associée. * +* data = éventuelles données à associer à la future classe. * +* * +* Description : Fournit un identifiant GLib pour un nouveau type. * +* * +* Retour : Identifiant d'un nouveau type valide, ou 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init, gconstpointer data) +{ + GType result; /* Identifiant à retourner */ + + result = g_type_from_name(name); + + if (result == 0) + result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, init, data); + + return result; + +} diff --git a/src/plugins/dt.h b/src/plugins/dt.h new file mode 100644 index 0000000..b9d4656 --- /dev/null +++ b/src/plugins/dt.h @@ -0,0 +1,47 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_DT_H +#define _PLUGINS_DT_H + + +#include <glib-object.h> +#include <stdbool.h> + + + +/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */ + + +/* Lance le support de dérivations de types dans Chrysalide. */ +bool init_chrysalide_dynamic_types(void); + +/* Arrête le support de dérivations de types dans Chrysalide. */ +void exit_chrysalide_dynamic_types(void); + +/* Fournit un identifiant GLib pour un nouveau type. */ +GType built_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_DT_H */ diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 4c59606..b8cdca8 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -45,7 +45,7 @@ typedef uint32_t plugin_abi_version_t; #define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff) #define GET_ABI_REV_VERSION(vs) (vs & 0xffff) -#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 1, 0) +#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 2, 0) //#define HARD_CODE_CURRENT_ABI_VERSION const plugin_abi_version_t abi_version = CURRENT_ABI_VERSION @@ -223,6 +223,7 @@ typedef struct _plugin_interface uint64_t magic; /* Vérification a minima */ plugin_abi_version_t abi_version; /* Version du protocole utilisé*/ + const char *gtp_name; /* Désignation du GType associé*/ const char *name; /* Désignation humaine courte */ const char *desc; /* Description plus loquace */ const char *version; /* Version du greffon */ @@ -253,12 +254,13 @@ typedef struct _plugin_interface #define RL(...) BUILD_PG_LIST(.required, ((const char *[]){ __VA_ARGS__ })) -#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, r, a) \ +#define DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, r, a) \ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ \ .magic = CHRYSALIDE_PLUGIN_MAGIC, \ .abi_version = CURRENT_ABI_VERSION, \ \ + .gtp_name = t, \ .name = n, \ .desc = d, \ .version = v, \ @@ -271,12 +273,13 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ \ } -#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, r, a) \ +#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(t, n, d, v, r, a) \ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ \ .magic = CHRYSALIDE_PLUGIN_MAGIC, \ .abi_version = CURRENT_ABI_VERSION, \ \ + .gtp_name = t, \ .name = n, \ .desc = d, \ .version = v, \ @@ -291,8 +294,8 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ /* Interfaçage primaire avec Chrysalide */ -#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(n, d, v, ...) \ - DEFINE_CHRYSALIDE_PLUGIN(n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ )) +#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(t, n, d, v, ...) \ + DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ )) diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 2d98217..4746867 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -83,6 +83,14 @@ struct _GPluginModule bitfield_t *dependencies; /* Cartographie des dépendances*/ +}; + + +/* Greffon pour Chrysalide (classe) */ +struct _GPluginModuleClass +{ + GObjectClass parent; /* A laisser en premier */ + pg_management_fc init; /* Procédure d'initialisation */ pg_management_fc exit; /* Procédure d'extinction */ @@ -104,14 +112,6 @@ struct _GPluginModule }; -/* Greffon pour Chrysalide (classe) */ -struct _GPluginModuleClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - /* Présente dans le journal un message simple. */ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index a9bd9da..ff3db31 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -35,6 +35,7 @@ #include <string.h> +#include "dt.h" #include "pglist.h" #include "plugin-int.h" @@ -52,6 +53,10 @@ static void g_plugin_module_dispose(GPluginModule *); /* Procède à la libération totale de la mémoire. */ static void g_plugin_module_finalize(GPluginModule *); +/* Initialise la classe des greffons d'extension. */ +static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *); + + /* Indique le type défini pour un greffon. */ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT); @@ -117,6 +122,7 @@ static void g_plugin_module_dispose(GPluginModule *plugin) const plugin_interface *pg_iface; /* Définition du greffon */ size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ + GPluginModuleClass *class; /* Classe de l'instance active */ pg_iface = g_plugin_module_get_interface(plugin); @@ -145,11 +151,16 @@ static void g_plugin_module_dispose(GPluginModule *plugin) } - if (plugin->exit != NULL) - plugin->exit(plugin); + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + if (class->exit != NULL) + class->exit(plugin); if (plugin->module != NULL) + { g_module_close(plugin->module); + plugin->module = NULL; + } G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin)); @@ -195,25 +206,26 @@ static void g_plugin_module_finalize(GPluginModule *plugin) GPluginModule *g_plugin_module_new(const gchar *filename) { GPluginModule *result; /* Structure à retourner */ + GModule *module; /* Abstration de manipulation */ + const plugin_interface *interface; /* Déclaration d'interfaçage */ plugin_abi_version_t current; /* Version de l'ABI actuelle */ + bool valid; /* Statut de validité */ size_t i; /* Boucle de parcours */ uint32_t action; /* Identifiant d'une action */ uint32_t category; /* Catégorie principale */ uint32_t sub; /* Sous-catégorie visée */ + GType gtype; /* Nouveau type de greffon */ - result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL); - - result->filename = strdup(filename); - - result->module = g_module_open(filename, G_MODULE_BIND_LAZY); - if (result->module == NULL) + module = g_module_open(filename, G_MODULE_BIND_LAZY); + if (module == NULL) { log_variadic_message(LMT_ERROR, _("Error while loading the plugin candidate '%s' : %s"), filename, g_module_error()); - goto bad_plugin; + goto bad_module; } + #define load_plugin_symbol(mod, sym, dest) \ ({ \ bool __result; \ @@ -221,7 +233,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename) { \ log_variadic_message(LMT_ERROR, \ _("No '%s' entry in plugin candidate '%s'"), \ - sym, result->filename); \ + sym, filename); \ __result = false; \ } \ else __result = true; \ @@ -231,12 +243,12 @@ GPluginModule *g_plugin_module_new(const gchar *filename) /* Récupération de la version d'ABI */ - if (!load_plugin_symbol(result->module, "_chrysalide_plugin", &result->interface)) + if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface)) goto bad_plugin; current = CURRENT_ABI_VERSION; - if (current != result->interface->abi_version) + if (current != interface->abi_version) { log_variadic_message(LMT_ERROR, _("ABI mismatch detected! Plugin '%s' rejected"), @@ -247,9 +259,20 @@ GPluginModule *g_plugin_module_new(const gchar *filename) /* Localisation des différents points d'entrée déclarés */ - for (i = 0; i < result->interface->actions_count; i++) + +#define check_plugin_symbol(mod, sym) \ + ({ \ + bool __result; \ + __result = g_module_symbol(mod, sym, (gpointer []) { 0 }); \ + __result; \ + }) + + + valid = true; + + for (i = 0; i < interface->actions_count && valid; i++) { - action = result->interface->actions[i]; + action = interface->actions[i]; category = MASK_PLUGIN_CATEGORY(action); sub = MASK_PLUGIN_SUB_CATEGORY(action); @@ -267,21 +290,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename) switch (action) { case PGA_PLUGIN_INIT: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_init", &result->init)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_init"); break; case PGA_PLUGIN_EXIT: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_exit", &result->exit)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_exit"); break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + interface->actions[i], filename); break; } @@ -293,16 +312,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename) switch (action) { case PGA_NATIVE_LOADED: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_on_native_loaded", - &result->native_loaded)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_on_native_loaded"); break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + interface->actions[i], filename); break; } @@ -327,15 +343,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename) switch (action) { case PGA_GUI_THEME: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_include_theme", &result->include_theme)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme"); break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + interface->actions[i], filename); break; } @@ -361,23 +375,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename) { case PGA_CONTENT_EXPLORER: case PGA_CONTENT_RESOLVER: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_handle_binary_content", - &result->handle_content)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content"); break; case PGA_CONTENT_ANALYZED: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_handle_loaded_content", - &result->handle_loaded)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content"); break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + interface->actions[i], filename); break; } @@ -392,28 +400,21 @@ GPluginModule *g_plugin_module_new(const gchar *filename) case PGA_FORMAT_ANALYSIS_ENDED: case PGA_FORMAT_POST_ANALYSIS_STARTED: case PGA_FORMAT_POST_ANALYSIS_ENDED: - if (!load_plugin_symbol(result->module, - "handle_binary_format_analysis", - &result->handle_fmt_analysis)) - goto bad_plugin; + valid = check_plugin_symbol(module, "handle_binary_format_analysis"); break; case PGA_FORMAT_PRELOAD: - if (!load_plugin_symbol(result->module, - "preload_binary_format", &result->preload_format)) - goto bad_plugin; + valid = check_plugin_symbol(module, "preload_binary_format"); break; case PGA_FORMAT_ATTACH_DEBUG: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_attach_debug", &result->attach_debug)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug"); break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + interface->actions[i], filename); break; } @@ -421,15 +422,11 @@ GPluginModule *g_plugin_module_new(const gchar *filename) break; case DPS_DISASSEMBLY: - if (!load_plugin_symbol(result->module, - "process_binary_disassembly", &result->process_disass)) - goto bad_plugin; + valid = check_plugin_symbol(module, "process_binary_disassembly"); break; case DPS_DETECTION: - if (!load_plugin_symbol(result->module, - "chrysalide_plugin_detect_external_tools", &result->detect)) - goto bad_plugin; + valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools"); break; default: @@ -450,11 +447,29 @@ GPluginModule *g_plugin_module_new(const gchar *filename) } + if (!valid) + goto bad_plugin; + + gtype = built_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name, + (GClassInitFunc)g_plugin_module_init_gclass, module); + + if (gtype == G_TYPE_INVALID) + goto bad_plugin; + + result = g_object_new(gtype, NULL); + + result->filename = strdup(filename); + result->module = module; + + result->interface = interface; + return result; bad_plugin: - g_object_unref(G_OBJECT(result)); + g_module_close(module); + + bad_module: return NULL; @@ -463,6 +478,212 @@ GPluginModule *g_plugin_module_new(const gchar *filename) /****************************************************************************** * * +* Paramètres : class = classe à initialiser. * +* module = module représentant le greffon chargé en mémoire. * +* * +* Description : Initialise la classe des greffons d'extension. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module) +{ + const plugin_interface *interface; /* Déclaration d'interfaçage */ + size_t i; /* Boucle de parcours */ + uint32_t action; /* Identifiant d'une action */ + uint32_t category; /* Catégorie principale */ + uint32_t sub; /* Sous-catégorie visée */ + + +#undef load_plugin_symbol + +#define load_plugin_symbol(mod, sym, dest) \ + ({ \ + bool __result; \ + __result = g_module_symbol(mod, sym, (gpointer *)dest); \ + assert(__result); \ + __result; \ + }) + + + load_plugin_symbol(module, "_chrysalide_plugin", &interface); + + for (i = 0; i < interface->actions_count; i++) + { + action = interface->actions[i]; + category = MASK_PLUGIN_CATEGORY(action); + sub = MASK_PLUGIN_SUB_CATEGORY(action); + + switch (category) + { + case DPC_BASIC: + + switch (sub) + { + case DPS_NONE: + break; + + case DPS_PG_MANAGEMENT: + + switch (action) + { + case PGA_PLUGIN_INIT: + load_plugin_symbol(module, "chrysalide_plugin_init", &class->init); + break; + + case PGA_PLUGIN_EXIT: + load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit); + break; + + default: + assert(false); + break; + + } + + break; + + case DPS_CORE_MANAGEMENT: + + switch (action) + { + case PGA_NATIVE_LOADED: + load_plugin_symbol(module, "chrysalide_plugin_on_native_loaded", + &class->native_loaded); + break; + + default: + assert(false); + break; + + } + + break; + + default: + assert(false); + break; + + } + + break; + + case DPC_GUI: + + switch (sub) + { + case DPS_SETUP: + + switch (action) + { + case PGA_GUI_THEME: + load_plugin_symbol(module, "chrysalide_plugin_include_theme", + &class->include_theme); + break; + + default: + assert(false); + break; + + } + + break; + + default: + assert(false); + break; + + } + + break; + + case DPC_BINARY_PROCESSING: + + switch (sub) + { + case DPS_CONTENT: + + switch (action) + { + case PGA_CONTENT_EXPLORER: + case PGA_CONTENT_RESOLVER: + load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content", + &class->handle_content); + break; + + case PGA_CONTENT_ANALYZED: + load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content", + &class->handle_loaded); + break; + + default: + assert(false); + break; + + } + + break; + + case DPS_FORMAT: + + switch (action) + { + case PGA_FORMAT_ANALYSIS_STARTED: + case PGA_FORMAT_ANALYSIS_ENDED: + case PGA_FORMAT_POST_ANALYSIS_STARTED: + case PGA_FORMAT_POST_ANALYSIS_ENDED: + load_plugin_symbol(module, "handle_binary_format_analysis", + &class->handle_fmt_analysis); + break; + + case PGA_FORMAT_PRELOAD: + load_plugin_symbol(module, "preload_binary_format", &class->preload_format); + break; + + case PGA_FORMAT_ATTACH_DEBUG: + load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug); + break; + + default: + assert(false); + break; + + } + + break; + + case DPS_DISASSEMBLY: + load_plugin_symbol(module, "process_binary_disassembly", &class->process_disass); + break; + + case DPS_DETECTION: + load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect); + break; + + default: + assert(false); + break; + + } + + break; + + default: + assert(false); + break; + + } + + } + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à consulter. * * * * Description : Indique le fichier contenant le greffon manipulé. * @@ -654,6 +875,7 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co const plugin_interface *pg_iface; /* Définition du greffon */ size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ + GPluginModuleClass *class; /* Classe de l'instance active */ char *dir; /* Répertoire modifiable */ /* Si un essai précédent a déjà échoué ou réussi... */ @@ -689,9 +911,11 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co if (result) { - if (plugin->init != NULL) + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + if (class->init != NULL) { - result = plugin->init(plugin); + result = class->init(plugin); if (!result) { @@ -810,7 +1034,11 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction action, void *unused) { - plugin->native_loaded(plugin, action); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->native_loaded(plugin, action); } @@ -832,7 +1060,11 @@ void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction ac void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count) { - plugin->include_theme(plugin, action, resources, count); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->include_theme(plugin, action, resources, count); } @@ -855,7 +1087,11 @@ void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction act void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status) { - return plugin->handle_content(plugin, action, content, wid, status); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->handle_content(plugin, action, content, wid, status); } @@ -878,7 +1114,11 @@ void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAc void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status) { - return plugin->handle_loaded(plugin, action, content, wid, status); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + return class->handle_loaded(plugin, action, content, wid, status); } @@ -901,7 +1141,11 @@ void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAc bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status) { - return plugin->handle_fmt_analysis(plugin, action, format, gid, status); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + return class->handle_fmt_analysis(plugin, action, format, gid, status); } @@ -924,7 +1168,11 @@ bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin, bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status) { - return plugin->preload_format(plugin, action, format, info, status); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + return class->preload_format(plugin, action, format, info, status); } @@ -945,7 +1193,11 @@ bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAc void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginAction action, GExeFormat *format) { - plugin->attach_debug(plugin, action, format); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->attach_debug(plugin, action, format); } @@ -968,7 +1220,11 @@ void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginActi void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context) { - plugin->process_disass(plugin, action, binary, status, context); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->process_disass(plugin, action, binary, status, context); } @@ -992,6 +1248,10 @@ void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, Plug void g_plugin_module_detect_external_tools(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count) { - plugin->detect(plugin, action, content, version, names, count); + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->detect(plugin, action, content, version, names, count); } diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index 4b3b306..cccd39b 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -59,12 +59,12 @@ typedef enum _PluginStatusFlags #define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE) -#define G_TYPE_PLUGIN_MODULE (g_plugin_module_get_type()) -#define G_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule)) -#define G_IS_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE)) -#define G_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass)) -#define G_IS_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE)) -#define G_PLUGIN_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass)) +#define G_TYPE_PLUGIN_MODULE (g_plugin_module_get_type()) +#define G_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule)) +#define G_IS_PLUGIN_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE)) +#define G_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass)) +#define G_IS_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE)) +#define G_PLUGIN_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass)) /* Indique le type défini pour un greffon. */ |