From a59fb1b3fb67a348c40bc3668445d64213e9e674 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 7 Mar 2025 10:29:32 +0100 Subject: Prepare a new way to store objects. --- plugins/pychrysalide/analysis/storage/serialize.c | 501 ------------- plugins/pychrysalide/analysis/storage/serialize.h | 45 -- plugins/pychrysalide/analysis/storage/storage.c | 687 ----------------- plugins/pychrysalide/analysis/storage/storage.h | 48 -- plugins/pychrysalide/analysis/storage/tpmem.c | 508 ------------- plugins/pychrysalide/analysis/storage/tpmem.h | 45 -- plugins/pychrysalide/glibext/serialize.c | 501 +++++++++++++ plugins/pychrysalide/glibext/serialize.h | 45 ++ plugins/pychrysalide/glibext/storage.c | 687 +++++++++++++++++ plugins/pychrysalide/glibext/storage.h | 48 ++ plugins/pychrysalide/glibext/tpmem.c | 508 +++++++++++++ plugins/pychrysalide/glibext/tpmem.h | 45 ++ src/analysis/storage/Makefile.am | 7 +- src/analysis/storage/serialize-int.h | 58 -- src/analysis/storage/serialize.c | 111 --- src/analysis/storage/serialize.h | 64 -- src/analysis/storage/storage-int.h | 66 -- src/analysis/storage/storage.c | 867 ---------------------- src/analysis/storage/storage.h | 89 --- src/analysis/storage/tpmem.c | 429 ----------- src/analysis/storage/tpmem.h | 70 -- src/glibext/serialize-int.h | 58 ++ src/glibext/serialize.c | 111 +++ src/glibext/serialize.h | 64 ++ src/glibext/storage-int.h | 66 ++ src/glibext/storage.c | 867 ++++++++++++++++++++++ src/glibext/storage.h | 89 +++ src/glibext/tpmem.c | 429 +++++++++++ src/glibext/tpmem.h | 70 ++ tests/analysis/storage/storage.py | 81 -- tests/glibext/storage.py | 81 ++ 31 files changed, 3670 insertions(+), 3675 deletions(-) delete mode 100644 plugins/pychrysalide/analysis/storage/serialize.c delete mode 100644 plugins/pychrysalide/analysis/storage/serialize.h delete mode 100644 plugins/pychrysalide/analysis/storage/storage.c delete mode 100644 plugins/pychrysalide/analysis/storage/storage.h delete mode 100644 plugins/pychrysalide/analysis/storage/tpmem.c delete mode 100644 plugins/pychrysalide/analysis/storage/tpmem.h create mode 100644 plugins/pychrysalide/glibext/serialize.c create mode 100644 plugins/pychrysalide/glibext/serialize.h create mode 100644 plugins/pychrysalide/glibext/storage.c create mode 100644 plugins/pychrysalide/glibext/storage.h create mode 100644 plugins/pychrysalide/glibext/tpmem.c create mode 100644 plugins/pychrysalide/glibext/tpmem.h delete mode 100644 src/analysis/storage/serialize-int.h delete mode 100644 src/analysis/storage/serialize.c delete mode 100644 src/analysis/storage/serialize.h delete mode 100644 src/analysis/storage/storage-int.h delete mode 100644 src/analysis/storage/storage.c delete mode 100644 src/analysis/storage/storage.h delete mode 100644 src/analysis/storage/tpmem.c delete mode 100644 src/analysis/storage/tpmem.h create mode 100644 src/glibext/serialize-int.h create mode 100644 src/glibext/serialize.c create mode 100644 src/glibext/serialize.h create mode 100644 src/glibext/storage-int.h create mode 100644 src/glibext/storage.c create mode 100644 src/glibext/storage.h create mode 100644 src/glibext/tpmem.c create mode 100644 src/glibext/tpmem.h delete mode 100644 tests/analysis/storage/storage.py create mode 100644 tests/glibext/storage.py diff --git a/plugins/pychrysalide/analysis/storage/serialize.c b/plugins/pychrysalide/analysis/storage/serialize.c deleted file mode 100644 index 40fcef7..0000000 --- a/plugins/pychrysalide/analysis/storage/serialize.c +++ /dev/null @@ -1,501 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * serialize.c - équivalent Python du fichier "analysis/storage/serialize.h" - * - * Copyright (C) 2020 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 "serialize.h" - - -#include - - -#include - - -#include "storage.h" -#include "../../access.h" -#include "../../helpers.h" -#include "../../common/packed.h" - - - -/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ - - -/* Procède à l'initialisation de l'interface de génération. */ -static void py_serializable_object_interface_init(GSerializableObjectIface *, gpointer *); - -/* Charge un objet depuis une mémoire tampon. */ -static bool py_serializable_object_load_wrapper(GSerializableObject *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un objet dans une mémoire tampon. */ -static bool py_serializable_object_store_wrapper(const GSerializableObject *, GObjectStorage *, packed_buffer_t *); - - - -/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ - - -/* Charge un objet depuis une mémoire tampon. */ -static bool py_serializable_object_load(PyObject *, PyObject *); - -/* Sauvegarde un objet dans une mémoire tampon. */ -static bool py_serializable_object_store(PyObject *, PyObject *); - - - -/* ---------------------------------------------------------------------------------- */ -/* GLUE POUR CREATION DEPUIS PYTHON */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* unused = adresse non utilisée ici. * -* * -* Description : Procède à l'initialisation de l'interface de génération. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void py_serializable_object_interface_init(GSerializableObjectIface *iface, gpointer *unused) -{ - -#define SERIALIZABLE_OBJECT_DOC \ - "SerializableObject defines an interface used to store and load" \ - " objects to and from a data buffer.\n" \ - "\n" \ - "A typical class declaration for a new implementation looks like:\n" \ - "\n" \ - " class NewImplem(GObject.Object, SerializableObject):\n" \ - " ...\n" \ - "\n" \ - "The following methods have to be defined for new implementations:\n" \ - "* pychrysalide.analysis.storage.SerializableObject._load();\n" \ - "* pychrysalide.analysis.storage.SerializableObject._store();\n" - - iface->load = py_serializable_object_load_wrapper; - iface->store = py_serializable_object_store_wrapper; - -} - - -/****************************************************************************** -* * -* Paramètres : object = instruction d'assemblage à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge un objet depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_serializable_object_load_wrapper(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *storage_obj; /* Objet Python à emmployer */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *pyret; /* Bilan de consultation */ - -#define SERIALIZABLE_OBJECT_LOAD_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _load, "$self, storage, pbuf, /", \ - METH_VARARGS, \ - "Abstract method used to load an object definition from buffered data.\n" \ - "\n" \ - "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ - " provided to store inner objects, if relevant, or None. The *pbuf*" \ - " argument points to a pychrysalide.common.PackedBuffer object containing" \ - " the data to process.\n" \ - "\n" \ - "The result is a boolean indicating the status of the operation." \ -) - - result = false; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(object)); - - if (has_python_method(pyobj, "_load")) - { - if (storage == NULL) - { - storage_obj = Py_None; - Py_INCREF(storage_obj); - } - else - storage_obj = pygobject_new(G_OBJECT(storage)); - - args = PyTuple_New(2); - PyTuple_SetItem(args, 0, storage_obj); - PyTuple_SetItem(args, 1, build_from_internal_packed_buffer(pbuf)); - - pyret = run_python_method(pyobj, "_load", args); - - result = (pyret == Py_True ? true : false); - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : object = instruction d'assemblage à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un objet dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_serializable_object_store_wrapper(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *storage_obj; /* Objet Python à emmployer */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *pyret; /* Bilan de consultation */ - -#define SERIALIZABLE_OBJECT_STORE_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _store, "$self, storage, pbuf, /", \ - METH_VARARGS, \ - "Abstract method used to store an object definition into buffered data.\n" \ - "\n" \ - "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ - " provided to store inner objects, if relevant, or None. The *pbuf*" \ - " argument points to a pychrysalide.common.PackedBuffer object containing" \ - " the data to process.\n" \ - "\n" \ - "The result is a boolean indicating the status of the operation." \ -) - - result = false; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(object)); - - if (has_python_method(pyobj, "_store")) - { - if (storage == NULL) - { - storage_obj = Py_None; - Py_INCREF(storage_obj); - } - else - storage_obj = pygobject_new(G_OBJECT(storage)); - - args = PyTuple_New(2); - PyTuple_SetItem(args, 0, storage_obj); - PyTuple_SetItem(args, 1, build_from_internal_packed_buffer(pbuf)); - - pyret = run_python_method(pyobj, "_store", args); - - result = (pyret == Py_True ? true : false); - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONNEXION AVEC L'API DE PYTHON */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant un générateur à manipuler. * -* args = arguments fournis à l'appel. * -* * -* Description : Charge un objet depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_serializable_object_load(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GObjectStorage *storage; /* Conservateur à manipuler */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GSerializableObject *object; /* Version native */ - bool status; /* Bilan de l'opération */ - -#define SERIALIZABLE_OBJECT_LOAD_METHOD PYTHON_METHOD_DEF \ -( \ - load, "$self, storage, pbuf, /", \ - METH_VARARGS, py_serializable_object, \ - "Load an object definition from buffered data.\n" \ - "\n" \ - "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ - " provided to store inner objects, if relevant, or None. The *pbuf*" \ - " argument points to a pychrysalide.common.PackedBuffer object containing" \ - " the data to process.\n" \ - "\n" \ - "The result is a boolean indicating the status of the operation." \ -) - - ret = PyArg_ParseTuple(args, "O&O&", convert_to_object_storage_or_none, &storage, - convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); - - status = g_serializable_object_load(object, storage, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant un générateur à manipuler. * -* args = arguments fournis à l'appel. * -* * -* Description : Sauvegarde un objet dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_serializable_object_store(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GObjectStorage *storage; /* Conservateur à manipuler */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GSerializableObject *object; /* Version native */ - bool status; /* Bilan de l'opération */ - -#define SERIALIZABLE_OBJECT_STORE_METHOD PYTHON_METHOD_DEF \ -( \ - store, "$self, storage, pbuf, /", \ - METH_VARARGS, py_serializable_object, \ - "Store an object definition into buffered data.\n" \ - "\n" \ - "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ - " provided to store inner objects, if relevant, or None. The *pbuf*" \ - " argument points to a pychrysalide.common.PackedBuffer object containing" \ - " the data to process.\n" \ - "\n" \ - "The result is a boolean indicating the status of the operation." \ -) - - ret = PyArg_ParseTuple(args, "O&O&", convert_to_object_storage_or_none, &storage, - convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); - - status = g_serializable_object_store(object, storage, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_serializable_object_type(void) -{ - static PyMethodDef py_serializable_object_methods[] = { - SERIALIZABLE_OBJECT_LOAD_WRAPPER, - SERIALIZABLE_OBJECT_STORE_WRAPPER, - SERIALIZABLE_OBJECT_LOAD_METHOD, - SERIALIZABLE_OBJECT_STORE_METHOD, - { NULL } - }; - - static PyGetSetDef py_serializable_object_getseters[] = { - { NULL } - }; - - static PyTypeObject py_serializable_object_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.analysis.storage.SerializableObject", - .tp_basicsize = sizeof(PyObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = SERIALIZABLE_OBJECT_DOC, - - .tp_methods = py_serializable_object_methods, - .tp_getset = py_serializable_object_getseters, - - }; - - return &py_serializable_object_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide....SerializableObject'.* -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool ensure_python_serializable_object_is_registered(void) -{ - PyTypeObject *type; /* Type 'SerializableObject' */ - PyObject *module; /* Module à recompléter */ - PyObject *dict; /* Dictionnaire du module */ - - static GInterfaceInfo info = { /* Paramètres d'inscription */ - - .interface_init = (GInterfaceInitFunc)py_serializable_object_interface_init, - .interface_finalize = NULL, - .interface_data = NULL, - - }; - - type = get_python_serializable_object_type(); - - if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) - { - module = get_access_to_python_module("pychrysalide.analysis.storage"); - - dict = PyModule_GetDict(module); - - if (!register_interface_for_pygobject(dict, G_TYPE_SERIALIZABLE_OBJECT, type, &info)) - return false; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en objet adapté à une mise en cache. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_serializable_object(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - - result = PyObject_IsInstance(arg, (PyObject *)get_python_serializable_object_type()); - - switch (result) - { - case -1: - /* L'exception est déjà fixée par Python */ - result = 0; - break; - - case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to serializable object"); - break; - - case 1: - *((GSerializableObject **)dst) = G_SERIALIZABLE_OBJECT(pygobject_get(arg)); - break; - - default: - assert(false); - break; - - } - - return result; - -} diff --git a/plugins/pychrysalide/analysis/storage/serialize.h b/plugins/pychrysalide/analysis/storage/serialize.h deleted file mode 100644 index 7e831e5..0000000 --- a/plugins/pychrysalide/analysis/storage/serialize.h +++ /dev/null @@ -1,45 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * serialize.h - prototypes pour l'équivalent Python du fichier "analysis/storage/serialize.h" - * - * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H -#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_serializable_object_type(void); - -/* Prend en charge l'objet 'pychrysalide.analysis.storage.SerializableObject'. */ -bool ensure_python_serializable_object_is_registered(void); - -/* Tente de convertir en objet adapté à une mise en cache. */ -int convert_to_serializable_object(PyObject *, void *); - - - -#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H */ diff --git a/plugins/pychrysalide/analysis/storage/storage.c b/plugins/pychrysalide/analysis/storage/storage.c deleted file mode 100644 index c54fe0f..0000000 --- a/plugins/pychrysalide/analysis/storage/storage.c +++ /dev/null @@ -1,687 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * storage.c - équivalent Python du fichier "analysis/storage/storage.c" - * - * Copyright (C) 2020 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 "storage.h" - - -#include - - -#include -#include - - -#include "serialize.h" -#include "../../access.h" -#include "../../helpers.h" -#include "../../common/packed.h" - - - -/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ - - -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_object_storage_new(PyTypeObject *, PyObject *, PyObject *); - -/* Initialise une instance sur la base du dérivé de GObject. */ -static int py_object_storage_init(PyObject *, PyObject *, PyObject *); - - - -/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ - - -/* Charge le support d'une conservation d'objets en place. */ -static PyObject *py_object_storage_load(PyObject *, PyObject *); - -/* Sauvegarde le support d'une conservation d'objets en place. */ -static PyObject *py_object_storage_store(PyObject *, PyObject *); - -/* Charge un objet à partir de données rassemblées. */ -static PyObject *py_object_storage_load_object(PyObject *, PyObject *); - -/* Charge un objet interne à partir de données rassemblées. */ -static PyObject *py_object_storage_unpack_object(PyObject *, PyObject *); - -/* Sauvegarde un object sous forme de données rassemblées. */ -static PyObject *py_object_storage_store_object(PyObject *, PyObject *); - -/* Sauvegarde un object interne sous forme de données. */ -static PyObject *py_object_storage_pack_object(PyObject *, PyObject *); - - - -/* ---------------------------------------------------------------------------------- */ -/* GLUE POUR CREATION DEPUIS PYTHON */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * -* * -* Description : Accompagne la création d'une instance dérivée en Python. * -* * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type de base à dériver */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ - - /* Validations diverses */ - - base = get_python_object_storage_type(); - - if (type == base) - goto simple_way; - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(G_TYPE_OBJECT_STORAGE, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* 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_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - const char *hash; /* Empreinte de contenu */ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - -#define OBJECT_STORAGE_DOC \ - "The ObjectStorage object manages the generic storage of GLib" \ - " objects through serialization.\n" \ - "\n" \ - "Instances can be created using the following constructor:\n" \ - "\n" \ - " ObjectStorage(hash)" \ - "\n" \ - "Where *hash* should a string built from the checksum of the" \ - " relative binary content linked to the storage.pychrysalide." - - /* Récupération des paramètres */ - - ret = PyArg_ParseTuple(args, "s", &hash); - if (!ret) return -1; - - /* Initialisation d'un objet GLib */ - - ret = forward_pygobjet_init(self); - if (ret == -1) return -1; - - /* Eléments de base */ - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - storage->hash = strdup(hash); - - return 0; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* TAMPON POUR CODE DESASSEMBLE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Charge le support d'une conservation d'objets en place. * -* * -* Retour : Gestionnaire de conservations construit ou None si erreur. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_load(PyObject *self, PyObject *args) -{ - PyObject *result; /* Emplacement à retourner */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - -#define OBJECT_STORAGE_LOAD_METHOD PYTHON_METHOD_DEF \ -( \ - load, "pbuf, /", \ - METH_STATIC | METH_VARARGS, py_object_storage, \ - "Construct a new storage from a buffer.\n" \ - "\n" \ - "The *pbuf* has to be an instance of type" \ - " pychrysalide.common.PackedBuffer.\n" \ - "\n" \ - "The result is a new pychrysalide.analysis.storage.ObjectStorage" \ - " object on success, *None* otherwise." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - storage = g_object_storage_load(pbuf); - - if (storage == NULL) - { - result = Py_None; - Py_INCREF(result); - } - else - { - result = pygobject_new(G_OBJECT(storage)); - g_object_unref(G_OBJECT(storage)); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Sauvegarde le support d'une conservation d'objets en place. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_store(PyObject *self, PyObject *args) -{ - PyObject *result; /* Emplacement à retourner */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - bool status; /* Bilan de l'opération */ - -#define OBJECT_STORAGE_STORE_METHOD PYTHON_METHOD_DEF \ -( \ - store, "$self, pbuf, /", \ - METH_VARARGS, py_object_storage, \ - "Save a storage into a buffer.\n" \ - "\n" \ - "The *pbuf* has to be an instance of type" \ - " pychrysalide.common.PackedBuffer.\n" \ - "\n" \ - "The result is *True* on success, *False* otherwise." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - status = g_object_storage_store(storage, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Charge un objet à partir de données rassemblées. * -* * -* Retour : Objet restauré en mémoire ou None en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_load_object(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - const char *name; /* Désignation de groupe */ - unsigned long long pos; /* Emplacement des données */ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - GSerializableObject *object; /* Objet reconstruit ou NULL */ - -#define OBJECT_STORAGE_LOAD_OBJECT_METHOD PYTHON_METHOD_DEF \ -( \ - load_object, "$self, name, pos, /", \ - METH_VARARGS, py_object_storage, \ - "Load an object from serialized data.\n" \ - "\n" \ - "The *name* is a string label for the group of target objects and" \ - " *pos* is an offset into the data stream indicating the start of" \ - " the data to unserialize.\n" \ - "\n" \ - "The result is a pychrysalide.analysis.storage.SerializableObject" \ - " instancet in case of success, or None in case of failure." \ -) - - ret = PyArg_ParseTuple(args, "sK", &name, &pos); - if (!ret) return NULL; - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - object = g_object_storage_load_object(storage, name, pos); - - if (object != NULL) - result = pygobject_new(G_OBJECT(object)); - else - { - result = Py_None; - Py_INCREF(result); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Charge un objet interne à partir de données rassemblées. * -* * -* Retour : Objet restauré en mémoire ou None en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_unpack_object(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - const char *name; /* Désignation de groupe */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - GSerializableObject *object; /* Objet reconstruit ou NULL */ - -#define OBJECT_STORAGE_UNPACK_OBJECT_METHOD PYTHON_METHOD_DEF \ -( \ - unpack_object, "$self, name, pbuf, /", \ - METH_VARARGS, py_object_storage, \ - "Load an object from a buffer with a location pointing to data.\n" \ - "\n" \ - "The *name* is a string label for the group of target objects and" \ - " *pbuf* has to be a pychrysalide.common.PackedBuffer instance.\n" \ - "\n" \ - "The result is a pychrysalide.analysis.storage.SerializableObject" \ - " instancet in case of success, or None in case of failure." \ -) - - ret = PyArg_ParseTuple(args, "sO&", &name, convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - object = g_object_storage_unpack_object(storage, name, pbuf); - - if (object != NULL) - result = pygobject_new(G_OBJECT(object)); - else - { - result = Py_None; - Py_INCREF(result); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Sauvegarde un object sous forme de données rassemblées. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_store_object(PyObject *self, PyObject *args) -{ - PyObject *result; /* Emplacement à retourner */ - const char *name; /* Désignation de groupe */ - GSerializableObject *object; /* Objet à traiter */ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - off64_t pos; /* Emplacement d'enregistrement*/ - bool status; /* Bilan de l'opération */ - -#define OBJECT_STORAGE_STORE_OBJECT_METHOD PYTHON_METHOD_DEF \ -( \ - store_object, "$self, name, object, /", \ - METH_VARARGS, py_object_storage, \ - "Save an object as serialized data.\n" \ - "\n" \ - "The *name* is a string label for the group of target objects" \ - " and the processed *object* has to be a" \ - " pychrysalide.analysis.storage.SerializableObject instance.\n" \ - "\n" \ - "The result is the position of the data for stored object," \ - " provided as an integer offset, in case of success or None" \ - " in case of failure." \ -) - - ret = PyArg_ParseTuple(args, "sO&", &name, convert_to_serializable_object, &object); - if (!ret) return NULL; - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - status = g_object_storage_store_object(storage, name, object, &pos); - - if (status) - result = PyLong_FromUnsignedLongLong((unsigned long long)pos); - else - { - result = Py_None; - Py_INCREF(result); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Sauvegarde un object interne sous forme de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_object_storage_pack_object(PyObject *self, PyObject *args) -{ - PyObject *result; /* Emplacement à retourner */ - const char *name; /* Désignation de groupe */ - GSerializableObject *object; /* Objet à traiter */ - packed_buffer_t *pbuf; /* Tampon de données à employer*/ - int ret; /* Bilan de lecture des args. */ - GObjectStorage *storage; /* Mécanismes natifs */ - bool status; /* Bilan de l'opération */ - -#define OBJECT_STORAGE_PACK_OBJECT_METHOD PYTHON_METHOD_DEF \ -( \ - pack_object, "$self, name, object, pbuf/", \ - METH_VARARGS, py_object_storage, \ - "Save an object as serialized data and store the location of" \ - " the data intro a buffer.\n" \ - "\n" \ - "The *name* is a string label for the group of target objects," \ - " the processed *object* has to be a" \ - " pychrysalide.analysis.storage.SerializableObject instance" \ - " and *pbuf* is expected to be a" \ - " pychrysalide.common.PackedBuffer instance.\n" \ - "\n" \ - "The status of the operation is returned as a boolean value:" \ - " *True* for success, *False* for failure." \ -) - - ret = PyArg_ParseTuple(args, "sO&O&", &name, convert_to_serializable_object, &object, - convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - storage = G_OBJECT_STORAGE(pygobject_get(self)); - - status = g_object_storage_pack_object(storage, name, object, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_object_storage_type(void) -{ - static PyMethodDef py_object_storage_methods[] = { - OBJECT_STORAGE_LOAD_METHOD, - OBJECT_STORAGE_STORE_METHOD, - OBJECT_STORAGE_LOAD_OBJECT_METHOD, - OBJECT_STORAGE_UNPACK_OBJECT_METHOD, - OBJECT_STORAGE_STORE_OBJECT_METHOD, - OBJECT_STORAGE_PACK_OBJECT_METHOD, - { NULL } - }; - - static PyGetSetDef py_object_storage_getseters[] = { - { NULL } - }; - - static PyTypeObject py_object_storage_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.analysis.storage.ObjectStorage", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = OBJECT_STORAGE_DOC, - - .tp_methods = py_object_storage_methods, - .tp_getset = py_object_storage_getseters, - - .tp_init = py_object_storage_init, - .tp_new = py_object_storage_new - - }; - - return &py_object_storage_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide....ObjectStorage'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool ensure_python_object_storage_is_registered(void) -{ - PyTypeObject *type; /* Type Python 'ObjectStorage' */ - PyObject *module; /* Module à recompléter */ - PyObject *dict; /* Dictionnaire du module */ - - type = get_python_object_storage_type(); - - if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) - { - module = get_access_to_python_module("pychrysalide.analysis.storage"); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type)) - return false; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en conservateur d'objets. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_object_storage(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - - result = PyObject_IsInstance(arg, (PyObject *)get_python_object_storage_type()); - - switch (result) - { - case -1: - /* L'exception est déjà fixée par Python */ - result = 0; - break; - - case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to object storage"); - break; - - case 1: - *((GObjectStorage **)dst) = G_OBJECT_STORAGE(pygobject_get(arg)); - break; - - default: - assert(false); - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en conservateur d'objets ou NULL. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_object_storage_or_none(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - - if (arg == Py_None) - { - *((GTypeMemory **)dst) = NULL; - result = 1; - } - - else - result = convert_to_object_storage(arg, dst); - - return result; - -} diff --git a/plugins/pychrysalide/analysis/storage/storage.h b/plugins/pychrysalide/analysis/storage/storage.h deleted file mode 100644 index a0a2c18..0000000 --- a/plugins/pychrysalide/analysis/storage/storage.h +++ /dev/null @@ -1,48 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * storage.h - prototypes pour l'équivalent Python du fichier "analysis/storage/storage.h" - * - * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H -#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_object_storage_type(void); - -/* Prend en charge l'objet 'pychrysalide.analysis.storage.ObjectStorage'. */ -bool ensure_python_object_storage_is_registered(void); - -/* Tente de convertir en conservateur d'objets. */ -int convert_to_object_storage(PyObject *, void *); - -/* Tente de convertir en conservateur d'objets ou NULL. */ -int convert_to_object_storage_or_none(PyObject *, void *); - - - -#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H */ diff --git a/plugins/pychrysalide/analysis/storage/tpmem.c b/plugins/pychrysalide/analysis/storage/tpmem.c deleted file mode 100644 index ae07008..0000000 --- a/plugins/pychrysalide/analysis/storage/tpmem.c +++ /dev/null @@ -1,508 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tpmem.c - équivalent Python du fichier "analysis/storage/tpmem.c" - * - * Copyright (C) 2020 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 "tpmem.h" - - -#include - - -#include -#include - - -#include "../../access.h" -#include "../../helpers.h" -#include "../../common/packed.h" - - - -/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ - - -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_type_memory_new(PyTypeObject *, PyObject *, PyObject *); - -/* Initialise une instance sur la base du dérivé de GObject. */ -static int py_type_memory_init(PyObject *, PyObject *, PyObject *); - - - -/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ - - -/* Apprend tous les types mémorisés dans un tampon. */ -static PyObject *py_type_memory_load_types(PyObject *, PyObject *); - -/* Crée une nouvelle instance d'objet à partir de son type. */ -static PyObject *py_type_memory_create_object(PyObject *, PyObject *); - -/* Sauvegarde le type d'un objet instancié. */ -static PyObject *py_type_memory_store_object_gtype(PyObject *, PyObject *); - -/* Enregistre tous les types mémorisés dans un tampon. */ -static PyObject *py_type_memory_store_types(PyObject *, PyObject *); - - - -/* ---------------------------------------------------------------------------------- */ -/* GLUE POUR CREATION DEPUIS PYTHON */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * -* * -* Description : Accompagne la création d'une instance dérivée en Python. * -* * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_type_memory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type de base à dériver */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ - - /* Validations diverses */ - - base = get_python_type_memory_type(); - - if (type == base) - goto simple_way; - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(G_TYPE_TYPE_MEMORY, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* 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_type_memory_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - int ret; /* Bilan de lecture des args. */ - -#define TYPE_MEMORY_DOC \ - "The TypeMemory remembers all the types of objects involved in" \ - " a serialization process.\n" \ - "\n" \ - "Instances can be created using the following constructor:\n" \ - "\n" \ - " TypeMemory()" \ - - /* Initialisation d'un objet GLib */ - - ret = forward_pygobjet_init(self); - if (ret == -1) return -1; - - return 0; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* TAMPON POUR CODE DESASSEMBLE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Apprend tous les types mémorisés dans un tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_type_memory_load_types(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - packed_buffer_t *pbuf; /* Tampon à consulter */ - int ret; /* Bilan de lecture des args. */ - GTypeMemory *tpmem; /* Mémorisation native */ - bool status; /* Bilan de l'opération */ - -#define TYPE_MEMORY_LOAD_TYPES_METHOD PYTHON_METHOD_DEF \ -( \ - load_types, "$self, pbuf", \ - METH_VARARGS, py_type_memory, \ - "Read types from a buffer.\n" \ - "\n" \ - "This operation is usually handled internally by the" \ - " Chrysalide's core.\n" \ - "\n" \ - "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ - " instance providing buffered data to read." \ - "\n" \ - "The result is a boolean value indicating the status of" \ - " the operation: True for success, False for failure." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - tpmem = G_TYPE_MEMORY(pygobject_get(self)); - - status = g_type_memory_load_types(tpmem, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Crée une nouvelle instance d'objet à partir de son type. * -* * -* Retour : Instance issue de l'opération ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_type_memory_create_object(PyObject *self, PyObject *args) -{ - PyObject *result; /* Instance à retourner */ - packed_buffer_t *pbuf; /* Tampon à consulter */ - int ret; /* Bilan de lecture des args. */ - GTypeMemory *tpmem; /* Mémorisation native */ - GObject *obj; /* Instance retournée */ - -#define TYPE_MEMORY_CREATE_OBJECT_METHOD PYTHON_METHOD_DEF \ -( \ - create_object, "$self, pbuf", \ - METH_VARARGS, py_type_memory, \ - "Create a new GLib object from serialized data.\n" \ - "\n" \ - "The *pbuf* parameter is a pychrysalide.common.PackedBuffer" \ - " instance providing buffered data to read." \ - "\n" \ - "The result is a Python object linked to a native GLib" \ - " object instance." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - tpmem = G_TYPE_MEMORY(pygobject_get(self)); - - obj = g_type_memory_create_object(tpmem, pbuf); - - result = pygobject_new(obj); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Sauvegarde le type d'un objet instancié. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_type_memory_store_object_gtype(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GObject *obj; /* Instance à traiter */ - packed_buffer_t *pbuf; /* Tampon à consulter */ - int ret; /* Bilan de lecture des args. */ - GTypeMemory *tpmem; /* Mémorisation native */ - bool status; /* Bilan de l'opération */ - -#define TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD PYTHON_METHOD_DEF \ -( \ - store_object_gtype, "$self, obj, pbuf", \ - METH_VARARGS, py_type_memory, \ - "Create a new GLib object from serialized data.\n" \ - "\n" \ - "The *obj* parameter is the Python version of the GObject" \ - " whose type is to process and the *pbuf* parameter is a" \ - " pychrysalide.common.PackedBuffer instance providing buffered" \ - " data to extend." \ - "\n" \ - "The result is a boolean value indicating the status of the" \ - " operation: True for success, False for failure." \ -) - - ret = PyArg_ParseTuple(args, "O!O&", PyGObject_Type, &obj, convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - tpmem = G_TYPE_MEMORY(pygobject_get(self)); - - status = g_type_memory_store_object_gtype(tpmem, obj, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une mémorisation de types. * -* args = arguments fournis à l'appel. * -* * -* Description : Enregistre tous les types mémorisés dans un tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_type_memory_store_types(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - packed_buffer_t *pbuf; /* Tampon à consulter */ - int ret; /* Bilan de lecture des args. */ - GTypeMemory *tpmem; /* Mémorisation native */ - bool status; /* Bilan de l'opération */ - -#define TYPE_MEMORY_STORE_TYPES_METHOD PYTHON_METHOD_DEF \ -( \ - store_types, "$self, pbuf", \ - METH_VARARGS, py_type_memory, \ - "Write types into a buffer.\n" \ - "\n" \ - "This operation is usually handled internally by the" \ - " Chrysalide's core.\n" \ - "\n" \ - "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ - " instance providing buffered data to read." \ - "\n" \ - "The result is a boolean value indicating the status of" \ - " the operation: True for success, False for failure." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); - if (!ret) return NULL; - - tpmem = G_TYPE_MEMORY(pygobject_get(self)); - - status = g_type_memory_store_types(tpmem, pbuf); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_type_memory_type(void) -{ - static PyMethodDef py_type_memory_methods[] = { - TYPE_MEMORY_LOAD_TYPES_METHOD, - TYPE_MEMORY_CREATE_OBJECT_METHOD, - TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD, - TYPE_MEMORY_STORE_TYPES_METHOD, - { NULL } - }; - - static PyGetSetDef py_type_memory_getseters[] = { - { NULL } - }; - - static PyTypeObject py_type_memory_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.analysis.storage.TypeMemory", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = TYPE_MEMORY_DOC, - - .tp_methods = py_type_memory_methods, - .tp_getset = py_type_memory_getseters, - - .tp_init = py_type_memory_init, - .tp_new = py_type_memory_new - - }; - - return &py_type_memory_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.analysis...TypeMemory'.* -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool ensure_python_type_memory_is_registered(void) -{ - PyTypeObject *type; /* Type Python 'BufferCache' */ - PyObject *module; /* Module à recompléter */ - PyObject *dict; /* Dictionnaire du module */ - - type = get_python_type_memory_type(); - - if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) - { - module = get_access_to_python_module("pychrysalide.analysis.storage"); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type)) - return false; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en mémorisation de types. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_type_memory(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - - result = PyObject_IsInstance(arg, (PyObject *)get_python_type_memory_type()); - - switch (result) - { - case -1: - /* L'exception est déjà fixée par Python */ - result = 0; - break; - - case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to buffer cache"); - break; - - case 1: - *((GTypeMemory **)dst) = G_TYPE_MEMORY(pygobject_get(arg)); - break; - - default: - assert(false); - break; - - } - - return result; - -} diff --git a/plugins/pychrysalide/analysis/storage/tpmem.h b/plugins/pychrysalide/analysis/storage/tpmem.h deleted file mode 100644 index 1085632..0000000 --- a/plugins/pychrysalide/analysis/storage/tpmem.h +++ /dev/null @@ -1,45 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tpmem.h - prototypes pour l'équivalent Python du fichier "analysis/storage/tpmem.h" - * - * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H -#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_type_memory_type(void); - -/* Prend en charge l'objet 'pychrysalide.analysis.storage.TypeMemory'. */ -bool ensure_python_type_memory_is_registered(void); - -/* Tente de convertir en mémorisation de types. */ -int convert_to_type_memory(PyObject *, void *); - - - -#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H */ diff --git a/plugins/pychrysalide/glibext/serialize.c b/plugins/pychrysalide/glibext/serialize.c new file mode 100644 index 0000000..40fcef7 --- /dev/null +++ b/plugins/pychrysalide/glibext/serialize.c @@ -0,0 +1,501 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.c - équivalent Python du fichier "analysis/storage/serialize.h" + * + * Copyright (C) 2020 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 "serialize.h" + + +#include + + +#include + + +#include "storage.h" +#include "../../access.h" +#include "../../helpers.h" +#include "../../common/packed.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +static void py_serializable_object_interface_init(GSerializableObjectIface *, gpointer *); + +/* Charge un objet depuis une mémoire tampon. */ +static bool py_serializable_object_load_wrapper(GSerializableObject *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un objet dans une mémoire tampon. */ +static bool py_serializable_object_store_wrapper(const GSerializableObject *, GObjectStorage *, packed_buffer_t *); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + + +/* Charge un objet depuis une mémoire tampon. */ +static bool py_serializable_object_load(PyObject *, PyObject *); + +/* Sauvegarde un objet dans une mémoire tampon. */ +static bool py_serializable_object_store(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_serializable_object_interface_init(GSerializableObjectIface *iface, gpointer *unused) +{ + +#define SERIALIZABLE_OBJECT_DOC \ + "SerializableObject defines an interface used to store and load" \ + " objects to and from a data buffer.\n" \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, SerializableObject):\n" \ + " ...\n" \ + "\n" \ + "The following methods have to be defined for new implementations:\n" \ + "* pychrysalide.analysis.storage.SerializableObject._load();\n" \ + "* pychrysalide.analysis.storage.SerializableObject._store();\n" + + iface->load = py_serializable_object_load_wrapper; + iface->store = py_serializable_object_store_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : object = instruction d'assemblage à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un objet depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_load_wrapper(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *storage_obj; /* Objet Python à emmployer */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define SERIALIZABLE_OBJECT_LOAD_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _load, "$self, storage, pbuf, /", \ + METH_VARARGS, \ + "Abstract method used to load an object definition from buffered data.\n" \ + "\n" \ + "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ + " provided to store inner objects, if relevant, or None. The *pbuf*" \ + " argument points to a pychrysalide.common.PackedBuffer object containing" \ + " the data to process.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(object)); + + if (has_python_method(pyobj, "_load")) + { + if (storage == NULL) + { + storage_obj = Py_None; + Py_INCREF(storage_obj); + } + else + storage_obj = pygobject_new(G_OBJECT(storage)); + + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, storage_obj); + PyTuple_SetItem(args, 1, build_from_internal_packed_buffer(pbuf)); + + pyret = run_python_method(pyobj, "_load", args); + + result = (pyret == Py_True ? true : false); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = instruction d'assemblage à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un objet dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_store_wrapper(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *storage_obj; /* Objet Python à emmployer */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define SERIALIZABLE_OBJECT_STORE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _store, "$self, storage, pbuf, /", \ + METH_VARARGS, \ + "Abstract method used to store an object definition into buffered data.\n" \ + "\n" \ + "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ + " provided to store inner objects, if relevant, or None. The *pbuf*" \ + " argument points to a pychrysalide.common.PackedBuffer object containing" \ + " the data to process.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(object)); + + if (has_python_method(pyobj, "_store")) + { + if (storage == NULL) + { + storage_obj = Py_None; + Py_INCREF(storage_obj); + } + else + storage_obj = pygobject_new(G_OBJECT(storage)); + + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, storage_obj); + PyTuple_SetItem(args, 1, build_from_internal_packed_buffer(pbuf)); + + pyret = run_python_method(pyobj, "_store", args); + + result = (pyret == Py_True ? true : false); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_load(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObjectStorage *storage; /* Conservateur à manipuler */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GSerializableObject *object; /* Version native */ + bool status; /* Bilan de l'opération */ + +#define SERIALIZABLE_OBJECT_LOAD_METHOD PYTHON_METHOD_DEF \ +( \ + load, "$self, storage, pbuf, /", \ + METH_VARARGS, py_serializable_object, \ + "Load an object definition from buffered data.\n" \ + "\n" \ + "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ + " provided to store inner objects, if relevant, or None. The *pbuf*" \ + " argument points to a pychrysalide.common.PackedBuffer object containing" \ + " the data to process.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + ret = PyArg_ParseTuple(args, "O&O&", convert_to_object_storage_or_none, &storage, + convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); + + status = g_serializable_object_load(object, storage, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde un objet dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_store(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObjectStorage *storage; /* Conservateur à manipuler */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GSerializableObject *object; /* Version native */ + bool status; /* Bilan de l'opération */ + +#define SERIALIZABLE_OBJECT_STORE_METHOD PYTHON_METHOD_DEF \ +( \ + store, "$self, storage, pbuf, /", \ + METH_VARARGS, py_serializable_object, \ + "Store an object definition into buffered data.\n" \ + "\n" \ + "The *storage* is a pychrysalide.analysis.storage.ObjectStorage instance" \ + " provided to store inner objects, if relevant, or None. The *pbuf*" \ + " argument points to a pychrysalide.common.PackedBuffer object containing" \ + " the data to process.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + ret = PyArg_ParseTuple(args, "O&O&", convert_to_object_storage_or_none, &storage, + convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); + + status = g_serializable_object_store(object, storage, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_serializable_object_type(void) +{ + static PyMethodDef py_serializable_object_methods[] = { + SERIALIZABLE_OBJECT_LOAD_WRAPPER, + SERIALIZABLE_OBJECT_STORE_WRAPPER, + SERIALIZABLE_OBJECT_LOAD_METHOD, + SERIALIZABLE_OBJECT_STORE_METHOD, + { NULL } + }; + + static PyGetSetDef py_serializable_object_getseters[] = { + { NULL } + }; + + static PyTypeObject py_serializable_object_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.storage.SerializableObject", + .tp_basicsize = sizeof(PyObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SERIALIZABLE_OBJECT_DOC, + + .tp_methods = py_serializable_object_methods, + .tp_getset = py_serializable_object_getseters, + + }; + + return &py_serializable_object_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide....SerializableObject'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_serializable_object_is_registered(void) +{ + PyTypeObject *type; /* Type 'SerializableObject' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_serializable_object_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + + type = get_python_serializable_object_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.storage"); + + dict = PyModule_GetDict(module); + + if (!register_interface_for_pygobject(dict, G_TYPE_SERIALIZABLE_OBJECT, type, &info)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en objet adapté à une mise en cache. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_serializable_object(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_serializable_object_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to serializable object"); + break; + + case 1: + *((GSerializableObject **)dst) = G_SERIALIZABLE_OBJECT(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/serialize.h b/plugins/pychrysalide/glibext/serialize.h new file mode 100644 index 0000000..7e831e5 --- /dev/null +++ b/plugins/pychrysalide/glibext/serialize.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.h - prototypes pour l'équivalent Python du fichier "analysis/storage/serialize.h" + * + * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_serializable_object_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.storage.SerializableObject'. */ +bool ensure_python_serializable_object_is_registered(void); + +/* Tente de convertir en objet adapté à une mise en cache. */ +int convert_to_serializable_object(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_SERIALIZE_H */ diff --git a/plugins/pychrysalide/glibext/storage.c b/plugins/pychrysalide/glibext/storage.c new file mode 100644 index 0000000..c54fe0f --- /dev/null +++ b/plugins/pychrysalide/glibext/storage.c @@ -0,0 +1,687 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.c - équivalent Python du fichier "analysis/storage/storage.c" + * + * Copyright (C) 2020 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 "storage.h" + + +#include + + +#include +#include + + +#include "serialize.h" +#include "../../access.h" +#include "../../helpers.h" +#include "../../common/packed.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_object_storage_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_object_storage_init(PyObject *, PyObject *, PyObject *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Charge le support d'une conservation d'objets en place. */ +static PyObject *py_object_storage_load(PyObject *, PyObject *); + +/* Sauvegarde le support d'une conservation d'objets en place. */ +static PyObject *py_object_storage_store(PyObject *, PyObject *); + +/* Charge un objet à partir de données rassemblées. */ +static PyObject *py_object_storage_load_object(PyObject *, PyObject *); + +/* Charge un objet interne à partir de données rassemblées. */ +static PyObject *py_object_storage_unpack_object(PyObject *, PyObject *); + +/* Sauvegarde un object sous forme de données rassemblées. */ +static PyObject *py_object_storage_store_object(PyObject *, PyObject *); + +/* Sauvegarde un object interne sous forme de données. */ +static PyObject *py_object_storage_pack_object(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_object_storage_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_OBJECT_STORAGE, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* 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_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *hash; /* Empreinte de contenu */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + +#define OBJECT_STORAGE_DOC \ + "The ObjectStorage object manages the generic storage of GLib" \ + " objects through serialization.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " ObjectStorage(hash)" \ + "\n" \ + "Where *hash* should a string built from the checksum of the" \ + " relative binary content linked to the storage.pychrysalide." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "s", &hash); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + storage->hash = strdup(hash); + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge le support d'une conservation d'objets en place. * +* * +* Retour : Gestionnaire de conservations construit ou None si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_load(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + +#define OBJECT_STORAGE_LOAD_METHOD PYTHON_METHOD_DEF \ +( \ + load, "pbuf, /", \ + METH_STATIC | METH_VARARGS, py_object_storage, \ + "Construct a new storage from a buffer.\n" \ + "\n" \ + "The *pbuf* has to be an instance of type" \ + " pychrysalide.common.PackedBuffer.\n" \ + "\n" \ + "The result is a new pychrysalide.analysis.storage.ObjectStorage" \ + " object on success, *None* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + storage = g_object_storage_load(pbuf); + + if (storage == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + { + result = pygobject_new(G_OBJECT(storage)); + g_object_unref(G_OBJECT(storage)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde le support d'une conservation d'objets en place. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_store(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + bool status; /* Bilan de l'opération */ + +#define OBJECT_STORAGE_STORE_METHOD PYTHON_METHOD_DEF \ +( \ + store, "$self, pbuf, /", \ + METH_VARARGS, py_object_storage, \ + "Save a storage into a buffer.\n" \ + "\n" \ + "The *pbuf* has to be an instance of type" \ + " pychrysalide.common.PackedBuffer.\n" \ + "\n" \ + "The result is *True* on success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + status = g_object_storage_store(storage, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_load_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + const char *name; /* Désignation de groupe */ + unsigned long long pos; /* Emplacement des données */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + GSerializableObject *object; /* Objet reconstruit ou NULL */ + +#define OBJECT_STORAGE_LOAD_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + load_object, "$self, name, pos, /", \ + METH_VARARGS, py_object_storage, \ + "Load an object from serialized data.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects and" \ + " *pos* is an offset into the data stream indicating the start of" \ + " the data to unserialize.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.storage.SerializableObject" \ + " instancet in case of success, or None in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "sK", &name, &pos); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + object = g_object_storage_load_object(storage, name, pos); + + if (object != NULL) + result = pygobject_new(G_OBJECT(object)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet interne à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_unpack_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + const char *name; /* Désignation de groupe */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + GSerializableObject *object; /* Objet reconstruit ou NULL */ + +#define OBJECT_STORAGE_UNPACK_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + unpack_object, "$self, name, pbuf, /", \ + METH_VARARGS, py_object_storage, \ + "Load an object from a buffer with a location pointing to data.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects and" \ + " *pbuf* has to be a pychrysalide.common.PackedBuffer instance.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.storage.SerializableObject" \ + " instancet in case of success, or None in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "sO&", &name, convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + object = g_object_storage_unpack_object(storage, name, pbuf); + + if (object != NULL) + result = pygobject_new(G_OBJECT(object)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde un object sous forme de données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_store_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + const char *name; /* Désignation de groupe */ + GSerializableObject *object; /* Objet à traiter */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + off64_t pos; /* Emplacement d'enregistrement*/ + bool status; /* Bilan de l'opération */ + +#define OBJECT_STORAGE_STORE_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + store_object, "$self, name, object, /", \ + METH_VARARGS, py_object_storage, \ + "Save an object as serialized data.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects" \ + " and the processed *object* has to be a" \ + " pychrysalide.analysis.storage.SerializableObject instance.\n" \ + "\n" \ + "The result is the position of the data for stored object," \ + " provided as an integer offset, in case of success or None" \ + " in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "sO&", &name, convert_to_serializable_object, &object); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + status = g_object_storage_store_object(storage, name, object, &pos); + + if (status) + result = PyLong_FromUnsignedLongLong((unsigned long long)pos); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde un object interne sous forme de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_pack_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + const char *name; /* Désignation de groupe */ + GSerializableObject *object; /* Objet à traiter */ + packed_buffer_t *pbuf; /* Tampon de données à employer*/ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + bool status; /* Bilan de l'opération */ + +#define OBJECT_STORAGE_PACK_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + pack_object, "$self, name, object, pbuf/", \ + METH_VARARGS, py_object_storage, \ + "Save an object as serialized data and store the location of" \ + " the data intro a buffer.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects," \ + " the processed *object* has to be a" \ + " pychrysalide.analysis.storage.SerializableObject instance" \ + " and *pbuf* is expected to be a" \ + " pychrysalide.common.PackedBuffer instance.\n" \ + "\n" \ + "The status of the operation is returned as a boolean value:" \ + " *True* for success, *False* for failure." \ +) + + ret = PyArg_ParseTuple(args, "sO&O&", &name, convert_to_serializable_object, &object, + convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + status = g_object_storage_pack_object(storage, name, object, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_object_storage_type(void) +{ + static PyMethodDef py_object_storage_methods[] = { + OBJECT_STORAGE_LOAD_METHOD, + OBJECT_STORAGE_STORE_METHOD, + OBJECT_STORAGE_LOAD_OBJECT_METHOD, + OBJECT_STORAGE_UNPACK_OBJECT_METHOD, + OBJECT_STORAGE_STORE_OBJECT_METHOD, + OBJECT_STORAGE_PACK_OBJECT_METHOD, + { NULL } + }; + + static PyGetSetDef py_object_storage_getseters[] = { + { NULL } + }; + + static PyTypeObject py_object_storage_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.storage.ObjectStorage", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = OBJECT_STORAGE_DOC, + + .tp_methods = py_object_storage_methods, + .tp_getset = py_object_storage_getseters, + + .tp_init = py_object_storage_init, + .tp_new = py_object_storage_new + + }; + + return &py_object_storage_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide....ObjectStorage'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_object_storage_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'ObjectStorage' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_object_storage_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.storage"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en conservateur d'objets. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_object_storage(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_object_storage_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to object storage"); + break; + + case 1: + *((GObjectStorage **)dst) = G_OBJECT_STORAGE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en conservateur d'objets ou NULL. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_object_storage_or_none(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + if (arg == Py_None) + { + *((GTypeMemory **)dst) = NULL; + result = 1; + } + + else + result = convert_to_object_storage(arg, dst); + + return result; + +} diff --git a/plugins/pychrysalide/glibext/storage.h b/plugins/pychrysalide/glibext/storage.h new file mode 100644 index 0000000..a0a2c18 --- /dev/null +++ b/plugins/pychrysalide/glibext/storage.h @@ -0,0 +1,48 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.h - prototypes pour l'équivalent Python du fichier "analysis/storage/storage.h" + * + * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_object_storage_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.storage.ObjectStorage'. */ +bool ensure_python_object_storage_is_registered(void); + +/* Tente de convertir en conservateur d'objets. */ +int convert_to_object_storage(PyObject *, void *); + +/* Tente de convertir en conservateur d'objets ou NULL. */ +int convert_to_object_storage_or_none(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_STORAGE_H */ diff --git a/plugins/pychrysalide/glibext/tpmem.c b/plugins/pychrysalide/glibext/tpmem.c new file mode 100644 index 0000000..ae07008 --- /dev/null +++ b/plugins/pychrysalide/glibext/tpmem.c @@ -0,0 +1,508 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.c - équivalent Python du fichier "analysis/storage/tpmem.c" + * + * Copyright (C) 2020 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 "tpmem.h" + + +#include + + +#include +#include + + +#include "../../access.h" +#include "../../helpers.h" +#include "../../common/packed.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_type_memory_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_type_memory_init(PyObject *, PyObject *, PyObject *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Apprend tous les types mémorisés dans un tampon. */ +static PyObject *py_type_memory_load_types(PyObject *, PyObject *); + +/* Crée une nouvelle instance d'objet à partir de son type. */ +static PyObject *py_type_memory_create_object(PyObject *, PyObject *); + +/* Sauvegarde le type d'un objet instancié. */ +static PyObject *py_type_memory_store_object_gtype(PyObject *, PyObject *); + +/* Enregistre tous les types mémorisés dans un tampon. */ +static PyObject *py_type_memory_store_types(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_type_memory_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_TYPE_MEMORY, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* 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_type_memory_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define TYPE_MEMORY_DOC \ + "The TypeMemory remembers all the types of objects involved in" \ + " a serialization process.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " TypeMemory()" \ + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Apprend tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_load_types(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_LOAD_TYPES_METHOD PYTHON_METHOD_DEF \ +( \ + load_types, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Read types from a buffer.\n" \ + "\n" \ + "This operation is usually handled internally by the" \ + " Chrysalide's core.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ + " instance providing buffered data to read." \ + "\n" \ + "The result is a boolean value indicating the status of" \ + " the operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_load_types(tpmem, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Crée une nouvelle instance d'objet à partir de son type. * +* * +* Retour : Instance issue de l'opération ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_create_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + GObject *obj; /* Instance retournée */ + +#define TYPE_MEMORY_CREATE_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + create_object, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Create a new GLib object from serialized data.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer" \ + " instance providing buffered data to read." \ + "\n" \ + "The result is a Python object linked to a native GLib" \ + " object instance." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + obj = g_type_memory_create_object(tpmem, pbuf); + + result = pygobject_new(obj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde le type d'un objet instancié. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_store_object_gtype(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObject *obj; /* Instance à traiter */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD PYTHON_METHOD_DEF \ +( \ + store_object_gtype, "$self, obj, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Create a new GLib object from serialized data.\n" \ + "\n" \ + "The *obj* parameter is the Python version of the GObject" \ + " whose type is to process and the *pbuf* parameter is a" \ + " pychrysalide.common.PackedBuffer instance providing buffered" \ + " data to extend." \ + "\n" \ + "The result is a boolean value indicating the status of the" \ + " operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O!O&", PyGObject_Type, &obj, convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_store_object_gtype(tpmem, obj, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Enregistre tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_store_types(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_STORE_TYPES_METHOD PYTHON_METHOD_DEF \ +( \ + store_types, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Write types into a buffer.\n" \ + "\n" \ + "This operation is usually handled internally by the" \ + " Chrysalide's core.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ + " instance providing buffered data to read." \ + "\n" \ + "The result is a boolean value indicating the status of" \ + " the operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_store_types(tpmem, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_type_memory_type(void) +{ + static PyMethodDef py_type_memory_methods[] = { + TYPE_MEMORY_LOAD_TYPES_METHOD, + TYPE_MEMORY_CREATE_OBJECT_METHOD, + TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD, + TYPE_MEMORY_STORE_TYPES_METHOD, + { NULL } + }; + + static PyGetSetDef py_type_memory_getseters[] = { + { NULL } + }; + + static PyTypeObject py_type_memory_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.storage.TypeMemory", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = TYPE_MEMORY_DOC, + + .tp_methods = py_type_memory_methods, + .tp_getset = py_type_memory_getseters, + + .tp_init = py_type_memory_init, + .tp_new = py_type_memory_new + + }; + + return &py_type_memory_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis...TypeMemory'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_type_memory_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'BufferCache' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_type_memory_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.storage"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en mémorisation de types. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_type_memory(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_type_memory_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to buffer cache"); + break; + + case 1: + *((GTypeMemory **)dst) = G_TYPE_MEMORY(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/tpmem.h b/plugins/pychrysalide/glibext/tpmem.h new file mode 100644 index 0000000..1085632 --- /dev/null +++ b/plugins/pychrysalide/glibext/tpmem.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.h - prototypes pour l'équivalent Python du fichier "analysis/storage/tpmem.h" + * + * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_type_memory_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.storage.TypeMemory'. */ +bool ensure_python_type_memory_is_registered(void); + +/* Tente de convertir en mémorisation de types. */ +int convert_to_type_memory(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H */ diff --git a/src/analysis/storage/Makefile.am b/src/analysis/storage/Makefile.am index 3eb287b..dad7411 100644 --- a/src/analysis/storage/Makefile.am +++ b/src/analysis/storage/Makefile.am @@ -6,12 +6,7 @@ libanalysisstorage_la_SOURCES = \ cache-int.h \ cache.h cache.c \ container-int.h \ - container.h container.c \ - serialize-int.h \ - serialize.h serialize.c \ - storage-int.h \ - storage.h storage.c \ - tpmem.h tpmem.c + container.h container.c libanalysisstorage_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) diff --git a/src/analysis/storage/serialize-int.h b/src/analysis/storage/serialize-int.h deleted file mode 100644 index de8d3e3..0000000 --- a/src/analysis/storage/serialize-int.h +++ /dev/null @@ -1,58 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * serialize-int.h - définitions internes propres aux objets entreposables dans un cache - * - * Copyright (C) 2020 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 . - */ - - -#ifndef _ANALYSIS_STORAGE_SERIALIZE_INT_H -#define _ANALYSIS_STORAGE_SERIALIZE_INT_H - - -#include "serialize.h" - - -#include "storage.h" - - - -/* Charge un objet depuis une mémoire tampon. */ -typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un objet dans une mémoire tampon. */ -typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, packed_buffer_t *); - - -/* Intermédiaire pour la mise en cache d'objet (interface) */ -struct _GSerializableObjectIface -{ - GTypeInterface base_iface; /* A laisser en premier */ - - load_serializable_object_cb load; /* Chargement */ - store_serializable_object_cb store; /* Enregistrement */ - -}; - - -/* Redéfinition */ -typedef GSerializableObjectIface GSerializableObjectInterface; - - - -#endif /* _ANALYSIS_STORAGE_SERIALIZE_INT_H */ diff --git a/src/analysis/storage/serialize.c b/src/analysis/storage/serialize.c deleted file mode 100644 index d1b0502..0000000 --- a/src/analysis/storage/serialize.c +++ /dev/null @@ -1,111 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * serialize.h - objets entreposables dans un cache - * - * Copyright (C) 2020 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 . - */ - - -#include "serialize.h" - - -#include "serialize-int.h" - - - -/* Procède à l'initialisation de l'interface de mise en cache. */ -static void g_serializable_object_default_init(GSerializableObjectInterface *); - - - -/* Détermine le type d'une interface pour la mise en cache d'objet. */ -G_DEFINE_INTERFACE(GSerializableObject, g_serializable_object, G_TYPE_OBJECT) - - -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * -* Description : Procède à l'initialisation de l'interface de mise en cache. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_serializable_object_default_init(GSerializableObjectInterface *iface) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : object = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un objet depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GSerializableObjectIface *iface; /* Interface utilisée */ - - iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - - result = iface->load(object, storage, pbuf); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : object = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un objet dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GSerializableObjectIface *iface; /* Interface utilisée */ - - iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - - result = iface->store(object, storage, pbuf); - - return result; - -} diff --git a/src/analysis/storage/serialize.h b/src/analysis/storage/serialize.h deleted file mode 100644 index 93a4496..0000000 --- a/src/analysis/storage/serialize.h +++ /dev/null @@ -1,64 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * serialize.h - prototypes pour les objets entreposables dans un cache - * - * Copyright (C) 2020 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 . - */ - - -#ifndef _ANALYSIS_STORAGE_SERIALIZE_H -#define _ANALYSIS_STORAGE_SERIALIZE_H - - -#include - - -#include "../../common/packed.h" - - - -#define G_TYPE_SERIALIZABLE_OBJECT g_serializable_object_get_type() -#define G_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObject)) -#define G_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) -#define G_IS_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SERIALIZABLE_OBJECT)) -#define G_IS_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SERIALIZABLE_OBJECT)) -#define G_SERIALIZABLE_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) - - -/* Intermédiaire pour la mise en cache d'objet (coquille vide) */ -typedef struct _GSerializableObject GSerializableObject; - -/* Intermédiaire pour la mise en cache d'objet (interface) */ -typedef struct _GSerializableObjectIface GSerializableObjectIface; - - -/* Détermine le type d'une interface pour la mise en cache d'objet. */ -GType g_serializable_object_get_type(void) G_GNUC_CONST; - -/* storage.h : définition d'une conservation d'objets construits */ -typedef struct _GObjectStorage GObjectStorage; - -/* Charge un objet depuis une mémoire tampon. */ -bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un objet dans une mémoire tampon. */ -bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, packed_buffer_t *); - - - -#endif /* _ANALYSIS_STORAGE_SERIALIZE_H */ diff --git a/src/analysis/storage/storage-int.h b/src/analysis/storage/storage-int.h deleted file mode 100644 index 4883aa8..0000000 --- a/src/analysis/storage/storage-int.h +++ /dev/null @@ -1,66 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * storage.h - prototypes internes pour la conservation sur disque d'objets construits - * - * Copyright (C) 2020 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 . - */ - - -#ifndef _ANALYSIS_STORAGE_STORAGE_INT_H -#define _ANALYSIS_STORAGE_STORAGE_INT_H - - -#include "storage.h" - - - -/* Gestion d'enregistrements spécifiques */ -typedef struct _storage_backend_t -{ - char *name; /* Désignation du groupe */ - - char *filename; /* Nom du fichier associé */ - int fd; /* Flux d'accès correspondant */ - -} storage_backend_t; - -/* Définition d'une conservation d'objets construits (instance) */ -struct _GObjectStorage -{ - GObject parent; /* A laisser en premier */ - - GTypeMemory *tpmem; /* Mémorisation de types */ - - char *hash; /* Empreinte du contenu */ - - storage_backend_t *backends; /* Gestionnaires existants */ - size_t count; /* Quantité de gestionnaires */ - GMutex mutex; /* Contrôle d'accès à la liste */ - -}; - -/* Définition d'une conservation d'objets construits (classe) */ -struct _GObjectStorageClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - - -#endif /* _ANALYSIS_STORAGE_STORAGE_INT_H */ diff --git a/src/analysis/storage/storage.c b/src/analysis/storage/storage.c deleted file mode 100644 index 610a0f6..0000000 --- a/src/analysis/storage/storage.c +++ /dev/null @@ -1,867 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * storage.c - conservation hors mémoire d'objets choisis - * - * Copyright (C) 2020 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 . - */ - - -#include "storage.h" - - -#include -#include -#include -#include -#include - - -#include "storage-int.h" -#include "../db/misc/rlestr.h" -#include "../../common/io.h" -#include "../../common/leb128.h" -#include "../../common/pathname.h" -#include "../../core/logs.h" - - - -#define STORAGE_MAGIC "CSTR" -#define STORAGE_NUMBER "\x00\x01" - - -/* Initialise la classe des conservations d'objets en place. */ -static void g_object_storage_class_init(GObjectStorageClass *); - -/* Initialise une instance de conservation d'objets en place. */ -static void g_object_storage_init(GObjectStorage *); - -/* Supprime toutes les références externes. */ -static void g_object_storage_dispose(GObjectStorage *); - -/* Procède à la libération totale de la mémoire. */ -static void g_object_storage_finalize(GObjectStorage *); - -/* Retrouve l'encadrement pour un nouveau groupe d'objets. */ -static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *); - -/* Ajoute le support d'un nouveau groupe d'objets construits. */ -static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **); - -/* Extrait d'un tampon des enregistrements spécifiques. */ -static bool g_object_storage_load_backend(GObjectStorage *, packed_buffer_t *); - -/* Place dans un tampon les données liées à des enregistrements. */ -static bool pack_storage_backend(const storage_backend_t *, packed_buffer_t *); - - - -/* Indique le type défini pour une conservation d'objets construits. */ -G_DEFINE_TYPE(GObjectStorage, g_object_storage, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des conservations d'objets en place. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_object_storage_class_init(GObjectStorageClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_object_storage_dispose; - object->finalize = (GObjectFinalizeFunc)g_object_storage_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = instance à initialiser. * -* * -* Description : Initialise une instance de conservation d'objets en place. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_object_storage_init(GObjectStorage *storage) -{ - storage->tpmem = g_type_memory_new(); - - storage->hash = NULL; - - storage->backends = NULL; - storage->count = 0; - g_mutex_init(&storage->mutex); - -} - - -/****************************************************************************** -* * -* Paramètres : storage = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_object_storage_dispose(GObjectStorage *storage) -{ - g_clear_object(&storage->tpmem); - - G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(G_OBJECT(storage)); - -} - - -/****************************************************************************** -* * -* Paramètres : storage = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_object_storage_finalize(GObjectStorage *storage) -{ - size_t i; /* Boucle de parcours */ - storage_backend_t *backend; /* Gestionnaire à manipuler */ - int ret; /* Bilan d'un appel */ - - g_mutex_lock(&storage->mutex); - - for (i = 0; i < storage->count; i++) - { - backend = &storage->backends[i]; - - if (backend->fd != -1) - close(backend->fd); - else - assert(false); - - ret = access(backend->filename, W_OK); - if (ret == 0) - { - ret = unlink(backend->filename); - if (ret != 0) LOG_ERROR_N("unlink"); - } - - free(backend->name); - - free(backend->filename); - - } - - if (storage->backends != NULL) - free(storage->backends); - - g_mutex_unlock(&storage->mutex); - - g_mutex_clear(&storage->mutex); - - if (storage->hash != NULL) - free(storage->hash); - - G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(G_OBJECT(storage)); - -} - - -/****************************************************************************** -* * -* Paramètres : loaded = contenu binaire à associer. * -* * -* Description : Crée le support d'une conservation d'objets en place. * -* * -* Retour : Mécanismes mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObjectStorage *g_object_storage_new(const char *hash) -{ - GObjectStorage *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - - result->hash = strdup(hash); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : pbuf = zone tampon à lire. * -* * -* Description : Charge le support d'une conservation d'objets en place. * -* * -* Retour : Gestionnaire de conservations construit ou NULL si erreur. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObjectStorage *g_object_storage_load(packed_buffer_t *pbuf) -{ - GObjectStorage *result; /* Structure à retourner */ - char header[6]; /* Entête attendue des données */ - bool status; /* Bilan d'une extraction */ - rle_string str; /* Chaîne à conserver */ - uleb128_t count; /* Nombre de groupes à charger */ - uleb128_t i; /* Boucle de parcours */ - - result = NULL; - - status = extract_packed_buffer(pbuf, header, 6, false); - if (!status) goto quick_exit; - - if (strncmp(header, STORAGE_MAGIC STORAGE_NUMBER, 6) != 0) - goto quick_exit; - - setup_empty_rle_string(&str); - - status = unpack_rle_string(&str, pbuf); - if (!status) goto quick_exit; - - if (get_rle_string(&str) == NULL) - { - exit_rle_string(&str); - goto quick_exit; - } - - result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - - result->hash = strdup(get_rle_string(&str)); - - exit_rle_string(&str); - - status = g_type_memory_load_types(result->tpmem, pbuf); - if (!status) goto exit_while_loading; - - status = unpack_uleb128(&count, pbuf); - - for (i = 0; i < count && status; i++) - status = g_object_storage_load_backend(result, pbuf); - - exit_while_loading: - - if (!status) - { - g_object_unref(G_OBJECT(result)); - result = NULL; - } - - quick_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à manipuler. * -* pbuf = zone tampon à remplir. [OUT] * -* * -* Description : Sauvegarde le support d'une conservation d'objets en place. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_object_storage_store(GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - size_t i; /* Boucle de parcours */ - - result = extend_packed_buffer(pbuf, STORAGE_MAGIC STORAGE_NUMBER, 6, false); - - if (result) - { - init_static_rle_string(&str, storage->hash); - - result = pack_rle_string(&str, pbuf); - - exit_rle_string(&str); - - } - - g_mutex_lock(&storage->mutex); - - if (result) - result = g_type_memory_store_types(storage->tpmem, pbuf); - - if (result) - result = pack_uleb128((uleb128_t []){ storage->count }, pbuf); - - for (i = 0; i < storage->count && result; i++) - result = pack_storage_backend(&storage->backends[i], pbuf); - - g_mutex_unlock(&storage->mutex); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* name = désignation d'un nouveau groupe d'objets. * -* * -* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. * -* * -* Retour : Informations liées à un groupe ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name) -{ - storage_backend_t *result; /* Encadrement à retourner */ - size_t i; /* Boucle de parcours */ - - assert(!g_mutex_trylock(&storage->mutex)); - - for (i = 0; i < storage->count; i++) - if (strcmp(storage->backends[i].name, name) == 0) - break; - - if (i == storage->count) - result = NULL; - else - result = &storage->backends[i]; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* name = désignation d'un nouveau groupe d'objets. * -* backend = support mis en place pour les enregistrements. * -* * -* Description : Ajoute le support d'un nouveau groupe d'objets construits. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend) -{ - bool result; /* Bilan à retourner */ - char *prefix; /* Début de nom de fichier */ - char *filename; /* Chemin d'accès aux données */ - int fd; /* Descripteur de flux ouvert */ - - result = false; - - *backend = NULL; - - assert(!g_mutex_trylock(&storage->mutex)); - - if (g_object_storage_find_backend(storage, name) != NULL) - goto exit; - - /* Préparatifs */ - - asprintf(&prefix, "%s-%s", storage->hash, name); - - fd = make_tmp_file(prefix, "cache", &filename); - - free(prefix); - - if (fd == -1) - goto exit; - - /* Inscription en bonne et due forme */ - - storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); - - *backend = &storage->backends[storage->count - 1]; - - (*backend)->name = strdup(name); - - (*backend)->filename = filename; - (*backend)->fd = fd; - - result = true; - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* pbuf = zone tampon à lire. * -* * -* Description : Extrait d'un tampon des enregistrements spécifiques. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - bool status; /* Bilan de lecture de contenu */ - storage_backend_t *backend; /* Informations à intégrer */ - uleb128_t length; /* Taille des données à charger*/ - off_t moved; /* Nouvelle position établie */ - - result = false; - - g_mutex_lock(&storage->mutex); - - /* Récupération du nom et création du support */ - - setup_empty_rle_string(&str); - - status = unpack_rle_string(&str, pbuf); - if (!status) goto exit; - - if (get_rle_string(&str) == NULL) - { - exit_rle_string(&str); - goto exit; - } - - status = g_object_storage_add_backend(storage, get_rle_string(&str), &backend); - - exit_rle_string(&str); - - if (!status) goto exit; - - /* Récupération du contenu */ - - status = unpack_uleb128(&length, pbuf); - if (!status) goto exit; - - status = safe_write(backend->fd, pbuf->data + pbuf->pos, length); - if (!status) goto exit; - - advance_packed_buffer(pbuf, length); - - moved = lseek(backend->fd, 0, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } - - result = true; - - exit: - - g_mutex_unlock(&storage->mutex); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : backend = stockage des enregistrements spécifiques. * -* pbuf = zone tampon à remplir. [OUT] * -* * -* Description : Place dans un tampon les données liées à des enregistrements.* -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - bool status; /* Bilan de lecture de contenu */ - off_t current; /* Position courante */ - off_t moved; /* Nouvelle position établie */ - void *data; /* Données à transférer */ - - result = false; - - /* Inscription du nom */ - - init_static_rle_string(&str, backend->name); - - status = pack_rle_string(&str, pbuf); - - exit_rle_string(&str); - - if (!status) goto exit; - - /* Inscription du contenu */ - - current = lseek(backend->fd, 0, SEEK_CUR); - if (current == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } - - moved = lseek(backend->fd, 0, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } - - data = malloc(current); - if (data == NULL) - { - LOG_ERROR_N("malloc"); - goto restore; - } - - status = safe_read(backend->fd, data, current); - if (!status) goto free_mem; - - status = pack_uleb128((uleb128_t []){ current }, pbuf); - if (!status) goto free_mem; - - status = extend_packed_buffer(pbuf, data, current, false); - - free_mem: - - free(data); - - restore: - - moved = lseek(backend->fd, current, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } - - result = status; - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pos = tête de lecture avant écriture. * -* * -* Description : Charge un objet à partir de données rassemblées. * -* * -* Retour : Objet restauré en mémoire ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos) -{ - GSerializableObject *result; /* Instance à retourner */ - bool status; /* Bilan d'une opération */ - storage_backend_t *backend; /* Informations à consulter */ - packed_buffer_t pbuf; /* Tampon des données à lire */ - off64_t new; /* Nouvelle position de lecture*/ - - result = NULL; - - /* Chargement */ - - status = false; - - g_mutex_lock(&storage->mutex); - - backend = g_object_storage_find_backend(storage, name); - - if (backend != NULL) - { - new = lseek64(backend->fd, pos, SEEK_SET); - - if (new == pos) - { - init_packed_buffer(&pbuf); - status = read_packed_buffer(&pbuf, backend->fd); - } - - } - - g_mutex_unlock(&storage->mutex); - - if (!status) - goto exit; - - /* Phase de conversion */ - - result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object(storage->tpmem, &pbuf)); - - if (result) - { - status = g_serializable_object_load(result, storage, &pbuf); - - if (!status) - g_clear_object(&result); - - } - - exit_packed_buffer(&pbuf); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à parcourir. * -* * -* Description : Charge un objet interne à partir de données rassemblées. * -* * -* Retour : Objet restauré en mémoire ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf) -{ - GSerializableObject *result; /* Instance à retourner */ - uint64_t pos; /* Localisation des données */ - bool status; /* Bilan d'une opération */ - - result = NULL; - - status = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); - - if (status) - result = g_object_storage_load_object(storage, name, pos); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à parcourir. * -* expected = type d'objet attendu. * -* ... = élément restauré ou NULL en cas d'échec. [OUT] * -* * -* Description : Charge un objet interne à partir de données rassemblées. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf, GType expected, ...) -{ - bool result; /* Bilan d'une opération */ - uint64_t pos; /* Localisation des données */ - GSerializableObject *instance; /* Objet rechargé à valider */ - va_list ap; /* Liste d'arguments variables */ - void **object; /* Lieu d'enregistrement final */ - - result = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); - - if (result) - { - if (pos == 0) - *object = NULL; - - else - { - instance = g_object_storage_load_object(storage, name, pos); - - result = G_TYPE_CHECK_INSTANCE_TYPE(instance, expected); - - if (result) - { - va_start(ap, expected); - - object = va_arg(ap, void **); - - *object = instance; - - va_end(ap); - - } - - else - g_clear_object(&instance); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* object = objet sérialisable à traiter. * -* pos = tête de lecture avant écriture. [OUT] * -* * -* Description : Sauvegarde un object sous forme de données rassemblées. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_object_storage_store_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, off64_t *pos) -{ - bool result; /* Bilan à retourner */ - packed_buffer_t pbuf; /* Tampon des données à écrire */ - storage_backend_t *backend; /* Informations à consulter */ - off64_t tmp; /* Conservation éphémère */ - - /* Phase de conversion */ - - init_packed_buffer(&pbuf); - - result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), &pbuf); - if (!result) goto exit; - - result = g_serializable_object_store(object, storage, &pbuf); - if (!result) goto exit; - - /* Enregistrement */ - - result = false; - - g_mutex_lock(&storage->mutex); - - backend = g_object_storage_find_backend(storage, name); - - if (backend == NULL) - g_object_storage_add_backend(storage, name, &backend); - - if (backend != NULL) - { - if (pos == NULL) - pos = &tmp; - - *pos = lseek64(backend->fd, 0, SEEK_CUR); - - if (*pos != (off64_t)-1) - result = write_packed_buffer(&pbuf, backend->fd); - - } - - g_mutex_unlock(&storage->mutex); - - /* Sortie propre */ - - exit: - - exit_packed_buffer(&pbuf); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un object interne sous forme de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_object_storage_pack_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - off64_t pos; /* Localisation des données */ - - if (object == NULL) - result = extend_packed_buffer(pbuf, (uint64_t []){ 0 }, sizeof(uint64_t), true); - - else - { - result = g_object_storage_store_object(storage, name, object, &pos); - - if (result) - result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true); - - } - - return result; - -} diff --git a/src/analysis/storage/storage.h b/src/analysis/storage/storage.h deleted file mode 100644 index cc0caad..0000000 --- a/src/analysis/storage/storage.h +++ /dev/null @@ -1,89 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * storage.h - prototypes pour la conservation sur disque d'objets construits - * - * Copyright (C) 2020 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 . - */ - - -#ifndef _ANALYSIS_STORAGE_STORAGE_H -#define _ANALYSIS_STORAGE_STORAGE_H - - -#include -#include - - -#include "serialize.h" -#include "tpmem.h" - - - -#define G_TYPE_OBJECT_STORAGE g_object_storage_get_type() -#define G_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_OBJECT_STORAGE, GObjectStorage)) -#define G_IS_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_OBJECT_STORAGE)) -#define G_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) -#define G_IS_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_OBJECT_STORAGE)) -#define G_OBJECT_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) - - -/* Définition d'une conservation d'objets construits (instance) */ -typedef struct _GObjectStorage GObjectStorage; - -/* Définition d'une conservation d'objets construits (classe) */ -typedef struct _GObjectStorageClass GObjectStorageClass; - - -/* Indique le type défini pour une conservation d'objets construits. */ -GType g_object_storage_get_type(void); - -/* Crée le support d'une conservation d'objets en place. */ -GObjectStorage *g_object_storage_new(const char *); - -#define get_storage_linked_format(s) \ - ({ \ - void*__result; \ - __result = g_object_get_data(G_OBJECT(s), "format"); \ - g_object_ref(G_OBJECT(__result)); \ - __result; \ - }) - -/* Charge le support d'une conservation d'objets en place. */ -GObjectStorage *g_object_storage_load(packed_buffer_t *); - -/* Sauvegarde le support d'une conservation d'objets en place. */ -bool g_object_storage_store(GObjectStorage *, packed_buffer_t *); - -/* Charge un objet à partir de données rassemblées. */ -GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t); - -/* Charge un objet interne à partir de données rassemblées. */ -GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char *, packed_buffer_t *); - -/* Sauvegarde un object sous forme de données rassemblées. */ -bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *); - -/* Charge un objet interne à partir de données rassemblées. */ -bool g_object_storage_unpack_object_2(GObjectStorage *, const char *, packed_buffer_t *, GType, ...); - -/* Sauvegarde un object interne sous forme de données. */ -bool g_object_storage_pack_object(GObjectStorage *, const char *, const GSerializableObject *, packed_buffer_t *); - - - -#endif /* _ANALYSIS_STORAGE_STORAGE_H */ diff --git a/src/analysis/storage/tpmem.c b/src/analysis/storage/tpmem.c deleted file mode 100644 index 0703aeb..0000000 --- a/src/analysis/storage/tpmem.c +++ /dev/null @@ -1,429 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tpmem.c - mémorisation des types d'objets mis en cache - * - * Copyright (C) 2020 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 . - */ - - -#include "tpmem.h" - - -#include -#include - - -#include "../db/misc/rlestr.h" -#include "../../arch/operands/target.h" -#include "../../core/logs.h" - - - -/* Conservation d'une référence sur un type */ -typedef struct _gtype_ref_info_t -{ - GType gtype; /* Type pour la GLib */ - gpointer gclass; /* Lien vers sa classe */ - - /** - * La GLib n'est pas très claire sur la taille de GType : - * - * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus - * typedef gsize GType; - * #else // for historic reasons, C++ links against gulong GTypes - * typedef gulong GType; - * #endif - * - * Et : - * - * typedef unsigned $glib_size_type_define gsize; - * - * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits - * lors des enregistrements. - */ - -} gtype_ref_info_t; - -/* Définition d'une mémoire de types d'objets (instance) */ -struct _GTypeMemory -{ - GObject parent; /* A laisser en premier */ - - gtype_ref_info_t *gtypes; /* Types des objets reconnus */ - size_t count; /* Quantité de ces objets */ - GMutex mutex; /* Contrôle d'accès à la liste */ - -}; - -/* Définition d'une mémoire de types d'objets (classe) */ -struct _GTypeMemoryClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des mémoires de types d'objets. */ -static void g_type_memory_class_init(GTypeMemoryClass *); - -/* Initialise une instance de mémoire de types d'objets. */ -static void g_type_memory_init(GTypeMemory *); - -/* Supprime toutes les références externes. */ -static void g_type_memory_dispose(GTypeMemory *); - -/* Procède à la libération totale de la mémoire. */ -static void g_type_memory_finalize(GTypeMemory *); - - - -/* Indique le type défini pour une mémoire de types d'objets. */ -G_DEFINE_TYPE(GTypeMemory, g_type_memory, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des mémoires de types d'objets. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_type_memory_class_init(GTypeMemoryClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_type_memory_dispose; - object->finalize = (GObjectFinalizeFunc)g_type_memory_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = instance à initialiser. * -* * -* Description : Initialise une instance de mémoire de types d'objets. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_type_memory_init(GTypeMemory *tpmem) -{ - tpmem->gtypes = NULL; - tpmem->count = 0; - g_mutex_init(&tpmem->mutex); - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_type_memory_dispose(GTypeMemory *tpmem) -{ - uint64_t i; /* Boucle de parcours */ - - g_mutex_lock(&tpmem->mutex); - - for (i = 0; i < tpmem->count; i++) - if (tpmem->gtypes[i].gclass != NULL) - g_type_class_unref(tpmem->gtypes[i].gclass); - - g_mutex_unlock(&tpmem->mutex); - - g_mutex_clear(&tpmem->mutex); - - G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(G_OBJECT(tpmem)); - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_type_memory_finalize(GTypeMemory *tpmem) -{ - if (tpmem->gtypes != NULL) - free(tpmem->gtypes); - - G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(G_OBJECT(tpmem)); - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée une mémoire pour types d'objets. * -* * -* Retour : Instance mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GTypeMemory *g_type_memory_new(void) -{ - GTypeMemory *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_TYPE_MEMORY, NULL); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = mémoire à compléter. * -* pbuf = zone tampon à lire. * -* * -* Description : Apprend tous les types mémorisés dans un tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à enregistrer */ - uleb128_t count; /* Nombre d'éléments détectés */ - uleb128_t i; /* Boucle de parcours */ - rle_string str; /* Chaîne à charger */ - - result = unpack_uleb128(&count, pbuf); - - if (result) - { - g_mutex_lock(&tpmem->mutex); - - tpmem->count = count; - - assert(tpmem->gtypes == NULL); - tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t)); - - setup_empty_rle_string(&str); - - for (i = 0; i < tpmem->count && result; i++) - { - result = unpack_rle_string(&str, pbuf); - if (!result) break; - - if (get_rle_string(&str) == NULL) - { - exit_rle_string(&str); - break; - } - - tpmem->gtypes[i].gtype = g_type_from_name(get_rle_string(&str)); - result = (tpmem->gtypes[i].gtype != 0); - - if (!result) - log_variadic_message(LMT_ERROR, "Unknown type: '%s'", get_rle_string(&str)); - - else - tpmem->gtypes[i].gclass = g_type_class_ref(tpmem->gtypes[i].gtype); - - exit_rle_string(&str); - - } - - } - - g_mutex_unlock(&tpmem->mutex); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = mémoire à manipuler. * -* pbuf = zone tampon à venir lire. * -* * -* Description : Crée une nouvelle instance d'objet à partir de son type. * -* * -* Retour : Instance issue de l'opération ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) -{ - GObject *result; /* Nouvelle instance à renvoyer*/ - uleb128_t index; /* Indice du point d'insertion */ - bool status; /* Bilan d'une récupération */ - - result = NULL; - - status = unpack_uleb128(&index, pbuf); - - if (status) - { - g_mutex_lock(&tpmem->mutex); - - if (index < tpmem->count) - result = g_object_new(tpmem->gtypes[index].gtype, NULL); - - g_mutex_unlock(&tpmem->mutex); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = mémoire à manipuler. * -* obj = instance dont le type est à mémoriser. * -* pbuf = zone tampon à remplir. [OUT] * -* * -* Description : Sauvegarde le type d'un objet instancié. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GType gtype; /* Type à enregistrer */ - size_t index; /* Indice du point d'insertion */ - - gtype = G_TYPE_FROM_INSTANCE(obj); - - /** - * Pour quelques explications sur l'esquive suivante, se rapporter aux - * commentaires de g_target_operand_unserialize(). - * - * Dans la situation présente, on ne doit pas enregistrer le type dans le tampon, - * car l'opérande va relancer l'opération entière (avec un opérande temporaire), - * ce qui conduirait à l'enregistrement de deux types successifs dans les données. - */ - - if (gtype == G_TYPE_TARGET_OPERAND) - result = true; - - else - { - g_mutex_lock(&tpmem->mutex); - - for (index = 0; index < tpmem->count; index++) - if (tpmem->gtypes[index].gtype == gtype) - break; - - if (index == tpmem->count) - { - tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t)); - - assert(tpmem->count > 0); - - tpmem->gtypes[index].gtype = gtype; - tpmem->gtypes[index].gclass = g_type_class_ref(gtype); - - } - - g_mutex_unlock(&tpmem->mutex); - - result = pack_uleb128((uleb128_t []){ index }, pbuf); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : tpmem = mémoire à consulter. * -* pbuf = zone tampon à remplir. [OUT] * -* * -* Description : Enregistre tous les types mémorisés dans un tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_type_memory_store_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à enregistrer */ - uint64_t i; /* Boucle de parcours */ - const gchar *name; /* Désignation d'un type */ - rle_string str; /* Chaîne à conserver */ - - g_mutex_lock(&tpmem->mutex); - - result = pack_uleb128((uleb128_t []){ tpmem->count }, pbuf); - - for (i = 0; i < tpmem->count && result; i++) - { - name = g_type_name(tpmem->gtypes[i].gtype); - - init_static_rle_string(&str, name); - - result = pack_rle_string(&str, pbuf); - - exit_rle_string(&str); - - } - - g_mutex_unlock(&tpmem->mutex); - - return result; - -} diff --git a/src/analysis/storage/tpmem.h b/src/analysis/storage/tpmem.h deleted file mode 100644 index 34cbde6..0000000 --- a/src/analysis/storage/tpmem.h +++ /dev/null @@ -1,70 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache - * - * Copyright (C) 2020 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 . - */ - - -#ifndef _ANALYSIS_STORAGE_TPMEM_H -#define _ANALYSIS_STORAGE_TPMEM_H - - -#include - - -#include "../../common/packed.h" - - - -#define G_TYPE_TYPE_MEMORY g_type_memory_get_type() -#define G_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TYPE_MEMORY, GTypeMemory)) -#define G_IS_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TYPE_MEMORY)) -#define G_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) -#define G_IS_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPE_MEMORY)) -#define G_TYPE_MEMORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) - - -/* Définition d'une mémoire de types d'objets (instance) */ -typedef struct _GTypeMemory GTypeMemory; - -/* Définition d'une mémoire de types d'objets (classe) */ -typedef struct _GTypeMemoryClass GTypeMemoryClass; - - -/* Indique le type défini pour une mémoire de types d'objets. */ -GType g_type_memory_get_type(void); - -/* Crée une mémoire pour types d'objets. */ -GTypeMemory *g_type_memory_new(void); - -/* Apprend tous les types mémorisés dans un tampon. */ -bool g_type_memory_load_types(GTypeMemory *, packed_buffer_t *); - -/* Crée une nouvelle instance d'objet à partir de son type. */ -GObject *g_type_memory_create_object(GTypeMemory *, packed_buffer_t *); - -/* Sauvegarde le type d'un objet instancié. */ -bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, packed_buffer_t *); - -/* Enregistre tous les types mémorisés dans un tampon. */ -bool g_type_memory_store_types(GTypeMemory *, packed_buffer_t *); - - - -#endif /* _ANALYSIS_STORAGE_TPMEM_H */ diff --git a/src/glibext/serialize-int.h b/src/glibext/serialize-int.h new file mode 100644 index 0000000..de8d3e3 --- /dev/null +++ b/src/glibext/serialize-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize-int.h - définitions internes propres aux objets entreposables dans un cache + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ANALYSIS_STORAGE_SERIALIZE_INT_H +#define _ANALYSIS_STORAGE_SERIALIZE_INT_H + + +#include "serialize.h" + + +#include "storage.h" + + + +/* Charge un objet depuis une mémoire tampon. */ +typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un objet dans une mémoire tampon. */ +typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, packed_buffer_t *); + + +/* Intermédiaire pour la mise en cache d'objet (interface) */ +struct _GSerializableObjectIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + load_serializable_object_cb load; /* Chargement */ + store_serializable_object_cb store; /* Enregistrement */ + +}; + + +/* Redéfinition */ +typedef GSerializableObjectIface GSerializableObjectInterface; + + + +#endif /* _ANALYSIS_STORAGE_SERIALIZE_INT_H */ diff --git a/src/glibext/serialize.c b/src/glibext/serialize.c new file mode 100644 index 0000000..d1b0502 --- /dev/null +++ b/src/glibext/serialize.c @@ -0,0 +1,111 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.h - objets entreposables dans un cache + * + * Copyright (C) 2020 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 . + */ + + +#include "serialize.h" + + +#include "serialize-int.h" + + + +/* Procède à l'initialisation de l'interface de mise en cache. */ +static void g_serializable_object_default_init(GSerializableObjectInterface *); + + + +/* Détermine le type d'une interface pour la mise en cache d'objet. */ +G_DEFINE_INTERFACE(GSerializableObject, g_serializable_object, G_TYPE_OBJECT) + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de mise en cache. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_serializable_object_default_init(GSerializableObjectInterface *iface) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un objet depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GSerializableObjectIface *iface; /* Interface utilisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + result = iface->load(object, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un objet dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GSerializableObjectIface *iface; /* Interface utilisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + result = iface->store(object, storage, pbuf); + + return result; + +} diff --git a/src/glibext/serialize.h b/src/glibext/serialize.h new file mode 100644 index 0000000..93a4496 --- /dev/null +++ b/src/glibext/serialize.h @@ -0,0 +1,64 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.h - prototypes pour les objets entreposables dans un cache + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ANALYSIS_STORAGE_SERIALIZE_H +#define _ANALYSIS_STORAGE_SERIALIZE_H + + +#include + + +#include "../../common/packed.h" + + + +#define G_TYPE_SERIALIZABLE_OBJECT g_serializable_object_get_type() +#define G_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObject)) +#define G_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) +#define G_IS_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SERIALIZABLE_OBJECT)) +#define G_IS_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SERIALIZABLE_OBJECT)) +#define G_SERIALIZABLE_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) + + +/* Intermédiaire pour la mise en cache d'objet (coquille vide) */ +typedef struct _GSerializableObject GSerializableObject; + +/* Intermédiaire pour la mise en cache d'objet (interface) */ +typedef struct _GSerializableObjectIface GSerializableObjectIface; + + +/* Détermine le type d'une interface pour la mise en cache d'objet. */ +GType g_serializable_object_get_type(void) G_GNUC_CONST; + +/* storage.h : définition d'une conservation d'objets construits */ +typedef struct _GObjectStorage GObjectStorage; + +/* Charge un objet depuis une mémoire tampon. */ +bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un objet dans une mémoire tampon. */ +bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, packed_buffer_t *); + + + +#endif /* _ANALYSIS_STORAGE_SERIALIZE_H */ diff --git a/src/glibext/storage-int.h b/src/glibext/storage-int.h new file mode 100644 index 0000000..4883aa8 --- /dev/null +++ b/src/glibext/storage-int.h @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.h - prototypes internes pour la conservation sur disque d'objets construits + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ANALYSIS_STORAGE_STORAGE_INT_H +#define _ANALYSIS_STORAGE_STORAGE_INT_H + + +#include "storage.h" + + + +/* Gestion d'enregistrements spécifiques */ +typedef struct _storage_backend_t +{ + char *name; /* Désignation du groupe */ + + char *filename; /* Nom du fichier associé */ + int fd; /* Flux d'accès correspondant */ + +} storage_backend_t; + +/* Définition d'une conservation d'objets construits (instance) */ +struct _GObjectStorage +{ + GObject parent; /* A laisser en premier */ + + GTypeMemory *tpmem; /* Mémorisation de types */ + + char *hash; /* Empreinte du contenu */ + + storage_backend_t *backends; /* Gestionnaires existants */ + size_t count; /* Quantité de gestionnaires */ + GMutex mutex; /* Contrôle d'accès à la liste */ + +}; + +/* Définition d'une conservation d'objets construits (classe) */ +struct _GObjectStorageClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _ANALYSIS_STORAGE_STORAGE_INT_H */ diff --git a/src/glibext/storage.c b/src/glibext/storage.c new file mode 100644 index 0000000..610a0f6 --- /dev/null +++ b/src/glibext/storage.c @@ -0,0 +1,867 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.c - conservation hors mémoire d'objets choisis + * + * Copyright (C) 2020 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 . + */ + + +#include "storage.h" + + +#include +#include +#include +#include +#include + + +#include "storage-int.h" +#include "../db/misc/rlestr.h" +#include "../../common/io.h" +#include "../../common/leb128.h" +#include "../../common/pathname.h" +#include "../../core/logs.h" + + + +#define STORAGE_MAGIC "CSTR" +#define STORAGE_NUMBER "\x00\x01" + + +/* Initialise la classe des conservations d'objets en place. */ +static void g_object_storage_class_init(GObjectStorageClass *); + +/* Initialise une instance de conservation d'objets en place. */ +static void g_object_storage_init(GObjectStorage *); + +/* Supprime toutes les références externes. */ +static void g_object_storage_dispose(GObjectStorage *); + +/* Procède à la libération totale de la mémoire. */ +static void g_object_storage_finalize(GObjectStorage *); + +/* Retrouve l'encadrement pour un nouveau groupe d'objets. */ +static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *); + +/* Ajoute le support d'un nouveau groupe d'objets construits. */ +static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **); + +/* Extrait d'un tampon des enregistrements spécifiques. */ +static bool g_object_storage_load_backend(GObjectStorage *, packed_buffer_t *); + +/* Place dans un tampon les données liées à des enregistrements. */ +static bool pack_storage_backend(const storage_backend_t *, packed_buffer_t *); + + + +/* Indique le type défini pour une conservation d'objets construits. */ +G_DEFINE_TYPE(GObjectStorage, g_object_storage, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des conservations d'objets en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_object_storage_class_init(GObjectStorageClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_object_storage_dispose; + object->finalize = (GObjectFinalizeFunc)g_object_storage_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance à initialiser. * +* * +* Description : Initialise une instance de conservation d'objets en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_object_storage_init(GObjectStorage *storage) +{ + storage->tpmem = g_type_memory_new(); + + storage->hash = NULL; + + storage->backends = NULL; + storage->count = 0; + g_mutex_init(&storage->mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_object_storage_dispose(GObjectStorage *storage) +{ + g_clear_object(&storage->tpmem); + + G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(G_OBJECT(storage)); + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_object_storage_finalize(GObjectStorage *storage) +{ + size_t i; /* Boucle de parcours */ + storage_backend_t *backend; /* Gestionnaire à manipuler */ + int ret; /* Bilan d'un appel */ + + g_mutex_lock(&storage->mutex); + + for (i = 0; i < storage->count; i++) + { + backend = &storage->backends[i]; + + if (backend->fd != -1) + close(backend->fd); + else + assert(false); + + ret = access(backend->filename, W_OK); + if (ret == 0) + { + ret = unlink(backend->filename); + if (ret != 0) LOG_ERROR_N("unlink"); + } + + free(backend->name); + + free(backend->filename); + + } + + if (storage->backends != NULL) + free(storage->backends); + + g_mutex_unlock(&storage->mutex); + + g_mutex_clear(&storage->mutex); + + if (storage->hash != NULL) + free(storage->hash); + + G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(G_OBJECT(storage)); + +} + + +/****************************************************************************** +* * +* Paramètres : loaded = contenu binaire à associer. * +* * +* Description : Crée le support d'une conservation d'objets en place. * +* * +* Retour : Mécanismes mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObjectStorage *g_object_storage_new(const char *hash) +{ + GObjectStorage *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); + + result->hash = strdup(hash); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pbuf = zone tampon à lire. * +* * +* Description : Charge le support d'une conservation d'objets en place. * +* * +* Retour : Gestionnaire de conservations construit ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObjectStorage *g_object_storage_load(packed_buffer_t *pbuf) +{ + GObjectStorage *result; /* Structure à retourner */ + char header[6]; /* Entête attendue des données */ + bool status; /* Bilan d'une extraction */ + rle_string str; /* Chaîne à conserver */ + uleb128_t count; /* Nombre de groupes à charger */ + uleb128_t i; /* Boucle de parcours */ + + result = NULL; + + status = extract_packed_buffer(pbuf, header, 6, false); + if (!status) goto quick_exit; + + if (strncmp(header, STORAGE_MAGIC STORAGE_NUMBER, 6) != 0) + goto quick_exit; + + setup_empty_rle_string(&str); + + status = unpack_rle_string(&str, pbuf); + if (!status) goto quick_exit; + + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); + goto quick_exit; + } + + result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); + + result->hash = strdup(get_rle_string(&str)); + + exit_rle_string(&str); + + status = g_type_memory_load_types(result->tpmem, pbuf); + if (!status) goto exit_while_loading; + + status = unpack_uleb128(&count, pbuf); + + for (i = 0; i < count && status; i++) + status = g_object_storage_load_backend(result, pbuf); + + exit_while_loading: + + if (!status) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + quick_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à manipuler. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Sauvegarde le support d'une conservation d'objets en place. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_store(GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + size_t i; /* Boucle de parcours */ + + result = extend_packed_buffer(pbuf, STORAGE_MAGIC STORAGE_NUMBER, 6, false); + + if (result) + { + init_static_rle_string(&str, storage->hash); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } + + g_mutex_lock(&storage->mutex); + + if (result) + result = g_type_memory_store_types(storage->tpmem, pbuf); + + if (result) + result = pack_uleb128((uleb128_t []){ storage->count }, pbuf); + + for (i = 0; i < storage->count && result; i++) + result = pack_storage_backend(&storage->backends[i], pbuf); + + g_mutex_unlock(&storage->mutex); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* name = désignation d'un nouveau groupe d'objets. * +* * +* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. * +* * +* Retour : Informations liées à un groupe ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name) +{ + storage_backend_t *result; /* Encadrement à retourner */ + size_t i; /* Boucle de parcours */ + + assert(!g_mutex_trylock(&storage->mutex)); + + for (i = 0; i < storage->count; i++) + if (strcmp(storage->backends[i].name, name) == 0) + break; + + if (i == storage->count) + result = NULL; + else + result = &storage->backends[i]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* name = désignation d'un nouveau groupe d'objets. * +* backend = support mis en place pour les enregistrements. * +* * +* Description : Ajoute le support d'un nouveau groupe d'objets construits. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend) +{ + bool result; /* Bilan à retourner */ + char *prefix; /* Début de nom de fichier */ + char *filename; /* Chemin d'accès aux données */ + int fd; /* Descripteur de flux ouvert */ + + result = false; + + *backend = NULL; + + assert(!g_mutex_trylock(&storage->mutex)); + + if (g_object_storage_find_backend(storage, name) != NULL) + goto exit; + + /* Préparatifs */ + + asprintf(&prefix, "%s-%s", storage->hash, name); + + fd = make_tmp_file(prefix, "cache", &filename); + + free(prefix); + + if (fd == -1) + goto exit; + + /* Inscription en bonne et due forme */ + + storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); + + *backend = &storage->backends[storage->count - 1]; + + (*backend)->name = strdup(name); + + (*backend)->filename = filename; + (*backend)->fd = fd; + + result = true; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* pbuf = zone tampon à lire. * +* * +* Description : Extrait d'un tampon des enregistrements spécifiques. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + bool status; /* Bilan de lecture de contenu */ + storage_backend_t *backend; /* Informations à intégrer */ + uleb128_t length; /* Taille des données à charger*/ + off_t moved; /* Nouvelle position établie */ + + result = false; + + g_mutex_lock(&storage->mutex); + + /* Récupération du nom et création du support */ + + setup_empty_rle_string(&str); + + status = unpack_rle_string(&str, pbuf); + if (!status) goto exit; + + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); + goto exit; + } + + status = g_object_storage_add_backend(storage, get_rle_string(&str), &backend); + + exit_rle_string(&str); + + if (!status) goto exit; + + /* Récupération du contenu */ + + status = unpack_uleb128(&length, pbuf); + if (!status) goto exit; + + status = safe_write(backend->fd, pbuf->data + pbuf->pos, length); + if (!status) goto exit; + + advance_packed_buffer(pbuf, length); + + moved = lseek(backend->fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + result = true; + + exit: + + g_mutex_unlock(&storage->mutex); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : backend = stockage des enregistrements spécifiques. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Place dans un tampon les données liées à des enregistrements.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string str; /* Chaîne à conserver */ + bool status; /* Bilan de lecture de contenu */ + off_t current; /* Position courante */ + off_t moved; /* Nouvelle position établie */ + void *data; /* Données à transférer */ + + result = false; + + /* Inscription du nom */ + + init_static_rle_string(&str, backend->name); + + status = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + if (!status) goto exit; + + /* Inscription du contenu */ + + current = lseek(backend->fd, 0, SEEK_CUR); + if (current == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + moved = lseek(backend->fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + data = malloc(current); + if (data == NULL) + { + LOG_ERROR_N("malloc"); + goto restore; + } + + status = safe_read(backend->fd, data, current); + if (!status) goto free_mem; + + status = pack_uleb128((uleb128_t []){ current }, pbuf); + if (!status) goto free_mem; + + status = extend_packed_buffer(pbuf, data, current, false); + + free_mem: + + free(data); + + restore: + + moved = lseek(backend->fd, current, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit; + } + + result = status; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un nouveau groupe d'objets. * +* pos = tête de lecture avant écriture. * +* * +* Description : Charge un objet à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos) +{ + GSerializableObject *result; /* Instance à retourner */ + bool status; /* Bilan d'une opération */ + storage_backend_t *backend; /* Informations à consulter */ + packed_buffer_t pbuf; /* Tampon des données à lire */ + off64_t new; /* Nouvelle position de lecture*/ + + result = NULL; + + /* Chargement */ + + status = false; + + g_mutex_lock(&storage->mutex); + + backend = g_object_storage_find_backend(storage, name); + + if (backend != NULL) + { + new = lseek64(backend->fd, pos, SEEK_SET); + + if (new == pos) + { + init_packed_buffer(&pbuf); + status = read_packed_buffer(&pbuf, backend->fd); + } + + } + + g_mutex_unlock(&storage->mutex); + + if (!status) + goto exit; + + /* Phase de conversion */ + + result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object(storage->tpmem, &pbuf)); + + if (result) + { + status = g_serializable_object_load(result, storage, &pbuf); + + if (!status) + g_clear_object(&result); + + } + + exit_packed_buffer(&pbuf); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un nouveau groupe d'objets. * +* pbuf = zone tampon à parcourir. * +* * +* Description : Charge un objet interne à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf) +{ + GSerializableObject *result; /* Instance à retourner */ + uint64_t pos; /* Localisation des données */ + bool status; /* Bilan d'une opération */ + + result = NULL; + + status = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); + + if (status) + result = g_object_storage_load_object(storage, name, pos); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un nouveau groupe d'objets. * +* pbuf = zone tampon à parcourir. * +* expected = type d'objet attendu. * +* ... = élément restauré ou NULL en cas d'échec. [OUT] * +* * +* Description : Charge un objet interne à partir de données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf, GType expected, ...) +{ + bool result; /* Bilan d'une opération */ + uint64_t pos; /* Localisation des données */ + GSerializableObject *instance; /* Objet rechargé à valider */ + va_list ap; /* Liste d'arguments variables */ + void **object; /* Lieu d'enregistrement final */ + + result = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); + + if (result) + { + if (pos == 0) + *object = NULL; + + else + { + instance = g_object_storage_load_object(storage, name, pos); + + result = G_TYPE_CHECK_INSTANCE_TYPE(instance, expected); + + if (result) + { + va_start(ap, expected); + + object = va_arg(ap, void **); + + *object = instance; + + va_end(ap); + + } + + else + g_clear_object(&instance); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un nouveau groupe d'objets. * +* object = objet sérialisable à traiter. * +* pos = tête de lecture avant écriture. [OUT] * +* * +* Description : Sauvegarde un object sous forme de données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_store_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, off64_t *pos) +{ + bool result; /* Bilan à retourner */ + packed_buffer_t pbuf; /* Tampon des données à écrire */ + storage_backend_t *backend; /* Informations à consulter */ + off64_t tmp; /* Conservation éphémère */ + + /* Phase de conversion */ + + init_packed_buffer(&pbuf); + + result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), &pbuf); + if (!result) goto exit; + + result = g_serializable_object_store(object, storage, &pbuf); + if (!result) goto exit; + + /* Enregistrement */ + + result = false; + + g_mutex_lock(&storage->mutex); + + backend = g_object_storage_find_backend(storage, name); + + if (backend == NULL) + g_object_storage_add_backend(storage, name, &backend); + + if (backend != NULL) + { + if (pos == NULL) + pos = &tmp; + + *pos = lseek64(backend->fd, 0, SEEK_CUR); + + if (*pos != (off64_t)-1) + result = write_packed_buffer(&pbuf, backend->fd); + + } + + g_mutex_unlock(&storage->mutex); + + /* Sortie propre */ + + exit: + + exit_packed_buffer(&pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un nouveau groupe d'objets. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un object interne sous forme de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_pack_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + off64_t pos; /* Localisation des données */ + + if (object == NULL) + result = extend_packed_buffer(pbuf, (uint64_t []){ 0 }, sizeof(uint64_t), true); + + else + { + result = g_object_storage_store_object(storage, name, object, &pos); + + if (result) + result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true); + + } + + return result; + +} diff --git a/src/glibext/storage.h b/src/glibext/storage.h new file mode 100644 index 0000000..cc0caad --- /dev/null +++ b/src/glibext/storage.h @@ -0,0 +1,89 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.h - prototypes pour la conservation sur disque d'objets construits + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ANALYSIS_STORAGE_STORAGE_H +#define _ANALYSIS_STORAGE_STORAGE_H + + +#include +#include + + +#include "serialize.h" +#include "tpmem.h" + + + +#define G_TYPE_OBJECT_STORAGE g_object_storage_get_type() +#define G_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_OBJECT_STORAGE, GObjectStorage)) +#define G_IS_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_OBJECT_STORAGE)) +#define G_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) +#define G_IS_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_OBJECT_STORAGE)) +#define G_OBJECT_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) + + +/* Définition d'une conservation d'objets construits (instance) */ +typedef struct _GObjectStorage GObjectStorage; + +/* Définition d'une conservation d'objets construits (classe) */ +typedef struct _GObjectStorageClass GObjectStorageClass; + + +/* Indique le type défini pour une conservation d'objets construits. */ +GType g_object_storage_get_type(void); + +/* Crée le support d'une conservation d'objets en place. */ +GObjectStorage *g_object_storage_new(const char *); + +#define get_storage_linked_format(s) \ + ({ \ + void*__result; \ + __result = g_object_get_data(G_OBJECT(s), "format"); \ + g_object_ref(G_OBJECT(__result)); \ + __result; \ + }) + +/* Charge le support d'une conservation d'objets en place. */ +GObjectStorage *g_object_storage_load(packed_buffer_t *); + +/* Sauvegarde le support d'une conservation d'objets en place. */ +bool g_object_storage_store(GObjectStorage *, packed_buffer_t *); + +/* Charge un objet à partir de données rassemblées. */ +GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t); + +/* Charge un objet interne à partir de données rassemblées. */ +GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char *, packed_buffer_t *); + +/* Sauvegarde un object sous forme de données rassemblées. */ +bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *); + +/* Charge un objet interne à partir de données rassemblées. */ +bool g_object_storage_unpack_object_2(GObjectStorage *, const char *, packed_buffer_t *, GType, ...); + +/* Sauvegarde un object interne sous forme de données. */ +bool g_object_storage_pack_object(GObjectStorage *, const char *, const GSerializableObject *, packed_buffer_t *); + + + +#endif /* _ANALYSIS_STORAGE_STORAGE_H */ diff --git a/src/glibext/tpmem.c b/src/glibext/tpmem.c new file mode 100644 index 0000000..0703aeb --- /dev/null +++ b/src/glibext/tpmem.c @@ -0,0 +1,429 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.c - mémorisation des types d'objets mis en cache + * + * Copyright (C) 2020 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 . + */ + + +#include "tpmem.h" + + +#include +#include + + +#include "../db/misc/rlestr.h" +#include "../../arch/operands/target.h" +#include "../../core/logs.h" + + + +/* Conservation d'une référence sur un type */ +typedef struct _gtype_ref_info_t +{ + GType gtype; /* Type pour la GLib */ + gpointer gclass; /* Lien vers sa classe */ + + /** + * La GLib n'est pas très claire sur la taille de GType : + * + * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus + * typedef gsize GType; + * #else // for historic reasons, C++ links against gulong GTypes + * typedef gulong GType; + * #endif + * + * Et : + * + * typedef unsigned $glib_size_type_define gsize; + * + * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits + * lors des enregistrements. + */ + +} gtype_ref_info_t; + +/* Définition d'une mémoire de types d'objets (instance) */ +struct _GTypeMemory +{ + GObject parent; /* A laisser en premier */ + + gtype_ref_info_t *gtypes; /* Types des objets reconnus */ + size_t count; /* Quantité de ces objets */ + GMutex mutex; /* Contrôle d'accès à la liste */ + +}; + +/* Définition d'une mémoire de types d'objets (classe) */ +struct _GTypeMemoryClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des mémoires de types d'objets. */ +static void g_type_memory_class_init(GTypeMemoryClass *); + +/* Initialise une instance de mémoire de types d'objets. */ +static void g_type_memory_init(GTypeMemory *); + +/* Supprime toutes les références externes. */ +static void g_type_memory_dispose(GTypeMemory *); + +/* Procède à la libération totale de la mémoire. */ +static void g_type_memory_finalize(GTypeMemory *); + + + +/* Indique le type défini pour une mémoire de types d'objets. */ +G_DEFINE_TYPE(GTypeMemory, g_type_memory, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des mémoires de types d'objets. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_type_memory_class_init(GTypeMemoryClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_type_memory_dispose; + object->finalize = (GObjectFinalizeFunc)g_type_memory_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = instance à initialiser. * +* * +* Description : Initialise une instance de mémoire de types d'objets. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_type_memory_init(GTypeMemory *tpmem) +{ + tpmem->gtypes = NULL; + tpmem->count = 0; + g_mutex_init(&tpmem->mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_type_memory_dispose(GTypeMemory *tpmem) +{ + uint64_t i; /* Boucle de parcours */ + + g_mutex_lock(&tpmem->mutex); + + for (i = 0; i < tpmem->count; i++) + if (tpmem->gtypes[i].gclass != NULL) + g_type_class_unref(tpmem->gtypes[i].gclass); + + g_mutex_unlock(&tpmem->mutex); + + g_mutex_clear(&tpmem->mutex); + + G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(G_OBJECT(tpmem)); + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_type_memory_finalize(GTypeMemory *tpmem) +{ + if (tpmem->gtypes != NULL) + free(tpmem->gtypes); + + G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(G_OBJECT(tpmem)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une mémoire pour types d'objets. * +* * +* Retour : Instance mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GTypeMemory *g_type_memory_new(void) +{ + GTypeMemory *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_TYPE_MEMORY, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = mémoire à compléter. * +* pbuf = zone tampon à lire. * +* * +* Description : Apprend tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à enregistrer */ + uleb128_t count; /* Nombre d'éléments détectés */ + uleb128_t i; /* Boucle de parcours */ + rle_string str; /* Chaîne à charger */ + + result = unpack_uleb128(&count, pbuf); + + if (result) + { + g_mutex_lock(&tpmem->mutex); + + tpmem->count = count; + + assert(tpmem->gtypes == NULL); + tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t)); + + setup_empty_rle_string(&str); + + for (i = 0; i < tpmem->count && result; i++) + { + result = unpack_rle_string(&str, pbuf); + if (!result) break; + + if (get_rle_string(&str) == NULL) + { + exit_rle_string(&str); + break; + } + + tpmem->gtypes[i].gtype = g_type_from_name(get_rle_string(&str)); + result = (tpmem->gtypes[i].gtype != 0); + + if (!result) + log_variadic_message(LMT_ERROR, "Unknown type: '%s'", get_rle_string(&str)); + + else + tpmem->gtypes[i].gclass = g_type_class_ref(tpmem->gtypes[i].gtype); + + exit_rle_string(&str); + + } + + } + + g_mutex_unlock(&tpmem->mutex); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = mémoire à manipuler. * +* pbuf = zone tampon à venir lire. * +* * +* Description : Crée une nouvelle instance d'objet à partir de son type. * +* * +* Retour : Instance issue de l'opération ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) +{ + GObject *result; /* Nouvelle instance à renvoyer*/ + uleb128_t index; /* Indice du point d'insertion */ + bool status; /* Bilan d'une récupération */ + + result = NULL; + + status = unpack_uleb128(&index, pbuf); + + if (status) + { + g_mutex_lock(&tpmem->mutex); + + if (index < tpmem->count) + result = g_object_new(tpmem->gtypes[index].gtype, NULL); + + g_mutex_unlock(&tpmem->mutex); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = mémoire à manipuler. * +* obj = instance dont le type est à mémoriser. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Sauvegarde le type d'un objet instancié. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GType gtype; /* Type à enregistrer */ + size_t index; /* Indice du point d'insertion */ + + gtype = G_TYPE_FROM_INSTANCE(obj); + + /** + * Pour quelques explications sur l'esquive suivante, se rapporter aux + * commentaires de g_target_operand_unserialize(). + * + * Dans la situation présente, on ne doit pas enregistrer le type dans le tampon, + * car l'opérande va relancer l'opération entière (avec un opérande temporaire), + * ce qui conduirait à l'enregistrement de deux types successifs dans les données. + */ + + if (gtype == G_TYPE_TARGET_OPERAND) + result = true; + + else + { + g_mutex_lock(&tpmem->mutex); + + for (index = 0; index < tpmem->count; index++) + if (tpmem->gtypes[index].gtype == gtype) + break; + + if (index == tpmem->count) + { + tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t)); + + assert(tpmem->count > 0); + + tpmem->gtypes[index].gtype = gtype; + tpmem->gtypes[index].gclass = g_type_class_ref(gtype); + + } + + g_mutex_unlock(&tpmem->mutex); + + result = pack_uleb128((uleb128_t []){ index }, pbuf); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : tpmem = mémoire à consulter. * +* pbuf = zone tampon à remplir. [OUT] * +* * +* Description : Enregistre tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_type_memory_store_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à enregistrer */ + uint64_t i; /* Boucle de parcours */ + const gchar *name; /* Désignation d'un type */ + rle_string str; /* Chaîne à conserver */ + + g_mutex_lock(&tpmem->mutex); + + result = pack_uleb128((uleb128_t []){ tpmem->count }, pbuf); + + for (i = 0; i < tpmem->count && result; i++) + { + name = g_type_name(tpmem->gtypes[i].gtype); + + init_static_rle_string(&str, name); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } + + g_mutex_unlock(&tpmem->mutex); + + return result; + +} diff --git a/src/glibext/tpmem.h b/src/glibext/tpmem.h new file mode 100644 index 0000000..34cbde6 --- /dev/null +++ b/src/glibext/tpmem.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ANALYSIS_STORAGE_TPMEM_H +#define _ANALYSIS_STORAGE_TPMEM_H + + +#include + + +#include "../../common/packed.h" + + + +#define G_TYPE_TYPE_MEMORY g_type_memory_get_type() +#define G_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TYPE_MEMORY, GTypeMemory)) +#define G_IS_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TYPE_MEMORY)) +#define G_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) +#define G_IS_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPE_MEMORY)) +#define G_TYPE_MEMORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) + + +/* Définition d'une mémoire de types d'objets (instance) */ +typedef struct _GTypeMemory GTypeMemory; + +/* Définition d'une mémoire de types d'objets (classe) */ +typedef struct _GTypeMemoryClass GTypeMemoryClass; + + +/* Indique le type défini pour une mémoire de types d'objets. */ +GType g_type_memory_get_type(void); + +/* Crée une mémoire pour types d'objets. */ +GTypeMemory *g_type_memory_new(void); + +/* Apprend tous les types mémorisés dans un tampon. */ +bool g_type_memory_load_types(GTypeMemory *, packed_buffer_t *); + +/* Crée une nouvelle instance d'objet à partir de son type. */ +GObject *g_type_memory_create_object(GTypeMemory *, packed_buffer_t *); + +/* Sauvegarde le type d'un objet instancié. */ +bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, packed_buffer_t *); + +/* Enregistre tous les types mémorisés dans un tampon. */ +bool g_type_memory_store_types(GTypeMemory *, packed_buffer_t *); + + + +#endif /* _ANALYSIS_STORAGE_TPMEM_H */ diff --git a/tests/analysis/storage/storage.py b/tests/analysis/storage/storage.py deleted file mode 100644 index 612d500..0000000 --- a/tests/analysis/storage/storage.py +++ /dev/null @@ -1,81 +0,0 @@ - -from chrysacase import ChrysalideTestCase -from pychrysalide import core -from pychrysalide.analysis.contents import FileContent -from pychrysalide.analysis.storage import ObjectStorage -from pychrysalide.common import PackedBuffer -import os -import shutil -import tempfile - - -class TestObjectStorage(ChrysalideTestCase): - """TestCase for analysis.storage.""" - - @classmethod - def setUpClass(cls): - - super(TestObjectStorage, cls).setUpClass() - - cls._tmp_path = tempfile.mkdtemp() - - config = core.get_main_configuration() - param = config.search(core.MainParameterKeys.TMPDIR) - - cls._old_tmpdir = param.value - param.value = cls._tmp_path - - cls.log('Using temporary directory "%s"' % cls._tmp_path) - - - @classmethod - def tearDownClass(cls): - - super(TestObjectStorage, cls).tearDownClass() - - config = core.get_main_configuration() - param = config.search(core.MainParameterKeys.TMPDIR) - - param.value = cls._old_tmpdir - - # import os - # os.system('ls -laihR %s' % cls._tmp_path) - - cls.log('Delete directory "%s"' % cls._tmp_path) - - shutil.rmtree(cls._tmp_path) - - - def testFileContentStorage(self): - """Store and load file binary content.""" - - storage = ObjectStorage('my-storage-hash') - self.assertIsNotNone(storage) - - filename = os.path.join(self._tmp_path, 'test.bin') - - with open(filename, 'wb') as fd: - fd.write(b'ABC') - - cnt = FileContent(filename) - self.assertIsNotNone(cnt) - - ret = storage.store_object('contents', cnt) - self.assertEqual(ret, 0) - - pbuf = PackedBuffer() - - ret = storage.store(pbuf) - self.assertTrue(ret) - - self.assertTrue(pbuf.payload_length > 0) - - pbuf.rewind() - - storage2 = ObjectStorage.load(pbuf) - self.assertIsNotNone(storage2) - - cnt2 = storage2.load_object('contents', 0) - self.assertIsNotNone(cnt2) - - self.assertEqual(cnt.data, cnt2.data) diff --git a/tests/glibext/storage.py b/tests/glibext/storage.py new file mode 100644 index 0000000..612d500 --- /dev/null +++ b/tests/glibext/storage.py @@ -0,0 +1,81 @@ + +from chrysacase import ChrysalideTestCase +from pychrysalide import core +from pychrysalide.analysis.contents import FileContent +from pychrysalide.analysis.storage import ObjectStorage +from pychrysalide.common import PackedBuffer +import os +import shutil +import tempfile + + +class TestObjectStorage(ChrysalideTestCase): + """TestCase for analysis.storage.""" + + @classmethod + def setUpClass(cls): + + super(TestObjectStorage, cls).setUpClass() + + cls._tmp_path = tempfile.mkdtemp() + + config = core.get_main_configuration() + param = config.search(core.MainParameterKeys.TMPDIR) + + cls._old_tmpdir = param.value + param.value = cls._tmp_path + + cls.log('Using temporary directory "%s"' % cls._tmp_path) + + + @classmethod + def tearDownClass(cls): + + super(TestObjectStorage, cls).tearDownClass() + + config = core.get_main_configuration() + param = config.search(core.MainParameterKeys.TMPDIR) + + param.value = cls._old_tmpdir + + # import os + # os.system('ls -laihR %s' % cls._tmp_path) + + cls.log('Delete directory "%s"' % cls._tmp_path) + + shutil.rmtree(cls._tmp_path) + + + def testFileContentStorage(self): + """Store and load file binary content.""" + + storage = ObjectStorage('my-storage-hash') + self.assertIsNotNone(storage) + + filename = os.path.join(self._tmp_path, 'test.bin') + + with open(filename, 'wb') as fd: + fd.write(b'ABC') + + cnt = FileContent(filename) + self.assertIsNotNone(cnt) + + ret = storage.store_object('contents', cnt) + self.assertEqual(ret, 0) + + pbuf = PackedBuffer() + + ret = storage.store(pbuf) + self.assertTrue(ret) + + self.assertTrue(pbuf.payload_length > 0) + + pbuf.rewind() + + storage2 = ObjectStorage.load(pbuf) + self.assertIsNotNone(storage2) + + cnt2 = storage2.load_object('contents', 0) + self.assertIsNotNone(cnt2) + + self.assertEqual(cnt.data, cnt2.data) -- cgit v0.11.2-87-g4458