diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2025-03-17 07:36:58 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2025-03-17 07:36:58 (GMT) |
commit | a28e1b94a83bee9a2424ab84818a5547eafaf0cf (patch) | |
tree | ecaf5556433afd4f19f4bfcbf378cdde3f619e51 /plugins | |
parent | b18c64b69c8c048c640b5d9f6c45b1cfda605ae8 (diff) |
Restore the definition of main operands.gtk4
Diffstat (limited to 'plugins')
22 files changed, 1296 insertions, 1020 deletions
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am index d1bf457..a09938f 100644 --- a/plugins/pychrysalide/Makefile.am +++ b/plugins/pychrysalide/Makefile.am @@ -80,7 +80,8 @@ pychrysalideui_la_SOURCES = \ core-ui-int.h \ core-ui.h core-ui.c -pychrysalideui_la_LIBADD = +pychrysalideui_la_LIBADD = \ + arch/libpychrysaarchui.la # -ldl: dladdr(), dlerror() pychrysalideui_la_LDFLAGS = \ diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am index d3ee3f0..a134947 100644 --- a/plugins/pychrysalide/arch/Makefile.am +++ b/plugins/pychrysalide/arch/Makefile.am @@ -1,5 +1,5 @@ -noinst_LTLIBRARIES = libpychrysaarch4.la # libpychrysaarch.la +noinst_LTLIBRARIES = libpychrysaarch4.la libpychrysaarchui.la # libpychrysaarch.la # libpychrysaarch_la_SOURCES = \ # constants.h constants.c \ @@ -9,7 +9,6 @@ noinst_LTLIBRARIES = libpychrysaarch4.la # libpychrysaarch.la # module.h module.c \ # operand.h operand.c \ # processor.h processor.c \ -# register.h register.c \ # vmpa.h vmpa.c # libpychrysaarch_la_LIBADD = \ @@ -23,20 +22,31 @@ noinst_LTLIBRARIES = libpychrysaarch4.la # libpychrysaarch.la libpychrysaarch4_la_SOURCES = \ constants.h constants.c \ module.h module.c \ + operand.h operand.c \ + register.h register.c \ vmpa.h vmpa.c -# libpychrysaarch4_la_LIBADD = \ -# instructions/libpychrysaarchinstructions.la \ -# operands/libpychrysaarchoperands.la +libpychrysaarch4_la_LIBADD = \ + operands/libpychrysaarchoperands.la libpychrysaarch4_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ $(TOOLKIT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT +libpychrysaarchui_la_SOURCES = \ + module-ui.h module-ui.c \ + operand-ui.h operand-ui.c + +libpychrysaarchui_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + $(TOOLKIT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + devdir = $(includedir)/chrysalide/$(subdir) dev_HEADERS = $(libpychrysaarch_la_SOURCES:%c=) # SUBDIRS = instructions operands +SUBDIRS = operands diff --git a/plugins/pychrysalide/arch/module-ui.c b/plugins/pychrysalide/arch/module-ui.c new file mode 100644 index 0000000..201f760 --- /dev/null +++ b/plugins/pychrysalide/arch/module-ui.c @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire arch (forme graphique) en tant que module + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module-ui.h" + + +#include <assert.h> + + +#include "operand-ui.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'arch' (mode UI). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_arch_module_ui(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_arch_operand_ui_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/pychrysalide/arch/module-ui.h b/plugins/pychrysalide/arch/module-ui.h new file mode 100644 index 0000000..afa31d2 --- /dev/null +++ b/plugins/pychrysalide/arch/module-ui.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire arch (forme graphique) en tant que module + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_MODULE_UI_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_MODULE_UI_H + + +#include <Python.h> +#include <stdbool.h> + + +/* Intègre les objets du module 'arch' (mode UI). */ +bool populate_arch_module_ui(void); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_MODULE_UI_H */ diff --git a/plugins/pychrysalide/arch/module.c b/plugins/pychrysalide/arch/module.c index 0127348..3f52a58 100644 --- a/plugins/pychrysalide/arch/module.c +++ b/plugins/pychrysalide/arch/module.c @@ -31,16 +31,16 @@ /* #include "context.h" #include "instriter.h" -#include "instruction.h" +*/ +//#include "instruction.h" #include "operand.h" -#include "processor.h" +//#include "processor.h" #include "register.h" -*/ #include "vmpa.h" /* #include "instructions/module.h" -#include "operands/module.h" */ +#include "operands/module.h" #include "../helpers.h" @@ -79,8 +79,8 @@ bool add_arch_module(PyObject *super) /* if (result) result = add_arch_instructions_module(module); - if (result) result = add_arch_operands_module(module); */ + if (result) result = add_arch_operands_module(module); return result; @@ -108,18 +108,18 @@ bool populate_arch_module(void) /* if (result) result = ensure_python_proc_context_is_registered(); if (result) result = ensure_python_instr_iterator_is_registered(); - if (result) result = ensure_python_arch_instruction_is_registered(); + */ + //if (result) result = ensure_python_arch_instruction_is_registered(); if (result) result = ensure_python_arch_operand_is_registered(); - if (result) result = ensure_python_arch_processor_is_registered(); + //if (result) result = ensure_python_arch_processor_is_registered(); if (result) result = ensure_python_arch_register_is_registered(); - */ if (result) result = ensure_python_vmpa_is_registered(); if (result) result = ensure_python_mrange_is_registered(); /* if (result) result = populate_arch_instructions_module(); - if (result) result = populate_arch_operands_module(); */ + if (result) result = populate_arch_operands_module(); assert(result); diff --git a/plugins/pychrysalide/arch/operand-ui.c b/plugins/pychrysalide/arch/operand-ui.c new file mode 100644 index 0000000..5062513 --- /dev/null +++ b/plugins/pychrysalide/arch/operand-ui.c @@ -0,0 +1,461 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.c - équivalent Python du fichier "arch/operand-ui.c" + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "operand-ui.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <arch/operand-ui-int.h> + + +#include "../access.h" +#include "../helpers.h" + + + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void py_arch_operand_ui_interface_init(GArchOperandUIInterface *, gpointer *); + +/* Traduit un opérande en version humainement lisible. */ +static void py_arch_operand_ui_print_wrapper(const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +static char *py_arch_operand_ui_build_tooltip_wrapper(const GArchOperandUI *, const GLoadedBinary *); + +/* Traduit un opérande en version humainement lisible. */ +static PyObject *py_arch_operand_ui_print(PyObject *, PyObject *); + +/* Construit un petit résumé concis de l'opérande. */ +static PyObject *py_arch_operand_ui_build_tooltip(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface d'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_arch_operand_ui_interface_init(GArchOperandUIInterface *iface, gpointer *unused) +{ +#define ARCH_OPERAND_UI_DOC \ + "The ArchOperandUI interface ensure pychrysalide.arch.ArchOperand" \ + " implementations provide UI features when Chrysalide is running with" \ + " a GUI.\n" \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(ArchOperand, ArchOperandUi):\n" \ + " ...\n" \ + "\n" \ + "The following method has to be defined for new implementations:\n" \ + "* pychrysalide.arch.ArchOperandUI._print();\n" \ + "* pychrysalide.arch.ArchOperandUI._build_tooltip().\n" + + iface->print = py_arch_operand_ui_print_wrapper; + iface->build_tooltip = py_arch_operand_ui_build_tooltip_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = registre visé par la procédure. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_arch_operand_ui_print_wrapper(const GArchOperandUI *operand, GBufferLine *line) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + +#define ARCH_OPERAND_UI_PRINT_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _print, "$self, line, /", \ + METH_VARARGS, \ + "Abstract method used to print an operand into a rendering" \ + " *line*, which is a provided pychrysalide.glibext.BufferLine" \ + " instance." \ +) + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(operand)); + + if (has_python_method(pyobj, "_print")) + { + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); + + pyret = run_python_method(pyobj, "_print", args); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* binary = informations relatives au binaire chargé. * +* * +* Description : Construit un petit résumé concis de l'opérande. * +* * +* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_arch_operand_ui_build_tooltip_wrapper(const GArchOperandUI *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + +#define ARCH_OPERAND_UI_BUILD_TOOLTIP_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _build_tooltip, "$self, binary, /", \ + METH_VARARGS, \ + "Abstract method used to build a tooltip text shown when the" \ + " mouse is over an operand.\n" \ + "\n" \ + "A pychrysalide.analysis.LoadedBinary instance is provided in" \ + " case of need." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(operand)); + + if (has_python_method(pyobj, "_build_tooltip")) + { + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary))); + + pyret = run_python_method(pyobj, "_build_tooltip", args); + + if (pyret != NULL) + { + if (PyUnicode_Check(pyret)) + result = strdup(PyUnicode_AsUTF8(pyret)); + } + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet manipulé ici. * +* args = adresse non utilisée ici. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_ui_print(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + +#if 0 // TODO + + GBufferLine *line; /* Zone d'impression du rendu */ + int ret; /* Bilan de lecture des args. */ + GArchOperandUI *operand; /* Mécanismes natifs */ + +#define ARCH_OPERAND_UI_PRINT_METHOD PYTHON_METHOD_DEF \ +( \ + print, "$self, line", \ + METH_VARARGS, py_arch_operand_ui, \ + "Translate an operand into a human readable version.\n" \ + "\n" \ + "The *line* arguement is a pychrysalide.glibext.BufferLine" \ + " instance which has to get filled with rendering" \ + " information.\n" \ + "\n" \ + "The result returns nothing (*None*)." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_buffer_line, &line); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND_UI(pygobject_get(self)); + + g_arch_operand_ui_print(operand, line); + +#endif + + result = Py_None; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet manipulé ici. * +* args = adresse non utilisée ici. * +* * +* Description : Construit un petit résumé concis de l'opérande. * +* * +* Retour : Chaîne de caractères à libérer après usage ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_ui_build_tooltip(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + +#if 0 // TODO + + GLoadedBinary *binary; /* Infos sur le binaire chargé */ + int ret; /* Bilan de lecture des args. */ + GArchOperandUI *operand; /* Mécanismes natifs */ + char *tooltip; /* Eventuelle indication */ + +#define ARCH_OPERAND_UI_BUILD_TOOLTIP_METHOD PYTHON_METHOD_DEF \ +( \ + build_tooltip, "$self, binary", \ + METH_VARARGS, py_arch_operand_ui, \ + "Build a tooltip text shown when the mouse is over an" \ + " operand.\n" \ + "\n" \ + "The *binary* argument is a pychrysalide.analysis.LoadedBinary" \ + " instance provided in case of need." \ + "\n" \ + "The result is a string or *None* in case of error." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_loaded_binary, &binary); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND_UI(pygobject_get(self)); + + tooltip = g_arch_operand_ui_build_tooltip(operand, binary); + + if (tooltip != NULL) + { + PyUnicode_FromString(tooltip); + free(tooltip); + } + else + +#endif + + { + result = Py_None; + 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_arch_operand_ui_type(void) +{ + static PyMethodDef py_arch_operand_ui_methods[] = { + ARCH_OPERAND_UI_PRINT_WRAPPER, + ARCH_OPERAND_UI_BUILD_TOOLTIP_WRAPPER, +#if 0 // TODO + ARCH_OPERAND_UI_PRINT_METHOD, + ARCH_OPERAND_UI_BUILD_TOOLTIP_METHOD, +#endif + { NULL } + }; + + static PyGetSetDef py_arch_operand_ui_getseters[] = { + { NULL } + }; + + static PyTypeObject py_arch_operand_ui_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.ArchOperandUI", + .tp_basicsize = sizeof(PyObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = ARCH_OPERAND_UI_DOC, + + .tp_methods = py_arch_operand_ui_methods, + .tp_getset = py_arch_operand_ui_getseters + + }; + + return &py_arch_operand_ui_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.ArchOperandUI'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_arch_operand_ui_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'ArchOperandUI' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_arch_operand_ui_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + + type = get_python_arch_operand_ui_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.arch"); + + dict = PyModule_GetDict(module); + + if (!register_interface_for_pygobject(dict, G_TYPE_ARCH_OPERAND_UI, 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 interface d'exportation graphique. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_arch_operand_ui(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_arch_operand_ui_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 UI arch operand"); + break; + + case 1: + *((GArchOperandUI **)dst) = G_ARCH_OPERAND_UI(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/arch/operand-ui.h b/plugins/pychrysalide/arch/operand-ui.h new file mode 100644 index 0000000..b9e2131 --- /dev/null +++ b/plugins/pychrysalide/arch/operand-ui.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.h - prototypes pour l'équivalent Python du fichier "arch/operand-ui.h" + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_OPERAND_UI_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_OPERAND_UI_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_arch_operand_ui_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.ArchOperandUI'. */ +bool ensure_python_arch_operand_ui_is_registered(void); + +/* Tente de convertir en interface d'exportation graphique. */ +int convert_to_arch_operand_ui(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERAND_UI_H */ diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c index 0aee4f7..42bd247 100644 --- a/plugins/pychrysalide/arch/operand.c +++ b/plugins/pychrysalide/arch/operand.c @@ -30,23 +30,32 @@ #include <i18n.h> #include <arch/operand-int.h> -#include <plugins/dt.h> +#include <glibext/strbuilder-int.h> #include "../access.h" #include "../helpers.h" +#include "../glibext/comparable.h" +#include "../glibext/hashable.h" +#include "../glibext/objhole.h" +#include "../glibext/serialize.h" #include "../glibext/singleton.h" +#include "../glibext/strbuilder.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_arch_operand_new(PyTypeObject *, PyObject *, PyObject *); - /* Initialise la classe générique des opérandes. */ -static void py_arch_operand_init_gclass(GArchOperandClass *, gpointer); +static int py_arch_operand_init_gclass(GArchOperandClass *, PyTypeObject *); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_operand, G_TYPE_ARCH_OPERAND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_arch_operand_init(PyObject *, PyObject *, PyObject *); + +#if 0 /* Compare un opérande avec un autre. */ static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *, bool); @@ -57,14 +66,6 @@ static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand /* Obtient l'opérande correspondant à un chemin donné. */ static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *, const char *); -/* Traduit un opérande en version humainement lisible. */ -static void py_arch_operand_print_wrapper(const GArchOperand *, GBufferLine *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Construit un petit résumé concis de l'opérande. */ -static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const GLoadedBinary *); - #endif @@ -72,6 +73,9 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const G /* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ +#if 0 + + /* Effectue une comparaison avec un objet Python 'ArchOperand'. */ static PyObject *py_arch_operand_richcompare(PyObject *, PyObject *, int); @@ -81,6 +85,15 @@ static PyObject *py_arch_operand_find_inner_operand_path(PyObject *, PyObject *) /* Obtient l'opérande correspondant à un chemin donné. */ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObject *); +#endif + + +/* Ajoute une information complémentaire à un opérande. */ +static PyObject *py_arch_operand_set_flag(PyObject *, PyObject *); + +/* Retire une information complémentaire à un opérande. */ +static PyObject *py_arch_operand_unset_flag(PyObject *, PyObject *); + /* ---------------------------------------------------------------------------------- */ @@ -90,113 +103,109 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObjec /****************************************************************************** * * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* Paramètres : gclass = classe GLib à initialiser. * +* pyclass = classe Python à initialiser. * * * -* Description : Accompagne la création d'une instance dérivée en Python. * +* Description : Initialise la classe générique des opérandes. * * * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* Retour : 0 pour indiquer un succès de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_arch_operand_init_gclass(GArchOperandClass *gclass, PyTypeObject *pyclass) { - 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 */ -#define ARCH_OPERAND_DOC \ - "The ArchOperand object aims to get subclassed to create" \ - " operands of any kind for new architectures.\n" \ - "\n" \ - "Calls to the *__init__* constructor of this abstract object expect"\ - " no particular argument.\n" \ - "\n" \ - "The following methods have to be defined for new classes:\n" \ - "* pychrysalide.arch.ArchRegister.__cmp__();\n" \ - "* pychrysalide.arch.ArchRegister._print();\n" \ - "* pychrysalide.arch.ArchRegister._build_tooltip().\n" \ - "\n" \ - "Some extra method definitions are optional for new classes:\n" \ - "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \ - "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\ - "\n" \ - "Chrysalide creates an internal glue to provide rich comparisons" \ - " for operands based on the old-style *__cmp__* function." +#if 0 + GStringBuilderInterface *iface; /* Interface utilisée */ - /* Validations diverses */ + iface = g_type_interface_peek(gclass, G_TYPE_STRING_BUILDER); - base = get_python_arch_operand_type(); - if (type == base) - { - result = NULL; - PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); - goto exit; - } + /* + printf("???????? init Python Operand ?????????????? -> class: %p '%s' - strbuilder iface: %p\n", + gclass, g_type_name(G_TYPE_FROM_CLASS(gclass)), iface); + */ - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); +#endif - gtype = build_dynamic_type(G_TYPE_ARCH_OPERAND, type->tp_name, - (GClassInitFunc)py_arch_operand_init_gclass, NULL, NULL); +#if 0 - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); + class->compare = py_arch_operand___cmp___wrapper; + class->find_inner = py_arch_operand_find_inner_operand_path_wrapper; + class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper; - if (!status) - { - result = NULL; - goto exit; - } - } +#endif - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - result = PyType_GenericNew(type, args, kwds); - exit: + //PY_CLASS_SET_WRAPPER(gclass->xxx, py_arch_operand_xxx_wrapper); - return result; + return 0; } /****************************************************************************** * * -* Paramètres : class = classe à initialiser. * -* unused = données non utilisées ici. * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * * * -* Description : Initialise la classe générique des opérandes. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : - * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unused) +static int py_arch_operand_init(PyObject *self, PyObject *args, PyObject *kwds) { - class->compare = py_arch_operand___cmp___wrapper; - class->find_inner = py_arch_operand_find_inner_operand_path_wrapper; - class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper; + //unsigned int endianness; /* Boutisme du processeur */ + int ret; /* Bilan de lecture des args. */ + //GArchProcessor *proc; /* Processeur à manipuler */ - class->print = py_arch_operand_print_wrapper; -#ifdef INCLUDE_GTK_SUPPORT - class->build_tooltip = py_arch_operand_build_tooltip_wrapper; -#endif +#define ARCH_OPERAND_DOC \ + "The ArchOperand object aims to get subclassed to create" \ + " operands of any kind for new architectures.\n" \ + "\n" \ + "Calls to the *__init__* constructor of this abstract object expect"\ + " no particular argument.\n" \ + "\n" \ + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.arch.ArchRegister.__cmp__();\n" \ + "* pychrysalide.arch.ArchRegister._print();\n" \ + "* pychrysalide.arch.ArchRegister._build_tooltip().\n" \ + "\n" \ + "Some extra method definitions are optional for new classes:\n" \ + "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \ + "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\ + "\n" \ + "Chrysalide creates an internal glue to provide rich comparisons" \ + " for operands based on the old-style *__cmp__* function." + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + //proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + //proc->endianness = endianness; + + return 0; } + +#if 0 + /****************************************************************************** * * * Paramètres : a = premier opérande à consulter. * @@ -410,126 +419,6 @@ static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const G } -/****************************************************************************** -* * -* Paramètres : operand = registre visé par la procédure. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void py_arch_operand_print_wrapper(const GArchOperand *operand, GBufferLine *line) -{ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_OPERAND_PRINT_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _print, "$self, line, /", \ - METH_VARARGS, \ - "Abstract method used to print the operand into a rendering" \ - " line, which is a provided pychrysalide.glibext.BufferLine" \ - " instance." \ -) - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(operand)); - - if (has_python_method(pyobj, "_print")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); - - pyret = run_python_method(pyobj, "_print", args); - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * -* * -* Description : Construit un petit résumé concis de l'opérande. * -* * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand, const GLoadedBinary *binary) -{ - char *result; /* Description à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _build_tooltip, "$self, line, /", \ - METH_VARARGS, \ - "Abstract method used to build a tooltip text shown when the" \ - " mouse is over the operand.\n" \ - "\n" \ - "A pychrysalide.analysis.LoadedBinary instance is provided in" \ - " case of need." \ -) - - result = NULL; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(operand)); - - if (has_python_method(pyobj, "_build_tooltip")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary))); - - pyret = run_python_method(pyobj, "_build_tooltip", args); - - if (pyret != NULL) - { - if (PyUnicode_Check(pyret)) - result = strdup(PyUnicode_AsUTF8(pyret)); - } - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; - -} - #endif @@ -540,6 +429,9 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand, /* ---------------------------------------------------------------------------------- */ + +#if 0 + /****************************************************************************** * * * Paramètres : a = premier object Python à consulter. * @@ -701,6 +593,164 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyO } +#endif + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Ajoute une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_set_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_SET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + set_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Add some flags to the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to apply to the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* for operation" \ + " success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_set_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Retire une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_unset_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_UNSET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + unset_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Remove some flags from the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to delete from the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* for operation" \ + " success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_unset_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Détermine si un opérande possède un fanion particulier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_has_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_HAS_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + has_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Tell if some flags are set for the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to test for the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* if the bits" \ + " are active, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_has_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + /****************************************************************************** * * @@ -717,6 +767,11 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyO PyTypeObject *get_python_arch_operand_type(void) { static PyMethodDef py_arch_operand_methods[] = { + ARCH_OPERAND_SET_FLAG_METHOD, + ARCH_OPERAND_UNSET_FLAG_METHOD, + ARCH_OPERAND_HAS_FLAG_METHOD, + + /* ARCH_OPERAND_CMP_WRAPPER, ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER, ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER, @@ -726,6 +781,7 @@ PyTypeObject *get_python_arch_operand_type(void) #endif ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD, ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD, + */ { NULL } }; @@ -744,11 +800,12 @@ PyTypeObject *get_python_arch_operand_type(void) .tp_doc = ARCH_OPERAND_DOC, - .tp_richcompare = py_arch_operand_richcompare, + //.tp_richcompare = py_arch_operand_richcompare, .tp_methods = py_arch_operand_methods, .tp_getset = py_arch_operand_getseters, + .tp_init = py_arch_operand_init, .tp_new = py_arch_operand_new, }; @@ -784,9 +841,26 @@ bool ensure_python_arch_operand_is_registered(void) dict = PyModule_GetDict(module); + if (!ensure_python_thick_object_is_registered()) + return false; + + if (!ensure_python_comparable_object_is_registered()) + return false; + + if (!ensure_python_hashable_object_is_registered()) + return false; + + if (!ensure_python_serializable_object_is_registered()) + return false; + if (!ensure_python_singleton_candidate_is_registered()) return false; + if (!ensure_python_string_builder_is_registered()) + return false; + + pyg_register_class_init(G_TYPE_ARCH_OPERAND, (PyGClassInitFunc)py_arch_operand_init_gclass); + if (!register_class_for_pygobject(dict, G_TYPE_ARCH_OPERAND, type)) return false; diff --git a/plugins/pychrysalide/arch/operand.h b/plugins/pychrysalide/arch/operand.h index 9cb40a0..f3bfbf2 100644 --- a/plugins/pychrysalide/arch/operand.h +++ b/plugins/pychrysalide/arch/operand.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand.h - prototypes pour l'équivalent Python du fichier "arch/operand.h" * - * Copyright (C) 2018-2019 Cyrille Bagard + * Copyright (C) 2018-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -31,9 +31,6 @@ -/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ - - /* Fournit un accès à une définition de type à diffuser. */ PyTypeObject *get_python_arch_operand_type(void); diff --git a/plugins/pychrysalide/arch/operands/Makefile.am b/plugins/pychrysalide/arch/operands/Makefile.am index a41cbbb..3b753cc 100644 --- a/plugins/pychrysalide/arch/operands/Makefile.am +++ b/plugins/pychrysalide/arch/operands/Makefile.am @@ -1,19 +1,21 @@ noinst_LTLIBRARIES = libpychrysaarchoperands.la +# libpychrysaarchoperands_la_SOURCES = \ +# feeder.h feeder.c \ +# proxy.h proxy.c \ +# rename.h rename.c \ +# target.h target.c \ +# targetable.h targetable.c + libpychrysaarchoperands_la_SOURCES = \ constants.h constants.c \ - feeder.h feeder.c \ immediate.h immediate.c \ known.h known.c \ module.h module.c \ - proxy.h proxy.c \ - register.h register.c \ - rename.h rename.c \ - target.h target.c \ - targetable.h targetable.c + register.h register.c -libpychrysaarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +libpychrysaarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/pychrysalide/arch/operands/constants.c b/plugins/pychrysalide/arch/operands/constants.c index b9d80e4..78eeded 100644 --- a/plugins/pychrysalide/arch/operands/constants.c +++ b/plugins/pychrysalide/arch/operands/constants.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * constants.c - ajout des constantes de base pour les opérandes * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -47,20 +47,33 @@ * * ******************************************************************************/ -bool define_imm_operand_constants(PyTypeObject *type) +bool define_immediate_operand_constants(PyTypeObject *type) { bool result; /* Bilan à retourner */ PyObject *values; /* Groupe de valeurs à établir */ values = PyDict_New(); + result = add_const_to_group(values, "ZERO_PADDING_BY_DEFAULT", IOF_ZERO_PADDING_BY_DEFAULT); + if (result) result = add_const_to_group(values, "ZERO_PADDING", IOF_ZERO_PADDING); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, true, "ImmOperandFlag", values, + "Specific state bits for immediate operands."); + + values = PyDict_New(); + result = add_const_to_group(values, "BIN", IOD_BIN); if (result) result = add_const_to_group(values, "OCT", IOD_OCT); if (result) result = add_const_to_group(values, "DEC", IOD_DEC); if (result) result = add_const_to_group(values, "HEX", IOD_HEX); if (result) result = add_const_to_group(values, "CHAR", IOD_CHAR); if (result) result = add_const_to_group(values, "COUNT", IOD_COUNT); - if (result) result = add_const_to_group(values, "LAST_VALID", IOD_LAST_VALID); if (!result) { diff --git a/plugins/pychrysalide/arch/operands/constants.h b/plugins/pychrysalide/arch/operands/constants.h index 71a26cc..5170faa 100644 --- a/plugins/pychrysalide/arch/operands/constants.h +++ b/plugins/pychrysalide/arch/operands/constants.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * constants.h - prototypes pour l'ajout des constantes de base pour les opérandes * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -32,11 +32,14 @@ /* Définit les constantes relatives aux opérandes d'immédiats. */ -bool define_imm_operand_constants(PyTypeObject *); +bool define_immediate_operand_constants(PyTypeObject *); /* Tente de convertir en constante ImmOperandDisplay. */ int convert_to_imm_operand_display(PyObject *, void *); +#define cast_imm_operand_display_to_python(v) \ + cast_with_constants_group_from_type(get_python_immediate_operand_type(), "ImmOperandDisplay", v) + #endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/arch/operands/immediate.c b/plugins/pychrysalide/arch/operands/immediate.c index 2239eb2..a335db3 100644 --- a/plugins/pychrysalide/arch/operands/immediate.c +++ b/plugins/pychrysalide/arch/operands/immediate.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.c - équivalent Python du fichier "arch/operands/immediate.h" * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -30,201 +30,119 @@ #include <i18n.h> - - -#include <arch/operands/immediate.h> +#include <arch/operands/immediate-int.h> #include "constants.h" -#include "rename.h" -#include "targetable.h" #include "../operand.h" #include "../../access.h" +#include "../../constants.h" #include "../../helpers.h" #include "../../analysis/content.h" -#include "../../glibext/bufferline.h" -/* Crée un nouvel objet Python de type 'ImmOperand'. */ -static PyObject *py_imm_operand_new(PyTypeObject *, PyObject *, PyObject *); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +CREATE_DYN_CONSTRUCTOR(immediate_operand, G_TYPE_IMMEDIATE_OPERAND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_immediate_operand_init(PyObject *, PyObject *, PyObject *); + + -/* Compare un opérande avec un autre. */ -static PyObject *py_imm_operand___cmp__(PyObject *, PyObject *); +/* ---------------------------- DEFINITION D'UN IMMEDIAT ---------------------------- */ -/* Traduit un opérande en version humainement lisible. */ -static PyObject *py_imm_operand__print(PyObject *, PyObject *); /* Renseigne la taille de la valeur indiquée à la construction. */ -static PyObject *py_imm_operand_get_size(PyObject *, void *); +static PyObject *py_immediate_operand_get_size(PyObject *, void *); /* Fournit la valeur portée par une opérande numérique. */ -static PyObject *py_imm_operand_get_value(PyObject *, void *); +static PyObject *py_immediate_operand_get_value(PyObject *, void *); + +/* Indique le signe d'une valeur immédiate. */ +static PyObject *py_immediate_operand_is_negative(PyObject *, void *); /* Indique le format textuel par défaut de la valeur. */ -static PyObject *py_imm_operand_get_default_display(PyObject *, void *); +static PyObject *py_immediate_operand_get_default_display(PyObject *, void *); /* Définit le format textuel par défaut de la valeur. */ -static int py_imm_operand_set_default_display(PyObject *, PyObject *, void *); +static int py_immediate_operand_set_default_display(PyObject *, PyObject *, void *); /* Indique la grande ligne du format textuel de la valeur. */ -static PyObject *py_imm_operand_get_display(PyObject *, void *); +static PyObject *py_immediate_operand_get_display(PyObject *, void *); /* Définit la grande ligne du format textuel de la valeur. */ -static int py_imm_operand_set_display(PyObject *, PyObject *, void *); +static int py_immediate_operand_set_display(PyObject *, PyObject *, void *); + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'ImmOperand'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_imm_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_immediate_operand_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ - unsigned int raw_size; /* Taille obtenue de Python */ + MemoryDataSize size; /* Taille des données finale */ unsigned long long value; /* Valeur brute à représenter */ int ret; /* Bilan de lecture des args. */ - MemoryDataSize size; /* Taille des données finale */ - GArchOperand *operand; /* Création GLib à transmettre */ + GImmediateOperand *operand; /* Opérande natif à manipuler */ -#define IMM_OPERAND_DOC \ - "The ImmOperand deals with immediate value as operand." \ +#define IMMEDIATE_OPERAND_DOC \ + "The ImmediateOperand deals with immediate value as operand." \ "\n" \ "There are several ways to display these values in a disassembly," \ " the operand handles that.\n" \ "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " ImmOperand(size, value)" \ + " ImmediateOperand(size, value)" \ "\n" \ - "Where size specifies the original size of the provided value, as" \ - " a pychrysalide.analysis.BinContent.MemoryDataSize." + "Where *size* specifies the original size of the provided *value*," \ + " as a pychrysalide.MemoryDataSize." - ret = PyArg_ParseTuple(args, "IK", &raw_size, &value); - if (!ret) return NULL; + /* Récupération des paramètres */ - size = raw_size; + ret = PyArg_ParseTuple(args, "O&K", convert_to_memory_data_size, &size, &value); + if (!ret) return -1; - if (size != MDS_UNDEFINED - && !(MDS_4_BITS_UNSIGNED <= size && size <= MDS_64_BITS_UNSIGNED) - && !(MDS_4_BITS_SIGNED <= size && size <= MDS_64_BITS_SIGNED)) - { - PyErr_SetString(PyExc_ValueError, _("Invalid size to build an immediate operand")); - return NULL; - } + /* Initialisation d'un objet GLib */ - operand = g_imm_operand_new_from_value(size, value); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - result = pygobject_new(G_OBJECT(operand)); + /* Eléments de base */ - g_object_unref(operand); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); - return (PyObject *)result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = serveur à manipuler. * -* args = arguments associés à l'appel. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_imm_operand___cmp__(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GImmOperand *other; /* Autre opérande à manipuler */ - int ret; /* Bilan de lecture des args. */ - GImmOperand *operand; /* Elément à manipuler */ - int status; /* Bilan de comparaison */ - -#define IMM_OPERAND_CMP_METHOD PYTHON_METHOD_DEF \ -( \ - __cmp__, "$self, other, /", \ - METH_VARARGS, py_imm_operand, \ - "Implementation of the required method used to compare the" \ - " operand with another one. This second object is always" \ - " an pychrysalide.arch.ImmOperand instance.\n" \ - "\n" \ - "See the parent class for more information about this method." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_imm_operand, &other); - if (!ret) return NULL; - - operand = G_IMM_OPERAND(pygobject_get(self)); - - status = g_arch_operand_compare(G_ARCH_OPERAND(operand), G_ARCH_OPERAND(other)); - - result = PyLong_FromLong(status); + if (!g_immediate_operand_create_from_value(operand, size, value)) + return -1; - return result; + return 0; } -/****************************************************************************** -* * -* Paramètres : self = serveur à manipuler. * -* args = arguments associés à l'appel. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ -static PyObject *py_imm_operand__print(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GBufferLine *line; /* Ligne fournie à peupler */ - int ret; /* Bilan de lecture des args. */ - GImmOperand *operand; /* Elément à manipuler */ - -#define IMM_OPERAND_PRINT_METHOD PYTHON_METHOD_DEF \ -( \ - _print, "$self, line, /", \ - METH_VARARGS, py_imm_operand, \ - "Implementation of the required method used to print the operand" \ - " into a rendering line, which is a provided" \ - " pychrysalide.glibext.BufferLine instance.\n" \ - "\n" \ - "See the parent class for more information about this method." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_buffer_line, &line); - if (!ret) return NULL; - - operand = G_IMM_OPERAND(pygobject_get(self)); - - g_arch_operand_print(G_ARCH_OPERAND(operand), line); - - result = Py_None; - Py_INCREF(result); - - return result; - -} +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN IMMEDIAT */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -240,25 +158,26 @@ static PyObject *py_imm_operand__print(PyObject *self, PyObject *args) * * ******************************************************************************/ -static PyObject *py_imm_operand_get_size(PyObject *self, void *closure) +static PyObject *py_immediate_operand_get_size(PyObject *self, void *closure) { PyObject *result; /* Instance Python à retourner */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ MemoryDataSize size; /* Type de donnée représentée */ -#define IMM_OPERAND_SIZE_ATTRIB PYTHON_GET_DEF_FULL \ +#define IMMEDIATE_OPERAND_SIZE_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - size, py_imm_operand, \ + size, py_immediate_operand, \ "Get or set the size of the value contained in the operand." \ "\n" \ "The property is a value of type" \ - " pychrysalide.analysis.BinContent.MemoryDataSize." \ + " pychrysalide.MemoryDataSize." \ ) - operand = G_IMM_OPERAND(pygobject_get(self)); - size = g_imm_operand_get_size(operand); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); + + size = g_immediate_operand_get_size(operand); - result = cast_with_constants_group_from_type(get_python_binary_content_type(), "MemoryDataSize", size); + result = cast_memory_data_size_to_python(size); return result; @@ -278,10 +197,10 @@ static PyObject *py_imm_operand_get_size(PyObject *self, void *closure) * * ******************************************************************************/ -static PyObject *py_imm_operand_get_value(PyObject *self, void *closure) +static PyObject *py_immediate_operand_get_value(PyObject *self, void *closure) { PyObject *result; /* Instance Python à retourner */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ MemoryDataSize size; /* Type de donnée représentée */ uint8_t uval8; /* Valeur sur 8 bits */ uint16_t uval16; /* Valeur sur 16 bits */ @@ -292,15 +211,15 @@ static PyObject *py_imm_operand_get_value(PyObject *self, void *closure) int32_t sval32; /* Valeur sur 32 bits */ int64_t sval64; /* Valeur sur 64 bits */ -#define IMM_OPERAND_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - value, py_imm_operand, \ - "Value of the immediate operand, as an integer." \ +#define IMMEDIATE_OPERAND_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + value, py_immediate_operand, \ + "Value of the immediate operand, as an integer." \ ) - operand = G_IMM_OPERAND(pygobject_get(self)); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); - size = g_imm_operand_get_size(operand); + size = g_immediate_operand_get_size(operand); switch (size) { @@ -311,36 +230,36 @@ static PyObject *py_imm_operand_get_value(PyObject *self, void *closure) break; case MDS_4_BITS_UNSIGNED: case MDS_8_BITS_UNSIGNED: - g_imm_operand_get_value(operand, size, &uval8); + g_immediate_operand_get_value(operand, size, &uval8); result = PyLong_FromUnsignedLong(uval8); break; case MDS_16_BITS_UNSIGNED: - g_imm_operand_get_value(operand, size, &uval16); + g_immediate_operand_get_value(operand, size, &uval16); result = PyLong_FromUnsignedLong(uval16); break; case MDS_32_BITS_UNSIGNED: - g_imm_operand_get_value(operand, size, &uval32); + g_immediate_operand_get_value(operand, size, &uval32); result = PyLong_FromUnsignedLong(uval32); break; case MDS_64_BITS_UNSIGNED: - g_imm_operand_get_value(operand, size, &uval64); + g_immediate_operand_get_value(operand, size, &uval64); result = PyLong_FromUnsignedLongLong(uval64); break; case MDS_4_BITS_SIGNED: case MDS_8_BITS_SIGNED: - g_imm_operand_get_value(operand, size, &sval8); + g_immediate_operand_get_value(operand, size, &sval8); result = PyLong_FromLong(sval8); break; case MDS_16_BITS_SIGNED: - g_imm_operand_get_value(operand, size, &sval16); + g_immediate_operand_get_value(operand, size, &sval16); result = PyLong_FromLong(sval16); break; case MDS_32_BITS_SIGNED: - g_imm_operand_get_value(operand, size, &sval32); + g_immediate_operand_get_value(operand, size, &sval32); result = PyLong_FromLong(sval32); break; case MDS_64_BITS_SIGNED: - g_imm_operand_get_value(operand, size, &sval64); + g_immediate_operand_get_value(operand, size, &sval64); result = PyLong_FromLongLong(sval64); break; @@ -363,6 +282,43 @@ static PyObject *py_imm_operand_get_value(PyObject *self, void *closure) * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * +* Description : Indique le signe d'une valeur immédiate. * +* * +* Retour : True si la valeur est strictement négative, False sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_immediate_operand_is_negative(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ + bool status; /* Etat à faire connaître */ + +#define IMMEDIATE_OPERAND_NEGATIVE_ATTRIB PYTHON_IS_DEF_FULL \ +( \ + negative, py_immediate_operand, \ + "Sign of the value, as a boolean status." \ +) + + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); + + status = g_immediate_operand_is_negative(operand); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * * Description : Indique le format textuel par défaut de la valeur. * * * * Retour : Format global d'un affichage de valeur. * @@ -371,25 +327,26 @@ static PyObject *py_imm_operand_get_value(PyObject *self, void *closure) * * ******************************************************************************/ -static PyObject *py_imm_operand_get_default_display(PyObject *self, void *closure) +static PyObject *py_immediate_operand_get_default_display(PyObject *self, void *closure) { PyObject *result; /* Instance Python à retourner */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ ImmOperandDisplay display; /* Type d'affichage courant */ -#define IMM_OPERAND_DEFAULT_DISPLAY_ATTRIB PYTHON_GETSET_DEF_FULL \ +#define IMMEDIATE_OPERAND_DEFAULT_DISPLAY_ATTRIB PYTHON_GETSET_DEF_FULL \ ( \ - default_display, py_imm_operand, \ + default_display, py_immediate_operand, \ "Define of the immediate operand default textual representation." \ "\n" \ "The property is a value of type" \ " pychrysalide.arch.operands.ImmOperand.ImmOperandDisplay." \ ) - operand = G_IMM_OPERAND(pygobject_get(self)); - display = g_imm_operand_get_default_display(operand); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); + + display = g_immediate_operand_get_default_display(operand); - result = cast_with_constants_group_from_type(get_python_imm_operand_type(), "ImmOperandDisplay", display); + result = cast_imm_operand_display_to_python(display); return result; @@ -410,10 +367,10 @@ static PyObject *py_imm_operand_get_default_display(PyObject *self, void *closur * * ******************************************************************************/ -static int py_imm_operand_set_default_display(PyObject *self, PyObject *value, void *closure) +static int py_immediate_operand_set_default_display(PyObject *self, PyObject *value, void *closure) { ImmOperandDisplay display; /* Type d'affichage demandé */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ if (!PyLong_Check(value)) { @@ -429,9 +386,9 @@ static int py_imm_operand_set_default_display(PyObject *self, PyObject *value, v return -1; } - operand = G_IMM_OPERAND(pygobject_get(self)); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); - g_imm_operand_set_default_display(operand, display); + g_immediate_operand_set_default_display(operand, display); return 0; @@ -451,25 +408,27 @@ static int py_imm_operand_set_default_display(PyObject *self, PyObject *value, v * * ******************************************************************************/ -static PyObject *py_imm_operand_get_display(PyObject *self, void *closure) +static PyObject *py_immediate_operand_get_display(PyObject *self, void *closure) { PyObject *result; /* Instance Python à retourner */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ ImmOperandDisplay display; /* Type d'affichage courant */ -#define IMM_OPERAND_DISPLAY_ATTRIB PYTHON_GETSET_DEF_FULL \ -( \ - display, py_imm_operand, \ - "Define of the immediate operand current textual representation." \ - "\n" \ - "The property is a value of type" \ - " pychrysalide.arch.operands.ImmOperand.ImmOperandDisplay." \ +#define IMMEDIATE_OPERAND_DISPLAY_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + display, py_immediate_operand, \ + "Retrieve or define of the immediate operand current textual" \ + " representation." \ + "\n" \ + "The property is a value of type" \ + " pychrysalide.arch.operands.ImmOperand.ImmOperandDisplay." \ ) - operand = G_IMM_OPERAND(pygobject_get(self)); - display = g_imm_operand_get_display(operand); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); - result = cast_with_constants_group_from_type(get_python_imm_operand_type(), "ImmOperandDisplay", display); + display = g_immediate_operand_get_display(operand); + + result = cast_imm_operand_display_to_python(display); return result; @@ -490,10 +449,10 @@ static PyObject *py_imm_operand_get_display(PyObject *self, void *closure) * * ******************************************************************************/ -static int py_imm_operand_set_display(PyObject *self, PyObject *value, void *closure) +static int py_immediate_operand_set_display(PyObject *self, PyObject *value, void *closure) { ImmOperandDisplay display; /* Type d'affichage demandé */ - GImmOperand *operand; /* Version GLib de l'opérande */ + GImmediateOperand *operand; /* Version GLib de l'opérande */ if (!PyLong_Check(value)) { @@ -509,9 +468,9 @@ static int py_imm_operand_set_display(PyObject *self, PyObject *value, void *clo return -1; } - operand = G_IMM_OPERAND(pygobject_get(self)); + operand = G_IMMEDIATE_OPERAND(pygobject_get(self)); - g_imm_operand_set_display(operand, display); + g_immediate_operand_set_display(operand, display); return 0; @@ -530,40 +489,41 @@ static int py_imm_operand_set_display(PyObject *self, PyObject *value, void *clo * * ******************************************************************************/ -PyTypeObject *get_python_imm_operand_type(void) +PyTypeObject *get_python_immediate_operand_type(void) { - static PyMethodDef py_imm_operand_methods[] = { - IMM_OPERAND_CMP_METHOD, - IMM_OPERAND_PRINT_METHOD, + static PyMethodDef py_immediate_operand_methods[] = { { NULL } }; - static PyGetSetDef py_imm_operand_getseters[] = { - IMM_OPERAND_SIZE_ATTRIB, - IMM_OPERAND_VALUE_ATTRIB, - IMM_OPERAND_DEFAULT_DISPLAY_ATTRIB, - IMM_OPERAND_DISPLAY_ATTRIB, + static PyGetSetDef py_immediate_operand_getseters[] = { + IMMEDIATE_OPERAND_SIZE_ATTRIB, + IMMEDIATE_OPERAND_VALUE_ATTRIB, + IMMEDIATE_OPERAND_NEGATIVE_ATTRIB, + IMMEDIATE_OPERAND_DEFAULT_DISPLAY_ATTRIB, + IMMEDIATE_OPERAND_DISPLAY_ATTRIB, { NULL } }; - static PyTypeObject py_imm_operand_type = { + static PyTypeObject py_immediate_operand_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.arch.operands.ImmOperand", + .tp_name = "pychrysalide.arch.operands.ImmediateOperand", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = IMM_OPERAND_DOC, + .tp_doc = IMMEDIATE_OPERAND_DOC, + + .tp_methods = py_immediate_operand_methods, + .tp_getset = py_immediate_operand_getseters, - .tp_methods = py_imm_operand_methods, - .tp_getset = py_imm_operand_getseters, - .tp_new = py_imm_operand_new + .tp_init = py_immediate_operand_init, + .tp_new = py_immediate_operand_new, }; - return &py_imm_operand_type; + return &py_immediate_operand_type; } @@ -580,13 +540,13 @@ PyTypeObject *get_python_imm_operand_type(void) * * ******************************************************************************/ -bool ensure_python_imm_operand_is_registered(void) +bool ensure_python_immediate_operand_is_registered(void) { - PyTypeObject *type; /* Type Python 'ImmOperand' */ + PyTypeObject *type; /* Type 'ImmediateOperand' */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - type = get_python_imm_operand_type(); + type = get_python_immediate_operand_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -597,16 +557,10 @@ bool ensure_python_imm_operand_is_registered(void) if (!ensure_python_arch_operand_is_registered()) return false; - if (!ensure_python_targetable_operand_is_registered()) - return false; - - if (!ensure_python_renameable_operand_is_registered()) - return false; - - if (!register_class_for_pygobject(dict, G_TYPE_IMM_OPERAND, type)) + if (!register_class_for_pygobject(dict, G_TYPE_IMMEDIATE_OPERAND, type)) return false; - if (!define_imm_operand_constants(type)) + if (!define_immediate_operand_constants(type)) return false; } @@ -629,11 +583,11 @@ bool ensure_python_imm_operand_is_registered(void) * * ******************************************************************************/ -int convert_to_imm_operand(PyObject *arg, void *dst) +int convert_to_immediate_operand(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_imm_operand_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_immediate_operand_type()); switch (result) { @@ -647,7 +601,7 @@ int convert_to_imm_operand(PyObject *arg, void *dst) break; case 1: - *((GImmOperand **)dst) = G_IMM_OPERAND(pygobject_get(arg)); + *((GImmediateOperand **)dst) = G_IMMEDIATE_OPERAND(pygobject_get(arg)); break; default: diff --git a/plugins/pychrysalide/arch/operands/immediate.h b/plugins/pychrysalide/arch/operands/immediate.h index 4a1e6de..8b8de83 100644 --- a/plugins/pychrysalide/arch/operands/immediate.h +++ b/plugins/pychrysalide/arch/operands/immediate.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.h - prototypes pour l'équivalent Python du fichier "arch/operands/immediate.h" * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -32,13 +32,13 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_imm_operand_type(void); +PyTypeObject *get_python_immediate_operand_type(void); -/* Prend en charge l'objet 'pychrysalide.arch.ImmOperand'. */ -bool ensure_python_imm_operand_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.arch.ImmediateOperand'. */ +bool ensure_python_immediate_operand_is_registered(void); /* Tente de convertir en opérande de valeur immédiate. */ -int convert_to_imm_operand(PyObject *, void *); +int convert_to_immediate_operand(PyObject *, void *); diff --git a/plugins/pychrysalide/arch/operands/known.c b/plugins/pychrysalide/arch/operands/known.c index fab426e..85cabc2 100644 --- a/plugins/pychrysalide/arch/operands/known.c +++ b/plugins/pychrysalide/arch/operands/known.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.c - équivalent Python du fichier "arch/operands/known.h" * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -29,70 +29,92 @@ #include <pygobject.h> -#include <arch/operands/known.h> +#include <arch/operands/known-int.h> #include "immediate.h" -#include "rename.h" #include "../../access.h" #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'KnownImmOperand'. */ -static PyObject *py_known_imm_operand_new(PyTypeObject *, PyObject *, PyObject *); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ +CREATE_DYN_CONSTRUCTOR(known_immediate_operand, G_TYPE_KNOWN_IMMEDIATE_OPERAND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_known_immediate_operand_init(PyObject *, PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'KnownImmOperand'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_known_imm_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_known_immediate_operand_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ - GImmOperand *imm; /* Opérande à remplacer */ + GImmediateOperand *imm; /* Opérande à remplacer */ const char *alt; /* Impression alternative */ int ret; /* Bilan de lecture des args. */ - GArchOperand *operand; /* Création GLib à transmettre */ - -#define KNOWN_IMM_OPERAND_DOC \ - "The KnownImmOperand provides replacement of" \ - " pychrysalide.arch.operands.ImmOperand instances by an alternative" \ - " text.\n" \ - "\n" \ - "Instances can be created using the following constructor:\n" \ - "\n" \ - " KnownImmOperand(imm, alt)" \ - "\n" \ - "Where imm is an operand of type pychrysalide.arch.operands.ImmOperand" \ - " and alt is a string providing the text to be rendered at object" \ + GKnownImmediateOperand *operand; /* Opérande natif à manipuler */ + +#define KNOWN_IMMEDIATE_OPERAND_DOC \ + "The KnownImmediateOperand provides replacement of" \ + " pychrysalide.arch.operands.ImmediateOperand instances by an alternative" \ + " text.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " KnownImmediateOperand(imm, alt)" \ + "\n" \ + "Where *imm* is an operand of type pychrysalide.arch.operands.ImmediateOperand" \ + " and *alt* is a string providing the text to be rendered at object" \ " display." - ret = PyArg_ParseTuple(args, "O&s", convert_to_imm_operand, &imm, &alt); - if (!ret) return NULL; + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&s", convert_to_immediate_operand, &imm, &alt); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ - operand = g_known_imm_operand_new(imm, alt); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - result = pygobject_new(G_OBJECT(operand)); + /* Eléments de base */ - g_object_unref(operand); + operand = G_KNOWN_IMMEDIATE_OPERAND(pygobject_get(self)); - return (PyObject *)result; + if (!g_known_immediate_operand_create(operand, imm, alt)) + return -1; + + return 0; } + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN IMMEDIAT CONNU */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : - * @@ -105,34 +127,36 @@ static PyObject *py_known_imm_operand_new(PyTypeObject *type, PyObject *args, Py * * ******************************************************************************/ -PyTypeObject *get_python_known_imm_operand_type(void) +PyTypeObject *get_python_known_immediate_operand_type(void) { - static PyMethodDef py_known_imm_operand_methods[] = { + static PyMethodDef py_known_immediate_operand_methods[] = { { NULL } }; - static PyGetSetDef py_known_imm_operand_getseters[] = { + static PyGetSetDef py_known_immediate_operand_getseters[] = { { NULL } }; - static PyTypeObject py_known_imm_operand_type = { + static PyTypeObject py_known_immediate_operand_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.arch.operands.KnownImmOperand", + .tp_name = "pychrysalide.arch.operands.KnownImmediateOperand", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = KNOWN_IMM_OPERAND_DOC, + .tp_doc = KNOWN_IMMEDIATE_OPERAND_DOC, - .tp_methods = py_known_imm_operand_methods, - .tp_getset = py_known_imm_operand_getseters, - .tp_new = py_known_imm_operand_new + .tp_methods = py_known_immediate_operand_methods, + .tp_getset = py_known_immediate_operand_getseters, + + .tp_init = py_known_immediate_operand_init, + .tp_new = py_known_immediate_operand_new, }; - return &py_known_imm_operand_type; + return &py_known_immediate_operand_type; } @@ -141,7 +165,7 @@ PyTypeObject *get_python_known_imm_operand_type(void) * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. * +* Description : Prend en charge l'objet '....KnownImmediateOperand'. * * * * Retour : Bilan de l'opération. * * * @@ -149,13 +173,13 @@ PyTypeObject *get_python_known_imm_operand_type(void) * * ******************************************************************************/ -bool ensure_python_known_imm_operand_is_registered(void) +bool ensure_python_known_immediate_operand_is_registered(void) { - PyTypeObject *type; /* Type Python 'ImmOperand' */ + PyTypeObject *type; /* Type 'KnownImmediateOperand'*/ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - type = get_python_known_imm_operand_type(); + type = get_python_known_immediate_operand_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -163,13 +187,10 @@ bool ensure_python_known_imm_operand_is_registered(void) dict = PyModule_GetDict(module); - if (!ensure_python_imm_operand_is_registered()) - return false; - - if (!ensure_python_renamed_operand_is_registered()) + if (!ensure_python_immediate_operand_is_registered()) return false; - if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_IMM_OPERAND, type)) + if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_IMMEDIATE_OPERAND, type)) return false; } @@ -192,11 +213,11 @@ bool ensure_python_known_imm_operand_is_registered(void) * * ******************************************************************************/ -int convert_to_known_imm_operand(PyObject *arg, void *dst) +int convert_to_known_immediate_operand(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_known_imm_operand_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_known_immediate_operand_type()); switch (result) { @@ -210,7 +231,7 @@ int convert_to_known_imm_operand(PyObject *arg, void *dst) break; case 1: - *((GKnownImmOperand **)dst) = G_KNOWN_IMM_OPERAND(pygobject_get(arg)); + *((GKnownImmediateOperand **)dst) = G_KNOWN_IMMEDIATE_OPERAND(pygobject_get(arg)); break; default: diff --git a/plugins/pychrysalide/arch/operands/known.h b/plugins/pychrysalide/arch/operands/known.h index b5ced68..f5b80e8 100644 --- a/plugins/pychrysalide/arch/operands/known.h +++ b/plugins/pychrysalide/arch/operands/known.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.h - prototypes pour l'équivalent Python du fichier "arch/operands/known.h" * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -32,13 +32,13 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_known_imm_operand_type(void); +PyTypeObject *get_python_known_immediate_operand_type(void); -/* Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. */ -bool ensure_python_known_imm_operand_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.arch.KnownImmediateOperand'. */ +bool ensure_python_known_immediate_operand_is_registered(void); /* Tente de convertir en remplaçant d'opérande d'immédiat. */ -int convert_to_known_imm_operand(PyObject *, void *); +int convert_to_known_immediate_operand(PyObject *, void *); diff --git a/plugins/pychrysalide/arch/operands/module.c b/plugins/pychrysalide/arch/operands/module.c index 89adecc..486e259 100644 --- a/plugins/pychrysalide/arch/operands/module.c +++ b/plugins/pychrysalide/arch/operands/module.c @@ -28,14 +28,20 @@ #include <assert.h> +/* #include "feeder.h" +*/ #include "immediate.h" #include "known.h" +/* #include "proxy.h" +*/ #include "register.h" +/* #include "rename.h" #include "target.h" #include "targetable.h" +*/ #include "../../helpers.h" @@ -101,15 +107,21 @@ bool populate_arch_operands_module(void) result = true; + /* if (result) result = ensure_python_proxy_feeder_is_registered(); - if (result) result = ensure_python_imm_operand_is_registered(); - if (result) result = ensure_python_known_imm_operand_is_registered(); + */ + if (result) result = ensure_python_immediate_operand_is_registered(); + if (result) result = ensure_python_known_immediate_operand_is_registered(); + /* if (result) result = ensure_python_proxy_operand_is_registered(); + */ if (result) result = ensure_python_register_operand_is_registered(); + /* if (result) result = ensure_python_renamed_operand_is_registered(); if (result) result = ensure_python_renameable_operand_is_registered(); if (result) result = ensure_python_target_operand_is_registered(); if (result) result = ensure_python_targetable_operand_is_registered(); + */ assert(result); diff --git a/plugins/pychrysalide/arch/operands/register.c b/plugins/pychrysalide/arch/operands/register.c index 2a48a0f..707524a 100644 --- a/plugins/pychrysalide/arch/operands/register.c +++ b/plugins/pychrysalide/arch/operands/register.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register.c - équivalent Python du fichier "arch/operands/register.c" * - * Copyright (C) 2019-2020 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -30,25 +30,19 @@ #include <i18n.h> #include <arch/operands/register-int.h> -#include <plugins/dt.h> #include "../operand.h" #include "../register.h" #include "../../access.h" #include "../../helpers.h" -#include "../../glibext/bufferline.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_register_operand_new(PyTypeObject *, PyObject *, PyObject *); - -/* Initialise la classe des descriptions de fichier binaire. */ -static void py_register_operand_init_gclass(GRegisterOperandClass *, gpointer); +CREATE_DYN_CONSTRUCTOR(register_operand, G_TYPE_REGISTER_OPERAND); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_register_operand_init(PyObject *, PyObject *, PyObject *); @@ -58,12 +52,6 @@ static int py_register_operand_init(PyObject *, PyObject *, PyObject *); /* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ -/* Compare un opérande avec un autre. */ -static PyObject *py_register_operand___cmp__(PyObject *, PyObject *); - -/* Traduit un opérande en version humainement lisible. */ -static PyObject *py_register_operand__print(PyObject *, PyObject *); - /* Fournit le registre associé à l'opérande. */ static PyObject *py_register_operand_get_register(PyObject *, void *); @@ -76,86 +64,6 @@ static PyObject *py_register_operand_get_register(PyObject *, void *); /****************************************************************************** * * -* 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_register_operand_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_register_operand_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_REGISTER_OPERAND, type->tp_name, - (GClassInitFunc)py_register_operand_init_gclass, 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 : class = classe à initialiser. * -* unused = données non utilisées ici. * -* * -* Description : Initialise la classe des descriptions de fichier binaire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void py_register_operand_init_gclass(GRegisterOperandClass *class, gpointer unused) -{ - -} - - -/****************************************************************************** -* * * Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * @@ -182,7 +90,7 @@ static int py_register_operand_init(PyObject *self, PyObject *args, PyObject *kw "\n" \ " RegisterOperand(reg)" \ "\n" \ - "Where reg is an architecture register defined from a subclass of" \ + "Where *reg* is an architecture register defined from a subclass of" \ " pychrysalide.arch.ArchRegister." /* Récupération des paramètres */ @@ -199,8 +107,8 @@ static int py_register_operand_init(PyObject *self, PyObject *args, PyObject *kw operand = G_REGISTER_OPERAND(pygobject_get(self)); - g_object_ref(G_OBJECT(reg)); - operand->reg = reg; + if (!g_register_operand_create(operand, reg)) + return -1; return 0; @@ -215,98 +123,6 @@ static int py_register_operand_init(PyObject *self, PyObject *args, PyObject *kw /****************************************************************************** * * -* Paramètres : self = serveur à manipuler. * -* args = arguments associés à l'appel. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_register_operand___cmp__(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GRegisterOperand *other; /* Autre opérande à manipuler */ - int ret; /* Bilan de lecture des args. */ - GRegisterOperand *operand; /* Elément à manipuler */ - int status; /* Bilan de comparaison */ - -#define REGISTER_OPERAND_CMP_METHOD PYTHON_METHOD_DEF \ -( \ - __cmp__, "$self, other, /", \ - METH_VARARGS, py_register_operand, \ - "Implementation of the required method used to compare the" \ - " operand with another one. This second object is always" \ - " a pychrysalide.arch.RegisterOperand instance.\n" \ - "\n" \ - "See the parent class for more information about this method." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_register_operand, &other); - if (!ret) return NULL; - - operand = G_REGISTER_OPERAND(pygobject_get(self)); - - status = g_arch_operand_compare(G_ARCH_OPERAND(operand), G_ARCH_OPERAND(other)); - - result = PyLong_FromLong(status); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = serveur à manipuler. * -* args = arguments associés à l'appel. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_register_operand__print(PyObject *self, PyObject *args) -{ - PyObject *result; /* Bilan à retourner */ - GBufferLine *line; /* Ligne fournie à peupler */ - int ret; /* Bilan de lecture des args. */ - GRegisterOperand *operand; /* Elément à manipuler */ - -#define REGISTER_OPERAND_PRINT_METHOD PYTHON_METHOD_DEF \ -( \ - _print, "$self, line, /", \ - METH_VARARGS, py_register_operand, \ - "Implementation of the required method used to print the operand" \ - " into a rendering line, which is a provided" \ - " pychrysalide.glibext.BufferLine instance.\n" \ - "\n" \ - "See the parent class for more information about this method." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_buffer_line, &line); - if (!ret) return NULL; - - operand = G_REGISTER_OPERAND(pygobject_get(self)); - - g_arch_operand_print(G_ARCH_OPERAND(operand), line); - - result = Py_None; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -367,8 +183,6 @@ static PyObject *py_register_operand_get_register(PyObject *self, void *closure) PyTypeObject *get_python_register_operand_type(void) { static PyMethodDef py_register_operand_methods[] = { - REGISTER_OPERAND_CMP_METHOD, - REGISTER_OPERAND_PRINT_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/arch/register.c b/plugins/pychrysalide/arch/register.c index 615a5b7..7139e47 100644 --- a/plugins/pychrysalide/arch/register.c +++ b/plugins/pychrysalide/arch/register.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register.c - équivalent Python du fichier "arch/register.c" * - * Copyright (C) 2019 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -31,32 +31,27 @@ #include <i18n.h> #include <arch/register-int.h> -#include <plugins/dt.h> #include "../access.h" #include "../helpers.h" -#include "../analysis/storage/serialize.h" +#include "../glibext/comparable.h" +#include "../glibext/hashable.h" +#include "../glibext/serialize.h" +#include "../glibext/strbuilder.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_arch_register_new(PyTypeObject *, PyObject *, PyObject *); - /* Initialise la classe des registres. */ -static void py_arch_register_init_gclass(GArchRegisterClass *, gpointer); - -/* Produit une empreinte à partir d'un registre. */ -static guint py_arch_register___hash___wrapper(const GArchRegister *); +static int py_arch_register_init_gclass(GArchRegisterClass *, PyTypeObject *); -/* Compare un registre avec un autre. */ -static int py_arch_register___cmp___wrapper(const GArchRegister *, const GArchRegister *); +CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_register, G_TYPE_ARCH_REGISTER); -/* Traduit un registre en version humainement lisible. */ -static void py_arch_register_print_wrapper(const GArchRegister *, GBufferLine *); +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_arch_register_init(PyObject *, PyObject *, PyObject *); /* Indique si le registre correspond à ebp ou similaire. */ static bool py_arch_register_is_base_pointer_wrapper(const GArchRegister *); @@ -69,9 +64,6 @@ static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *); /* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */ -/* Effectue une comparaison avec un objet Python 'ArchRegister'. */ -static PyObject *py_arch_register_richcompare(PyObject *, PyObject *, int); - /* Indique si le registre correspond à ebp ou similaire. */ static PyObject *py_arch_register_is_base_pointer(PyObject *, void *); @@ -87,88 +79,8 @@ static PyObject *py_arch_register_is_stack_pointer(PyObject *, void *); /****************************************************************************** * * -* 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_arch_register_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 registre */ - bool status; /* Bilan d'un enregistrement */ - -#define ARCH_REGISTER_DOC \ - "The ArchRegister object aims to get subclassed to create" \ - " registers suitable for new architectures.\n" \ - "\n" \ - "Calls to the *__init__* constructor of this abstract object expect"\ - " no particular argument.\n" \ - "\n" \ - "The following methods have to be defined for new classes:\n" \ - "* pychrysalide.arch.ArchRegister.__hash__();\n" \ - "* pychrysalide.arch.ArchRegister.__cmp__();\n" \ - "* pychrysalide.arch.ArchRegister._print();\n" \ - "* pychrysalide.arch.ArchRegister._is_base_pointer();\n" \ - "* pychrysalide.arch.ArchRegister._is_stack_pointer().\n" \ - "\n" \ - "Chrysalide creates an internal glue to provide rich comparisons" \ - " for registers based on the old-style *__cmp__* function." - - /* Validations diverses */ - - base = get_python_arch_register_type(); - - if (type == base) - { - result = NULL; - PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); - goto exit; - } - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(G_TYPE_ARCH_REGISTER, type->tp_name, - (GClassInitFunc)py_arch_register_init_gclass, 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() */ - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : class = classe à initialiser. * -* unused = données non utilisées ici. * +* Paramètres : gclass = classe GLib à initialiser. * +* pyclass = classe Python à initialiser. * * * * Description : Initialise la classe des registres. * * * @@ -178,190 +90,51 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje * * ******************************************************************************/ -static void py_arch_register_init_gclass(GArchRegisterClass *class, gpointer unused) -{ - class->hash = py_arch_register___hash___wrapper; - class->compare = py_arch_register___cmp___wrapper; - class->print = py_arch_register_print_wrapper; - class->is_bp = py_arch_register_is_base_pointer_wrapper; - class->is_sp = py_arch_register_is_stack_pointer_wrapper; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = registre visé par la procédure. * -* * -* Description : Produit une empreinte à partir d'un registre. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static guint py_arch_register___hash___wrapper(const GArchRegister *reg) -{ - guint result; /* Empreinte à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_REGISTER_HASH_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - __hash__, "$self, /", \ - METH_NOARGS, \ - "Abstract method used to produce a hash of the object. The" \ - " result must be an integer value." \ -) - - result = 0; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(reg)); - - if (has_python_method(pyobj, "__hash__")) - { - pyret = run_python_method(pyobj, "__hash__", NULL); - - if (pyret != NULL) - { - if (PyLong_Check(pyret)) - result = PyLong_AsUnsignedLong(pyret); - - Py_DECREF(pyret); - - } - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : a = premier registre à consulter. * -* b = second registre à consulter. * -* * -* Description : Compare un registre avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_arch_register___cmp___wrapper(const GArchRegister *a, const GArchRegister *b) +static int py_arch_register_init_gclass(GArchRegisterClass *gclass, PyTypeObject *pyclass) { - int result; /* Empreinte à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_REGISTER_CMP_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - __cmp__, "$self, other, /", \ - METH_VARARGS, \ - "Abstract method used to compare the register with another" \ - " one. This second object is always an" \ - " pychrysalide.arch.ArchRegister instance.\n" \ - "\n" \ - " This is the Python old-style comparison method, but" \ - " Chrysalide provides a glue to automatically build a rich" \ - " version of this function." \ -) - - result = 0; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(a)); - - if (has_python_method(pyobj, "__cmp__")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(b))); - - pyret = run_python_method(pyobj, "__cmp__", args); - - if (pyret != NULL) - { - if (PyLong_Check(pyret)) - result = PyLong_AsLong(pyret); - } + PY_CLASS_SET_WRAPPER(gclass->is_bp, py_arch_register_is_base_pointer_wrapper); + PY_CLASS_SET_WRAPPER(gclass->is_sp, py_arch_register_is_stack_pointer_wrapper); - Py_DECREF(args); - - Py_XDECREF(pyret); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; + return 0; } /****************************************************************************** * * -* Paramètres : reg = registre visé par la procédure. * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * * * -* Description : Traduit un registre en version humainement lisible. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : - * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static void py_arch_register_print_wrapper(const GArchRegister *reg, GBufferLine *line) +static int py_arch_register_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_REGISTER_PRINT_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _print, "$self, line, /", \ - METH_VARARGS, \ - "Abstract method used to print the register into a rendering" \ - " line, which is a provided pychrysalide.glibext.BufferLine" \ - " instance." \ -) - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(reg)); - - if (has_python_method(pyobj, "_print")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); - - pyret = run_python_method(pyobj, "_print", args); - - Py_DECREF(args); + int ret; /* Bilan de lecture des args. */ - Py_XDECREF(pyret); +#define ARCH_REGISTER_DOC \ + "The ArchRegister object aims to get subclassed in order to create" \ + " registers suitable for new architectures.\n" \ + "\n" \ + "Calls to the *__init__* constructor of this abstract object expect"\ + " no particular argument.\n" \ + "\n" \ + "The following methods may to be implemnted for new classes:\n" \ + "* pychrysalide.arch.ArchRegister._is_base_pointer();\n" \ + "* pychrysalide.arch.ArchRegister._is_stack_pointer().\n" - } + /* Initialisation d'un objet GLib */ - Py_DECREF(pyobj); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - PyGILState_Release(gstate); + return 0; } @@ -486,51 +259,6 @@ static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *reg) /****************************************************************************** * * -* Paramètres : a = premier object Python à consulter. * -* b = second object Python à consulter. * -* op = type de comparaison menée. * -* * -* Description : Effectue une comparaison avec un objet Python 'ArchRegister'.* -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_register_richcompare(PyObject *a, PyObject *b, int op) -{ - PyObject *result; /* Bilan à retourner */ - int ret; /* Bilan de lecture des args. */ - const GArchRegister *reg_a; /* Premier élément à traiter */ - const GArchRegister *reg_b; /* Second élément à traiter */ - int status; /* Résultat d'une comparaison */ - - ret = PyObject_IsInstance(b, (PyObject *)get_python_arch_register_type()); - if (!ret) - { - result = Py_NotImplemented; - goto cmp_done; - } - - reg_a = G_ARCH_REGISTER(pygobject_get(a)); - reg_b = G_ARCH_REGISTER(pygobject_get(b)); - - status = py_arch_register___cmp___wrapper(reg_a, reg_b); - - result = status_to_rich_cmp_state(status, op); - - cmp_done: - - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -618,9 +346,6 @@ static PyObject *py_arch_register_is_stack_pointer(PyObject *self, void *closure PyTypeObject *get_python_arch_register_type(void) { static PyMethodDef py_arch_register_methods[] = { - ARCH_REGISTER_HASH_WRAPPER, - ARCH_REGISTER_CMP_WRAPPER, - ARCH_REGISTER_PRINT_WRAPPER, ARCH_REGISTER_IS_BASE_POINTER_WRAPPER, ARCH_REGISTER_IS_STACK_POINTER_WRAPPER, { NULL } @@ -643,11 +368,10 @@ PyTypeObject *get_python_arch_register_type(void) .tp_doc = ARCH_REGISTER_DOC, - .tp_richcompare = py_arch_register_richcompare, - .tp_methods = py_arch_register_methods, .tp_getset = py_arch_register_getseters, + .tp_init = py_arch_register_init, .tp_new = py_arch_register_new, }; @@ -683,9 +407,20 @@ bool ensure_python_arch_register_is_registered(void) dict = PyModule_GetDict(module); + if (!ensure_python_comparable_object_is_registered()) + return false; + + if (!ensure_python_hashable_object_is_registered()) + return false; + if (!ensure_python_serializable_object_is_registered()) return false; + if (!ensure_python_string_builder_is_registered()) + return false; + + pyg_register_class_init(G_TYPE_ARCH_REGISTER, (PyGClassInitFunc)py_arch_register_init_gclass); + if (!register_class_for_pygobject(dict, G_TYPE_ARCH_REGISTER, type)) return false; diff --git a/plugins/pychrysalide/constants.h b/plugins/pychrysalide/constants.h index 332afe0..151f1eb 100644 --- a/plugins/pychrysalide/constants.h +++ b/plugins/pychrysalide/constants.h @@ -46,6 +46,9 @@ int convert_to_source_endian(PyObject *, void *); /* Tente de convertir en constante MemoryDataSize. */ int convert_to_memory_data_size(PyObject *, void *); +#define cast_memory_data_size_to_python(v) \ + cast_with_constants_group_from_module("pychrysalide", "MemoryDataSize", v) + #endif /* _PLUGINS_PYCHRYSALIDE_CONSTANTS_H */ diff --git a/plugins/pychrysalide/core-ui.c b/plugins/pychrysalide/core-ui.c index 1b332b7..ad3554c 100644 --- a/plugins/pychrysalide/core-ui.c +++ b/plugins/pychrysalide/core-ui.c @@ -33,6 +33,7 @@ #include "bindings.h" #include "core-ui-int.h" +#include "arch/module-ui.h" @@ -66,6 +67,14 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *); +/* --------------------------- POINT D'ENTREE POUR PYTHON --------------------------- */ + + +/* Inscrit les défintions des objets UI Python de Chrysalide. */ +static bool populate_python_modules_ui(void); + + + /* ---------------------------------------------------------------------------------- */ /* COMPOSITION DE NOUVEAU GREFFON NATIF */ /* ---------------------------------------------------------------------------------- */ @@ -165,7 +174,7 @@ static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *plugin) /****************************************************************************** * * -* Paramètres : filename = nom du fichier à charger. * +* Paramètres : module = extension vue du système. * * * * Description : Crée un module pour un greffon de support Python. * * * @@ -192,7 +201,7 @@ GPluginModule *g_pychrysalide_plugin_ui_new(GModule *module) /****************************************************************************** * * * Paramètres : plugin = instance à initialiser pleinement. * -* module = module système correspondant. * +* module = extension vue du système. * * * * Description : Met en place un module pour un greffon de support Python. * * * @@ -294,6 +303,31 @@ static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin) * * * Paramètres : - * * * +* Description : Inscrit les défintions des objets UI Python de Chrysalide. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool populate_python_modules_ui(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = populate_arch_module_ui(); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * * Description : Point d'entrée pour l'initialisation de Python. * * * * Retour : ? * @@ -309,7 +343,7 @@ PyMODINIT_FUNC PyInit_pychrysalideui(void) details.standalone = _standalone; - details.populate_extra = NULL; + details.populate_extra = populate_python_modules_ui; details.create_self = g_pychrysalide_plugin_ui_new; result = init_python_pychrysalide_module(&details); diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index 0e72b46..51a06a1 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -251,7 +251,7 @@ static void g_pychrysalide_plugin_finalize(GPyChrysalidePlugin *plugin) /****************************************************************************** * * -* Paramètres : filename = nom du fichier à charger. * +* Paramètres : module = extension vue du système. * * * * Description : Crée un module pour un greffon de support Python. * * * @@ -278,7 +278,7 @@ GPluginModule *g_pychrysalide_plugin_new(GModule *module) /****************************************************************************** * * * Paramètres : plugin = instance à initialiser pleinement. * -* module = module système correspondant. * +* module = extension vue du système. * * * * Description : Met en place un module pour un greffon de support Python. * * * |