From f3e136eab9fd6adcb51988c9f70ca7f35552abc4 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 17 May 2020 10:48:02 +0200 Subject: Introduced a new object of string constant sets. --- plugins/pychrysalide/Makefile.am | 1 + plugins/pychrysalide/glibext/binportion.c | 35 ---- plugins/pychrysalide/glibext/constants.c | 13 ++ plugins/pychrysalide/helpers.c | 69 ++++++++ plugins/pychrysalide/helpers.h | 27 +++ plugins/pychrysalide/pychrysa.c | 2 + plugins/pychrysalide/strenum.c | 262 ++++++++++++++++++++++++++++++ plugins/pychrysalide/strenum.h | 42 +++++ plugins/pychrysalide/struct.c | 2 +- 9 files changed, 417 insertions(+), 36 deletions(-) create mode 100644 plugins/pychrysalide/strenum.c create mode 100644 plugins/pychrysalide/strenum.h diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am index b85f417..6bcaef4 100644 --- a/plugins/pychrysalide/Makefile.am +++ b/plugins/pychrysalide/Makefile.am @@ -11,6 +11,7 @@ pychrysalide_la_SOURCES = \ plugin.h plugin.c \ pychrysa.h pychrysa.c \ star.h star.c \ + strenum.h strenum.c \ struct.h struct.c \ weak.h weak.c diff --git a/plugins/pychrysalide/glibext/binportion.c b/plugins/pychrysalide/glibext/binportion.c index 14df461..3065755 100644 --- a/plugins/pychrysalide/glibext/binportion.c +++ b/plugins/pychrysalide/glibext/binportion.c @@ -73,9 +73,6 @@ static PyObject *py_binary_portion_get_rights(PyObject *, void *); /* Définit les droits associés à une partie de code. */ static int py_binary_portion_set_rights(PyObject *, PyObject *, void *); -/* Définit les constantes pour les portions de binaire. */ -static bool py_binary_portion_define_constants(PyTypeObject *); - /****************************************************************************** @@ -608,35 +605,6 @@ static int py_binary_portion_set_rights(PyObject *self, PyObject *value, void *c /****************************************************************************** * * -* Paramètres : obj_type = type dont le dictionnaire est à compléter. * -* * -* Description : Définit les constantes pour les portions de binaire. * -* * -* Retour : true en cas de succès de l'opération, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_binary_portion_define_constants(PyTypeObject *obj_type) -{ - bool result; /* Bilan à retourner */ - - result = true; - - if (result) result = PyDict_AddStringMacro(obj_type, BPC_RAW); - if (result) result = PyDict_AddStringMacro(obj_type, BPC_CODE); - if (result) result = PyDict_AddStringMacro(obj_type, BPC_DATA); - if (result) result = PyDict_AddStringMacro(obj_type, BPC_DATA_RO); - if (result) result = PyDict_AddStringMacro(obj_type, BPC_DISASS_ERROR); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -718,9 +686,6 @@ bool ensure_python_binary_portion_is_registered(void) if (!register_class_for_pygobject(dict, G_TYPE_BIN_PORTION, type, &PyGObject_Type)) return false; - if (!py_binary_portion_define_constants(type)) - return false; - if (!define_binary_portion_constants(type)) return false; diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c index 680feaf..e24a6e0 100644 --- a/plugins/pychrysalide/glibext/constants.c +++ b/plugins/pychrysalide/glibext/constants.c @@ -49,8 +49,21 @@ bool define_binary_portion_constants(PyTypeObject *type) { bool result; /* Bilan à retourner */ + PyObject *strdict; /* Groupe de chaînes constantes*/ PyObject *values; /* Groupe de valeurs à établir */ + result = create_string_constants_group_to_type(type, "BinaryPortionCode", + "Selector names for the CSS rendering.", &strdict); + + if (result) result = extend_string_constants_group(strdict, "RAW", BPC_RAW); + if (result) result = extend_string_constants_group(strdict, "CODE", BPC_CODE); + if (result) result = extend_string_constants_group(strdict, "DATA", BPC_DATA); + if (result) result = extend_string_constants_group(strdict, "DATA_RO", BPC_DATA_RO); + if (result) result = extend_string_constants_group(strdict, "DISASS_ERROR", BPC_DISASS_ERROR); + + if (!result) + goto exit; + values = PyDict_New(); result = add_const_to_group(values, "NONE", PAC_NONE); diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index 5e911ea..73fb4a7 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -40,6 +40,7 @@ #include "access.h" #include "constval.h" +#include "strenum.h" @@ -1324,3 +1325,71 @@ PyObject *_cast_with_constants_group(const char *owner, const char *name, unsign return result; } + + +/****************************************************************************** +* * +* Paramètres : dict = dictionnaire dont le contenu est à compléter. * +* name = désignation humaine du groupe à constituer. * +* doc = documentation à associer au groupe. * +* out = dictionnaire à compléter. [OUT] * +* * +* Description : Officialise un groupe de constantes de chaînes de caractères.* +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _create_string_constants_group(PyObject *dict, const char *name, const char *doc, PyObject **out) +{ + bool result; /* Bilan à retourner */ + PyObject *class; /* Classe "Enum*" */ + PyObject *args; /* Argument de construction */ + int ret; /* Bilan d'une insertion */ + PyObject *features; /* Module à recompléter */ + PyObject *features_dict; /* Dictionnaire à compléter */ + + result = false; + + /* Recherche et instanciation de la classe Python */ + + class = (PyObject *)get_python_string_enum_type(); + + args = Py_BuildValue("(s)", doc); + + *out = PyObject_CallObject(class, args); + + Py_DECREF(args); + + if (*out == NULL) + goto exit; + + /* Constitution de l'énumération et enregistrement */ + + ret = PyDict_SetItemString(dict, name, *out); + if (ret != 0) goto register_0_error; + + features = get_access_to_python_module("pychrysalide.features"); + + features_dict = PyModule_GetDict(features); + + ret = PyDict_SetItemString(features_dict, name, *out); + if (ret != 0) goto register_1_error; + + result = true; + + /* Sortie propre */ + + register_1_error: + register_0_error: + + if (!result) + Py_DECREF(*out); + + exit: + + return result; + +} diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h index dbc9272..5f28c57 100644 --- a/plugins/pychrysalide/helpers.h +++ b/plugins/pychrysalide/helpers.h @@ -225,6 +225,33 @@ PyObject *_cast_with_constants_group(const char *, const char *, unsigned long); #define cast_with_constants_group_from_module(owner, name, value) \ _cast_with_constants_group(owner, name, value) +/* Officialise un groupe de constantes de chaînes de caractères. */ +bool _create_string_constants_group(PyObject *, const char *, const char *, PyObject **); + +#define create_string_constants_group_to_type(type, name, doc, out) \ + _create_string_constants_group(type->tp_dict, name, doc, out) + +#define create_string_constants_group_to_module(mod, name, doc, out) \ + ({ \ + bool __result; \ + PyObject *__dict; \ + __dict = PyModule_GetDict(mod); \ + __result = _create_string_constants_group(__dict, name, doc, out); \ + __result; \ + }) + +#define extend_string_constants_group(dict, key, str) \ + ({ \ + bool __result; \ + PyObject *__str_obj; \ + int __ret; \ + __str_obj = PyUnicode_FromString(str); \ + __ret = PyDict_SetItemString(dict, key, __str_obj); \ + Py_DECREF(__str_obj); \ + __result = (__ret == 0); \ + __result; \ + }) + #endif /* _PLUGINS_PYCHRYSALIDE_HELPERS_H */ diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c index 683e41e..333544a 100644 --- a/plugins/pychrysalide/pychrysa.c +++ b/plugins/pychrysalide/pychrysa.c @@ -51,6 +51,7 @@ #include "helpers.h" #include "plugin.h" #include "star.h" +#include "strenum.h" #include "struct.h" #include "analysis/module.h" #include "arch/module.h" @@ -527,6 +528,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) if (status) status = ensure_python_plugin_module_is_registered(); if (status) status = ensure_python_py_constval_is_registered(); + if (status) status = ensure_python_string_enum_is_registered(); if (status) status = ensure_python_py_struct_is_registered(); if (status) status = populate_analysis_module(); diff --git a/plugins/pychrysalide/strenum.c b/plugins/pychrysalide/strenum.c new file mode 100644 index 0000000..52ee383 --- /dev/null +++ b/plugins/pychrysalide/strenum.c @@ -0,0 +1,262 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strenum.c - mise à disposition de constantes pointant des chaînes de caractères + * + * 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 "strenum.h" + + +#include +#include +#include + + +#include "access.h" +#include "helpers.h" + + + +/* Objet à vocation abstraite */ +typedef struct _PyStringEnum +{ + PyDictObject base; /* A laisser en premier */ + + char *grp_doc; /* Documentation d'instance */ + + int val; + +} PyStringEnum; + + +/* Initialise un objet Python de type 'StringEnum'. */ +static int py_string_enum_init(PyStringEnum *, PyObject *, PyObject *); + +/* Accompagne la suppression complète d'un objet 'StringEnum'. */ +static void py_string_enum_finalize(PyStringEnum *); + +/* Assure l'encadrement des accès aux champs d'une structure. */ +static PyObject *py_string_enum_getattr(PyObject *, char *); + + + +/****************************************************************************** +* * +* Paramètres : self = instance d'objet à initialiser. * +* args = arguments passés pour l'appel. * +* kwds = mots clefs éventuellement fournis en complément. * +* * +* Description : Initialise un objet Python de type 'StringEnum'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_string_enum_init(PyStringEnum *self, PyObject *args, PyObject *kwds) +{ + int result; /* Bilan à retourner */ + char *doc; /* Documentation de l'instance */ + int ret; /* Bilan de lecture des args. */ + +#define STRING_ENUM_DOC \ + "StringEnum provides dictionaries collecting string constants." \ + "\n" \ + "Such constants are mainly used as keywords for accessing" \ + " configuration parameters." + + result = -1; + + doc = NULL; + + ret = PyArg_ParseTuple(args, "|s", &doc); + if (!ret) goto exit; + + if (doc != NULL) + self->grp_doc = strdup(doc); + + result = 0; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance d'objet à traiter. * +* * +* Description : Accompagne la suppression complète d'un objet 'StringEnum'. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_string_enum_finalize(PyStringEnum *self) +{ + if (self->grp_doc != NULL) + free(self->grp_doc); + +} + + +/****************************************************************************** +* * +* Paramètres : self = structure C convertie en Python. * +* name = nom du champ auquel un accès est demandé. * +* * +* Description : Assure l'encadrement des accès aux champs d'une structure. * +* * +* Retour : Valeur du champ demandé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_string_enum_getattr(PyObject *self, char *name) +{ + PyObject *result; /* Elément à retourner */ + PyObject *w; /* Conversion du nom de champ */ + PyTypeObject *tp; /* Type de l'objet manipulé */ + + result = PyDict_GetItemString(self, name); + + if (result != NULL) + Py_INCREF(result); + + else + { + w = PyUnicode_InternFromString(name); + if (w == NULL) return NULL; + + tp = Py_TYPE(self); + + if (tp->tp_base->tp_getattro != NULL) + result = tp->tp_base->tp_getattro(self, w); + + Py_DECREF(w); + + } + + 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_string_enum_type(void) +{ + static PyMethodDef py_string_enum_methods[] = { + { NULL } + }; + + static PyMemberDef py_string_enum_members[] = { + { + "__grp_doc__", T_STRING, offsetof(PyStringEnum, grp_doc), READONLY, + "Specialized documentation for an instance of the object." + }, + { NULL } + }; + + static PyGetSetDef py_string_enum_getseters[] = { + { NULL } + }; + + static PyTypeObject py_string_enum_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.StringEnum", + .tp_basicsize = sizeof(PyStringEnum), + + .tp_getattr = py_string_enum_getattr, + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE \ + | Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_HAVE_FINALIZE, + + .tp_doc = STRING_ENUM_DOC, + + .tp_methods = py_string_enum_methods, + .tp_members = py_string_enum_members, + .tp_getset = py_string_enum_getseters, + .tp_base = &PyDict_Type, + + .tp_init = (initproc)py_string_enum_init, + + .tp_finalize = (destructor)py_string_enum_finalize, + + }; + + return &py_string_enum_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.PyStringEnum'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_string_enum_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'StringEnum' */ + PyObject *module; /* Module à recompléter */ + + type = get_python_string_enum_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide"); + + if (PyType_Ready(type) != 0) + return false; + + if (!register_python_module_object(module, type)) + return false; + + } + + return true; + +} diff --git a/plugins/pychrysalide/strenum.h b/plugins/pychrysalide/strenum.h new file mode 100644 index 0000000..04b841c --- /dev/null +++ b/plugins/pychrysalide/strenum.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strenum.h - prototypes pour la mise à disposition de constantes pointant des chaînes de caractères + * + * 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_STRENUM_H +#define _PLUGINS_PYCHRYSALIDE_STRENUM_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_string_enum_type(void); + +/* Prend en charge l'objet 'pychrysalide.StringEnum'. */ +bool ensure_python_string_enum_is_registered(void); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_STRENUM_H */ diff --git a/plugins/pychrysalide/struct.c b/plugins/pychrysalide/struct.c index f34a9f3..2569fa2 100644 --- a/plugins/pychrysalide/struct.c +++ b/plugins/pychrysalide/struct.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * struct.c - prototypes pour la conversion de structures C en équivalent Python + * struct.c - conversion de structures C en équivalent Python * * Copyright (C) 2018-2019 Cyrille Bagard * -- cgit v0.11.2-87-g4458