From c1bcf3e7bd0a256005bd15832117b78cee5fdfab Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 22 Jan 2019 19:28:36 +0100 Subject: Allowed to initialize instances of created dynamic types if needed. --- plugins/pychrysalide/arch/operands/register.c | 4 +- plugins/pychrysalide/arch/processor.c | 105 +++++++++++++++++++++++++- plugins/pychrysalide/arch/register.c | 4 +- plugins/pychrysalide/gui/panels/panel.c | 4 +- plugins/pychrysalide/plugin.c | 4 +- src/plugins/dt.c | 98 +++++++++++++++++++++--- src/plugins/dt.h | 8 +- src/plugins/plugin.c | 4 +- tests/arch/errors.py | 13 +++- tests/arch/processor.py | 13 +++- 10 files changed, 229 insertions(+), 28 deletions(-) diff --git a/plugins/pychrysalide/arch/operands/register.c b/plugins/pychrysalide/arch/operands/register.c index 74b6a4f..8144af0 100644 --- a/plugins/pychrysalide/arch/operands/register.c +++ b/plugins/pychrysalide/arch/operands/register.c @@ -100,8 +100,8 @@ static PyObject *py_register_operand_new(PyTypeObject *type, PyObject *args, PyO first_time = (g_type_from_name(type->tp_name) == 0); - gtype = built_dynamic_type(G_TYPE_REGISTER_OPERAND, type->tp_name, - (GClassInitFunc)py_register_operand_init_gclass, NULL); + gtype = build_dynamic_type(G_TYPE_REGISTER_OPERAND, type->tp_name, + (GClassInitFunc)py_register_operand_init_gclass, NULL, NULL); if (first_time) { diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c index 8fc2598..b59e59b 100644 --- a/plugins/pychrysalide/arch/processor.c +++ b/plugins/pychrysalide/arch/processor.c @@ -54,6 +54,12 @@ static PyObject *py_arch_processor_new(PyTypeObject *, PyObject *, PyObject *); /* Initialise la classe des descriptions de fichier binaire. */ static void py_arch_processor_init_gclass(GArchProcessorClass *, gpointer); +/* Initialise une instance de processeur d'architecture. */ +static void py_arch_processor_init_ginstance(GArchProcessor *, GArchProcessor *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_arch_processor_init(PyObject *, PyObject *, PyObject *); + /* Fournit un contexte propre au processeur d'une architecture. */ static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *); @@ -160,8 +166,9 @@ static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObj first_time = (g_type_from_name(type->tp_name) == 0); - gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name, - (GClassInitFunc)py_arch_processor_init_gclass, NULL); + gtype = build_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name, + (GClassInitFunc)py_arch_processor_init_gclass, NULL, + (GInstanceInitFunc)py_arch_processor_init_ginstance); if (first_time) { @@ -191,7 +198,7 @@ static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObj * Paramètres : class = classe à initialiser. * * unused = données non utilisées ici. * * * -* Description : Initialise la classe des descriptions de fichier binaire. * +* Description : Initialise la classe générique des processeurs. * * * * Retour : - * * * @@ -210,6 +217,97 @@ static void py_arch_processor_init_gclass(GArchProcessorClass *class, gpointer u /****************************************************************************** * * +* Paramètres : proc = instance à initialiser. * +* class = classe du type correspondant. * +* * +* Description : Initialise une instance de processeur d'architecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_arch_processor_init_ginstance(GArchProcessor *proc, GArchProcessor *class) +{ + GType type; /* Type d'instances concerné */ + GArchProcessor *pattern; /* Patron de données à copier */ + + type = G_TYPE_FROM_INSTANCE(proc); + + pattern = get_dynamic_type_pattern(type); + + if (pattern != NULL) + { + proc->endianness = pattern->endianness; + proc->memsize = pattern->memsize; + proc->inssize = pattern->inssize; + proc->virt_space = pattern->virt_space; + } + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_arch_processor_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + unsigned long endianness; /* Boutisme du processeur */ + unsigned long mem_size; /* Taille d'adressage */ + unsigned long ins_min_size; /* Taille minimale d'instruct° */ + int vspace; /* Support d'un espace virtuel */ + int ret; /* Bilan de lecture des args. */ + PyObject *new_kwds; /* Nouveau dictionnaire épuré */ + GArchProcessor *proc; /* Processeur à manipuler */ + + static char *kwlist[] = { "endianness", "mem_size", "ins_min_size", "vspace", NULL }; + + /* Récupération des paramètres */ + + ret = PyArg_ParseTupleAndKeywords(args, kwds, "kkkp", kwlist, + &endianness, &mem_size, &ins_min_size, &vspace); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + new_kwds = PyDict_New(); + + ret = PyGObject_Type.tp_init(self, args, new_kwds); + + Py_DECREF(new_kwds); + + if (ret == -1) return -1; + + /* Eléments de base */ + + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + proc->endianness = endianness; + proc->memsize = mem_size; + proc->inssize = ins_min_size; + proc->virt_space = vspace; + + register_dynamic_type_pattern(G_OBJECT(proc)); + + return 0; + +} + + +/****************************************************************************** +* * * Paramètres : proc = architecture visée par la procédure. * * * * Description : Fournit un contexte propre au processeur d'une architecture. * @@ -930,6 +1028,7 @@ PyTypeObject *get_python_arch_processor_type(void) .tp_methods = py_arch_processor_methods, .tp_getset = py_arch_processor_getseters, + .tp_init = py_arch_processor_init, .tp_new = py_arch_processor_new, }; diff --git a/plugins/pychrysalide/arch/register.c b/plugins/pychrysalide/arch/register.c index 0299fa6..c55cd2b 100644 --- a/plugins/pychrysalide/arch/register.c +++ b/plugins/pychrysalide/arch/register.c @@ -103,8 +103,8 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje first_time = (g_type_from_name(type->tp_name) == 0); - gtype = built_dynamic_type(G_TYPE_ARCH_REGISTER, type->tp_name, - (GClassInitFunc)py_arch_register_init_gclass, NULL); + gtype = build_dynamic_type(G_TYPE_ARCH_REGISTER, type->tp_name, + (GClassInitFunc)py_arch_register_init_gclass, NULL, NULL); if (first_time) { diff --git a/plugins/pychrysalide/gui/panels/panel.c b/plugins/pychrysalide/gui/panels/panel.c index 0db1df8..2d0b562 100644 --- a/plugins/pychrysalide/gui/panels/panel.c +++ b/plugins/pychrysalide/gui/panels/panel.c @@ -109,8 +109,8 @@ static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject first_time = (g_type_from_name(type->tp_name) == 0); - gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name, - (GClassInitFunc)py_panel_item_init_gclass, NULL); + gtype = build_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name, + (GClassInitFunc)py_panel_item_init_gclass, NULL, NULL); if (first_time) { diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index 7667af7..51da910 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -175,8 +175,8 @@ static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObje first_time = (g_type_from_name(type->tp_name) == 0); - gtype = built_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name, - (GClassInitFunc)py_plugin_module_init_gclass, NULL); + gtype = build_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name, + (GClassInitFunc)py_plugin_module_init_gclass, NULL, NULL); if (first_time) { diff --git a/src/plugins/dt.c b/src/plugins/dt.c index afdba21..14b03f0 100644 --- a/src/plugins/dt.c +++ b/src/plugins/dt.c @@ -26,6 +26,7 @@ #include #include +#include @@ -44,9 +45,14 @@ typedef struct _type_dyn_info_t { GType type; /* Identifiant unique obtenu */ - GClassInitFunc init; /* Définition des méthodes */ + + GClassInitFunc cinit; /* Phase d'initialisation #1 */ gconstpointer data; /* Eventuelles données utiles */ + GInstanceInitFunc init; /* Phase d'initialisation #2 */ + + void *pattern; /* Modèle de données d'instance*/ + } type_dyn_info_t; /* Description de fichier binaire (instance) */ @@ -98,10 +104,10 @@ static void g_dynamic_types_unuse(GDynamicTypes *); 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); +static 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); +static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc); @@ -297,7 +303,7 @@ static void g_dynamic_types_unuse(GDynamicTypes *types) static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table) { - const type_dyn_info_t *nfo; /* Source d'inspiration */ + type_dyn_info_t *nfo; /* Source d'inspiration */ GType parent; /* Type parent du type */ GTypeQuery query; /* Informations complémentaires*/ @@ -312,10 +318,11 @@ static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTyp /* Définition */ info->class_size = query.class_size; - info->class_init = nfo->init; + info->class_init = nfo->cinit; info->class_data = nfo->data; info->instance_size = query.instance_size; + info->instance_init = nfo->init; } @@ -333,7 +340,7 @@ static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTyp * * ******************************************************************************/ -static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target) +static 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 */ @@ -353,8 +360,9 @@ static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, G * * * Paramètres : parent = type GLib parent. * * name = désignation du nouveau type. * -* init = procédure d'initialisation de la classe associée. * +* cinit = procédure d'initialisation de la classe associée. * * data = éventuelles données à associer à la future classe. * +* init = procédure d'initialisation pour chaque instance. * * * * Description : Fournit un identifiant GLib pour un nouveau type. * * * @@ -364,7 +372,7 @@ static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, G * * ******************************************************************************/ -static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init, gconstpointer data) +static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init) { GType result; /* Identifiant à retourner */ type_dyn_info_t *new; /* Mémorisation de paramètres */ @@ -379,9 +387,14 @@ static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, c new = malloc(sizeof(type_dyn_info_t)); new->type = result; - new->init = init; + + new->cinit = cinit; new->data = data; + new->init = init; + + new->pattern = NULL; + /* Inscription définitive */ types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *)); @@ -449,8 +462,9 @@ void exit_chrysalide_dynamic_types(void) * * * Paramètres : parent = type GLib parent. * * name = désignation du nouveau type. * -* init = procédure d'initialisation de la classe associée. * +* cinit = procédure d'initialisation de la classe associée. * * data = éventuelles données à associer à la future classe. * +* init = procédure d'initialisation pour chaque instance. * * * * Description : Fournit un identifiant GLib pour un nouveau type. * * * @@ -460,14 +474,74 @@ void exit_chrysalide_dynamic_types(void) * * ******************************************************************************/ -GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init, gconstpointer data) +GType build_dynamic_type(GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init) { 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); + result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, cinit, data, init); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instance = instance portant les données à conserver. * +* * +* Description : Enregistre les données correspondant à une instance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_dynamic_type_pattern(GObject *instance) +{ + GType type; /* Type d'instances concerné */ + type_dyn_info_t *nfo; /* Source d'inspiration */ + GTypeQuery query; /* Informations complémentaires*/ + + type = G_TYPE_FROM_INSTANCE(instance); + + nfo = g_dynamic_types_find(_chrysalide_dtypes, type); + assert(nfo != NULL); + + g_type_query(type, &query); + + if (nfo->pattern == NULL) + nfo->pattern = malloc(query.instance_size); + + memcpy(nfo->pattern, instance, query.instance_size); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'une instance créée sans initialisation. * +* * +* Description : Fournit les données correspondant à une instance initiale. * +* * +* Retour : Données issues de la première instance d'un type ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +void *get_dynamic_type_pattern(GType type) +{ + void *result; /* Modèle éventuel à retourner */ + type_dyn_info_t *nfo; /* Source d'inspiration */ + + nfo = g_dynamic_types_find(_chrysalide_dtypes, type); + assert(nfo != NULL); + + result = nfo->pattern; return result; diff --git a/src/plugins/dt.h b/src/plugins/dt.h index b9d4656..c25f4fd 100644 --- a/src/plugins/dt.h +++ b/src/plugins/dt.h @@ -40,7 +40,13 @@ bool init_chrysalide_dynamic_types(void); void exit_chrysalide_dynamic_types(void); /* Fournit un identifiant GLib pour un nouveau type. */ -GType built_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer); +GType build_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc); + +/* Enregistre les données correspondant à une instance. */ +void register_dynamic_type_pattern(GObject *); + +/* Fournit les données correspondant à une instance initiale. */ +void *get_dynamic_type_pattern(GType); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index ff3db31..1bdcf04 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -450,8 +450,8 @@ 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); + 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 bad_plugin; diff --git a/tests/arch/errors.py b/tests/arch/errors.py index 8affb77..e57b94b 100644 --- a/tests/arch/errors.py +++ b/tests/arch/errors.py @@ -6,6 +6,7 @@ from chrysacase import ChrysalideTestCase +from pychrysalide import arch from pychrysalide.arch import vmpa from pychrysalide.arch import ArchProcessor @@ -28,7 +29,17 @@ class TestArchErrors(ChrysalideTestCase): class NewProc(ArchProcessor): - pass + + def __init__(self): + + props = { + 'endianness': arch.SRE_LITTLE, + 'mem_size': arch.MDS_32_BITS_UNSIGNED, + 'ins_min_size': arch.MDS_32_BITS_UNSIGNED, + 'vspace': False + } + + super(NewProc, self).__init__(**props) proc = NewProc() diff --git a/tests/arch/processor.py b/tests/arch/processor.py index 97a713d..bf17b98 100644 --- a/tests/arch/processor.py +++ b/tests/arch/processor.py @@ -5,13 +5,13 @@ import pychrysalide from chrysacase import ChrysalideTestCase from pychrysalide.analysis.contents import MemoryContent +from pychrysalide import arch from pychrysalide.arch import ArchProcessor from pychrysalide.arch import ProcContext from pychrysalide.arch import vmpa from pychrysalide.format import FlatFormat - class TestProcessor(ChrysalideTestCase): """TestCase for arch.ArchProcessor.""" @@ -28,6 +28,17 @@ class TestProcessor(ChrysalideTestCase): class NewProcWithCtx(ArchProcessor): + def __init__(self): + + props = { + 'endianness': arch.SRE_LITTLE, + 'mem_size': arch.MDS_32_BITS_UNSIGNED, + 'ins_min_size': arch.MDS_32_BITS_UNSIGNED, + 'vspace': False + } + + super(NewProcWithCtx, self).__init__(**props) + def _get_context(self): return NewContext() -- cgit v0.11.2-87-g4458