From a28e1b94a83bee9a2424ab84818a5547eafaf0cf Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 17 Mar 2025 08:36:58 +0100 Subject: Restore the definition of main operands. --- plugins/pychrysalide/Makefile.am | 3 +- plugins/pychrysalide/arch/Makefile.am | 20 +- plugins/pychrysalide/arch/module-ui.c | 59 ++ plugins/pychrysalide/arch/module-ui.h | 38 + plugins/pychrysalide/arch/module.c | 18 +- plugins/pychrysalide/arch/operand-ui.c | 461 +++++++++ plugins/pychrysalide/arch/operand-ui.h | 45 + plugins/pychrysalide/arch/operand.c | 476 +++++---- plugins/pychrysalide/arch/operand.h | 5 +- plugins/pychrysalide/arch/operands/Makefile.am | 16 +- plugins/pychrysalide/arch/operands/constants.c | 19 +- plugins/pychrysalide/arch/operands/constants.h | 7 +- plugins/pychrysalide/arch/operands/immediate.c | 384 +++---- plugins/pychrysalide/arch/operands/immediate.h | 10 +- plugins/pychrysalide/arch/operands/known.c | 125 ++- plugins/pychrysalide/arch/operands/known.h | 10 +- plugins/pychrysalide/arch/operands/module.c | 16 +- plugins/pychrysalide/arch/operands/register.c | 196 +--- plugins/pychrysalide/arch/register.c | 361 +------ plugins/pychrysalide/constants.h | 3 + plugins/pychrysalide/core-ui.c | 40 +- plugins/pychrysalide/core.c | 4 +- src/Makefile.am | 3 +- src/arch/Makefile.am | 55 +- src/arch/operand-int.h | 92 +- src/arch/operand-ui-int.h | 52 + src/arch/operand-ui.c | 111 ++ src/arch/operand-ui.h | 55 + src/arch/operand.c | 653 ++++-------- src/arch/operand.h | 64 +- src/arch/operands/Makefile.am | 38 +- src/arch/operands/immediate-int.h | 66 +- src/arch/operands/immediate-ui.c | 184 ++++ src/arch/operands/immediate-ui.h | 37 + src/arch/operands/immediate.c | 1320 ++++++++++-------------- src/arch/operands/immediate.h | 86 +- src/arch/operands/known-int.h | 55 + src/arch/operands/known-ui.c | 79 ++ src/arch/operands/known-ui.h | 37 + src/arch/operands/known.c | 433 ++++---- src/arch/operands/known.h | 26 +- src/arch/operands/register-int.h | 6 +- src/arch/operands/register-ui.c | 93 ++ src/arch/operands/register-ui.h | 37 + src/arch/operands/register.c | 371 +++++-- src/arch/register-int.h | 24 +- src/arch/register.c | 225 +--- src/arch/register.h | 33 +- src/common/datatypes.h | 4 + src/glibext/comparable.c | 18 +- src/glibext/options/Makefile.am | 1 + src/glibext/options/disass.h | 56 + tests/arch/operand.py | 72 ++ tests/arch/operands/immediate.py | 76 +- 54 files changed, 3770 insertions(+), 3008 deletions(-) create mode 100644 plugins/pychrysalide/arch/module-ui.c create mode 100644 plugins/pychrysalide/arch/module-ui.h create mode 100644 plugins/pychrysalide/arch/operand-ui.c create mode 100644 plugins/pychrysalide/arch/operand-ui.h create mode 100644 src/arch/operand-ui-int.h create mode 100644 src/arch/operand-ui.c create mode 100644 src/arch/operand-ui.h create mode 100644 src/arch/operands/immediate-ui.c create mode 100644 src/arch/operands/immediate-ui.h create mode 100644 src/arch/operands/known-int.h create mode 100644 src/arch/operands/known-ui.c create mode 100644 src/arch/operands/known-ui.h create mode 100644 src/arch/operands/register-ui.c create mode 100644 src/arch/operands/register-ui.h create mode 100644 src/glibext/options/disass.h create mode 100644 tests/arch/operand.py 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 + + +#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 +#include + + +/* 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 +#include + + +#include + + +#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 +#include + + + +/* 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 #include -#include +#include #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 - - -#include +#include #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 -#include +#include #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 +/* #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 #include -#include #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 #include -#include #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. * * * diff --git a/src/Makefile.am b/src/Makefile.am index cfd1a4d..5c4d1e3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,7 +78,7 @@ libchrysacore4_la_SOURCES = libchrysacore4_la_LIBADD = \ analysis/libanalysis4.la \ - arch/libarch4.la \ + arch/libarch.la \ common/libcommon4.la \ core/libcore4.la \ format/libformat.la \ @@ -102,6 +102,7 @@ EXTRA_libchrysacoreui_la_DEPENDENCIES = libchrysacore4.la libchrysacoreui_la_SOURCES = libchrysacoreui_la_LIBADD = \ + arch/libarchui.la \ glibext/libglibextui.la \ gtkext/libgtkext4.la \ gui/libgui4.la diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 6ee2690..127ca4c 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -1,43 +1,56 @@ -noinst_LTLIBRARIES = libarch4.la # libarch.la +noinst_LTLIBRARIES = libarch.la libarchui.la + +# libarch_la_SOURCES = \ +# archbase.h archbase.c \ +# context-int.h \ +# context.h context.c \ +# instriter.h instriter.c \ +# link.h link.c \ +# post.h post.c \ +# storage.h storage.c + +# libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) + +# libarch_la_LIBADD = \ +# instructions/libarchinstructions.la \ +# operands/libarchoperands.la + + +# instruction-int.h \ +# instruction.h instruction.c \ +# +# processor-int.h \ +# processor.h processor.c \ +# libarch_la_SOURCES = \ - archbase.h archbase.c \ - context-int.h \ - context.h context.c \ - instriter.h instriter.c \ - instruction-int.h \ - instruction.h instruction.c \ - link.h link.c \ - operand-int.h operand-int.c \ + operand-int.h \ operand.h operand.c \ - post.h post.c \ - processor-int.h \ - processor.h processor.c \ register-int.h \ register.h register.c \ - storage.h storage.c \ vmpa.h vmpa.c -libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarch_la_CFLAGS = $(LIBGOBJ_CFLAGS) libarch_la_LIBADD = \ - instructions/libarchinstructions.la \ operands/libarchoperands.la -libarch4_la_SOURCES = \ - vmpa.h vmpa.c +libarchui_la_SOURCES = \ + operand-ui-int.h \ + operand-ui.h operand-ui.c -libarch4_la_CFLAGS = $(TOOLKIT_CFLAGS) +libarchui_la_CFLAGS = $(LIBGTK_CFLAGS) -libarch4_la_LIBADD = +libarchui_la_LIBADD = \ + operands/libarchoperandsui.la devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) -dev_HEADERS = $(libarch_la_SOURCES:%c=) +dev_HEADERS = $(libarch_la_SOURCES:%c=) $(libarchui_la_SOURCES:%c=) #SUBDIRS = instructions operands - +SUBDIRS = operands diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index e6c1232..a83d135 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand-int.h - prototypes pour la définition générique interne des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -28,11 +28,23 @@ #include "operand.h" +#include "../common/szbin.h" +#include "../glibext/objhole-int.h" + + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +//typedef bool (* arch_operand_to_string_fc) (const GArchOperand *operand, unsigned int flags, sized_binary_t *); + + + +#if 0 + + #include #include "../analysis/storage/storage.h" -#include "../glibext/objhole.h" @@ -71,46 +83,38 @@ typedef bool (* load_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffe typedef bool (* store_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _operand_extra_data_t -{ - ArchOperandFlag flags; /* Informations diverses */ -} operand_extra_data_t; -/* Encapsulation avec un verrou d'accès */ -typedef union _operand_obj_extra_t -{ - operand_extra_data_t data; /* Données embarquées */ - lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */ +#endif -} operand_obj_extra_t; + +#define ARCH_OPERAND_EXTRA_DATA(mx) \ + \ + unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \ + \ + /** \ + * ArchOperandFlag \ + */ \ + unsigned int flags : mx; /* Définition générique d'un opérande d'architecture (instance) */ struct _GArchOperand { - GObject parent; /* A laisser en premier */ - -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ - - /** - * L'inclusion des informations suivantes dépend de l'architecture. - * - * Si la structure GObject possède un trou, on remplit de préférence - * ce dernier. - */ - - operand_obj_extra_t extra; /* Externalisation embarquée */ - -#endif + GThickObject parent; /* A laisser en premier */ }; /* Définition générique d'un opérande d'architecture (classe) */ struct _GArchOperandClass { - GObjectClass parent; /* A laisser en premier */ + GThickObjectClass parent; /* A laisser en premier */ + + + + + +#if 0 operand_compare_fc compare; /* Comparaison d'opérandes */ find_inner_operand_fc find_inner; /* Définition d'un chemin */ @@ -128,6 +132,8 @@ struct _GArchOperandClass load_operand_fc load; /* Chargement depuis un tampon */ store_operand_fc store; /* Conservation dans un tampon */ +#endif + }; @@ -135,22 +141,36 @@ struct _GArchOperandClass * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _operand_extra_data_t +{ + ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/ -# define GET_ARCH_OP_EXTRA(op) (operand_extra_data_t *)&op->extra +} operand_extra_data_t; -#else -# define GET_ARCH_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), operand_extra_data_t) +#define GET_ARCH_OP_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, operand_extra_data_t) + +#define SET_ARCH_OP_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, operand_extra_data_t, data) + + + + + + + + +#if 0 -#endif /* Ajoute une information complémentaire à un opérande. */ -bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool); +//bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool); /* Retire une information complémentaire à un opérande. */ -bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool); +//bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool); @@ -190,5 +210,7 @@ bool g_arch_operand_store_generic_fixed(GArchOperand *, GObjectStorage *, packed bool g_arch_operand_store_generic_variadic(GArchOperand *, GObjectStorage *, packed_buffer_t *); +#endif + #endif /* _ARCH_OPERAND_INT_H */ diff --git a/src/arch/operand-ui-int.h b/src/arch/operand-ui-int.h new file mode 100644 index 0000000..c1173f3 --- /dev/null +++ b/src/arch/operand-ui-int.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui-int.h - prototypes pour la définition générique interne des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERAND_UI_INT_H +#define _ARCH_OPERAND_UI_INT_H + + +#include "operand-ui.h" + + + +/* Traduit un opérande en version humainement lisible. */ +typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *); + + + +/* Définition générique d'un opérande d'architecture (interface) */ +struct _GArchOperandUIInterface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + print_operand_ui_fc print; /* Texte humain équivalent */ + build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/ + +}; + + + +#endif /* _ARCH_OPERAND_UI_INT_H */ diff --git a/src/arch/operand-ui.c b/src/arch/operand-ui.c new file mode 100644 index 0000000..ff7ad1b --- /dev/null +++ b/src/arch/operand-ui.c @@ -0,0 +1,111 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.c - gestion générique des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#include "operand-ui.h" + + +#include "operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +static void g_arch_operand_ui_default_init(GArchOperandUIInterface *); + + + +/* Indique le type défini pour un opérande d'architecture avec représentation graphique. */ +G_DEFINE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_ui_default_init(GArchOperandUIInterface *iface) +{ + iface->print = NULL; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GArchOperandUIInterface *iface; /* Interface utilisée */ + + iface = G_ARCH_OPERAND_UI_GET_IFACE(operand); + + iface->print(operand, line); + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + GArchOperandUIInterface *iface; /* Interface utilisée */ + + iface = G_ARCH_OPERAND_UI_GET_IFACE(operand); + + if (iface->build_tooltip != NULL) + result = iface->build_tooltip(operand, binary); + else + result = NULL; + + return result; + +} diff --git a/src/arch/operand-ui.h b/src/arch/operand-ui.h new file mode 100644 index 0000000..4aacab7 --- /dev/null +++ b/src/arch/operand-ui.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.h - prototypes pour la gestion générique des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERAND_UI_H +#define _ARCH_OPERAND_UI_H + + + +#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" + + + +#define G_TYPE_ARCH_OPERAND_UI (g_arch_operand_ui_get_type()) + +DECLARE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G, ARCH_OPERAND_UI); + + + +// TODO : REMME +//typedef void *GBufferLine; +typedef void *GLoadedBinary; +///// + + + +/* Traduit un opérande en version humainement lisible. */ +void g_arch_operand_ui_print(const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *, const GLoadedBinary *); + + + +#endif /* _ARCH_OPERAND_UI_H */ diff --git a/src/arch/operand.c b/src/arch/operand.c index 0f5ffd5..f2f356b 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand.c - gestion générique des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,17 +25,16 @@ #include -#include -#include #include "operand-int.h" -#include "storage.h" -#include "../analysis/storage/serialize-int.h" #include "../common/fnv1a.h" #include "../common/sort.h" -#include "../core/logs.h" +#include "../glibext/comparable-int.h" +#include "../glibext/hashable-int.h" +#include "../glibext/serialize-int.h" #include "../glibext/singleton-int.h" +#include "../glibext/strbuilder-int.h" @@ -45,66 +44,67 @@ /* Initialise la classe générique des opérandes. */ static void g_arch_operand_class_init(GArchOperandClass *); -/* Initialise une instance d'opérande d'architecture. */ -static void g_arch_operand_init(GArchOperand *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *); -/* Procède à l'initialisation de l'interface de singleton. */ -static void g_arch_operand_singleton_init(GSingletonCandidateInterface *); +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *); /* Procède à l'initialisation de l'interface de sérialisation. */ -static void g_arch_operand_serializable_init(GSerializableObjectInterface *); +static void g_arch_operand_serializable_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface de rassemblement. */ +static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *); + +/* Initialise une instance d'opérande d'architecture. */ +static void g_arch_operand_init(GArchOperand *); /* Supprime toutes les références externes. */ -static void g_arch_operand_dispose(GArchOperand *); +static void g_arch_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_arch_operand_finalize(GArchOperand *); +static void g_arch_operand_finalize(GObject *); -/* Compare un opérande avec un autre. */ -static int _g_arch_operand_compare(const GArchOperand *, const GArchOperand *, bool); +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */ +/* Réalise une comparaison étendue entre objets. */ +static int g_arch_operand_compare(const GComparableObject *, const GComparableObject *); -/* Fournit une liste de candidats embarqués par un candidat. */ -GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *); -/* Met à jour une liste de candidats embarqués par un candidat. */ -void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint _g_arch_operand_hash(const GArchOperand *, bool); +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_arch_operand_hash(const GArchOperand *); -/* Détermine si deux candidats à l'unicité sont identiques. */ -static gboolean g_arch_operand_is_equal(const GArchOperand *, const GArchOperand *); +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_arch_operand_hash(const GHashableObject *); -/* Marque un candidat comme figé. */ -static void g_arch_operand_set_read_only(GArchOperand *); -/* Indique si le candidat est figé. */ -static bool g_arch_operand_is_read_only(GArchOperand *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_arch_operand_load(GSerializableObject *, GObjectStorage *, int); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_arch_operand_store(const GSerializableObject *, GObjectStorage *, int); -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */ -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); + +/* Marque un candidat comme figé. */ +static void g_arch_operand_mark_as_read_only(GSingletonCandidate *); + +/* Indique si le candidat est figé. */ +static bool g_arch_operand_is_read_only(const GSingletonCandidate *); @@ -114,9 +114,12 @@ static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer /* Indique le type défini pour un opérande d'architecture. */ -G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_init) - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_init)); +G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_THICK_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_candidate_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_operand_string_builder_iface_init)); /****************************************************************************** @@ -134,30 +137,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, static void g_arch_operand_class_init(GArchOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_arch_operand_finalize; - - operand = G_ARCH_OPERAND_CLASS(klass); - - operand->compare = (operand_compare_fc)_g_arch_operand_compare; - - operand->hash = _g_arch_operand_hash; - - operand->load = (load_operand_fc)_g_arch_operand_load; - operand->store = (store_operand_fc)_g_arch_operand_store; + object->dispose = g_arch_operand_dispose; + object->finalize = g_arch_operand_finalize; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance d'opérande d'architecture. * +* Description : Procède à l'initialisation de l'interface de comparaison. * * * * Retour : - * * * @@ -165,13 +158,9 @@ static void g_arch_operand_class_init(GArchOperandClass *klass) * * ******************************************************************************/ -static void g_arch_operand_init(GArchOperand *operand) +static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *iface) { - operand_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_OP_EXTRA(operand); - - INIT_GOBJECT_EXTRA_LOCK(extra); + iface->compare = g_arch_operand_compare; } @@ -180,7 +169,7 @@ static void g_arch_operand_init(GArchOperand *operand) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de singleton. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -188,16 +177,9 @@ static void g_arch_operand_init(GArchOperand *operand) * * ******************************************************************************/ -static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface) +static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - iface->list_inner = (list_inner_instances_fc)g_arch_operand_list_inner_instances; - iface->update_inner = (update_inner_instances_fc)g_arch_operand_update_inner_instances; - - iface->hash = (hash_candidate_fc)g_arch_operand_hash; - iface->is_equal = (is_candidate_equal_fc)g_arch_operand_is_equal; - - iface->set_ro = (set_candidate_ro_fc)g_arch_operand_set_read_only; - iface->is_ro = (is_candidate_ro_fc)g_arch_operand_is_read_only; + iface->hash = g_arch_operand_hash; } @@ -214,38 +196,19 @@ static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface) * * ******************************************************************************/ -static void g_arch_operand_serializable_init(GSerializableObjectInterface *iface) +static void g_arch_operand_serializable_iface_init(GSerializableObjectInterface *iface) { - iface->load = (load_serializable_object_cb)g_arch_operand_load; - iface->store = (store_serializable_object_cb)g_arch_operand_store; + iface->load = g_arch_operand_load; + iface->store = g_arch_operand_store; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_arch_operand_dispose(GArchOperand *operand) -{ - G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Procède à l'initialisation de l'interface de rassemblement. * * * * Retour : - * * * @@ -253,147 +216,59 @@ static void g_arch_operand_dispose(GArchOperand *operand) * * ******************************************************************************/ -static void g_arch_operand_finalize(GArchOperand *operand) +static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *iface) { - G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int _g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b, bool lock) -{ - int result; /* Bilan à faire remonter */ - operand_extra_data_t *ea; /* Données insérées à consulter*/ - operand_extra_data_t *eb; /* Données insérées à consulter*/ - - assert(!lock); - - ea = GET_ARCH_OP_EXTRA(a); - eb = GET_ARCH_OP_EXTRA(b); + iface->list_inner = NULL; + iface->update_inner = NULL; - result = sort_unsigned_long(ea->flags, eb->flags); - - return result; + iface->mark_as_ro = g_arch_operand_mark_as_read_only; + iface->is_ro = g_arch_operand_is_read_only; } /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b) -{ - int result; /* Bilan à faire remonter */ - GType type_a; /* Type de l'object A */ - GType type_b; /* Type de l'object B */ - - type_a = G_OBJECT_TYPE(G_OBJECT(a)); - type_b = G_OBJECT_TYPE(G_OBJECT(b)); - - assert(sizeof(GType) <= sizeof(unsigned long)); - - result = sort_unsigned_long(type_a, type_b); - - if (result == 0) - result = G_ARCH_OPERAND_GET_CLASS(a)->compare(a, b, true); - - return result; - -} - - -/****************************************************************************** +* Paramètres : iface = interface GLib à initialiser. * * * -* Paramètres : operand = opérande à consulter. * -* target = instruction à venir retrouver. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * -* Description : Détermine le chemin conduisant à un opérande interne. * -* * -* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target) +static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *iface) { - char *result; /* Chemin à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->find_inner != NULL) - result = class->find_inner(operand, target); - - else - result = NULL; - - return result; + iface->to_string = NULL; } /****************************************************************************** * * -* Paramètres : operand = opérande à consulter. * -* path = chemin d'accès à un opérande à retrouver. * +* Paramètres : operand = instance à initialiser. * * * -* Description : Obtient l'opérande correspondant à un chemin donné. * +* Description : Initialise une instance d'opérande d'architecture. * * * -* Retour : Opérande trouvé ou NULL en cas d'échec. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path) +static void g_arch_operand_init(GArchOperand *operand) { - GArchOperand *result; /* Opérande trouvée à renvoyer */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->get_inner != NULL) - result = class->get_inner(operand, path); - - else - result = NULL; - - return result; } /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Supprime toutes les références externes. * * * * Retour : - * * * @@ -401,54 +276,36 @@ GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *ope * * ******************************************************************************/ -void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line) +static void g_arch_operand_dispose(GObject *object) { - G_ARCH_OPERAND_GET_CLASS(operand)->print(operand, line); + G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(object); } -#ifdef INCLUDE_GTK_SUPPORT - - /****************************************************************************** * * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Construit un petit résumé concis de l'opérande. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBinary *binary) +static void g_arch_operand_finalize(GObject *object) { - char *result; /* Description à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->build_tooltip != NULL) - result = class->build_tooltip(operand, binary); - else - result = NULL; - - return result; + G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(object); } -#endif - - /****************************************************************************** * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * -* lock = indique un besoin de verrouillage des données. * * * * Description : Ajoute une information complémentaire à un opérande. * * * @@ -458,48 +315,20 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin * * ******************************************************************************/ -bool _g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) +bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - if (lock) - LOCK_GOBJECT_EXTRA(extra); - - result = !(extra->flags & flag); - - extra->flags |= flag; - - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à venir modifier. * -* flag = drapeau d'information complémentaire à planter. * -* * -* Description : Ajoute une information complémentaire à un opérande. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = !(extra.flags & flag); -bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) -{ - bool result; /* Bilan à retourner */ + extra.flags |= flag; - result = _g_arch_operand_set_flag(operand, flag, true); + SET_ARCH_OP_EXTRA(operand, &extra); return result; @@ -510,7 +339,6 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * -* lock = indique un besoin de verrouillage des données. * * * * Description : Retire une information complémentaire à un opérande. * * * @@ -520,46 +348,20 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * ******************************************************************************/ -bool _g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) +bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - extra->flags &= ~flag; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à venir modifier. * -* flag = drapeau d'information complémentaire à planter. * -* * -* Description : Retire une information complémentaire à un opérande. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = (extra.flags & flag); -bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) -{ - bool result; /* Bilan à retourner */ + extra.flags &= ~flag; - result = _g_arch_operand_unset_flag(operand, flag, true); + SET_ARCH_OP_EXTRA(operand, &extra); return result; @@ -582,17 +384,13 @@ bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - UNLOCK_GOBJECT_EXTRA(extra); + result = (extra.flags & flag); return result; @@ -614,15 +412,11 @@ bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag) ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand) { ArchOperandFlag result; /* Fanions à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->flags; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.flags; return result; @@ -630,39 +424,40 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand) -/* ---------------------------------------------------------------------------------- */ -/* CONTROLE DU VOLUME DES INSTANCES */ -/* ---------------------------------------------------------------------------------- */ + + + + +#if 0 + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* count = quantité d'instances à l'unicité internes. * +* Paramètres : operand = opérande à consulter. * +* target = instruction à venir retrouver. * * * -* Description : Fournit une liste de candidats embarqués par un candidat. * +* Description : Détermine le chemin conduisant à un opérande interne. * * * -* Retour : Liste de candidats internes ou NULL si aucun. * +* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count) +char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target) { - GArchOperand **result; /* Instances à retourner */ + char *result; /* Chemin à retourner */ GArchOperandClass *class; /* Classe associée à l'objet */ class = G_ARCH_OPERAND_GET_CLASS(operand); - if (class->list_inner == NULL) - { - *count = 0; - result = NULL; - } + if (class->find_inner != NULL) + result = class->find_inner(operand, target); else - result = class->list_inner(operand, count); + result = NULL; return result; @@ -671,105 +466,59 @@ GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* instances = liste de candidats internes devenus singletons. * -* count = quantité d'instances à l'unicité internes. * +* Paramètres : operand = opérande à consulter. * +* path = chemin d'accès à un opérande à retrouver. * * * -* Description : Met à jour une liste de candidats embarqués par un candidat. * +* Description : Obtient l'opérande correspondant à un chemin donné. * * * -* Retour : - * +* Retour : Opérande trouvé ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count) +GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path) { + GArchOperand *result; /* Opérande trouvée à renvoyer */ GArchOperandClass *class; /* Classe associée à l'objet */ class = G_ARCH_OPERAND_GET_CLASS(operand); - if (class->update_inner == NULL) - assert(class->list_inner == NULL); + if (class->get_inner != NULL) + result = class->get_inner(operand, path); else - { - assert(class->list_inner != NULL); - class->update_inner(operand, instances, count); - } + result = NULL; + + return result; } -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ +#endif -static guint _g_arch_operand_hash(const GArchOperand *operand, bool lock) -{ - guint result; /* Valeur à retourner */ - const char *name; /* Désignation du type d'object*/ - fnv64_t name_hash; /* Empreinte du nom */ - operand_extra_data_t *extra; /* Données insérées à modifier */ - assert(!lock); - name = G_OBJECT_TYPE_NAME(G_OBJECT(operand)); - name_hash = fnv_64a_hash(name); - result = (name_hash & 0xffffffff); - result ^= (name_hash >> 32); - extra = GET_ARCH_OP_EXTRA(operand); - result ^= extra->flags; - return result; -} -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ -static guint g_arch_operand_hash(const GArchOperand *operand) -{ - guint result; /* Valeur à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - result = class->hash(operand, true); - return result; - -} +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* other = second élément à analyser. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Détermine si deux candidats à l'unicité sont identiques. * +* Description : Réalise une comparaison étendue entre objets. * * * * Retour : Bilan de la comparaison. * * * @@ -777,56 +526,56 @@ static guint g_arch_operand_hash(const GArchOperand *operand) * * ******************************************************************************/ -static gboolean g_arch_operand_is_equal(const GArchOperand *operand, const GArchOperand *other) +static int g_arch_operand_compare(const GComparableObject *object, const GComparableObject *other) { - gboolean result; /* Bilan à renvoyer */ - int ret; /* Bilan d'une comparaison */ + int result; /* Bilan à retourner */ + operand_extra_data_t extra_op; /* Données insérées à consulter*/ + operand_extra_data_t extra_other; /* Données insérées à consulter*/ - ret = g_arch_operand_compare(operand, other); + extra_op = GET_ARCH_OP_EXTRA(object); + extra_other = GET_ARCH_OP_EXTRA(other); - result = (ret == 0); + result = sort_unsigned_long(extra_op.flags, extra_other.flags); return result; } -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* * -* Description : Marque un candidat comme figé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_arch_operand_set_read_only(GArchOperand *operand) -{ - g_arch_operand_set_flag(operand, AOF_READ_ONLY); -} +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Indique si le candidat est figé. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : true si le contenu du candidat ne peut plus être modifié. * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_operand_is_read_only(GArchOperand *operand) +static guint g_arch_operand_hash(const GHashableObject *object) { - bool result; /* Etat à retourner */ + guint result; /* Valeur à retourner */ + const char *name; /* Désignation du type d'object*/ + fnv64_t name_hash; /* Empreinte du nom */ + operand_extra_data_t extra; /* Données insérées à consulter*/ - result = g_arch_operand_has_flag(operand, AOF_READ_ONLY); + name = G_OBJECT_TYPE_NAME(G_OBJECT(object)); + name_hash = fnv_64a_hash(name); + + result = (name_hash & 0xffffffff); + result ^= (name_hash >> 32); + + extra = GET_ARCH_OP_EXTRA(object); + + result ^= extra.flags; return result; @@ -835,17 +584,17 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand) /* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Charge un objet depuis un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -853,22 +602,15 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand) * * ******************************************************************************/ -static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à consulter*/ - uleb128_t value; /* Valeur ULEB128 à charger */ - - extra = GET_ARCH_OP_EXTRA(operand); + uleb128_t extra; /* Données embarquées */ - LOCK_GOBJECT_EXTRA(extra); - - result = unpack_uleb128(&value, pbuf); + result = load_uleb128(&extra, fd); if (result) - extra->flags = value; - - UNLOCK_GOBJECT_EXTRA(extra); + g_thick_object_set_extra(G_THICK_OBJECT(object), extra); return result; @@ -877,11 +619,11 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -889,74 +631,69 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, * * ******************************************************************************/ -static bool g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe à activer */ + guint extra; /* Données embarquées */ - class = G_ARCH_OPERAND_GET_CLASS(operand); + extra = g_thick_object_get_extra(G_THICK_OBJECT(object)); - result = class->load(operand, storage, pbuf); + result = store_uleb128((uleb128_t []) { extra }, fd); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* CONTROLE DU VOLUME DES INSTANCES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : candidate = objet dont l'instance se veut unique. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Marque un candidat comme figé. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool _g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static void g_arch_operand_mark_as_read_only(GSingletonCandidate *candidate) { - bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_ARCH_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + GArchOperand *operand; /* Version spécialisée */ - UNLOCK_GOBJECT_EXTRA(extra); + operand = G_ARCH_OPERAND(candidate); - return result; + g_arch_operand_set_flag(operand, AOF_READ_ONLY); } /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : operand = objet dont l'instance se veut unique. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Indique si le candidat est figé. * * * -* Retour : Bilan de l'opération. * +* Retour : true si le contenu du candidat ne peut plus être modifié. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_is_read_only(const GSingletonCandidate *candidate) { - bool result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe à activer */ + bool result; /* Etat à retourner */ + GArchOperand *operand; /* Version spécialisée */ - class = G_ARCH_OPERAND_GET_CLASS(operand); + operand = G_ARCH_OPERAND(candidate); - result = class->store(operand, storage, pbuf); + result = g_arch_operand_has_flag(operand, AOF_READ_ONLY); return result; diff --git a/src/arch/operand.h b/src/arch/operand.h index 234ee64..72a1b56 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand.h - prototypes pour la gestion générique des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,20 +25,16 @@ #define _ARCH_OPERAND_H -#include - +#include -#include "../common/packed.h" -#include "../format/format.h" -#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" -/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ +#define G_TYPE_ARCH_OPERAND (g_arch_operand_get_type()) -/* Depuis "../analysis/binary.h" : description de fichier binaire */ -typedef struct _GLoadedBinary GLoadedBinary; +DECLARE_GTYPE(GArchOperand, g_arch_operand, G, ARCH_OPERAND); /* Indications supplémentaires liées aux opérandes */ @@ -58,6 +54,41 @@ typedef enum _ArchOperandFlag #define AOF_USER_FLAG(n) (1 << (AOF_USER_BIT + n)) +/* Ajoute une information complémentaire à un opérande. */ +bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag); + +/* Retire une information complémentaire à un opérande. */ +bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag); + +/* Détermine si un opérande possède un fanion particulier. */ +bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag); + +/* Fournit les particularités de l'opérande. */ +ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); + + + + +#if 0 + + +#include + + +#include "../common/packed.h" +#include "../format/format.h" +#include "../glibext/bufferline.h" + + + +/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ + + +/* Depuis "../analysis/binary.h" : description de fichier binaire */ +typedef struct _GLoadedBinary GLoadedBinary; + + + #define G_TYPE_ARCH_OPERAND g_arch_operand_get_type() #define G_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_OPERAND, GArchOperand)) #define G_IS_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_OPERAND)) @@ -95,18 +126,6 @@ char *g_arch_operand_build_tooltip(const GArchOperand *, const GLoadedBinary *); #endif -/* Ajoute une information complémentaire à un opérande. */ -bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag); - -/* Retire une information complémentaire à un opérande. */ -bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag); - -/* Détermine si un opérande possède un fanion particulier. */ -bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag); - -/* Fournit les particularités de l'opérande. */ -ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); - /* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ @@ -116,5 +135,8 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); typedef struct _GAsmStorage GAsmStorage; +#endif + + #endif /* _ARCH_OPERAND_H */ diff --git a/src/arch/operands/Makefile.am b/src/arch/operands/Makefile.am index f2a8767..9dc3b2f 100644 --- a/src/arch/operands/Makefile.am +++ b/src/arch/operands/Makefile.am @@ -1,26 +1,36 @@ -noinst_LTLIBRARIES = libarchoperands.la +noinst_LTLIBRARIES = libarchoperands.la libarchoperandsui.la + +# libarchoperands_la_SOURCES = \ +# feeder-int.h \ +# feeder.h feeder.c \ +# proxy-int.h \ +# proxy.h proxy.c \ +# rename-int.h \ +# rename.h rename.c \ +# target-int.h \ +# target.h target.c \ +# targetable-int.h \ +# targetable.h targetable.c libarchoperands_la_SOURCES = \ - feeder-int.h \ - feeder.h feeder.c \ immediate-int.h \ immediate.h immediate.c \ + known-int.h \ known.h known.c \ register-int.h \ - register.h register.c \ - proxy-int.h \ - proxy.h proxy.c \ - rename-int.h \ - rename.h rename.c \ - target-int.h \ - target.h target.c \ - targetable-int.h \ - targetable.h targetable.c + register.h register.c + +libarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) + +libarchoperandsui_la_SOURCES = \ + immediate-ui.h immediate-ui.c \ + known-ui.h known-ui.c \ + register-ui.h register-ui.c -libarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarchoperandsui_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBGTK4_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) -dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) +dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) $(libarchoperandsui_la_SOURCES:%c=) diff --git a/src/arch/operands/immediate-int.h b/src/arch/operands/immediate-int.h index d2313f5..3d60c7d 100644 --- a/src/arch/operands/immediate-int.h +++ b/src/arch/operands/immediate-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate-int.h - définitions internes propres aux opérandes représentant des valeurs numériques * - * Copyright (C) 2021 Cyrille Bagard + * Copyright (C) 2021-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -30,27 +30,8 @@ -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _immop_extra_data_t -{ - operand_extra_data_t parent; /* A laisser en premier */ - - MemoryDataSize size; /* Taille de l'opérande */ - - /** - * Les deux éléments suivants sont de type ImmOperandDisplay ; - * leur espace de conservation est réduit au maximum afin d'éviter - * un recouvrement . - */ - - unsigned int def_display : 3; /* Type par défaut d'affichage */ - unsigned int display : 3; /* Format général d'affichage */ - -} immop_extra_data_t; - - /* Définition d'un opérande de valeur numérique (instance) */ -struct _GImmOperand +struct _GImmediateOperand { GArchOperand parent; /* Instance parente */ @@ -59,7 +40,7 @@ struct _GImmOperand }; /* Définition d'un opérande de valeur numérique (classe) */ -struct _GImmOperandClass +struct _GImmediateOperandClass { GArchOperandClass parent; /* Classe parente */ @@ -70,15 +51,46 @@ struct _GImmOperandClass * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _immop_extra_data_t +{ + ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/ -# define GET_IMM_OP_EXTRA(op) ((immop_extra_data_t *)&((GArchOperand *)op)->extra) + /** + * MemoryDataSize + */ + unsigned int size : 4; /* Taille de l'opérande */ + + /** + * ImmOperandDisplay x 2 + */ + unsigned int def_display : 3; /* Type par défaut d'affichage */ + unsigned int display : 3; /* Format général d'affichage */ + +} immop_extra_data_t; + + +#define GET_IMM_OP_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, immop_extra_data_t) + +#define SET_IMM_OP_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, immop_extra_data_t, data) -#else -# define GET_IMM_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), immop_extra_data_t) +/* Met en place un opérande réprésentant une valeur numérique. */ +bool g_immediate_operand_create_from_value(GImmediateOperand *, MemoryDataSize, uint64_t); + +/* Crée un opérande réprésentant une valeur numérique. */ +bool g_immediate_operand_create_from_data(GImmediateOperand *, MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); + +/** + * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE, + * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire. + */ +#define IMM_MAX_SIZE 66 -#endif +/* Construit la chaîne de caractères correspondant à l'opérande. */ +size_t _g_immediate_operand_to_string(const GImmediateOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]); diff --git a/src/arch/operands/immediate-ui.c b/src/arch/operands/immediate-ui.c new file mode 100644 index 0000000..a6b4ae7 --- /dev/null +++ b/src/arch/operands/immediate-ui.c @@ -0,0 +1,184 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * immediate-ui.c - opérandes représentant des valeurs numériques sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#include "immediate-ui.h" + + +#include + + +#include "immediate-int.h" +#include "../../common/extstr.h" +#include "../../glibext/tokenstyle.h" +#include "../../glibext/options/disass.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_immediate_operand_ui_print(const GImmediateOperand *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +static char *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *, const GLoadedBinary *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = (print_operand_ui_fc)g_immediate_operand_ui_print; + iface->build_tooltip = (build_operand_ui_tooltip_fc)g_immediate_operand_ui_build_tooltip; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_immediate_operand_ui_print(const GImmediateOperand *operand, GBufferLine *line) +{ + GImmediateOperand *base; /* Version d'instance basique */ + ImmOperandDisplay display; /* Type d'affichage courant */ + char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ + size_t len; /* Taille de l'élément inséré */ + + base = G_IMMEDIATE_OPERAND(operand); + + display = g_immediate_operand_get_display(base); + + len = _g_immediate_operand_to_string(base, display, value); + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, value, len, NULL, G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* 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 *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + GImmediateOperand *base; /* Version d'instance basique */ + char value[IMM_MAX_SIZE]; /* Conversion artificielle */ + char *conv; /* Affichage de la Conversion */ + + base = G_IMMEDIATE_OPERAND(operand); + + if (base->raw <= UCHAR_MAX && isprint(base->raw)) + switch (base->raw) + { + case '&': + asprintf(&result, _("Character: '&'")); + break; + case '<': + asprintf(&result, _("Character: '<'")); + break; + case '>': + asprintf(&result, _("Character: '>'")); + break; + default: + asprintf(&result, _("Character: '%c'"), (char)base->raw); + break; + } + + else + asprintf(&result, _("Character: <not printable>")); + + /* Binaire */ + + _g_immediate_operand_to_string(base, IOD_BIN, value); + + asprintf(&conv, _("Binary: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Octal */ + + _g_immediate_operand_to_string(base, IOD_OCT, value); + + asprintf(&conv, _("Octal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Décimal */ + + _g_immediate_operand_to_string(base, IOD_DEC, value); + + asprintf(&conv, _("Decimal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Hexadécimal */ + + _g_immediate_operand_to_string(base, IOD_HEX, value); + + asprintf(&conv, _("Hexadecimal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + return result; + +} diff --git a/src/arch/operands/immediate-ui.h b/src/arch/operands/immediate-ui.h new file mode 100644 index 0000000..4dbddae --- /dev/null +++ b/src/arch/operands/immediate-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * immediate-ui.h - prototypes pour les opérandes représentant des valeurs numériques sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERANDS_IMMEDIATE_UI_H +#define _ARCH_OPERANDS_IMMEDIATE_UI_H + + +#include "../operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_IMMEDIATE_UI_H */ diff --git a/src/arch/operands/immediate.c b/src/arch/operands/immediate.c index f40c645..7ec5ebd 100644 --- a/src/arch/operands/immediate.c +++ b/src/arch/operands/immediate.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.c - opérandes représentant des valeurs numériques * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,25 +25,32 @@ #include +#include + + + +#if 0 + #include #include #include #include -#include #include #include +#endif + + #include "immediate-int.h" -#include "known.h" -#include "rename-int.h" -#include "targetable-int.h" #include "../../common/asm.h" -#include "../../common/extstr.h" #include "../../common/sort.h" -#include "../../core/columns.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" @@ -51,68 +58,75 @@ /* Initialise la classe des opérandes de valeur immédiate. */ -static void g_imm_operand_class_init(GImmOperandClass *); +static void g_immediate_operand_class_init(GImmediateOperandClass *); -/* Initialise un opérande de valeur immédiate. */ -static void g_imm_operand_init(GImmOperand *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_immediate_operand_serializable_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *, gpointer); + +#if 0 /* Procède à l'initialisation de l'interface de ciblage. */ -static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *); +static void g_immediate_operand_targetable_interface_init(GTargetableOperandInterface *); /* Procède à l'initialisation de l'interface de renommage. */ -static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *); +static void g_immediate_operand_renameable_interface_init(GRenameableOperandInterface *); + +#endif + +/* Initialise un opérande de valeur immédiate. */ +static void g_immediate_operand_init(GImmediateOperand *); /* Supprime toutes les références externes. */ -static void g_imm_operand_dispose(GImmOperand *); +static void g_immediate_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_imm_operand_finalize(GImmOperand *); +static void g_immediate_operand_finalize(GObject *); -/* Construit la chaîne de caractères correspondant à l'opérande. */ -static size_t _g_imm_operand_to_string(const GImmOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]); -/* Traduit un opérande en version humainement lisible. */ -static void g_imm_operand_print(const GImmOperand *, GBufferLine *); +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Réalise une comparaison étendue entre objets. */ +static int g_immediate_operand_compare(const GComparableObject *, const GComparableObject *); -/* Compare un opérande avec un autre. */ -static int g_imm_operand_compare(const GImmOperand *, const GImmOperand *, bool); -#ifdef INCLUDE_GTK_SUPPORT +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Construit un petit résumé concis de l'opérande. */ -static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinary *); -#endif +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_immediate_operand_hash(const GHashableObject *); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_imm_operand_hash(const GImmOperand *, bool); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_imm_operand_load(GImmOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_imm_operand_store(GImmOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_immediate_operand_load(GSerializableObject *, GObjectStorage *, int); -/* ---------------------- COMMUNICATION D'UN CIBLAGE POTENTIEL ---------------------- */ +/* Sauvegarde un objet dans un flux de données. */ +static bool g_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int); -/* Obtient l'adresse de la cible visée par un opérande. */ -static bool g_imm_operand_get_addr(const GImmOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *); +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ -/* ---------------------- CONSTRUCTION D'UN CONTENU ALTERNATIF ---------------------- */ +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); -/* Construit un opérande de représentation alternative. */ -static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *); @@ -122,9 +136,12 @@ static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *); /* Indique le type défini pour un opérande de valeur numérique. */ -G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND, - G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_imm_operand_targetable_interface_init) - G_IMPLEMENT_INTERFACE(G_TYPE_RENAMEABLE_OPERAND, g_imm_operand_renameable_interface_init)); +G_DEFINE_TYPE_WITH_CODE(GImmediateOperand, g_immediate_operand, G_TYPE_ARCH_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_immediate_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_immediate_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_immediate_operand_serializable_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_immediate_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_immediate_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -139,36 +156,42 @@ G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND, * * ******************************************************************************/ -static void g_imm_operand_class_init(GImmOperandClass *klass) +static void g_immediate_operand_class_init(GImmediateOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_imm_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_imm_operand_finalize; + object->dispose = g_immediate_operand_dispose; + object->finalize = g_immediate_operand_finalize; + +} - operand->compare = (operand_compare_fc)g_imm_operand_compare; - operand->print = (operand_print_fc)g_imm_operand_print; -#ifdef INCLUDE_GTK_SUPPORT - operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip; -#endif - operand->hash = (operand_hash_fc)g_imm_operand_hash; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - operand->load = (load_operand_fc)g_imm_operand_load; - operand->store = (store_operand_fc)g_imm_operand_store; +static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_immediate_operand_compare; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise un opérande de valeur immédiate. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -176,23 +199,39 @@ static void g_imm_operand_class_init(GImmOperandClass *klass) * * ******************************************************************************/ -static void g_imm_operand_init(GImmOperand *operand) +static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - GET_IMM_OP_EXTRA(operand)->size = MDS_UNDEFINED; + iface->hash = g_immediate_operand_hash; - GET_IMM_OP_EXTRA(operand)->def_display = IOD_HEX; - GET_IMM_OP_EXTRA(operand)->display = IOD_COUNT; +} - operand->raw = 0; + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_immediate_operand_serializable_iface_init(GSerializableObjectInterface *iface) +{ + iface->load = g_immediate_operand_load; + iface->store = g_immediate_operand_store; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * +* unused = pointeur non utilisé ici. * * * -* Description : Procède à l'initialisation de l'interface de ciblage. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -200,18 +239,18 @@ static void g_imm_operand_init(GImmOperand *operand) * * ******************************************************************************/ -static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *iface) +static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface, gpointer unused) { - iface->get_addr = (get_targetable_addr_fc)g_imm_operand_get_addr; + iface->to_string = g_immediate_operand_to_string; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : operand = instance à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de renommage. * +* Description : Initialise un opérande de valeur immédiate. * * * * Retour : - * * * @@ -219,16 +258,27 @@ static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface * * ******************************************************************************/ -static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *iface) +static void g_immediate_operand_init(GImmediateOperand *operand) { - iface->build = (build_renameable_fc)g_imm_operand_build; + immop_extra_data_t extra; /* Données insérées à consulter*/ + + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = MDS_UNDEFINED; + + extra.def_display = IOD_HEX; + extra.display = IOD_COUNT; + + SET_IMM_OP_EXTRA(operand, &extra); + + operand->raw = 0; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -238,16 +288,16 @@ static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface * * ******************************************************************************/ -static void g_imm_operand_dispose(GImmOperand *operand) +static void g_immediate_operand_dispose(GObject *object) { - G_OBJECT_CLASS(g_imm_operand_parent_class)->dispose(G_OBJECT(operand)); + G_OBJECT_CLASS(g_immediate_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -257,9 +307,74 @@ static void g_imm_operand_dispose(GImmOperand *operand) * * ******************************************************************************/ -static void g_imm_operand_finalize(GImmOperand *operand) +static void g_immediate_operand_finalize(GObject *object) +{ + G_OBJECT_CLASS(g_immediate_operand_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Crée un opérande réprésentant une valeur numérique. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize size, uint64_t value) +{ + GImmediateOperand *result; /* Opérande à retourner */ + + result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL); + + if (!g_immediate_operand_create_from_value(result, size, value)) + g_clear_object(&result); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Met en place un opérande réprésentant une valeur numérique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_immediate_operand_create_from_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value) { - G_OBJECT_CLASS(g_imm_operand_parent_class)->finalize(G_OBJECT(operand)); + bool result; /* Bilan à retourner */ + immop_extra_data_t extra; /* Données insérées à consulter*/ + + result = (size != MDS_UNDEFINED); + + if (result) + { + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = size; + + operand->raw = value; + + SET_IMM_OP_EXTRA(operand, &extra); + + } + + return result; } @@ -280,10 +395,41 @@ static void g_imm_operand_finalize(GImmOperand *operand) * * ******************************************************************************/ -GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) +GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) +{ + GImmediateOperand *result; /* Opérande à retourner */ + + result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL); + + if (!g_immediate_operand_create_from_data(result, size, content, addr, low, endian)) + g_clear_object(&result); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* size = taille de l'opérande souhaitée. * +* content = flux de données à analyser. * +* addr = position courante dans ce flux. [OUT] * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = ordre des bits dans la source. * +* * +* Description : Crée un opérande réprésentant une valeur numérique. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_immediate_operand_create_from_data(GImmediateOperand *operand, MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) { - GImmOperand *result; /* Opérande à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ + bool result; /* Bilan à retourner */ + uint64_t raw; /* Valeur brute lue */ uint8_t uval8; /* Valeur sur 8 bits */ uint16_t uval16; /* Valeur sur 16 bits */ uint32_t uval32; /* Valeur sur 32 bits */ @@ -293,125 +439,78 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten int32_t sval32; /* Valeur sur 32 bits */ int64_t sval64; /* Valeur sur 64 bits */ - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); - - extra = GET_IMM_OP_EXTRA(result); - - extra->size = size; - switch (size) { case MDS_4_BITS_UNSIGNED: - if (!g_binary_content_read_u4(content, addr, low, &uval8)) - goto gionfd_error; - result->raw = uval8; + result = g_binary_content_read_u4(content, addr, low, &uval8); + if (result) + raw = uval8; break; case MDS_8_BITS_UNSIGNED: - if (!g_binary_content_read_u8(content, addr, &uval8)) - goto gionfd_error; - result->raw = uval8; + result = g_binary_content_read_u8(content, addr, &uval8); + if (result) + raw = uval8; break; case MDS_16_BITS_UNSIGNED: - if (!g_binary_content_read_u16(content, addr, endian, &uval16)) - goto gionfd_error; - result->raw = uval16; + result = g_binary_content_read_u16(content, addr, endian, &uval16); + if (result) + raw = uval16; break; case MDS_32_BITS_UNSIGNED: - if (!g_binary_content_read_u32(content, addr, endian, &uval32)) - goto gionfd_error; - result->raw = uval32; + result = g_binary_content_read_u32(content, addr, endian, &uval32); + if (result) + raw = uval32; break; case MDS_64_BITS_UNSIGNED: - if (!g_binary_content_read_u64(content, addr, endian, &uval64)) - goto gionfd_error; - result->raw = uval64; + result = g_binary_content_read_u64(content, addr, endian, &uval64); + if (result) + raw = uval64; break; case MDS_4_BITS_SIGNED: - if (!g_binary_content_read_s4(content, addr, low, &sval8)) - goto gionfd_error; - result->raw = sval8; + result = g_binary_content_read_s4(content, addr, low, &sval8); + if (result) + raw = sval8; break; case MDS_8_BITS_SIGNED: - if (!g_binary_content_read_s8(content, addr, &sval8)) - goto gionfd_error; - result->raw = sval8; + result = g_binary_content_read_s8(content, addr, &sval8); + if (result) + raw = sval8; break; case MDS_16_BITS_SIGNED: - if (!g_binary_content_read_s16(content, addr, endian, &sval16)) - goto gionfd_error; - result->raw = sval16; + result = g_binary_content_read_s16(content, addr, endian, &sval16); + if (result) + raw = sval16; break; case MDS_32_BITS_SIGNED: - if (!g_binary_content_read_s32(content, addr, endian, &sval32)) - goto gionfd_error; - result->raw = sval32; + result = g_binary_content_read_s32(content, addr, endian, &sval32); + if (result) + raw = sval32; break; case MDS_64_BITS_SIGNED: - if (!g_binary_content_read_s64(content, addr, endian, &sval64)) - goto gionfd_error; - result->raw = sval64; + result = g_binary_content_read_s64(content, addr, endian, &sval64); + if (result) + raw = sval64; break; case MDS_UNDEFINED: - goto gionfd_error; + result = false; break; } - return G_ARCH_OPERAND(result); - - gionfd_error: - - g_object_unref(G_OBJECT(result)); - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : size = taille de l'opérande souhaitée. * -* value = valeur sur x bits à venir récupérer. * -* * -* Description : Crée un opérande réprésentant une valeur numérique. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value) -{ - GImmOperand *result; /* Opérande à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - - if (size == MDS_UNDEFINED) - result = NULL; - - else - { - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); - - extra = GET_IMM_OP_EXTRA(result); - - extra->size = size; - - result->raw = value; - - } + if (result) + result = g_immediate_operand_create_from_value(operand, size, raw); - return (result != NULL ? G_ARCH_OPERAND(result) : NULL); + return result; } @@ -428,18 +527,14 @@ GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value) * * ******************************************************************************/ -MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand) +MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *operand) { MemoryDataSize result; /* Taille à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->size; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.size; return result; @@ -460,10 +555,10 @@ MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand) * * ******************************************************************************/ -bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ...) +bool g_immediate_operand_get_value(const GImmediateOperand *operand, MemoryDataSize size, ...) { bool result; /* Bilan à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ va_list ap; /* Liste des compléments */ uint8_t *uval8; /* Valeur sur 8 bits */ uint16_t *uval16; /* Valeur sur 16 bits */ @@ -478,9 +573,7 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - if (extra->size != size) + if (extra.size != size) goto exit; va_start(ap, size); @@ -533,8 +626,6 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. exit: - UNLOCK_GOBJECT_EXTRA(extra); - return result; } @@ -542,6 +633,37 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. /****************************************************************************** * * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] * +* size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Définit la nouvelle valeur de l'opérande à une valeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_immediate_operand_set_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value) +{ + immop_extra_data_t extra; /* Données insérées à consulter*/ + + assert(size != MDS_UNDEFINED); + + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = size; + + operand->raw = value; + + SET_IMM_OP_EXTRA(operand, &extra); + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande à consulter. * * * * Description : Fournit la valeur brute représentée par l'opérande. * @@ -552,42 +674,55 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. * * ******************************************************************************/ -uint64_t g_imm_operand_get_raw_value(const GImmOperand *operand) +uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *operand) { - return operand->raw; + uint64_t result; /* Valeur brute à retourner */ + + result = operand->raw; + + return result; } /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] * -* size = taille de l'opérande souhaitée. * -* value = valeur sur x bits à venir récupérer. * +* Paramètres : operand = structure dont le contenu est à consulter. * * * -* Description : Définit la nouvelle valeur de l'opérande à une valeur. * +* Description : Indique le signe d'une valeur immédiate. * * * -* Retour : - * +* Retour : true si la valeur est strictement négative, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t value) +bool g_immediate_operand_is_negative(const GImmediateOperand *operand) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - assert(size != MDS_UNDEFINED); + bool result; /* Bilan à renvoyer */ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - extra->size = size; - - operand->raw = value; + switch (extra.size) + { + case MDS_4_BITS_SIGNED: + case MDS_8_BITS_SIGNED: + case MDS_16_BITS_SIGNED: + case MDS_32_BITS_SIGNED: + case MDS_64_BITS_SIGNED: + /** + * Pour les valeurs plus petites que 64 bits, le compilateur + * réalise une extension de signe lors du transtypage. + */ + result = (operand->raw & 0x8000000000000000ll); + break; + default: + result = false; + break; + } - UNLOCK_GOBJECT_EXTRA(extra); + return result; } @@ -605,17 +740,15 @@ void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t * * ******************************************************************************/ -void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay display) +void g_immediate_operand_set_default_display(GImmediateOperand *operand, ImmOperandDisplay display) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); + extra.def_display = display; - extra->def_display = display; - - UNLOCK_GOBJECT_EXTRA(extra); + SET_IMM_OP_EXTRA(operand, &extra); } @@ -632,18 +765,14 @@ void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay d * * ******************************************************************************/ -ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) +ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *operand) { ImmOperandDisplay result; /* Affichage à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->def_display; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.def_display; return result; @@ -663,17 +792,15 @@ ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) * * ******************************************************************************/ -void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display) +void g_immediate_operand_set_display(GImmediateOperand *operand, ImmOperandDisplay display) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - extra->display = display; + extra.display = display; - UNLOCK_GOBJECT_EXTRA(extra); + SET_IMM_OP_EXTRA(operand, &extra); } @@ -690,94 +817,225 @@ void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display) * * ******************************************************************************/ -ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *operand) +ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *operand) { ImmOperandDisplay result; /* Affichage à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - if (extra->display != IOD_COUNT) - result = extra->display; + if (extra.display != IOD_COUNT) + result = extra.display; else - result = extra->def_display; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.def_display; return result; } + +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à consulter. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Indique le signe d'une valeur immédiate. * +* Description : Réalise une comparaison étendue entre objets. * * * -* Retour : true si la valeur est strictement négative, false sinon. * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -bool g_imm_operand_is_negative(const GImmOperand *operand) +static int g_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other) { - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + int result; /* Bilan à retourner */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand_a; /* Version spécialisée #0 */ + GImmediateOperand *operand_b; /* Version spécialisée #1 */ + immop_extra_data_t extra_a; /* Données insérées à consulter*/ + immop_extra_data_t extra_b; /* Données insérées à consulter*/ - extra = GET_IMM_OP_EXTRA(operand); + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); - LOCK_GOBJECT_EXTRA(extra); + result = parent_iface->compare(object, other); - switch (extra->size) + if (result == 0) { - case MDS_4_BITS_SIGNED: - case MDS_8_BITS_SIGNED: - case MDS_16_BITS_SIGNED: - case MDS_32_BITS_SIGNED: - case MDS_64_BITS_SIGNED: - /** - * Pour les valeurs plus petites que 64 bits, le compilateur - * réalise une extension de signe lors du transtypage. - */ - result = (operand->raw & 0x8000000000000000ll); - break; - default: - result = false; - break; + operand_a = G_IMMEDIATE_OPERAND(object); + + extra_a = GET_IMM_OP_EXTRA(operand_a); + + operand_b = G_IMMEDIATE_OPERAND(other); + + extra_b = GET_IMM_OP_EXTRA(operand_b); + + result = sort_unsigned_long(extra_a.size, extra_b.size); + + if (result == 0) + sort_uint64_t(operand_a->raw, operand_b->raw); + + if (result == 0) + result = sort_unsigned_long(extra_a.def_display, extra_b.def_display); + + if (result == 0) + result = sort_unsigned_long(extra_a.display, extra_b.display); + } - UNLOCK_GOBJECT_EXTRA(extra); + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : object = objet dont l'instance est à consulter. * +* * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * +* * +* Retour : Valeur de représentation, unique pour l'objet ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_immediate_operand_hash(const GHashableObject *object) +{ + guint result; /* Valeur à retourner */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_HASHABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->hash(object); + + operand = G_IMMEDIATE_OPERAND(object); + + result ^= (operand->raw & 0xffffffff); + result ^= (operand->raw >> 32); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à consulter. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Indique si une valeur immédiate est nulle ou non. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : true si la valeur est nulle, false sinon. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -bool g_imm_operand_is_null(const GImmOperand *operand) +static bool g_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - return (operand->raw == 0ll); + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + uleb128_t val; /* Valeur sauvegardée */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->load(object, storage, fd); + + if (result) + { + result = load_uleb128(&val, fd); + + if (result) + { + operand = G_IMMEDIATE_OPERAND(object); + operand->raw = val; + } + + } + + return result; } /****************************************************************************** * * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * +* * +* Description : Sauvegarde un objet dans un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) +{ + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; + + operand = G_IMMEDIATE_OPERAND(object); + + result = store_uleb128((uleb128_t []) { operand->raw }, fd); + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * * Paramètres : operand = opérande à transcrire. * * display = type d'affichage demandé. * * value = valeur portée par l'opérande transcrite. [OUT] * @@ -790,10 +1048,10 @@ bool g_imm_operand_is_null(const GImmOperand *operand) * * ******************************************************************************/ -static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE]) +size_t _g_immediate_operand_to_string(const GImmediateOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE]) { size_t result; /* Longueur à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ unsigned int range; /* Catégorie de la taille */ const char *prefix; /* Entrée en matière */ const char *suffix; /* Sortie de matière */ @@ -813,13 +1071,11 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis static const char *conv_si_defs[] = { "", "o", "d", "x", "c" }; static const char *conv_us_defs[] = { "", "o", "u", "x", "c" }; - assert(display <= IOD_LAST_VALID); + assert(display < IOD_COUNT); extra = GET_IMM_OP_EXTRA(operand); - //LOCK_GOBJECT_EXTRA(extra); - - range = MDS_RANGE(extra->size); + range = MDS_RANGE(extra.size); /* Encadrement pour les caractères */ if (display == IOD_CHAR) @@ -862,10 +1118,10 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis if (do_padding) { - if (extra->display != IOD_COUNT) - do_padding = (extra->display != IOD_BIN && extra->display != IOD_HEX); + if (extra.display != IOD_COUNT) + do_padding = (extra.display == IOD_BIN || extra.display == IOD_HEX); else - do_padding = (extra->def_display != IOD_BIN && extra->def_display != IOD_HEX); + do_padding = (extra.def_display == IOD_BIN || extra.def_display == IOD_HEX); } switch (display) @@ -892,7 +1148,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis if (display != IOD_BIN) { - if (MDS_IS_SIGNED(extra->size)) + if (MDS_IS_SIGNED(extra.size)) conv = conv_si_defs[display]; else conv = conv_us_defs[display]; @@ -929,7 +1185,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis snprintf(format, sizeof(format), "%s%s%s%s%s%s%s", prefix, alternate, intro, zpad, lmod, conv, suffix); - switch (extra->size) + switch (extra.size) { case MDS_UNDEFINED: result = snprintf(value, IMM_MAX_SIZE, ""); @@ -982,8 +1238,6 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis } - //UNLOCK_GOBJECT_EXTRA(extra); - assert(result > 0); return result; @@ -993,555 +1247,37 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis /****************************************************************************** * * -* Paramètres : operand = opérande à transcrire. * -* syntax = type de représentation demandée. * -* value = valeur portée par l'opérande transcrite. [OUT] * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Construit la chaîne de caractères correspondant à l'opérande.* +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * -* Retour : Nombre de caractères utilisés. * +* Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -size_t g_imm_operand_to_string(const GImmOperand *operand, char value[IMM_MAX_SIZE]) +static bool g_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { - size_t result; /* Longueur à retourner */ + bool result; /* Bilan à retourner */ + const GImmediateOperand *operand; /* Version spécialisée */ ImmOperandDisplay display; /* Type d'affichage courant */ - - display = g_imm_operand_get_display(operand); - - result = _g_imm_operand_to_string(operand, display, value); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line) -{ char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ size_t len; /* Taille de l'élément inséré */ - len = g_imm_operand_to_string(operand, value); - - g_buffer_line_append_text(line, DLC_ASSEMBLY, value, len, RTT_IMMEDIATE, G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* pos = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en position de type phys_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_imm_operand_to_phys_t(const GImmOperand *operand, phys_t *pos) -{ - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = !MDS_IS_SIGNED(extra->size); - - if (result) - *pos = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* addr = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en adresse de type virt_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_imm_operand_to_virt_t(const GImmOperand *operand, virt_t *addr) -{ - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + operand = G_IMMEDIATE_OPERAND(builder); - extra = GET_IMM_OP_EXTRA(operand); + display = g_immediate_operand_get_display(operand); - LOCK_GOBJECT_EXTRA(extra); + len = _g_immediate_operand_to_string(operand, display, value); - result = !MDS_IS_SIGNED(extra->size); + result = (len > 0); if (result) - *addr = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* val = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en valeur de type leb128_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_imm_operand_as_leb128(const GImmOperand *operand, leb128_t *val) -{ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - *val = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* val = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en valeur de type uleb128_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_imm_operand_as_uleb128(const GImmOperand *operand, uleb128_t *val) -{ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - *val = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_imm_operand_compare(const GImmOperand *a, const GImmOperand *b, bool lock) -{ - int result; /* Bilan à retourner */ - immop_extra_data_t *ea; /* Données insérées à modifier */ - immop_extra_data_t *eb; /* Données insérées à modifier */ - GArchOperandClass *class; /* Classe parente normalisée */ - - ea = GET_IMM_OP_EXTRA(a); - eb = GET_IMM_OP_EXTRA(b); - - if (lock) - { - LOCK_GOBJECT_EXTRA(ea); - LOCK_GOBJECT_EXTRA(eb); - } - - result = sort_unsigned_long(ea->size, eb->size); - - if (result == 0) - sort_uint64_t(a->raw, b->raw); - - if (result == 0) - result = sort_unsigned_long(ea->def_display, eb->def_display); - - if (result == 0) - result = sort_unsigned_long(ea->display, eb->display); - - if (result == 0) - { - class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); - } - - if (lock) - { - UNLOCK_GOBJECT_EXTRA(eb); - UNLOCK_GOBJECT_EXTRA(ea); - } - - return result; - -} - - -#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 *g_imm_operand_build_tooltip(const GImmOperand *operand, const GLoadedBinary *binary) -{ - char *result; /* Description à retourner */ - char value[IMM_MAX_SIZE]; /* Conversion artificielle */ - char *conv; /* Affichage de la Conversion */ - - if (operand->raw <= UCHAR_MAX && isprint(operand->raw)) - switch (operand->raw) - { - case '&': - asprintf(&result, _("Character: '&'")); - break; - case '<': - asprintf(&result, _("Character: '<'")); - break; - case '>': - asprintf(&result, _("Character: '>'")); - break; - default: - asprintf(&result, _("Character: '%c'"), (char)operand->raw); - break; - } - - else - asprintf(&result, _("Character: <not printable>")); - - /* Binaire */ - - _g_imm_operand_to_string(operand, IOD_BIN, value); - - asprintf(&conv, _("Binary: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Octal */ - - _g_imm_operand_to_string(operand, IOD_OCT, value); - - asprintf(&conv, _("Octal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Décimal */ - - _g_imm_operand_to_string(operand, IOD_DEC, value); - - asprintf(&conv, _("Decimal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Hexadécimal */ - - _g_imm_operand_to_string(operand, IOD_HEX, value); - - asprintf(&conv, _("Hexadecimal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - return result; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static guint g_imm_operand_hash(const GImmOperand *operand, bool lock) -{ - guint result; /* Valeur à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - GArchOperandClass *class; /* Classe parente normalisée */ - - extra = GET_IMM_OP_EXTRA(operand); - - if (lock) - LOCK_GOBJECT_EXTRA(extra); - - class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); - - result ^= (operand->raw & 0xffffffff); - result ^= (operand->raw >> 32); - - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un contenu depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_imm_operand_load(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - uleb128_t value; /* Valeur ULEB128 à charger */ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = unpack_uleb128(&value, pbuf); - - if (result) - extra->size = value; - - if (result) - { - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - - if (result) - extra->def_display = val; - - } - - if (result) - { - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - - if (result) - extra->display = val; - - } - - UNLOCK_GOBJECT_EXTRA(extra); - - } - - if (result) - result = extract_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un contenu dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_imm_operand_store(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - - parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = pack_uleb128((uleb128_t []){ extra->size }, pbuf); - - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { extra->def_display }, sizeof(uint8_t), false); - - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { extra->display }, sizeof(uint8_t), false); - - UNLOCK_GOBJECT_EXTRA(extra); - - } - - if (result) - result = extend_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* COMMUNICATION D'UN CIBLAGE POTENTIEL */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = operande à consulter. * -* src = localisation de l'instruction mère. * -* format = format reconnu pour le binaire chargé. * -* proc = architecture associée à ce même binaire. * -* addr = localisation de la cible. [OUT] * -* * -* Description : Obtient l'adresse de la cible visée par un opérande. * -* * -* Retour : true si la cible est valide, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_imm_operand_get_addr(const GImmOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - virt_t virt; /* Adresse virtuelle */ - - result = g_imm_operand_to_virt_t(operand, &virt); - - if (result) - result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, addr); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSTRUCTION D'UN CONTENU ALTERNATIF */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = operande à consulter. * -* text = texte alternatif de représentation. * -* * -* Description : Construit un opérande de représentation alternative. * -* * -* Retour : Nouvel opérande, en version renommée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GRenamedOperand *g_imm_operand_build(const GImmOperand *operand, const char *text) -{ - GRenamedOperand *result; /* Instance à retourner */ - - result = G_RENAMED_OPERAND(g_known_imm_operand_new(operand, text)); + add_to_sized_binary(out, value, len); return result; diff --git a/src/arch/operands/immediate.h b/src/arch/operands/immediate.h index 7c1ff03..d66349a 100644 --- a/src/arch/operands/immediate.h +++ b/src/arch/operands/immediate.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.h - prototypes pour les opérandes représentant des valeurs numériques * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,17 +25,22 @@ #define _ARCH_OPERANDS_IMMEDIATE_H -#include #include #include -#include "../archbase.h" #include "../operand.h" #include "../../analysis/content.h" +#include "../../common/datatypes.h" +#include "../../glibext/helpers.h" +#define G_TYPE_IMMEDIATE_OPERAND (g_immediate_operand_get_type()) + +DECLARE_GTYPE(GImmediateOperand, g_immediate_operand, G, IMMEDIATE_OPERAND); + + /* Etats particuliers d'un opérande de valeur immédiate */ typedef enum _ImmOpFlag { @@ -57,86 +62,39 @@ typedef enum _ImmOperandDisplay } ImmOperandDisplay; -#define IOD_LAST_VALID IOD_CHAR - - -#define G_TYPE_IMM_OPERAND g_imm_operand_get_type() -#define G_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_IMM_OPERAND, GImmOperand)) -#define G_IS_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_IMM_OPERAND)) -#define G_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_IMM_OPERAND, GImmOperandClass)) -#define G_IS_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_IMM_OPERAND)) -#define G_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_IMM_OPERAND, GImmOperandClass)) - - -/* Définition d'un opérande de valeur numérique (instance) */ -typedef struct _GImmOperand GImmOperand; - -/* Définition d'un opérande de valeur numérique (classe) */ -typedef struct _GImmOperandClass GImmOperandClass; - - -/* Indique le type défini pour un opérande d'architecture. */ -GType g_imm_operand_get_type(void); /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); - -#define g_imm_operand_new_from_data(size, content, addr, endian) \ - _g_imm_operand_new_from_data(size, content, addr, NULL, endian) +GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize, uint64_t); /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *g_imm_operand_new_from_value(MemoryDataSize, uint64_t); +GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); /* Renseigne la taille de la valeur indiquée à la construction. */ -MemoryDataSize g_imm_operand_get_size(const GImmOperand *); +MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *); /* Fournit la valeur portée par une opérande numérique. */ -bool g_imm_operand_get_value(const GImmOperand *, MemoryDataSize, ...); +bool g_immediate_operand_get_value(const GImmediateOperand *, MemoryDataSize, ...); + +/* Définit la nouvelle valeur de l'opérande à une valeur. */ +void g_immediate_operand_set_value(GImmediateOperand *, MemoryDataSize, uint64_t); /* Fournit la valeur brute représentée par l'opérande. */ -uint64_t g_imm_operand_get_raw_value(const GImmOperand *); +uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *); -/* Définit la nouvelle valeur de l'opérande à une valeur. */ -void g_imm_operand_set_value(GImmOperand *, MemoryDataSize, uint64_t); +/* Indique le signe d'une valeur immédiate. */ +bool g_immediate_operand_is_negative(const GImmediateOperand *); /* Définit le format textuel par défaut de la valeur. */ -void g_imm_operand_set_default_display(GImmOperand *, ImmOperandDisplay); +void g_immediate_operand_set_default_display(GImmediateOperand *, ImmOperandDisplay); /* Indique le format textuel par défaut de la valeur. */ -ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *); +ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *); /* Définit la grande ligne du format textuel de la valeur. */ -void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay); +void g_immediate_operand_set_display(GImmediateOperand *, ImmOperandDisplay); /* Indique la grande ligne du format textuel de la valeur. */ -ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *); - -/* Indique le signe d'une valeur immédiate. */ -bool g_imm_operand_is_negative(const GImmOperand *); - -/* Indique si une valeur immédiate est nulle ou non. */ -bool g_imm_operand_is_null(const GImmOperand *); - -/** - * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE, - * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire. - */ -#define IMM_MAX_SIZE 66 - -/* Construit la chaîne de caractères correspondant à l'opérande. */ -size_t g_imm_operand_to_string(const GImmOperand *, char [IMM_MAX_SIZE]); - -/* Convertit une valeur immédiate en position de type phys_t. */ -bool g_imm_operand_to_phys_t(const GImmOperand *, phys_t *); - -/* Convertit une valeur immédiate en adresse de type virt_t. */ -bool g_imm_operand_to_virt_t(const GImmOperand *, virt_t *); - -/* Convertit une valeur immédiate en valeur de type leb128_t. */ -void g_imm_operand_as_leb128(const GImmOperand *, leb128_t *); - -/* Convertit une valeur immédiate en valeur de type uleb128_t. */ -void g_imm_operand_as_uleb128(const GImmOperand *, uleb128_t *); +ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *); diff --git a/src/arch/operands/known-int.h b/src/arch/operands/known-int.h new file mode 100644 index 0000000..021fbf2 --- /dev/null +++ b/src/arch/operands/known-int.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-int.h - définitions internes pour les opérandes représentant des valeurs numériques avec sémantique + * + * 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 Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERANDS_KNOWN_INT_H +#define _ARCH_OPERANDS_KNOWN_INT_H + + +#include "immediate-int.h" +#include "known.h" + + + +/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ +struct _GKnownImmediateOperand +{ + GImmediateOperand parent; /* Instance parente */ + + char *alt_text; /* Alternative humaine */ + +}; + +/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ +struct _GKnownImmediateOperandClass +{ + GImmediateOperandClass parent; /* Classe parente */ + +}; + + +/* Met en place un opérande remplaçant visuellement une valeur. */ +bool g_known_immediate_operand_create(GKnownImmediateOperand *, const GImmediateOperand *, const char *); + + + +#endif /* _ARCH_OPERANDS_KNOWN_INT_H */ diff --git a/src/arch/operands/known-ui.c b/src/arch/operands/known-ui.c new file mode 100644 index 0000000..b68e60c --- /dev/null +++ b/src/arch/operands/known-ui.c @@ -0,0 +1,79 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-ui.c - opérandes représentant des valeurs numériques avec sémantique sous forme graphique + * + * 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 Chrysalide. If not, see . + */ + + +#include "known-ui.h" + + +#include "known-int.h" +#include "../../common/cpp.h" +#include "../../glibext/options/disass.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_known_immediate_operand_ui_print(const GArchOperandUI *, GBufferLine *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = g_known_immediate_operand_ui_print; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_known_immediate_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GKnownImmediateOperand *known; /* Version de base */ + + known = G_KNOWN_IMMEDIATE_OPERAND(operand); + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, SL(known->alt_text), NULL, G_OBJECT(operand)); + +} diff --git a/src/arch/operands/known-ui.h b/src/arch/operands/known-ui.h new file mode 100644 index 0000000..fa2dc62 --- /dev/null +++ b/src/arch/operands/known-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-ui.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique sous forme graphique + * + * 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 Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERANDS_KNOWN_UI_H +#define _ARCH_OPERANDS_KNOWN_UI_H + + +#include "../operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_KNOWN_UI_H */ diff --git a/src/arch/operands/known.c b/src/arch/operands/known.c index 5402879..adb700d 100644 --- a/src/arch/operands/known.c +++ b/src/arch/operands/known.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.c - opérandes représentant des valeurs numériques avec sémantique * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -24,81 +24,80 @@ #include "known.h" -#include #include #include -#include "immediate-int.h" -#include "rename-int.h" -#include "../../analysis/db/misc/rlestr.h" -#include "../../core/columns.h" -#include "../../core/logs.h" +#include "known-int.h" +#include "../../common/cpp.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" /* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */ -/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ -struct _GKnownImmOperand -{ - GImmOperand parent; /* Instance parente */ +/* Initialise la classe des remplacements d'opérandes. */ +static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *); - char *alt_text; /* Alternative humaine */ +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *); -}; +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *); -/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ -struct _GKnownImmOperandClass -{ - GImmOperandClass parent; /* Classe parente */ +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_known_immediate_operand_serializable_iface_init(GSerializableObjectInterface *); -}; - - -/* Initialise la classe des remplacements d'opérandes. */ -static void g_known_imm_operand_class_init(GKnownImmOperandClass *); +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *); /* Initialise un remplacement d'opérande de valeur immédiate. */ -static void g_known_imm_operand_init(GKnownImmOperand *); - -/* Procède à l'initialisation de l'interface de renommage. */ -static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *); +static void g_known_immediate_operand_init(GKnownImmediateOperand *); /* Supprime toutes les références externes. */ -static void g_known_imm_operand_dispose(GKnownImmOperand *); +static void g_known_immediate_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_known_imm_operand_finalize(GKnownImmOperand *); +static void g_known_immediate_operand_finalize(GObject *); + + +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Réalise une comparaison étendue entre objets. */ +static int g_known_immediate_operand_compare(const GComparableObject *, const GComparableObject *); -/* Compare un opérande avec un autre. */ -static int g_known_imm_operand_compare(const GKnownImmOperand *, const GKnownImmOperand *, bool); -/* Traduit un opérande en version humainement lisible. */ -static void g_known_imm_operand_print(const GKnownImmOperand *, GBufferLine *); +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_known_imm_operand_hash(const GKnownImmOperand *, bool); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_known_imm_operand_load(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *); +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_known_immediate_operand_hash(const GHashableObject *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_known_imm_operand_store(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* ------------------------- AFFICHAGE D'UN CONTENU RENOMME ------------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_known_immediate_operand_load(GSerializableObject *, GObjectStorage *, int); -/* Fournit un texte comme représentation alternative d'opérande. */ -static const char *g_known_imm_operand_get_text(const GKnownImmOperand *); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_known_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int); + + + +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_known_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); @@ -108,8 +107,12 @@ static const char *g_known_imm_operand_get_text(const GKnownImmOperand *); /* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */ -G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAND, - G_IMPLEMENT_INTERFACE(G_TYPE_RENAMED_OPERAND, g_known_imm_operand_renamed_interface_init)); +G_DEFINE_TYPE_WITH_CODE(GKnownImmediateOperand, g_known_immediate_operand, G_TYPE_IMMEDIATE_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_known_immediate_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_known_immediate_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_immediate_operand_serializable_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_known_immediate_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_known_immediate_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -124,33 +127,42 @@ G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAN * * ******************************************************************************/ -static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass) +static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_known_imm_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_known_imm_operand_finalize; + object->dispose = g_known_immediate_operand_dispose; + object->finalize = g_known_immediate_operand_finalize; + +} - operand->compare = (operand_compare_fc)g_known_imm_operand_compare; - operand->print = (operand_print_fc)g_known_imm_operand_print; - operand->hash = (operand_hash_fc)g_known_imm_operand_hash; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - operand->load = (load_operand_fc)g_known_imm_operand_load; - operand->store = (store_operand_fc)g_known_imm_operand_store; +static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_known_immediate_operand_compare; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise un remplacement d'opérande de valeur immédiate. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -158,9 +170,9 @@ static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass) * * ******************************************************************************/ -static void g_known_imm_operand_init(GKnownImmOperand *operand) +static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - operand->alt_text = NULL; + iface->hash = g_known_immediate_operand_hash; } @@ -169,7 +181,7 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de renommage. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -177,18 +189,19 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand) * * ******************************************************************************/ -static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *iface) +static void g_known_immediate_operand_serializable_iface_init(GSerializableObjectInterface *iface) { - iface->get_text = (get_renamed_text_fc)g_known_imm_operand_get_text; + iface->load = g_known_immediate_operand_load; + iface->store = g_known_immediate_operand_store; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Supprime toutes les références externes. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -196,12 +209,28 @@ static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface * * ******************************************************************************/ -static void g_known_imm_operand_dispose(GKnownImmOperand *operand) +static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface) { - if (operand->alt_text != NULL) - free(operand->alt_text); + iface->to_string = g_known_immediate_operand_to_string; - G_OBJECT_CLASS(g_known_imm_operand_parent_class)->dispose(G_OBJECT(operand)); +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise un remplacement d'opérande de valeur immédiate. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_known_immediate_operand_init(GKnownImmediateOperand *operand) +{ + operand->alt_text = NULL; } @@ -210,7 +239,7 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand) * * * Paramètres : operand = instance d'objet GLib à traiter. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Supprime toutes les références externes. * * * * Retour : - * * * @@ -218,180 +247,199 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand) * * ******************************************************************************/ -static void g_known_imm_operand_finalize(GKnownImmOperand *operand) +static void g_known_immediate_operand_dispose(GObject *object) { - G_OBJECT_CLASS(g_known_imm_operand_parent_class)->finalize(G_OBJECT(operand)); + G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : old = opérande à venir copier avant son remplacement. * -* alt = texte alternatif à présenter pour l'impression. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Crée un opérande remplaçant visuellement une valeur. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Instruction mise en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_known_imm_operand_new(const GImmOperand *old, const char *alt) +static void g_known_immediate_operand_finalize(GObject *object) { - GKnownImmOperand *result; /* Remplacement à retourner */ - immop_extra_data_t *src; /* Données insérées à consulter*/ - immop_extra_data_t *dest; /* Données insérées à modifier */ + GKnownImmediateOperand *operand; /* Version spécialisée */ - result = g_object_new(G_TYPE_KNOWN_IMM_OPERAND, NULL); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - result->parent.raw = old->raw; + if (operand->alt_text != NULL) + free(operand->alt_text); - src = GET_IMM_OP_EXTRA(old); - dest = GET_IMM_OP_EXTRA(&result->parent); + G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->finalize(object); - LOCK_GOBJECT_EXTRA(src); +} - *(&dest->parent) = *(&src->parent); - dest->size = src->size; +/****************************************************************************** +* * +* Paramètres : old = opérande à venir copier avant son remplacement. * +* alt = texte alternatif à présenter pour l'impression. * +* * +* Description : Crée un opérande remplaçant visuellement une valeur. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ - dest->def_display = src->def_display; - dest->display = src->display; +GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *old, const char *alt) +{ + GKnownImmediateOperand *result; /* Remplacement à retourner */ - UNLOCK_GOBJECT_EXTRA(src); + result = g_object_new(G_TYPE_KNOWN_IMMEDIATE_OPERAND, NULL); - result->alt_text = strdup(alt); + if (!g_known_immediate_operand_create(result, old, alt)) + g_clear_object(&result); return G_ARCH_OPERAND(result); } - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * +* Paramètres : operand = instance à initialiser pleinement. * +* old = opérande à venir copier avant son remplacement. * +* alt = texte alternatif à présenter pour l'impression. * * * -* Description : Compare un opérande avec un autre. * +* Description : Met en place un opérande remplaçant visuellement une valeur. * * * -* Retour : Bilan de la comparaison. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static int g_known_imm_operand_compare(const GKnownImmOperand *a, const GKnownImmOperand *b, bool lock) +bool g_known_immediate_operand_create(GKnownImmediateOperand *operand, const GImmediateOperand *old, const char *alt) { - int result; /* Bilan à retourner */ - immop_extra_data_t *ea; /* Données insérées à consulter*/ - immop_extra_data_t *eb; /* Données insérées à consulter*/ - GArchOperandClass *class; /* Classe parente normalisée */ + bool result; /* Bilan à retourner */ + immop_extra_data_t extra; /* Données insérées à consulter*/ - ea = GET_IMM_OP_EXTRA(G_IMM_OPERAND(a)); - eb = GET_IMM_OP_EXTRA(G_IMM_OPERAND(b)); + result = true; - if (lock) - { - LOCK_GOBJECT_EXTRA(ea); - LOCK_GOBJECT_EXTRA(eb); - } + extra = GET_IMM_OP_EXTRA(old); - result = strcmp(a->alt_text, b->alt_text); + SET_IMM_OP_EXTRA(operand, &extra); - if (result == 0) - { - class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); - } + G_IMMEDIATE_OPERAND(operand)->raw = G_IMMEDIATE_OPERAND(old)->raw; - if (lock) - { - UNLOCK_GOBJECT_EXTRA(eb); - UNLOCK_GOBJECT_EXTRA(ea); - } + operand->alt_text = strdup(alt); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Réalise une comparaison étendue entre objets. * * * -* Retour : - * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -static void g_known_imm_operand_print(const GKnownImmOperand *operand, GBufferLine *line) +static int g_known_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other) { - size_t len; /* Taille de l'élément inséré */ + int result; /* Bilan à retourner */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand_a; /* Version spécialisée #0 */ + GKnownImmediateOperand *operand_b; /* Version spécialisée #1 */ + + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); - len = strlen(operand->alt_text); + parent_iface = g_type_interface_peek_parent(iface); - g_buffer_line_append_text(line, DLC_ASSEMBLY, operand->alt_text, len, RTT_IMMEDIATE, G_OBJECT(operand)); + result = parent_iface->compare(object, other); + + if (result == 0) + { + operand_a = G_KNOWN_IMMEDIATE_OPERAND(object); + operand_b = G_KNOWN_IMMEDIATE_OPERAND(other); + + result = strcmp(operand_a->alt_text, operand_b->alt_text); + + } + + return result; } +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : Empreinte de l'élément représenté. * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock) +static guint g_known_immediate_operand_hash(const GHashableObject *object) { guint result; /* Valeur à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - GArchOperandClass *class; /* Classe parente normalisée */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand; /* Version spécialisée */ - extra = GET_IMM_OP_EXTRA(G_IMM_OPERAND(operand)); + iface = G_HASHABLE_OBJECT_GET_IFACE(object); - if (lock) - LOCK_GOBJECT_EXTRA(extra); + parent_iface = g_type_interface_peek_parent(iface); - class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); + result = parent_iface->hash(object); - result ^= g_str_hash(operand->alt_text); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); + result ^= g_str_hash(operand->alt_text); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Charge un objet depuis un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -399,30 +447,31 @@ static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock * * ******************************************************************************/ -static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_known_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - rle_string str; /* Chaîne à charger */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + sized_binary_t str; /* Texte alternatif rechargé */ + GKnownImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); + parent_iface = g_type_interface_peek_parent(iface); - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); + result = parent_iface->load(object, storage, fd); if (result) { - setup_empty_rle_string(&str); + init_sized_binary(&str); - result = unpack_rle_string(&str, pbuf); + load_sized_binary_as_string(&str, fd); - if (result) - { - if (get_rle_string(&str) != NULL) - operand->alt_text = strdup(get_rle_string(&str)); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - exit_rle_string(&str); + operand->alt_text = strdup(str.static_data); - } + exit_sized_binary(&str); } @@ -433,11 +482,11 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage * /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -445,54 +494,64 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage * * * ******************************************************************************/ -static bool g_known_imm_operand_store(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_known_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - rle_string str; /* Chaîne à conserver */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand; /* Version spécialisée */ + sized_binary_t str; /* Texte alternatif à conserver*/ - parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); + parent_iface = g_type_interface_peek_parent(iface); - if (result) - { - init_static_rle_string(&str, operand->alt_text); + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; - result = pack_rle_string(&str, pbuf); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - exit_rle_string(&str); + setup_sized_binary_from_static_string(&str, operand->alt_text); - } + result = store_sized_binary_as_string(&str, fd); + + exit: return result; } - /* ---------------------------------------------------------------------------------- */ -/* AFFICHAGE D'UN CONTENU RENOMME */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = operande à consulter. * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Fournit un texte comme représentation alternative d'opérande.* +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * -* Retour : Chaîne de caractère de représentation alternative. * +* Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -static const char *g_known_imm_operand_get_text(const GKnownImmOperand *operand) +static bool g_known_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { - const char *result; /* Texte à retourner */ + bool result; /* Bilan à retourner */ + const GKnownImmediateOperand *operand; /* Version spécialisée */ + + result = true; + + operand = G_KNOWN_IMMEDIATE_OPERAND(builder); - result = operand->alt_text; + add_to_sized_binary(out, operand->alt_text, strlen(operand->alt_text)); return result; diff --git a/src/arch/operands/known.h b/src/arch/operands/known.h index eb84d3b..a8b563f 100644 --- a/src/arch/operands/known.h +++ b/src/arch/operands/known.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique * - * Copyright (C) 2021 Cyrille Bagard + * Copyright (C) 2021-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,34 +25,18 @@ #define _ARCH_OPERANDS_KNOWN_H -#include - - #include "immediate.h" -#include "../operand.h" - - - -#define G_TYPE_KNOWN_IMM_OPERAND g_known_imm_operand_get_type() -#define G_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperand)) -#define G_IS_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KNOWN_IMM_OPERAND)) -#define G_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass)) -#define G_IS_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KNOWN_IMM_OPERAND)) -#define G_KNOWN_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass)) +#include "../../glibext/helpers.h" -/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ -typedef struct _GKnownImmOperand GKnownImmOperand; -/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ -typedef struct _GKnownImmOperandClass GKnownImmOperandClass; +#define G_TYPE_KNOWN_IMMEDIATE_OPERAND (g_known_immediate_operand_get_type()) +DECLARE_GTYPE(GKnownImmediateOperand, g_known_immediate_operand, G, KNOWN_IMMEDIATE_OPERAND); -/* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */ -GType g_known_imm_operand_get_type(void); /* Crée un opérande remplaçant visuellement une valeur. */ -GArchOperand *g_known_imm_operand_new(const GImmOperand *, const char *); +GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *, const char *); diff --git a/src/arch/operands/register-int.h b/src/arch/operands/register-int.h index a887567..93cf025 100644 --- a/src/arch/operands/register-int.h +++ b/src/arch/operands/register-int.h @@ -26,8 +26,6 @@ #include "register.h" - - #include "../operand-int.h" @@ -49,5 +47,9 @@ struct _GRegisterOperandClass }; +/* Met en place un opérande réprésentant une valeur numérique. */ +bool g_register_operand_create(GRegisterOperand *, GArchRegister *); + + #endif /* _ARCH_OPERANDS_REGISTER_INT_H */ diff --git a/src/arch/operands/register-ui.c b/src/arch/operands/register-ui.c new file mode 100644 index 0000000..c5469e1 --- /dev/null +++ b/src/arch/operands/register-ui.c @@ -0,0 +1,93 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-ui.c - opérandes représentant des registres sous forme graphique + * + * 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 Chrysalide. If not, see . + */ + + +#include "register-ui.h" + + +#include "register.h" +#include "../../glibext/strbuilder.h" +#include "../../glibext/options/disass.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_register_operand_ui_print(const GArchOperandUI *, GBufferLine *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = g_register_operand_ui_print; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GStringBuilder *builder; /* Autre version de l'opérande */ + sized_binary_t str; /* Chaîne équivalente produite */ + bool status; /* Bilan d'une conversion */ + + builder = G_STRING_BUILDER(operand); + + init_sized_binary(&str); + + status = g_string_builder_to_string(builder, 0 /* flags */, &str); + + if (status) + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER, + str.static_data, str.size, NULL, G_OBJECT(operand)); + + else + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER, + "??", 2, NULL, G_OBJECT(operand)); + + exit_sized_binary(&str); + +} diff --git a/src/arch/operands/register-ui.h b/src/arch/operands/register-ui.h new file mode 100644 index 0000000..711f450 --- /dev/null +++ b/src/arch/operands/register-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-ui.h - prototypes pour les opérandes représentant des registres sous forme graphique + * + * 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 Chrysalide. If not, see . + */ + + +#ifndef _ARCH_OPERANDS_REGISTER_UI_H +#define _ARCH_OPERANDS_REGISTER_UI_H + + +#include "../operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_REGISTER_UI_H */ diff --git a/src/arch/operands/register.c b/src/arch/operands/register.c index 4615a99..07e35c4 100644 --- a/src/arch/operands/register.c +++ b/src/arch/operands/register.c @@ -28,7 +28,10 @@ #include "register-int.h" -#include "../storage.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" @@ -38,34 +41,61 @@ /* Initialise la classe des opérandes de registre. */ static void g_register_operand_class_init(GRegisterOperandClass *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_register_operand_serializable_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *); + /* Initialise une instance d'opérande de registre. */ static void g_register_operand_init(GRegisterOperand *); /* Supprime toutes les références externes. */ -static void g_register_operand_dispose(GRegisterOperand *); +static void g_register_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_register_operand_finalize(GRegisterOperand *); +static void g_register_operand_finalize(GObject *); + + + +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ + + +/* Réalise une comparaison étendue entre objets. */ +static int g_register_operand_compare(const GComparableObject *, const GComparableObject *); + +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_register_operand_hash(const GHashableObject *); -/* Compare un opérande avec un autre. */ -static int g_register_operand_compare(const GRegisterOperand *, const GRegisterOperand *, bool); -/* Traduit un opérande en version humainement lisible. */ -static void g_register_operand_print(const GRegisterOperand *, GBufferLine *); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_register_operand_hash(const GRegisterOperand *, bool); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_register_operand_load(GRegisterOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packed_buffer_t *); +/* Charge un objet depuis un flux de données. */ +static bool g_register_operand_load(GSerializableObject *, GObjectStorage *, int); + +/* Sauvegarde un objet dans un flux de données. */ +static bool g_register_operand_store(const GSerializableObject *, GObjectStorage *, int); + + + +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_register_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); @@ -75,7 +105,12 @@ static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packe /* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ -G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE_WITH_CODE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_register_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_register_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_register_operand_serializable_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_register_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_register_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -93,23 +128,88 @@ G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); static void g_register_operand_class_init(GRegisterOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize; + object->dispose = g_register_operand_dispose; + object->finalize = g_register_operand_finalize; - operand = G_ARCH_OPERAND_CLASS(klass); +} - operand->compare = (operand_compare_fc)g_register_operand_compare; - operand->print = (operand_print_fc)g_register_operand_print; - operand->hash = (operand_hash_fc)g_register_operand_hash; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - operand->load = (load_operand_fc)g_register_operand_load; - operand->store = (store_operand_fc)g_register_operand_store; +static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_register_operand_compare; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de détermination. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *iface) +{ + iface->hash = g_register_operand_hash; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_serializable_iface_init(GSerializableObjectInterface *iface) +{ + iface->load = g_register_operand_load; + iface->store = g_register_operand_store; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *iface) +{ + iface->to_string = g_register_operand_to_string; } @@ -135,7 +235,7 @@ static void g_register_operand_init(GRegisterOperand *operand) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -145,18 +245,22 @@ static void g_register_operand_init(GRegisterOperand *operand) * * ******************************************************************************/ -static void g_register_operand_dispose(GRegisterOperand *operand) +static void g_register_operand_dispose(GObject *object) { + GRegisterOperand *operand; /* Version spécialisée */ + + operand = G_REGISTER_OPERAND(object); + g_clear_object(&operand->reg); - G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(G_OBJECT(operand)); + G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -166,9 +270,36 @@ static void g_register_operand_dispose(GRegisterOperand *operand) * * ******************************************************************************/ -static void g_register_operand_finalize(GRegisterOperand *operand) +static void g_register_operand_finalize(GObject *object) +{ + G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* reg = registre matériel à représenter. * +* * +* Description : Met en place un opérande réprésentant une valeur numérique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_register_operand_create(GRegisterOperand *operand, GArchRegister *reg) { - G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(G_OBJECT(operand)); + bool result; /* Bilan à retourner */ + + result = true; + + operand->reg = reg; + ref_object(reg); + + return result; } @@ -190,8 +321,7 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) GArchRegister *result; /* Instance à retourner */ result = operand->reg; - - g_object_ref(G_OBJECT(result)); + ref_object(result); return result; @@ -200,17 +330,16 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) /* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Compare un opérande avec un autre. * +* Description : Réalise une comparaison étendue entre objets. * * * * Retour : Bilan de la comparaison. * * * @@ -218,17 +347,25 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) * * ******************************************************************************/ -static int g_register_operand_compare(const GRegisterOperand *a, const GRegisterOperand *b, bool lock) +static int g_register_operand_compare(const GComparableObject *object, const GComparableObject *other) { int result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe parente normalisée */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); - result = g_arch_register_compare(a->reg, b->reg); + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->compare(object, other); if (result == 0) { - class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); + operand = G_REGISTER_OPERAND(object); + + result = g_comparable_object_compare(G_COMPARABLE_OBJECT(operand->reg), other); + } return result; @@ -236,53 +373,96 @@ static int g_register_operand_compare(const GRegisterOperand *a, const GRegister } + +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : - * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static void g_register_operand_print(const GRegisterOperand *operand, GBufferLine *line) +static guint g_register_operand_hash(const GHashableObject *object) { - g_arch_register_print(operand->reg, line); + guint result; /* Valeur à retourner */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_HASHABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->hash(object); + + operand = G_REGISTER_OPERAND(object); + + result ^= g_hashable_object_hash(G_HASHABLE_OBJECT(operand->reg)); + + return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : Empreinte de l'élément représenté. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) +static bool g_register_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - guint result; /* Valeur à retourner */ - GArchOperandClass *class; /* Classe parente normalisée */ - GArchRegister *reg; /* Registre visé par l'opérande*/ + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GSerializableObject *reg; /* Registre récupéré */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->load(object, storage, fd); + + if (result) + { + reg = g_object_storage_unpack_object(storage, fd, "registers"); - class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); + if (reg == NULL) + result = false; - reg = g_register_operand_get_register(operand); + else + { + operand = G_REGISTER_OPERAND(object); - result ^= g_arch_register_hash(reg); + operand->reg = G_ARCH_REGISTER(reg); + + } - g_object_unref(G_OBJECT(reg)); + } return result; @@ -291,11 +471,11 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -303,61 +483,64 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) * * ******************************************************************************/ -static bool g_register_operand_load(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_register_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - GSerializableObject *reg; /* Registre manipulé */ + GRegisterOperand *operand; /* Version spécialisée */ + off64_t reg_pos; /* Position renvoyant au reg. */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + operand = G_REGISTER_OPERAND(object); - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); + result = g_object_storage_store_object(storage, "registers", G_SERIALIZABLE_OBJECT(operand->reg), ®_pos); + if (!result) goto exit; - if (result) - { - reg = g_object_storage_unpack_object(storage, "registers", pbuf); + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = (reg != NULL); + parent_iface = g_type_interface_peek_parent(iface); - if (result) - operand->reg = G_ARCH_REGISTER(reg); + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; - } + result = store_uleb128((uleb128_t []) { reg_pos }, fd); + + exit: return result; } + +/* ---------------------------------------------------------------------------------- */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * * Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -static bool g_register_operand_store(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_register_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - GSerializableObject *reg; /* Registre manipulé */ + const GRegisterOperand *operand; /* Version spécialisée */ - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + operand = G_REGISTER_OPERAND(builder); - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - reg = G_SERIALIZABLE_OBJECT(operand->reg); - result = g_object_storage_pack_object(storage, "registers", reg, pbuf); - } + result = g_string_builder_to_string(G_STRING_BUILDER(operand->reg), flags, out); return result; diff --git a/src/arch/register-int.h b/src/arch/register-int.h index f0b9af9..22ef2cc 100644 --- a/src/arch/register-int.h +++ b/src/arch/register-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register-int.h - définitions internes pour la représentation générique d'un registre * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,31 +26,15 @@ #include "register.h" -#include "../analysis/storage/serialize-int.h" -/* Produit une empreinte à partir d'un registre. */ -typedef guint (* reg_hash_fc) (const GArchRegister *); - -/* Compare un registre avec un autre. */ -typedef int (* reg_compare_fc) (const GArchRegister *, const GArchRegister *); - -/* Traduit un registre en version humainement lisible. */ -typedef void (* reg_print_fc) (const GArchRegister *, GBufferLine *); - /* Indique si le registre correspond à ebp ou similaire. */ typedef bool (* reg_is_base_pointer_fc) (const GArchRegister *); /* Indique si le registre correspond à esp ou similaire. */ typedef bool (* reg_is_stack_pointer_fc) (const GArchRegister *); -/* Charge un contenu depuis une mémoire tampon. */ -typedef bool (* load_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un contenu dans une mémoire tampon. */ -typedef bool (* store_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *); - /* Représentation d'un registre (instance) */ struct _GArchRegister @@ -64,15 +48,9 @@ struct _GArchRegisterClass { GObjectClass parent; /* A laisser en premier */ - reg_hash_fc hash; /* Production d'empreinte */ - reg_compare_fc compare; /* Comparaison de registres */ - reg_print_fc print; /* Impression du registre */ reg_is_base_pointer_fc is_bp; /* Correspondance avec ebp */ reg_is_stack_pointer_fc is_sp; /* Correspondance avec esp */ - load_register_fc load; /* Chargement depuis un tampon */ - store_register_fc store; /* Conservation dans un tampon */ - }; diff --git a/src/arch/register.c b/src/arch/register.c index f487419..6017373 100644 --- a/src/arch/register.c +++ b/src/arch/register.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * registers.c - aides auxiliaires relatives aux registres Dalvik * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,6 +25,10 @@ #include "register-int.h" +#include "../glibext/comparable-int.h" +#include "../glibext/hashable-int.h" +#include "../glibext/serialize-int.h" +#include "../glibext/strbuilder-int.h" @@ -34,34 +38,26 @@ /* Initialise la classe des registres. */ static void g_arch_register_class_init(GArchRegisterClass *); -/* Initialise une instance de registre. */ -static void g_arch_register_init(GArchRegister *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *); /* Procède à l'initialisation de l'interface de sérialisation. */ static void g_arch_register_serializable_init(GSerializableObjectInterface *); -/* Supprime toutes les références externes. */ -static void g_arch_register_dispose(GArchRegister *); - -/* Procède à la libération totale de la mémoire. */ -static void g_arch_register_finalize(GArchRegister *); - +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *); +/* Initialise une instance de registre. */ +static void g_arch_register_init(GArchRegister *); -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ - - -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *); +/* Supprime toutes les références externes. */ +static void g_arch_register_dispose(GObject *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *); +/* Procède à la libération totale de la mémoire. */ +static void g_arch_register_finalize(GObject *); @@ -72,7 +68,10 @@ static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buff /* Indique le type défini pour une représentation d'un registre. */ G_DEFINE_TYPE_WITH_CODE(GArchRegister, g_arch_register, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_register_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_register_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_register_string_builder_iface_init)); /****************************************************************************** @@ -93,20 +92,18 @@ static void g_arch_register_class_init(GArchRegisterClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_register_dispose; - object->finalize = (GObjectFinalizeFunc)g_arch_register_finalize; - - klass->load = (load_register_fc)_g_arch_register_load; - klass->store = (store_register_fc)_g_arch_register_store; + object->dispose = g_arch_register_dispose; + object->finalize = g_arch_register_finalize; } + /****************************************************************************** * * -* Paramètres : reg = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance de registre. * +* Description : Procède à l'initialisation de l'interface de comparaison. * * * * Retour : - * * * @@ -114,8 +111,9 @@ static void g_arch_register_class_init(GArchRegisterClass *klass) * * ******************************************************************************/ -static void g_arch_register_init(GArchRegister *reg) +static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *iface) { + iface->compare = NULL; } @@ -124,7 +122,7 @@ static void g_arch_register_init(GArchRegister *reg) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de sérialisation. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -132,19 +130,18 @@ static void g_arch_register_init(GArchRegister *reg) * * ******************************************************************************/ -static void g_arch_register_serializable_init(GSerializableObjectInterface *iface) +static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *iface) { - iface->load = (load_serializable_object_cb)g_arch_register_load; - iface->store = (store_serializable_object_cb)g_arch_register_store; + iface->hash = NULL; } /****************************************************************************** * * -* Paramètres : reg = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Supprime toutes les références externes. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -152,18 +149,19 @@ static void g_arch_register_serializable_init(GSerializableObjectInterface *ifac * * ******************************************************************************/ -static void g_arch_register_dispose(GArchRegister *reg) +static void g_arch_register_serializable_init(GSerializableObjectInterface *iface) { - G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(G_OBJECT(reg)); + iface->load = NULL; + iface->store = NULL; } /****************************************************************************** * * -* Paramètres : reg = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -171,58 +169,55 @@ static void g_arch_register_dispose(GArchRegister *reg) * * ******************************************************************************/ -static void g_arch_register_finalize(GArchRegister *reg) +static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *iface) { - G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(G_OBJECT(reg)); + iface->to_string = NULL; } /****************************************************************************** * * -* Paramètres : reg = opérande à consulter pour le calcul. * +* Paramètres : reg = instance à initialiser. * * * -* Description : Produit une empreinte à partir d'un registre. * +* Description : Initialise une instance de registre. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -guint g_arch_register_hash(const GArchRegister *reg) +static void g_arch_register_init(GArchRegister *reg) { - return G_ARCH_REGISTER_GET_CLASS(reg)->hash(reg); } /****************************************************************************** * * -* Paramètres : a = premier registre à consulter. * -* b = second registre à consulter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Compare un registre avec un autre. * +* Description : Supprime toutes les références externes. * * * -* Retour : Bilan de la comparaison. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b) +static void g_arch_register_dispose(GObject *object) { - return G_ARCH_REGISTER_GET_CLASS(a)->compare(a, b); + G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : reg = registre à transcrire. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Traduit un registre en version humainement lisible. * +* Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * @@ -230,9 +225,9 @@ int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b) * * ******************************************************************************/ -void g_arch_register_print(const GArchRegister *reg, GBufferLine *line) +static void g_arch_register_finalize(GObject *object) { - G_ARCH_REGISTER_GET_CLASS(reg)->print(reg, line); + G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(object); } @@ -287,115 +282,3 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *reg) return result; } - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : reg = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un contenu depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - - result = true; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un contenu depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchRegisterClass *class; /* Classe à activer */ - - class = G_ARCH_REGISTER_GET_CLASS(reg); - - result = class->load(reg, storage, pbuf); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un contenu dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool _g_arch_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - - result = true; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un contenu dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_arch_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchRegisterClass *class; /* Classe à activer */ - - class = G_ARCH_REGISTER_GET_CLASS(reg); - - result = class->store(reg, storage, pbuf); - - return result; - -} diff --git a/src/arch/register.h b/src/arch/register.h index 0265a73..16275e0 100644 --- a/src/arch/register.h +++ b/src/arch/register.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register.h - prototypes pour les aides auxiliaires relatives aux registres Dalvik * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,44 +25,19 @@ #define _ARCH_REGISTER_H -#include #include -#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" -/* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */ +#define G_TYPE_ARCH_REGISTER (g_arch_register_get_type()) +DECLARE_GTYPE(GArchRegister, g_arch_register, G, ARCH_REGISTER); -#define G_TYPE_ARCH_REGISTER g_arch_register_get_type() -#define G_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_REGISTER, GArchRegister)) -#define G_IS_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_REGISTER)) -#define G_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) -#define G_IS_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_REGISTER)) -#define G_ARCH_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) -/* Représentation d'un registre (instance) */ -typedef struct _GArchRegister GArchRegister; - -/* Représentation d'un registre (classe) */ -typedef struct _GArchRegisterClass GArchRegisterClass; - - -/* Indique le type défini pour une représentation d'un registre. */ -GType g_arch_register_get_type(void); - -/* Produit une empreinte à partir d'un registre. */ -guint g_arch_register_hash(const GArchRegister *); - -/* Compare un registre avec un autre. */ -int g_arch_register_compare(const GArchRegister *, const GArchRegister *); - -/* Traduit un registre en version humainement lisible. */ -void g_arch_register_print(const GArchRegister *, GBufferLine *); - /* Indique si le registre correspond à ebp ou similaire. */ bool g_arch_register_is_base_pointer(const GArchRegister *); diff --git a/src/common/datatypes.h b/src/common/datatypes.h index 681e232..248f4a1 100644 --- a/src/common/datatypes.h +++ b/src/common/datatypes.h @@ -71,6 +71,10 @@ typedef enum _MemoryDataSize } MemoryDataSize; +#define MDS_RANGE(mds) ((mds & 0x7) - 1) +#define MDS_SIGN 0x8 +#define MDS_IS_SIGNED(mds) (mds & MDS_SIGN) + #define MDS_4_BITS MDS_4_BITS_UNSIGNED #define MDS_8_BITS MDS_8_BITS_UNSIGNED #define MDS_16_BITS MDS_16_BITS_UNSIGNED diff --git a/src/glibext/comparable.c b/src/glibext/comparable.c index 95e7de7..40fd110 100644 --- a/src/glibext/comparable.c +++ b/src/glibext/comparable.c @@ -25,6 +25,7 @@ #include "comparable-int.h" +#include "../common/sort.h" @@ -72,11 +73,24 @@ static void g_comparable_object_default_init(GComparableObjectInterface *iface) int g_comparable_object_compare(const GComparableObject *object, const GComparableObject *other) { int result; /* Bilan à retourner */ + GType type_a; /* Type de l'object A */ + GType type_b; /* Type de l'object B */ GComparableObjectInterface *iface; /* Interface utilisée */ - iface = G_COMPARABLE_OBJECT_GET_IFACE(object); + type_a = G_OBJECT_TYPE(G_OBJECT(object)); + type_b = G_OBJECT_TYPE(G_OBJECT(other)); - result = iface->compare(object, other); + assert(sizeof(GType) <= sizeof(unsigned long)); + + result = sort_unsigned_long(type_a, type_b); + + if (result == 0) + { + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); + + result = iface->compare(object, other); + + } return result; diff --git a/src/glibext/options/Makefile.am b/src/glibext/options/Makefile.am index 448de7b..19881cf 100644 --- a/src/glibext/options/Makefile.am +++ b/src/glibext/options/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libglibextoptions.la libglibextoptions_la_SOURCES = \ + disass.h \ hex.h hex.c libglibextoptions_la_CFLAGS = $(TOOLKIT_CFLAGS) diff --git a/src/glibext/options/disass.h b/src/glibext/options/disass.h new file mode 100644 index 0000000..e916083 --- /dev/null +++ b/src/glibext/options/disass.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * disass.h - prototypes pour les options de rendus de code désassemblé + * + * 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 Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_OPTIONS_DISASS_H +#define _GLIBEXT_OPTIONS_DISASS_H + + +#include "../helpers.h" + + + +/* Liste des colonnes en options */ +typedef enum _DisassColumnOptions +{ + ACO_OFFSET, /* Position */ + + ACO_COUNT + +} DisassColumnOptions; + + +#define ACO_ASSEMBLY (ACO_COUNT + 0) /* Code pour assembleur */ + + +#if 0 +#define G_TYPE_HEX_OPTIONS (g_hex_options_get_type()) + +DECLARE_GTYPE(GHexOptions, g_hex_options, G, HEX_OPTIONS); + + +/* Crée un groupe d'options pour le rendu d'hexadécimal. */ +GHexOptions *g_hex_options_new(void); +#endif + + +#endif /* _GLIBEXT_OPTIONS_HEX_H */ diff --git a/tests/arch/operand.py b/tests/arch/operand.py new file mode 100644 index 0000000..e8df8b5 --- /dev/null +++ b/tests/arch/operand.py @@ -0,0 +1,72 @@ + +import pychrysalide + +from chrysacase import ChrysalideTestCase +from pychrysalide.arch import ArchOperand +from pychrysalide.glibext import HashableObject, StringBuilder + + +class TestOperand(ChrysalideTestCase): + """TestCase for arch.ArchOperand.""" + + + def testAbstractClass(self): + """Forbid operand class instance.""" + + with self.assertRaisesRegex(RuntimeError, 'pychrysalide.arch.ArchOperand is an abstract class'): + pc = ArchOperand() + + + def testStringBuilderMethodsOverriding(self): + """Override the StringBuilder interface provided by native implementations.""" + + class MyOperand(ArchOperand, StringBuilder): + + def __init__(self): + super().__init__(self) + + def _to_string(self, flags=0): + return 'my-op' + + op = MyOperand() + + self.assertEqual(op.to_string(), 'my-op') + self.assertEqual(str(op), 'my-op') + self.assertEqual(f'{op}', 'my-op') + + + def testHashableObjectMethods(self): + """Test the HashableObject methods implemantation for operands.""" + + # Pas d'implementation de particulière de HashableObject, + # c'est donc la définition d'implémentation d'ArchOperand + # qui s'applique. + + # Spécificité de l'implémentation GLib : hash 32 bits + + class DefaultHashableOperand(ArchOperand): + pass + + def_op = DefaultHashableOperand() + + h = hash(def_op) + + self.assertEqual(0, h & ~0xffffffff) + + + # Définition particulière de l'opérande, sur la base de + # l'implémentation parente. + + class CustomHashableOperand(ArchOperand, HashableObject): + + def _hash(self): + h = self.parent_hash() + h &= ~0xffff + return h + + cust_op = CustomHashableOperand() + + h = hash(cust_op) + + self.assertEqual(0, h & 0xffff) + self.assertEqual(0, h & ~0xffffffff) diff --git a/tests/arch/operands/immediate.py b/tests/arch/operands/immediate.py index 74b8069..c3fcb84 100644 --- a/tests/arch/operands/immediate.py +++ b/tests/arch/operands/immediate.py @@ -1,35 +1,59 @@ -#!/usr/bin/python3-dbg -# -*- coding: utf-8 -*- - import pychrysalide -from chrysacase import ChrysalideTestCase -from pychrysalide import arch -from pychrysalide.arch import ImmOperand +from chrysacase import ChrysalideTestCase +from pychrysalide import MemoryDataSize +from pychrysalide.arch.operands import ImmediateOperand +from pychrysalide.glibext import StringBuilder class TestImmediate(ChrysalideTestCase): - """TestCase for arch.ImmOperand.""" + """TestCase for arch.ImmediateOperand.""" + + + def testBasicImmediate(self): + """Check basic properties of immediate values.""" + + imm = ImmediateOperand(MemoryDataSize._32_BITS_UNSIGNED, 0x123) + + self.assertEqual(imm.size, MemoryDataSize._32_BITS_UNSIGNED) + self.assertEqual(imm.value, 0x123) + self.assertFalse(imm.is_negative) + + + def testStringBuilderForImmediatesOverriding(self): + """Override the StringBuilder interface for immediate values.""" + + class MyImmOperand(ImmediateOperand, StringBuilder): + + def __init__(self): + super().__init__(MemoryDataSize._32_BITS_UNSIGNED, 0x123) + + def _to_string(self, flags=0): + return 'NaN' + + op = MyImmOperand() + + self.assertEqual(op.to_string(), 'NaN') + self.assertEqual(str(op), 'NaN') + self.assertEqual(f'{op}', 'NaN') def validateValue(self, value, size, padding, strings): """Check all kinds of things with a given immediate operand.""" - display = [ - ImmOperand.IOD_BIN, ImmOperand.IOD_OCT, - ImmOperand.IOD_DEC, - ImmOperand.IOD_HEX - ] + for d in strings.keys(): - for d in display: - - op = ImmOperand(size, value) + op = ImmediateOperand(size, value) self.assertTrue(op.size == size) self.assertTrue(op.value == value) - op.padding = padding + if padding: + op.set_flag(ImmediateOperand.ImmOperandFlag.ZERO_PADDING) + else: + op.unset_flag(ImmediateOperand.ImmOperandFlag.ZERO_PADDING_BY_DEFAULT) + op.display = d string = op.to_string() @@ -40,23 +64,23 @@ class TestImmediate(ChrysalideTestCase): """Run sanity checks on immediate operand with value 1.""" strings = { - ImmOperand.IOD_BIN: 'b1', - ImmOperand.IOD_OCT: '01', - ImmOperand.IOD_DEC: '1', - ImmOperand.IOD_HEX: '0x1' + ImmediateOperand.ImmOperandDisplay.BIN: 'b1', + ImmediateOperand.ImmOperandDisplay.OCT: '01', + ImmediateOperand.ImmOperandDisplay.DEC: '1', + ImmediateOperand.ImmOperandDisplay.HEX: '0x1' } - self.validateValue(1, arch.MDS_8_BITS_UNSIGNED, False, strings) + self.validateValue(1, pychrysalide.MemoryDataSize._8_BITS_UNSIGNED, False, strings) def testByteOnePadded(self): """Run sanity checks on immediate operand with padded value 1.""" strings = { - ImmOperand.IOD_BIN: 'b00000001', - ImmOperand.IOD_OCT: '01', - ImmOperand.IOD_DEC: '1', - ImmOperand.IOD_HEX: '0x01' + ImmediateOperand.ImmOperandDisplay.BIN: 'b00000001', + ImmediateOperand.ImmOperandDisplay.OCT: '01', + ImmediateOperand.ImmOperandDisplay.DEC: '1', + ImmediateOperand.ImmOperandDisplay.HEX: '0x01' } - self.validateValue(1, arch.MDS_8_BITS_UNSIGNED, True, strings) + self.validateValue(1, pychrysalide.MemoryDataSize._8_BITS_UNSIGNED, True, strings) -- cgit v0.11.2-87-g4458