From bb7e4c5e6e4c51da0d9b1a33b571b0c64851c1a8 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 1 Apr 2025 02:05:16 +0200 Subject: Restore most features of core instructions. --- plugins/pychrysalide/arch/Makefile.am | 14 +- plugins/pychrysalide/arch/constants.c | 5 +- plugins/pychrysalide/arch/constants.h | 5 +- plugins/pychrysalide/arch/instruction.c | 866 ++++++--- plugins/pychrysalide/arch/instructions/Makefile.am | 3 +- plugins/pychrysalide/arch/instructions/constants.c | 58 +- plugins/pychrysalide/arch/instructions/constants.h | 5 +- plugins/pychrysalide/arch/instructions/raw.c | 142 +- plugins/pychrysalide/arch/instructions/undefined.c | 145 +- plugins/pychrysalide/arch/instructions/undefined.h | 4 +- plugins/pychrysalide/arch/module-ui.c | 7 + plugins/pychrysalide/arch/module.c | 10 +- plugins/pychrysalide/arch/operand.c | 4 + src/arch/Makefile.am | 11 +- src/arch/instruction-int.h | 126 +- src/arch/instruction-ui-int.h | 55 + src/arch/instruction-ui.c | 254 +++ src/arch/instruction-ui.h | 41 + src/arch/instruction.c | 2001 ++++++++------------ src/arch/instruction.h | 316 ++-- src/arch/instructions/Makefile.am | 11 +- src/arch/instructions/raw-int.h | 56 + src/arch/instructions/raw-ui.c | 261 +++ src/arch/instructions/raw-ui.h | 37 + src/arch/instructions/raw.c | 696 ++----- src/arch/instructions/raw.h | 41 +- src/arch/instructions/undefined-int.h | 52 +- src/arch/instructions/undefined-ui.c | 102 + src/arch/instructions/undefined-ui.h | 37 + src/arch/instructions/undefined.c | 383 +--- src/arch/instructions/undefined.h | 28 +- src/arch/vmpa.h | 29 + src/common/Makefile.am | 1 + src/common/cpp.h | 2 + src/core/Makefile.am | 3 +- src/core/core.c | 21 +- src/core/core.h | 5 +- src/core/processors.c | 23 +- src/core/processors.h | 6 +- src/glibext/bufferline.c | 334 ++-- src/glibext/bufferline.h | 14 +- src/glibext/options/asm.h | 19 +- tests/arch/instruction.py | 52 + 43 files changed, 3217 insertions(+), 3068 deletions(-) create mode 100644 src/arch/instruction-ui-int.h create mode 100644 src/arch/instruction-ui.c create mode 100644 src/arch/instruction-ui.h create mode 100644 src/arch/instructions/raw-int.h create mode 100644 src/arch/instructions/raw-ui.c create mode 100644 src/arch/instructions/raw-ui.h create mode 100644 src/arch/instructions/undefined-ui.c create mode 100644 src/arch/instructions/undefined-ui.h create mode 100644 tests/arch/instruction.py diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am index a134947..a0dcfdb 100644 --- a/plugins/pychrysalide/arch/Makefile.am +++ b/plugins/pychrysalide/arch/Makefile.am @@ -2,17 +2,12 @@ noinst_LTLIBRARIES = libpychrysaarch4.la libpychrysaarchui.la # libpychrysaarch.la # libpychrysaarch_la_SOURCES = \ -# constants.h constants.c \ # context.h context.c \ # instriter.h instriter.c \ -# instruction.h instruction.c \ -# module.h module.c \ -# operand.h operand.c \ -# processor.h processor.c \ -# vmpa.h vmpa.c +# processor.h processor.c # libpychrysaarch_la_LIBADD = \ -# instructions/libpychrysaarchinstructions.la \ +# \ # operands/libpychrysaarchoperands.la # libpychrysaarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ @@ -21,12 +16,14 @@ noinst_LTLIBRARIES = libpychrysaarch4.la libpychrysaarchui.la # libpychrysaarch. libpychrysaarch4_la_SOURCES = \ constants.h constants.c \ + instruction.h instruction.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_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ @@ -48,5 +45,4 @@ devdir = $(includedir)/chrysalide/$(subdir) dev_HEADERS = $(libpychrysaarch_la_SOURCES:%c=) -# SUBDIRS = instructions operands -SUBDIRS = operands +SUBDIRS = instructions operands diff --git a/plugins/pychrysalide/arch/constants.c b/plugins/pychrysalide/arch/constants.c index 3604795..5db59ff 100644 --- a/plugins/pychrysalide/arch/constants.c +++ b/plugins/pychrysalide/arch/constants.c @@ -25,7 +25,7 @@ #include "constants.h" -//#include +#include //#include #include @@ -33,7 +33,6 @@ #include "../helpers.h" -#if 0 // FIXME /****************************************************************************** * * @@ -116,6 +115,8 @@ bool define_arch_instruction_constants(PyTypeObject *type) } +#if 0 // FIXME + /****************************************************************************** * * * Paramètres : type = type dont le dictionnaire est à compléter. * diff --git a/plugins/pychrysalide/arch/constants.h b/plugins/pychrysalide/arch/constants.h index b12579e..2f16c4f 100644 --- a/plugins/pychrysalide/arch/constants.h +++ b/plugins/pychrysalide/arch/constants.h @@ -30,10 +30,13 @@ #include -#if 0 // FIXME + /* Définit les constantes relatives aux instructions. */ bool define_arch_instruction_constants(PyTypeObject *); + +#if 0 // FIXME + /* Définit les constantes relatives aux processeurs. */ bool define_arch_processor_constants(PyTypeObject *); diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c index 0a9ba16..49daa9c 100644 --- a/plugins/pychrysalide/arch/instruction.c +++ b/plugins/pychrysalide/arch/instruction.c @@ -27,13 +27,12 @@ #include #include -#include #include #include +#include #include -#include #include "constants.h" @@ -41,30 +40,38 @@ #include "vmpa.h" #include "../access.h" #include "../helpers.h" -#include "../glibext/linegen.h" - - - -static G_DEFINE_QUARK(cached_keyword, get_cached_keyword); +#include "../glibext/objhole.h" +#include "../glibext/serialize.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_arch_instruction_new(PyTypeObject *, PyObject *, PyObject *); - /* Initialise la classe générique des instructions. */ -static void py_arch_instruction_init_gclass(GArchInstructionClass *, gpointer); +static int py_arch_instruction_init_gclass(GArchInstructionClass *, PyTypeObject *); -CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_instruction, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_init_gclass); +CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_instruction, G_TYPE_ARCH_INSTRUCTION); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_arch_instruction_init(PyObject *, PyObject *, PyObject *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static char *py_arch_instruction_get_encoding_wrapper(const GArchInstruction *); + /* Fournit le nom humain de l'instruction manipulée. */ -static const char *py_arch_instruction_get_class_keyword(GArchInstruction *); +static char *py_arch_instruction_get_keyword_wrapper(const GArchInstruction *); + + + +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ + + +/* Fournit les origines d'une instruction donnée. */ +static PyObject *py_arch_instruction_get_sources(PyObject *, void *); + +/* Fournit les destinations d'une instruction donnée. */ +static PyObject *py_arch_instruction_get_destinations(PyObject *, void *); @@ -72,10 +79,7 @@ static const char *py_arch_instruction_get_class_keyword(GArchInstruction *); /* Attache un opérande supplémentaire à une instruction. */ -static PyObject *py_arch_instruction_attach_extra_operand(PyObject *, PyObject *); - -/* Fournit tous les opérandes d'une instruction. */ -static PyObject *py_arch_instruction_get_operands(PyObject *, void *); +static PyObject *py_arch_instruction_attach_operand(PyObject *, PyObject *); /* Remplace un opérande d'une instruction par un autre. */ static PyObject *py_arch_instruction_replace_operand(PyObject *, PyObject *); @@ -89,34 +93,35 @@ static PyObject *py_arch_instruction_find_operand_path(PyObject *, PyObject *); /* Obtient l'opérande correspondant à un chemin donné. */ static PyObject *py_arch_instruction_get_operand_from_path(PyObject *, PyObject *); +/* Fournit tous les opérandes d'une instruction. */ +static PyObject *py_arch_instruction_get_operands(PyObject *, void *); -/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ +/* ------------------ LIAISON DE FONCTIONNALITES AVEC L'API PYTHON ------------------ */ -/* Fournit les origines d'une instruction donnée. */ -static PyObject *py_arch_instruction_get_sources(PyObject *, void *); -/* Fournit les destinations d'une instruction donnée. */ -static PyObject *py_arch_instruction_get_destinations(PyObject *, void *); +/* Ajoute une information complémentaire à une instruction. */ +static PyObject *py_arch_instruction_set_flag(PyObject *, PyObject *); +/* Retire une information complémentaire à une instruction. */ +static PyObject *py_arch_instruction_unset_flag(PyObject *, PyObject *); +/* Détermine si une instruction possède un fanion particulier. */ +static PyObject *py_arch_instruction_has_flag(PyObject *, PyObject *); -/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */ +/* Fournit l'identifiant correspondant à un type d'instructions. */ +static PyObject *py_arch_instruction_get_type_id(PyObject *, void *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static PyObject *py_arch_instruction_get_encoding(PyObject *, void *); -/* Fournit l'identifiant unique pour un ensemble d'instructions. */ -static PyObject *py_arch_instruction_get_unique_id(PyObject *, void *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static PyObject *py_arch_instruction_get_keyword(PyObject *, void *); /* Fournit la place mémoire d'une instruction. */ static PyObject *py_arch_instruction_get_range(PyObject *, void *); -/* Définit la localisation d'une instruction. */ -static int py_arch_instruction_set_range(PyObject *, PyObject *, void *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static PyObject *py_arch_instruction_get_keyword(PyObject *, void *); - /* ---------------------------------------------------------------------------------- */ @@ -126,24 +131,23 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *, void *); /****************************************************************************** * * -* 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 générique des instructions. * * * -* Retour : - * +* Retour : 0 pour indiquer un succès de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static void py_arch_instruction_init_gclass(GArchInstructionClass *class, gpointer unused) +static int py_arch_instruction_init_gclass(GArchInstructionClass *gclass, PyTypeObject *pyclass) { - GArchInstructionClass *instr; /* Encore une autre vision... */ - - instr = G_ARCH_INSTRUCTION_CLASS(class); + PY_CLASS_SET_WRAPPER(gclass->get_encoding, py_arch_instruction_get_encoding_wrapper); + PY_CLASS_SET_WRAPPER(gclass->get_keyword, py_arch_instruction_get_keyword_wrapper); - instr->get_keyword = (get_instruction_keyword_fc)py_arch_instruction_get_class_keyword; + return 0; } @@ -164,17 +168,25 @@ static void py_arch_instruction_init_gclass(GArchInstructionClass *class, gpoint static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kwds) { - unsigned short int uid; /* Indentifiant unique de type */ - const char *keyword; /* Désignation d'instruction */ + unsigned short int tid; /* Indentifiant unique de type */ int ret; /* Bilan de lecture des args. */ GArchInstruction *instr; /* Instruction à manipuler */ - GQuark cache_key; /* Emplacement local */ - static char *kwlist[] = { "uid", "keyword", NULL }; +#define ARCH_INSTRUCTION_DOC \ + "The ArchInstruction object provides a base class for instructions" \ + " of any architecture.\n" \ + " operands of any kind for new architectures.\n" \ + "\n" \ + "Calls to the *__init__* constructor of this abstract object expect"\ + " one argument: an unique identifier, as an integer value.\n" \ + "\n" \ + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.arch.ArchRegister._get_encoding();\n" \ + "* pychrysalide.arch.ArchRegister._get_keyword().\n" /* Récupération des paramètres */ - ret = PyArg_ParseTupleAndKeywords(args, kwds, "Hs", kwlist, &uid, &keyword); + ret = PyArg_ParseTuple(args, "H", &tid); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -186,13 +198,72 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - cache_key = get_cached_keyword_quark(); + if (!g_arch_instruction_create(instr, tid)) + return -1; + + return 0; - g_object_set_qdata_full(G_OBJECT(instr), cache_key, strdup(keyword), g_free); +} - g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(instr), uid); - return 0; +/****************************************************************************** +* * +* Paramètres : instr = instruction quelconque à consulter. * +* * +* Description : Indique l'encodage d'une instruction de façon détaillée. * +* * +* Retour : Description humaine de l'encodage utilisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_arch_instruction_get_encoding_wrapper(const GArchInstruction *instr) +{ + char *result; /* Encodage à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan d'exécution */ + +#define PLUGIN_MODULE_GET_ENCODING_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_encoding, "$self, /", \ + METH_NOARGS, \ + "Abstract method describing the encoding related to an" \ + " instruction.\n" \ + "\n" \ + "The result should be the string value.\n" \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(instr)); + + if (has_python_method(pyobj, "_get_encoding")) + { + pyret = run_python_method(pyobj, "_get_encoding", NULL); + + if (pyret != NULL) + { + if (!PyUnicode_Check(pyret)) + log_variadic_message(LMT_ERROR, _("The returned raw name must be a string")); + + else + result = strdup(PyUnicode_DATA(pyret)); + + } + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; } @@ -209,15 +280,50 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw * * ******************************************************************************/ -static const char *py_arch_instruction_get_class_keyword(GArchInstruction *instr) +static char *py_arch_instruction_get_keyword_wrapper(const GArchInstruction *instr) { - const char *result; /* Désignation à retourner */ - GQuark cache_key; /* Emplacement local */ + char *result; /* Etiquette à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan d'exécution */ + +#define PLUGIN_MODULE_GET_KEYWORD_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_keyword, "$self, /", \ + METH_NOARGS, \ + "Abstract method giving the official name of the assembly" \ + " instruction.\n" \ + "\n" \ + "The result should be the string value.\n" \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(instr)); + + if (has_python_method(pyobj, "_get_keyword")) + { + pyret = run_python_method(pyobj, "_get_keyword", NULL); + + if (pyret != NULL) + { + if (!PyUnicode_Check(pyret)) + log_variadic_message(LMT_ERROR, _("The returned raw name must be a string")); - cache_key = get_cached_keyword_quark(); + else + result = strdup(PyUnicode_DATA(pyret)); - result = g_object_get_qdata(G_OBJECT(instr), cache_key); - assert(result != NULL); + } + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); return result; @@ -226,94 +332,201 @@ static const char *py_arch_instruction_get_class_keyword(GArchInstruction *instr /* ---------------------------------------------------------------------------------- */ -/* MANIPULATION DES OPERANDES */ +/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : self = architecture concernée par la procédure. * -* args = instruction représentant le point de départ. * +* Paramètres : self = instruction d'architecture à manipuler. * +* unused = adresse non utilisée ici. * * * -* Description : Attache un opérande supplémentaire à une instruction. * +* Description : Fournit les origines d'une instruction donnée. * * * -* Retour : None. * +* Retour : Nombre de ces origines. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_attach_extra_operand(PyObject *self, PyObject *args) +static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused) { - GArchOperand *op; /* Opérande concerné à ajouter */ - int ret; /* Bilan de lecture des args. */ - GArchInstruction *instr; /* Instruction manipulée */ + PyObject *result; /* Instance à retourner */ + GArchInstruction *instr; /* Version native */ + size_t count; /* Nombre de liens présents */ + size_t i; /* Boucle de parcours */ - ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &op); - if (!ret) return NULL; + + GArchInstruction *src; /* Instruction en source */ + InstructionLinkType src_type; /* Type de lien */ + PyObject *linked; /* Source de lien Python */ + PyObject *lnk_type; /* Nature du lien en Python */ +#ifndef NDEBUG + int ret; /* Bilan d'une écriture d'arg. */ +#endif + +#define ARCH_INSTRUCTION_SOURCES_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + sources, py_arch_instruction, \ + "Provide the instructions list driving to the current instruction.\n" \ + "\n" \ + "Each item of the resulting tuple is a pair of" \ + " pychrysalide.arch.ArchInstruction instance and" \ + " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \ +) instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_object_ref(G_OBJECT(op)); + g_thick_object_lock(G_THICK_OBJECT(instr)); + + count = g_arch_instruction_count_src_links(instr); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + src = g_arch_instruction_get_linked_source(instr, i, &src_type); + + linked = pygobject_new(G_OBJECT(src)); + lnk_type = cast_with_constants_group_from_type(get_python_arch_instruction_type(), + "InstructionLinkType", src_type); + +#ifndef NDEBUG + ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type)); + assert(ret == 0); +#else + PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type)); +#endif + + unref_object(src); + + } - g_arch_instruction_attach_extra_operand(instr, op); + g_thick_object_unlock(G_THICK_OBJECT(instr)); - Py_RETURN_NONE; + return result; } /****************************************************************************** * * -* Paramètres : self = objet représentant une instruction. * +* Paramètres : self = instruction d'architecture à manipuler. * * unused = adresse non utilisée ici. * * * -* Description : Fournit tous les opérandes d'une instruction. * +* Description : Fournit les destinations d'une instruction donnée. * * * -* Retour : Valeur associée à la propriété consultée. * +* Retour : Nombre de ces destinations. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused) +static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unused) { PyObject *result; /* Instance à retourner */ GArchInstruction *instr; /* Version native */ - size_t count; /* Nombre d'opérandes présents */ + size_t count; /* Nombre de liens présents */ size_t i; /* Boucle de parcours */ - GArchOperand *operand; /* Opérande à manipuler */ - PyObject *opobj; /* Version Python */ + GArchInstruction *dest; /* Instruction en source */ + InstructionLinkType dest_type; /* Type de lien */ + PyObject *linked; /* Destination de lien Python */ + PyObject *lnk_type; /* Nature du lien en Python */ #ifndef NDEBUG int ret; /* Bilan d'une écriture d'arg. */ #endif +#define ARCH_INSTRUCTION_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + destinations, py_arch_instruction, \ + "Provide the instructions list following the current instruction.\n" \ + "\n" \ + "Each item of the resulting tuple is a pair of" \ + " pychrysalide.arch.ArchInstruction instance and" \ + " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \ +) + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_lock_operands(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); - count = _g_arch_instruction_count_operands(instr); + count = g_arch_instruction_count_dest_links(instr); result = PyTuple_New(count); for (i = 0; i < count; i++) { - operand = _g_arch_instruction_get_operand(instr, i); + dest = g_arch_instruction_get_linked_destination(instr, i, &dest_type); - opobj = pygobject_new(G_OBJECT(operand)); + linked = pygobject_new(G_OBJECT(dest)); + lnk_type = cast_with_constants_group_from_type(get_python_arch_instruction_type(), + "InstructionLinkType", dest_type); #ifndef NDEBUG - ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj)); + ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type)); assert(ret == 0); #else - PyTuple_SetItem(result, i, Py_BuildValue("O", opobj)); + PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, lnk_type)); #endif - g_object_unref(G_OBJECT(operand)); + unref_object(dest); } - g_arch_instruction_unlock_operands(instr); + g_thick_object_unlock(G_THICK_OBJECT(instr)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Attache un opérande supplémentaire à une instruction. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_attach_operand(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GArchOperand *op; /* Opérande concerné à ajouter */ + int ret; /* Bilan de lecture des args. */ + GArchInstruction *instr; /* Instruction manipulée */ + +#define ARCH_INSTRUCTION_ATTACH_OPERAND_METHOD PYTHON_METHOD_DEF \ +( \ + attach_operand, "$self, operand, /", \ + METH_VARARGS, py_arch_instruction, \ + "Add an extra operand to an instruction.\n" \ + "\n" \ + "The instruction has to be locked during the instruction.\n" \ + "\n" \ + "The *operand* argument has to be a pychrysalide.arch.ArchOperand" \ + " instance." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &op); + if (!ret) return NULL; + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + + g_arch_instruction_attach_operand(instr, op); + + result = Py_None; + Py_INCREF(result); return result; @@ -342,6 +555,21 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *self, PyObject *a GArchInstruction *instr; /* Instruction manipulée */ bool status; /* Bilan de l'opération */ +#define ARCH_INSTRUCTION_REPLACE_OPERAND_METHOD PYTHON_METHOD_DEF \ +( \ + replace_operand, "$self, old, new, /", \ + METH_VARARGS, py_arch_instruction, \ + "Replace an old instruction operand by a another one.\n" \ + "\n" \ + "The instruction has to be locked during the instruction.\n" \ + "\n" \ + "Both the *old* and *new* arguments have to be a" \ + " pychrysalide.arch.ArchOperand instance.\n" \ + "\n" \ + "The status of the operation is returned as a boolean value: *True*"\ + " if the operand has been replaced, *False* in case of failure." \ +) + ret = PyArg_ParseTuple(args, "O&O&", convert_to_arch_operand, &old, convert_to_arch_operand, &new); if (!ret) return NULL; @@ -349,9 +577,6 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *self, PyObject *a status = g_arch_instruction_replace_operand(instr, old, new); - if (status) - g_object_ref(G_OBJECT(new)); - result = status ? Py_True : Py_False; Py_INCREF(result); @@ -381,6 +606,21 @@ static PyObject *py_arch_instruction_detach_operand(PyObject *self, PyObject *ar GArchInstruction *instr; /* Instruction manipulée */ bool status; /* Bilan de l'opération */ +#define ARCH_INSTRUCTION_DETACH_OPERAND_METHOD PYTHON_METHOD_DEF \ +( \ + detach_operand, "$self, operand, /", \ + METH_VARARGS, py_arch_instruction, \ + "Remove an operand from the instruction.\n" \ + "\n" \ + "The instruction has to be locked during the instruction.\n" \ + "\n" \ + "The *operand* argument has to be a pychrysalide.arch.ArchOperand" \ + " instance.\n" \ + "\n" \ + "The status of the operation is returned as a boolean value: *True*"\ + " if the operand has been removed, *False* in case of failure." \ +) + ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target); if (!ret) return NULL; @@ -500,7 +740,7 @@ static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObj if (op != NULL) { result = pygobject_new(G_OBJECT(op)); - g_object_unref(G_OBJECT(op)); + unref_object(op); } else { @@ -513,182 +753,258 @@ static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObj } - -/* ---------------------------------------------------------------------------------- */ -/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : self = instruction d'architecture à manipuler. * +* Paramètres : self = objet représentant une instruction. * * unused = adresse non utilisée ici. * * * -* Description : Fournit les origines d'une instruction donnée. * +* Description : Fournit tous les opérandes d'une instruction. * * * -* Retour : Nombre de ces origines. * +* Retour : Valeur associée à la propriété consultée. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused) +static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused) { PyObject *result; /* Instance à retourner */ GArchInstruction *instr; /* Version native */ - size_t count; /* Nombre de liens présents */ + size_t count; /* Nombre d'opérandes présents */ size_t i; /* Boucle de parcours */ - const instr_link_t *source; /* Origine des liens */ - PyObject *linked; /* Source de lien Python */ - PyObject *type; /* Nature du lien en Python */ + GArchOperand *operand; /* Opérande à manipuler */ + PyObject *opobj; /* Version Python */ #ifndef NDEBUG int ret; /* Bilan d'une écriture d'arg. */ #endif -#define ARCH_INSTRUCTION_SOURCES_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - sources, py_arch_instruction, \ - "Provide the instructions list driving to the current instruction.\n" \ - "\n" \ - "Each item of the resulting tuple is a pair of" \ - " pychrysalide.arch.ArchInstruction instance and" \ - " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \ +#define ARCH_INSTRUCTION_OPERANDS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + operands, py_arch_instruction, \ + "List of instruction attached operands.\n" \ + "\n" \ + "The result is a list of pychrysalide.arch.ArchOperand" \ + " instances, which can be empty." \ ) instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_lock_src(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); - count = g_arch_instruction_count_sources(instr); + count = g_arch_instruction_count_operands(instr); result = PyTuple_New(count); for (i = 0; i < count; i++) { - source = g_arch_instruction_get_source(instr, i); + operand = g_arch_instruction_get_operand(instr, i); - linked = pygobject_new(G_OBJECT(source->linked)); - type = cast_with_constants_group_from_type(get_python_arch_instruction_type(), - "InstructionLinkType", source->type); + opobj = pygobject_new(G_OBJECT(operand)); #ifndef NDEBUG - ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type)); + ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj)); assert(ret == 0); #else - PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type)); + PyTuple_SetItem(result, i, Py_BuildValue("O", opobj)); #endif - unref_instr_link(source); + unref_object(operand); } - g_arch_instruction_unlock_src(instr); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* LIAISON DE FONCTIONNALITES AVEC L'API PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : self = instruction d'architecture à manipuler. * -* unused = adresse non utilisée ici. * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * * * -* Description : Fournit les destinations d'une instruction donnée. * +* Description : Ajoute une information complémentaire à une instruction. * * * -* Retour : Nombre de ces destinations. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unused) +static PyObject *py_arch_instruction_set_flag(PyObject *self, PyObject *args) { - PyObject *result; /* Instance à retourner */ - GArchInstruction *instr; /* Version native */ - size_t count; /* Nombre de liens présents */ - size_t i; /* Boucle de parcours */ - const instr_link_t *dest; /* Destination des liens */ - PyObject *linked; /* Destination de lien Python */ - PyObject *type; /* Nature du lien en Python */ -#ifndef NDEBUG - int ret; /* Bilan d'une écriture d'arg. */ -#endif - -#define ARCH_INSTRUCTION_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - destinations, py_arch_instruction, \ - "Provide the instructions list following the current instruction.\n" \ - "\n" \ - "Each item of the resulting tuple is a pair of" \ - " pychrysalide.arch.ArchInstruction instance and" \ - " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchInstruction *instr; /* Instruction manipulée */ + bool status; /* Bilan à transmettre */ + +#define ARCH_INSTRUCTION_SET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + set_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_instruction, \ + "Add some flags to the instruction.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to apply to the instruction 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; + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_lock_dest(instr); + status = g_arch_instruction_set_flag(instr, flag); - count = g_arch_instruction_count_destinations(instr); + result = status ? Py_True : Py_False; + Py_INCREF(result); - result = PyTuple_New(count); + return result; - for (i = 0; i < count; i++) - { - dest = g_arch_instruction_get_destination(instr, i); +} - linked = pygobject_new(G_OBJECT(dest->linked)); - type = cast_with_constants_group_from_type(get_python_arch_instruction_type(), - "InstructionLinkType", dest->type); -#ifndef NDEBUG - ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type)); - assert(ret == 0); -#else - PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type)); -#endif +/****************************************************************************** +* * +* 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 à une instruction. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_unset_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchInstruction *instr; /* Instruction manipulée */ + bool status; /* Bilan à transmettre */ + +#define ARCH_INSTRUCTION_UNSET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + unset_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_instruction, \ + "Remove some flags from the instruction.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to delete from the instruction state.\n" \ + "\n" \ + "The result is an boolean status: *True* for operation" \ + " success, *False* otherwise." \ +) - unref_instr_link(dest); + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; - } + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_unlock_dest(instr); + status = g_arch_instruction_unset_flag(instr, 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 une instruction possède un fanion particulier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ -/* ---------------------------------------------------------------------------------- */ -/* INSTRUCTIONS D'ARCHITECTURES EN PYTHON */ -/* ---------------------------------------------------------------------------------- */ +static PyObject *py_arch_instruction_has_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchInstruction *instr; /* Instruction manipulée */ + bool status; /* Bilan à transmettre */ + +#define ARCH_INSTRUCTION_HAS_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + has_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_instruction, \ + "Tell if some flags are set for the instruction.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to test for the instruction 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; + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + + status = g_arch_instruction_has_flag(instr, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} /****************************************************************************** * * -* Paramètres : self = classe représentant une instruction. * -* closure = adresse non utilisée ici. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Fournit l'identifiant unique pour un ensemble d'instructions.* +* Description : Fournit l'identifiant correspondant à un type d'instructions.* * * -* Retour : Identifiant unique par type d'instruction. * +* Retour : Identifiant unique par type d'instruction et architecture. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_unique_id(PyObject *self, void *closure) +static PyObject *py_arch_instruction_get_type_id(PyObject *self, void *closure) { - PyObject *result; /* Conversion à retourner */ - GArchInstruction *instr; /* Version native */ - itid_t uid; /* Identifiant unique associé */ + PyObject *result; /* Valeur à retourner */ + GArchInstruction *instr; /* Instruction manipulée */ + itid_t tid; /* Identifiant à transmettre */ + +#define ARCH_INSTRUCTION_TYPE_ID_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + type_id, py_arch_instruction, \ + "Provide the unique identifier given to this kind of" \ + " instruction.\n" \ + "\n" \ + "The returned value is an integer." \ +) instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - uid = g_arch_instruction_get_unique_id(instr); + tid = g_arch_instruction_get_type_id(instr); - result = PyLong_FromUnsignedLong(uid); + result = PyLong_FromUnsignedLong(tid); return result; @@ -697,27 +1013,61 @@ static PyObject *py_arch_instruction_get_unique_id(PyObject *self, void *closure /****************************************************************************** * * -* Paramètres : self = classe représentant une instruction. * -* closure = adresse non utilisée ici. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Fournit la place mémoire d'une instruction. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Valeur associée à la propriété consultée. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure) +static PyObject *py_arch_instruction_get_encoding(PyObject *self, void *closure) { - PyObject *result; /* Conversion à retourner */ - GArchInstruction *instr; /* Version native */ - const mrange_t *range; /* Espace mémoire à exporter */ + PyObject *result; /* Valeur à retourner */ + GArchInstruction *instr; /* Instruction manipulée */ + char *encoding; /* Encodage d'une instruction */ + +#define ARCH_INSTRUCTION_ENCODING_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + encoding, py_arch_instruction, \ + "Describe the encoding related to an instruction.\n" \ + "\n" \ + "The returned value is an arbitrary string value." \ +) instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - range = g_arch_instruction_get_range(instr); - result = build_from_internal_mrange(range); + encoding = g_arch_instruction_get_encoding(instr); + + if (encoding != NULL) + { + result = PyUnicode_FromString(encoding); + + free(encoding); + + } + + else + { + /** + * La méthode de classe sollicitée a renvoyé une valeur nulle. + * + * Si cette méthode correspond à une implémentation Python + * (avec un appel à not_yet_implemented_method()), une exception + * est déjà en place. + * + * Si aucune exception n'a été prévue, un rattrapage est effectué ici. + */ + + if (PyErr_Occurred() == NULL) + PyErr_SetString(PyExc_NotImplementedError, _("unexpected NULL value as encoding")); + + result = NULL; + + } return result; @@ -727,59 +1077,108 @@ static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure) /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * -* value = valeur fournie à intégrer ou prendre en compte. * -* closure = adresse non utilisée ici. * +* closure = non utilisé ici. * * * -* Description : Définit la localisation d'une instruction. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Bilan de l'opération pour Python. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static int py_arch_instruction_set_range(PyObject *self, PyObject *value, void *closure) +static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *closure) { - int ret; /* Bilan d'analyse */ - mrange_t *range; /* Espace mémoire à manipuler */ - GArchInstruction *instr; /* Version native */ + PyObject *result; /* Valeur à retourner */ + GArchInstruction *instr; /* Instruction manipulée */ + char *keyword; /* Désignation d'une instruct° */ + +#define ARCH_INSTRUCTION_KEYWORD_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + keyword, py_arch_instruction, \ + "Give the official name of the assembly instruction.\n" \ + "\n" \ + "The returned value is a string value." \ +) - ret = PyObject_IsInstance(value, (PyObject *)get_python_mrange_type()); - if (!ret) return -1; + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - range = get_internal_mrange(value); + keyword = g_arch_instruction_get_keyword(instr); - instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_set_range(instr, range); + if (keyword != NULL) + { + result = PyUnicode_FromString(keyword); - return 0; + free(keyword); + + } + + else + { + /** + * La méthode de classe sollicitée a renvoyé une valeur nulle. + * + * Si cette méthode correspond à une implémentation Python + * (avec un appel à not_yet_implemented_method()), une exception + * est déjà en place. + * + * Si aucune exception n'a été prévue, un rattrapage est effectué ici. + */ + + if (PyErr_Occurred() == NULL) + PyErr_SetString(PyExc_NotImplementedError, _("unexpected NULL value as keyword")); + + result = NULL; + + } + + return result; } /****************************************************************************** * * -* Paramètres : self = classe représentant une instruction. * -* unused = adresse non utilisée ici. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Fournit le nom humain de l'instruction manipulée. * +* Description : Fournit la place mémoire d'une instruction. * * * -* Retour : Valeur associée à la propriété consultée. * +* Retour : Définition de localisation ou *None*. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused) +static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure) { - PyObject *result; /* Trouvailles à retourner */ - GArchInstruction *instr; /* Version native */ - const char *kw; /* Valeur récupérée */ + PyObject *result; /* Valeur à retourner */ + GArchInstruction *instr; /* Instruction manipulée */ + mrange_t range; /* Localisation d'instruction */ + bool valid; /* Validité de la localisation */ + +#define ARCH_INSTRUCTION_RANGE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + range, py_arch_instruction, \ + "Give access to the memory range covered by the" \ + " current instruction.\n" \ + "\n" \ + "The returned value is a pychrysalide.arch.mrange" \ + " instance or *None* if no location is currently" \ + " defined." \ +) instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - kw = g_arch_instruction_get_keyword(instr); - result = PyUnicode_FromString(kw); + valid = g_arch_instruction_get_range(instr, &range); + + if (valid) + result = build_from_internal_mrange(&range); + else + { + result = Py_None; + Py_INCREF(result); + } return result; @@ -801,45 +1200,25 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused) PyTypeObject *get_python_arch_instruction_type(void) { static PyMethodDef py_arch_instruction_methods[] = { - { - "attach_operand", py_arch_instruction_attach_extra_operand, - METH_VARARGS, - "attach_operand($self, op, /)\n--\n\nAdd a new operand to the instruction." - }, - { - "replace_operand", py_arch_instruction_replace_operand, - METH_VARARGS, - "replace_operand($self, old, new, /)\n--\n\nReplace an old instruction operand by a another one." - }, - { - "detach_operand", py_arch_instruction_detach_operand, - METH_VARARGS, - "detach_operand($self, target, /)\n--\n\nRemove an operand from the instruction." - }, + ARCH_INSTRUCTION_ATTACH_OPERAND_METHOD, + ARCH_INSTRUCTION_REPLACE_OPERAND_METHOD, + ARCH_INSTRUCTION_DETACH_OPERAND_METHOD, ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD, ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD, + ARCH_INSTRUCTION_SET_FLAG_METHOD, + ARCH_INSTRUCTION_UNSET_FLAG_METHOD, + ARCH_INSTRUCTION_HAS_FLAG_METHOD, { NULL } }; static PyGetSetDef py_arch_instruction_getseters[] = { - { - "uid", py_arch_instruction_get_unique_id, NULL, - "Provide the unique identification number given to this kind of instruction.", NULL - }, - { - "range", py_arch_instruction_get_range, py_arch_instruction_set_range, - "Give access to the memory range covered by the current instruction.", NULL - }, - { - "keyword", (getter)py_arch_instruction_get_keyword, (setter)NULL, - "Give le name of the assembly instruction.", NULL - }, - { - "operands", (getter)py_arch_instruction_get_operands, (setter)NULL, - "Provide the list of instruction attached operands.", NULL - }, ARCH_INSTRUCTION_SOURCES_ATTRIB, ARCH_INSTRUCTION_DESTINATIONS_ATTRIB, + ARCH_INSTRUCTION_OPERANDS_ATTRIB, + ARCH_INSTRUCTION_TYPE_ID_ATTRIB, + ARCH_INSTRUCTION_ENCODING_ATTRIB, + ARCH_INSTRUCTION_KEYWORD_ATTRIB, + ARCH_INSTRUCTION_RANGE_ATTRIB, { NULL } }; @@ -852,7 +1231,7 @@ PyTypeObject *get_python_arch_instruction_type(void) .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide instruction for a given architecture.", + .tp_doc = ARCH_INSTRUCTION_DOC, .tp_methods = py_arch_instruction_methods, .tp_getset = py_arch_instruction_getseters, @@ -893,9 +1272,14 @@ bool ensure_python_arch_instruction_is_registered(void) dict = PyModule_GetDict(module); - if (!ensure_python_line_generator_is_registered()) + if (!ensure_python_thick_object_is_registered()) return false; + if (!ensure_python_serializable_object_is_registered()) + return false; + + pyg_register_class_init(G_TYPE_ARCH_INSTRUCTION, (PyGClassInitFunc)py_arch_instruction_init_gclass); + if (!register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, type)) return false; diff --git a/plugins/pychrysalide/arch/instructions/Makefile.am b/plugins/pychrysalide/arch/instructions/Makefile.am index 65efe42..29c2a45 100644 --- a/plugins/pychrysalide/arch/instructions/Makefile.am +++ b/plugins/pychrysalide/arch/instructions/Makefile.am @@ -7,7 +7,8 @@ libpychrysaarchinstructions_la_SOURCES = \ raw.h raw.c \ undefined.h undefined.c -libpychrysaarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +libpychrysaarchinstructions_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + $(TOOLKIT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/pychrysalide/arch/instructions/constants.c b/plugins/pychrysalide/arch/instructions/constants.c index af7baa9..257c501 100644 --- a/plugins/pychrysalide/arch/instructions/constants.c +++ b/plugins/pychrysalide/arch/instructions/constants.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * constants.c - ajout des constantes de base pour les instructions * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -112,3 +112,59 @@ bool define_undefined_instruction_constants(PyTypeObject *type) return result; } + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en constante ExpectedBehavior. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_undefined_expected_behavior(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur récupérée */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 ExpectedBehavior"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if (value > IEB_RESERVED) + { + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ExpectedBehavior"); + result = 0; + } + + else + *((InstrExpectedBehavior *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/arch/instructions/constants.h b/plugins/pychrysalide/arch/instructions/constants.h index 2f0c587..b6ef9a4 100644 --- a/plugins/pychrysalide/arch/instructions/constants.h +++ b/plugins/pychrysalide/arch/instructions/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 instructions * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -37,6 +37,9 @@ bool define_raw_instruction_constants(PyTypeObject *); /* Définit les constantes liées aux comportements erratiques. */ bool define_undefined_instruction_constants(PyTypeObject *); +/* Tente de convertir en constante ExpectedBehavior. */ +int convert_to_undefined_expected_behavior(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ARCH_INSTRUCTIONS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/arch/instructions/raw.c b/plugins/pychrysalide/arch/instructions/raw.c index 7e58b96..ae730e8 100644 --- a/plugins/pychrysalide/arch/instructions/raw.c +++ b/plugins/pychrysalide/arch/instructions/raw.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * raw.c - équivalent Python du fichier "arch/instructions/raw.h" * - * Copyright (C) 2018-2020 Cyrille Bagard + * Copyright (C) 2018-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -28,26 +28,33 @@ #include -#include -#include -#include +#include #include "constants.h" #include "../instruction.h" #include "../vmpa.h" #include "../../access.h" +#include "../../constants.h" #include "../../helpers.h" #include "../../analysis/content.h" +#include "../../glibext/portion.h" -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_raw_instruction_new(PyTypeObject *, PyObject *, PyObject *); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +CREATE_DYN_CONSTRUCTOR(raw_instruction, G_TYPE_RAW_INSTRUCTION); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_raw_instruction_init(PyObject *, PyObject *, PyObject *); + + +/* ------------------------ FONCTIONNALITES DE L'INSTRUCTION ------------------------ */ + + /* Indique si le contenu de l'instruction est du bourrage. */ static PyObject *py_raw_instruction_get_padding(PyObject *, void *); @@ -62,64 +69,9 @@ static int py_raw_instruction_set_string(PyObject *, 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_raw_instruction_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_raw_instruction_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_RAW_INSTRUCTION, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -139,20 +91,17 @@ static PyObject *py_raw_instruction_new(PyTypeObject *type, PyObject *args, PyOb static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwds) { int result; /* Bilan à retourner */ + GBinaryPortion *area; /* Zone de contenance */ vmpa2t *addr; /* Texte de lecture */ - unsigned long mem_size; /* Taille de portion brute */ + MemoryDataSize size; /* Taille de portion brute */ unsigned long long value; /* Valeur brute à considérer */ GBinContent *content; /* Contenu à lire au besoin */ unsigned long count; /* Nombre d'éléments à lister */ - unsigned int endian; /* Type de boutisme impliqué */ + SourceEndian endian; /* Type de boutisme impliqué */ int ret; /* Bilan de lecture des args. */ - GArchInstruction *fake; /* Instruction à copier */ - GArchInstruction *instr; /* Instruction à manipuler */ - size_t op_count; /* Nombre d'opérande à copier */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à transférer */ + GRawInstruction *instr; /* Instruction à manipuler */ - static char *kwlist[] = { "addr", "mem_size", "value", "content", "count", "endian", NULL }; + static char *kwlist[] = { "area", "addr", "size", "value", "content", "count", "endian", NULL }; #define RAW_INSTRUCTION_DOC \ "The RawInstruction object handles data which is not (yet?) disassembled" \ @@ -187,9 +136,14 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd count = 0; endian = 0; - ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&k|KO&kI", kwlist, - convert_any_to_vmpa, &addr, &mem_size, - &value, convert_to_binary_content, &content, &count, &endian); + ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&O&O&|KO&kO&", kwlist, + convert_to_binary_portion, &area, + convert_any_to_vmpa, &addr, + convert_to_memory_data_size, &size, + &value, + convert_to_binary_content, &content, + &count, + convert_to_source_endian, &endian); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -199,35 +153,19 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd /* Eléments de base */ - if (content != NULL) - fake = g_raw_instruction_new_array(content, mem_size, count, addr, endian); - else - fake = g_raw_instruction_new_from_value(addr, mem_size, value); + instr = G_RAW_INSTRUCTION(pygobject_get(self)); - if (fake == NULL) + if (content != NULL) { - PyErr_SetString(PyExc_ValueError, _("Unable to build the object with the given parameters.")); - goto clean_exit; + if (!g_raw_instruction_create_array(instr, area, addr, size, content, count, endian)) + goto clean_exit; } - - instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - - g_arch_instruction_lock_operands(fake); - - op_count = _g_arch_instruction_count_operands(fake); - - for (i = 0; i < op_count; i++) + else { - op = _g_arch_instruction_get_operand(fake, i); - g_arch_instruction_attach_extra_operand(instr, op); + if (!g_raw_instruction_create_value(instr, area, addr, size, value)) + goto clean_exit; } - g_arch_instruction_unlock_operands(fake); - - g_arch_instruction_set_range(instr, g_arch_instruction_get_range(fake)); - - g_object_unref(G_OBJECT(fake)); - result = 0; clean_exit: @@ -239,6 +177,12 @@ static int py_raw_instruction_init(PyObject *self, PyObject *args, PyObject *kwd } + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONNALITES DE L'INSTRUCTION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = classe représentant une instruction. * @@ -271,7 +215,6 @@ static PyObject *py_raw_instruction_get_padding(PyObject *self, void *closure) result = state ? Py_True : Py_False; Py_INCREF(result); - return result; } @@ -342,7 +285,6 @@ static PyObject *py_raw_instruction_get_string(PyObject *self, void *closure) result = state ? Py_True : Py_False; Py_INCREF(result); - return result; } diff --git a/plugins/pychrysalide/arch/instructions/undefined.c b/plugins/pychrysalide/arch/instructions/undefined.c index 1246daa..1c2bccc 100644 --- a/plugins/pychrysalide/arch/instructions/undefined.c +++ b/plugins/pychrysalide/arch/instructions/undefined.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.c - équivalent Python du fichier "arch/instructions/undefined.h" * - * Copyright (C) 2019 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -28,9 +28,7 @@ #include -#include #include -#include #include "constants.h" @@ -40,75 +38,27 @@ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_undef_instruction_new(PyTypeObject *, PyObject *, PyObject *); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Initialise une instance sur la base du dérivé de GObject. */ -static int py_undef_instruction_init(PyObject *, PyObject *, PyObject *); - -/* Indique le type de conséquences réél de l'instruction. */ -static PyObject *py_undef_instruction_get_behavior(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_undef_instruction_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_undefined_instruction_type(); +CREATE_DYN_CONSTRUCTOR(undefined_instruction, G_TYPE_UNDEFINED_INSTRUCTION); - 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_UNDEF_INSTRUCTION, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_undefined_instruction_init(PyObject *, PyObject *, PyObject *); - if (!status) - { - result = NULL; - goto exit; - } - } - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ +/* ------------------------ FONCTIONNALITES DE L'INSTRUCTION ------------------------ */ - simple_way: - result = PyType_GenericNew(type, args, kwds); +/* Indique le type de conséquences réél de l'instruction. */ +static PyObject *py_undefined_instruction_get_behavior(PyObject *, void *); - exit: - return result; -} +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -125,30 +75,27 @@ static PyObject *py_undef_instruction_new(PyTypeObject *type, PyObject *args, Py * * ******************************************************************************/ -static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *kwds) +static int py_undefined_instruction_init(PyObject *self, PyObject *args, PyObject *kwds) { - unsigned long behavior; /* Conséquence pour l'instruct°*/ + InstrExpectedBehavior behavior; /* Conséquence pour l'instruct°*/ int ret; /* Bilan de lecture des args. */ - GUndefInstruction *instr; /* Instruction à manipuler */ - undef_extra_data_t *extra; /* Données insérées à modifier */ + GUndefinedInstruction *instr; /* Instruction à manipuler */ - static char *kwlist[] = { "behavior", NULL }; - -#define UNDEF_INSTRUCTION_DOC \ - "UndefInstruction represents all kinds of instructions which are" \ +#define UNDEFINED_INSTRUCTION_DOC \ + "UndefinedInstruction represents all kinds of instructions which are" \ " officially not part of a runnable instruction set.\n" \ "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " UndefInstruction(behavior)" \ + " UndefinedInstruction(behavior)" \ "\n" \ "Where behavior is a" \ - " pychrysalide.arch.instructions.UndefInstruction.ExpectedBehavior" \ + " pychrysalide.arch.instructions.UndefinedInstruction.ExpectedBehavior" \ " constant describing the state of the CPU once the instruction is run." /* Récupération des paramètres */ - ret = PyArg_ParseTupleAndKeywords(args, kwds, "k", kwlist, &behavior); + ret = PyArg_ParseTuple(args, "O&", convert_to_undefined_expected_behavior, &behavior); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -158,17 +105,22 @@ static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *k /* Eléments de base */ - instr = G_UNDEF_INSTRUCTION(pygobject_get(self)); - - extra = GET_UNDEF_INSTR_EXTRA(instr); + instr = G_UNDEFINED_INSTRUCTION(pygobject_get(self)); - extra->behavior = behavior; + if (!g_undefined_instruction_create(instr, behavior)) + return -1; return 0; } + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONNALITES DE L'INSTRUCTION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = classe représentant une instruction. * @@ -182,24 +134,25 @@ static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *k * * ******************************************************************************/ -static PyObject *py_undef_instruction_get_behavior(PyObject *self, void *closure) +static PyObject *py_undefined_instruction_get_behavior(PyObject *self, void *closure) { PyObject *result; /* Conversion à retourner */ - GUndefInstruction *instr; /* Version native */ + GUndefinedInstruction *instr; /* Version native */ InstrExpectedBehavior behavior; /* Comportement attendu */ -#define UNDEF_INSTRUCTION_BEHAVIOR_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - behavior, py_undef_instruction, \ - "Consequence carried by the undefined instruction.\n" \ - "\n" \ - "The result is provided as a" \ - " pychrysalide.arch.instructions.UndefInstruction.ExpectedBehavior" \ - " constant." \ +#define UNDEFINED_INSTRUCTION_BEHAVIOR_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + behavior, py_undefined_instruction, \ + "Consequence carried by the undefined instruction.\n" \ + "\n" \ + "The result is provided as a" \ + " pychrysalide.arch.instructions.UndefinedInstruction.ExpectedBehavior" \ + " constant." \ ) - instr = G_UNDEF_INSTRUCTION(pygobject_get(self)); - behavior = g_undef_instruction_get_behavior(instr); + instr = G_UNDEFINED_INSTRUCTION(pygobject_get(self)); + + behavior = g_undefined_instruction_get_behavior(instr); result = cast_with_constants_group_from_type(get_python_undefined_instruction_type(), "ExpectedBehavior", behavior); @@ -228,7 +181,7 @@ PyTypeObject *get_python_undefined_instruction_type(void) }; static PyGetSetDef py_undefined_instruction_getseters[] = { - UNDEF_INSTRUCTION_BEHAVIOR_ATTRIB, + UNDEFINED_INSTRUCTION_BEHAVIOR_ATTRIB, { NULL } }; @@ -236,18 +189,18 @@ PyTypeObject *get_python_undefined_instruction_type(void) PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.arch.instructions.UndefInstruction", + .tp_name = "pychrysalide.arch.instructions.UndefinedInstruction", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = UNDEF_INSTRUCTION_DOC, + .tp_doc = UNDEFINED_INSTRUCTION_DOC, .tp_methods = py_undefined_instruction_methods, .tp_getset = py_undefined_instruction_getseters, - .tp_init = py_undef_instruction_init, - .tp_new = py_undef_instruction_new, + .tp_init = py_undefined_instruction_init, + .tp_new = py_undefined_instruction_new, }; @@ -260,7 +213,7 @@ PyTypeObject *get_python_undefined_instruction_type(void) * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Prend en charge l'objet 'pychrysalide.....UndefInstruction'. * +* Description : Prend en charge l'objet '....UndefinedInstruction'. * * * * Retour : Bilan de l'opération. * * * @@ -285,7 +238,7 @@ bool ensure_python_undefined_instruction_is_registered(void) if (!ensure_python_arch_instruction_is_registered()) return false; - if (!register_class_for_pygobject(dict, G_TYPE_UNDEF_INSTRUCTION, type)) + if (!register_class_for_pygobject(dict, G_TYPE_UNDEFINED_INSTRUCTION, type)) return false; if (!define_undefined_instruction_constants(type)) @@ -329,7 +282,7 @@ int convert_to_undefined_instruction(PyObject *arg, void *dst) break; case 1: - *((GUndefInstruction **)dst) = G_UNDEF_INSTRUCTION(pygobject_get(arg)); + *((GUndefinedInstruction **)dst) = G_UNDEFINED_INSTRUCTION(pygobject_get(arg)); break; default: diff --git a/plugins/pychrysalide/arch/instructions/undefined.h b/plugins/pychrysalide/arch/instructions/undefined.h index 3fa0453..1453612 100644 --- a/plugins/pychrysalide/arch/instructions/undefined.h +++ b/plugins/pychrysalide/arch/instructions/undefined.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.h - prototypes pour l'équivalent Python du fichier "arch/instructions/undefined.h" * - * Copyright (C) 2019 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -34,7 +34,7 @@ /* Fournit un accès à une définition de type à diffuser. */ PyTypeObject *get_python_undefined_instruction_type(void); -/* Prend en charge l'objet 'pychrysalide.arch.instructions.UndefInstruction'. */ +/* Prend en charge l'objet 'pychrysalide.arch.instructions.UndefinedInstruction'. */ bool ensure_python_undefined_instruction_is_registered(void); /* Tente de convertir en instruction non définie. */ diff --git a/plugins/pychrysalide/arch/module-ui.c b/plugins/pychrysalide/arch/module-ui.c index 201f760..65d1290 100644 --- a/plugins/pychrysalide/arch/module-ui.c +++ b/plugins/pychrysalide/arch/module-ui.c @@ -29,6 +29,7 @@ #include "operand-ui.h" +#include "../glibext/generator.h" @@ -52,6 +53,12 @@ bool populate_arch_module_ui(void) if (result) result = ensure_python_arch_operand_ui_is_registered(); + /** + * Préparation du terrain pour les instructions, sans lien directe + * de la partie UI depuis la partie NOX. + */ + if (result) result = ensure_python_token_generator_is_registered(); + assert(result); return result; diff --git a/plugins/pychrysalide/arch/module.c b/plugins/pychrysalide/arch/module.c index 3f52a58..94f5ad7 100644 --- a/plugins/pychrysalide/arch/module.c +++ b/plugins/pychrysalide/arch/module.c @@ -32,14 +32,12 @@ #include "context.h" #include "instriter.h" */ -//#include "instruction.h" +#include "instruction.h" #include "operand.h" //#include "processor.h" #include "register.h" #include "vmpa.h" -/* #include "instructions/module.h" -*/ #include "operands/module.h" #include "../helpers.h" @@ -77,9 +75,7 @@ bool add_arch_module(PyObject *super) result = (module != NULL); - /* if (result) result = add_arch_instructions_module(module); - */ if (result) result = add_arch_operands_module(module); return result; @@ -109,16 +105,14 @@ 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_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(); assert(result); diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c index 42bd247..2281dae 100644 --- a/plugins/pychrysalide/arch/operand.c +++ b/plugins/pychrysalide/arch/operand.c @@ -94,6 +94,10 @@ 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 *); +/* Détermine si un opérande possède un fanion particulier. */ +static PyObject *py_arch_operand_has_flag(PyObject *, PyObject *); + + /* ---------------------------------------------------------------------------------- */ diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 127ca4c..6683854 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -13,18 +13,17 @@ noinst_LTLIBRARIES = libarch.la libarchui.la # 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 = \ + instruction-int.h \ + instruction.h instruction.c \ operand-int.h \ operand.h operand.c \ register-int.h \ @@ -34,10 +33,13 @@ libarch_la_SOURCES = \ libarch_la_CFLAGS = $(LIBGOBJ_CFLAGS) libarch_la_LIBADD = \ + instructions/libarchinstructions.la \ operands/libarchoperands.la libarchui_la_SOURCES = \ + instruction-ui-int.h \ + instruction-ui.h instruction-ui.c \ operand-ui-int.h \ operand-ui.h operand-ui.c @@ -52,5 +54,4 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libarch_la_SOURCES:%c=) $(libarchui_la_SOURCES:%c=) -#SUBDIRS = instructions operands -SUBDIRS = operands +SUBDIRS = instructions operands diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 7dbbe27..d426cea 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction-int.h - prototypes pour la définition générique interne des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,18 +25,29 @@ #define _ARCH_INSTRUCTION_INT_H +#include + + #include "instruction.h" -#include "../analysis/storage/storage.h" #include "../common/array.h" -#include "../glibext/objhole.h" +#include "../glibext/objhole-int.h" /* Indique l'encodage d'une instruction de façon détaillée. */ -typedef const char * (* get_instruction_encoding_fc) (const GArchInstruction *); +typedef char * (* get_instruction_encoding_fc) (const GArchInstruction *); /* Fournit le nom humain de l'instruction manipulée. */ -typedef const char * (* get_instruction_keyword_fc) (GArchInstruction * ); +typedef char * (* get_instruction_keyword_fc) (const GArchInstruction *); + + + +#if 0 + +#include "../analysis/storage/storage.h" + + + /* Complète un désassemblage accompli pour une instruction. */ typedef void (* call_instruction_hook_fc) (GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); @@ -67,80 +78,45 @@ typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, pac -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _instr_extra_data_t -{ - itid_t uid; /* Identifiant unique du type */ - - ArchInstrFlag flags; /* Informations complémentaires*/ - -} instr_extra_data_t; +#endif -/* Informations glissées dans la structure GObject de GArchInstruction */ -typedef union _instr_obj_extra_t -{ - instr_extra_data_t data; /* Données embarquées */ - lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */ -} instr_obj_extra_t; +/* Conservation d'une adresse et de propriétées */ +typedef unsigned long compact_ins_link_t; /* Définition générique d'une instruction d'architecture (instance) */ struct _GArchInstruction { - GObject parent; /* A laisser en premier */ + GThickObject parent; /* A laisser en premier */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ + GBinaryPortion *rel_area; /* Zone de référence */ + rel_mrange_t rel_range; /* Emplacement compressé */ /** - * 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. + * A laisser à la suite de la localisation précédente pour éviter + * les espaces vide dans la structure. */ + uint16_t link_count; /* Quantité de liens établis */ - instr_obj_extra_t extra; /* Externalisation embarquée */ - -#endif - - mrange_t range; /* Emplacement en mémoire */ + compact_ins_link_t *links; /* Liste de ces liens */ flat_array_t *operands; /* Liste des opérandes */ - /** - * Il existe le besoin indéniable d'un verrou pour les accès aux instructions - * liées. Il faut par ailleurs un verrou distinct pour les sources et les - * destinations car une même instruction peut boucler sur elle même et la - * fonction g_arch_instruction_change_link() pose des verrous sur les - * deux extrémités. - * - * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais - * sans distinction entre lectures et écritures. Tant pis : la réduction de - * l'empreinte mémoire prime ! - * - * Par contre la documentation indique : - * - * """ - * Attempting to lock on two different bits within the same integer is not supported. - * """ - * - * Donc on doit bien conserver un compteur distinct pour chaque extrémité. - * Cela correspond de toute façon à la définition optimisée des tableaux - * suivante. - */ - - flat_array_t *from; /* Origines des références */ - flat_array_t *to; /* Instructions visées */ - }; /* Définition générique d'une instruction d'architecture (classe) */ struct _GArchInstructionClass { - GObjectClass parent; /* A laisser en premier */ + GThickObjectClass parent; /* A laisser en premier */ get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */ get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */ + +#if 0 + + //get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */ + //get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */ call_instruction_hook_fc call_hook; /* Décrochages éventuels */ build_instruction_tooltip_fc build_tooltip; /* Construction d'une bulle*/ get_instruction_desc_fc get_desc; /* Description assez complète */ @@ -155,22 +131,50 @@ struct _GArchInstructionClass //get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */ +#endif + }; +/* Met en place une instruction d'architecture. */ +bool g_arch_instruction_create(GArchInstruction *, itid_t); + + + /** * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ -# define GET_ARCH_INSTR_EXTRA(ins) (instr_extra_data_t *)&ins->extra +#define ARCH_INSTRUCTION_EXTRA_DATA \ + \ + unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \ + \ + /** \ + * itid_t \ + */ \ + unsigned int tid : 16; \ + \ + /** \ + * ArchOperandFlag \ + */ \ + unsigned int flags : 8; -#else -# define GET_ARCH_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), instr_extra_data_t) +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _instruction_extra_data_t +{ + ARCH_INSTRUCTION_EXTRA_DATA; /* Socle commun */ + +} instruction_extra_data_t; + + +#define GET_ARCH_INSTR_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, instruction_extra_data_t) + +#define SET_ARCH_INSTR_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, instruction_extra_data_t, data) -#endif /** diff --git a/src/arch/instruction-ui-int.h b/src/arch/instruction-ui-int.h new file mode 100644 index 0000000..b07f40c --- /dev/null +++ b/src/arch/instruction-ui-int.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui-int.h - prototypes pour la définition générique interne des instructions 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_INSTRUCTION_UI_INT_H +#define _ARCH_INSTRUCTION_UI_INT_H + + +#include "instruction-ui.h" + + + +#if 0 + +/* 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 + + +#endif /* _ARCH_INSTRUCTION_UI_INT_H */ diff --git a/src/arch/instruction-ui.c b/src/arch/instruction-ui.c new file mode 100644 index 0000000..7f923d8 --- /dev/null +++ b/src/arch/instruction-ui.c @@ -0,0 +1,254 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui.c - gestion générique des instructions 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 "instruction-ui.h" + + +#include "instruction-int.h" +#include "operand-ui.h" +#include "../analysis/content.h" +#include "../common/cpp.h" +#include "../glibext/generator-int.h" +#include "../glibext/options/asm.h" + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *, size_t, size_t); + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_arch_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + +#if 0 + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *); + +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + /** + * La procédure par défaut de iface->count() ne doit pas être retouchée ! + */ + + iface->get_flags = g_arch_instruction_ui_get_flags; + iface->populate = g_arch_instruction_ui_populate_line; + +#if 0 + iface->compute = (linegen_compute_fc)g_arch_instruction_ui_compute_cursor; + iface->contain = (linegen_contain_fc)g_arch_instruction_ui_contain_cursor; +#endif + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat) +{ + BufferLineFlags result; /* Fanions à retourner */ + + result = BLF_HAS_CODE; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + char *key; /* Mot clef principal */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + + instr = G_ARCH_INSTRUCTION(generator); + content = G_BIN_CONTENT(data); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr)); + + free(key); + + /* Liste des opérandes */ + + g_thick_object_lock(G_THICK_OBJECT(instr)); + + count = g_arch_instruction_count_operands(instr); + + if (count > 0) + { + op = g_arch_instruction_get_operand(instr, 0); + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + unref_object(op); + + for (i = 1; i < count; i++) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_NONE, STCSL(" "), NULL, NULL); + + op = g_arch_instruction_get_operand(instr, i); + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + unref_object(op); + + } + + } + + g_thick_object_unlock(G_THICK_OBJECT(instr)); + +} + + +#if 0 + + +/****************************************************************************** +* * +* Paramètres : instr = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à constituer. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor) +{ + *cursor = g_binary_cursor_new(); + + g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à analyser. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor) +{ + int result; /* Conclusion à retourner */ + vmpa2t addr; /* Autre emplacement à comparer*/ + + assert(G_IS_BINARY_CURSOR(cursor)); + + g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + + result = cmp_mrange_with_vmpa(&instr->range, &addr); + + return result; + +} + + +#endif diff --git a/src/arch/instruction-ui.h b/src/arch/instruction-ui.h new file mode 100644 index 0000000..62a52f2 --- /dev/null +++ b/src/arch/instruction-ui.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui.h - prototypes pour la gestion générique des instructions 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_INSTRUCTION_UI_H +#define _ARCH_INSTRUCTION_UI_H + + +#include "../glibext/generator.h" +#include "../glibext/helpers.h" + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_INSTRUCTION_UI_H */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index cd1e9c7..36bdecb 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction.c - gestion générique des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,102 +26,93 @@ #include #include -#include -#include -#include +#include #include #include "instruction-int.h" -#include "storage.h" -#include "../analysis/storage/serialize-int.h" -#include "../core/columns.h" +#include "../common/leb128.h" #include "../core/logs.h" #include "../core/processors.h" -#include "../glibext/gbinarycursor.h" -#include "../glibext/linegen-int.h" +#include "../glibext/serialize-int.h" -/* Initialise la classe générique des instructions. */ -static void g_arch_instruction_class_init(GArchInstructionClass *); - -/* Initialise une instance d'opérande d'architecture. */ -static void g_arch_instruction_init(GArchInstruction *); - -/* Procède à l'initialisation de l'interface de génération. */ -static void g_arch_instruction_generator_init(GLineGeneratorInterface *); - -/* Procède à l'initialisation de l'interface de sérialisation. */ -static void g_arch_instruction_serializable_init(GSerializableObjectInterface *); -/* Supprime toutes les références externes. */ -static void g_arch_instruction_dispose(GArchInstruction *); -/* Procède à la libération totale de la mémoire. */ -static void g_arch_instruction_finalize(GArchInstruction *); +/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */ +/* Initialise la classe générique des instructions. */ +static void g_arch_instruction_class_init(GArchInstructionClass *); +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Initialise une instance d'opérande d'architecture. */ +static void g_arch_instruction_init(GArchInstruction *); -/* Sauvegarde toutes les destinations d'une instruction. */ -bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Supprime toutes les références externes. */ +static void g_arch_instruction_dispose(GObject *); +/* Procède à la libération totale de la mémoire. */ +static void g_arch_instruction_finalize(GObject *); +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ +#define COMPACT_INS_LINK_MASK_DIR (1ul << (__WORDSIZE - 1)) +#define COMPACT_INS_LINK_MASK_TYPE 0xf +#define COMPACT_INS_LINK_MASK (COMPACT_INS_LINK_MASK_DIR | COMPACT_INS_LINK_MASK_TYPE) -/* Indique le nombre de ligne prêtes à être générées. */ -static size_t g_arch_instruction_count_lines(const GArchInstruction *); +#define COMPACT_INS_LINK_FROM (0ul << (__WORDSIZE - 1)) +#define COMPACT_INS_LINK_TO (1ul << (__WORDSIZE - 1)) -#ifdef INCLUDE_GTK_SUPPORT +#define COMPACT_INS_LINK_DIR(cl) (cl & COMPACT_INS_LINK_MASK_DIR) +#define COMPACT_INS_LINK_PTR(cl) ((GArchInstruction *)(cl & ~COMPACT_INS_LINK_MASK)) +#define COMPACT_INS_LINK_TYPE(cl) (cl & COMPACT_INS_LINK_MASK_TYPE) -/* Retrouve l'emplacement correspondant à une position donnée. */ -static void g_arch_instruction_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **); +#define MAKE_COMPACT_INS_LINK(d, i, t) \ + (compact_ins_link_t)(d | (unsigned long)i | t) -/* Détermine si le conteneur s'inscrit dans une plage donnée. */ -static int g_arch_instruction_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *); +/* Détermine si un type de lien existe dans une instruction. */ +static bool _g_arch_instruction_has_link(const GArchInstruction *, compact_ins_link_t, InstructionLinkType); -#endif +/* Détermine si un lien existe entre deux instructions. */ +static bool _g_arch_instruction_has_link_with(const GArchInstruction *, compact_ins_link_t, const GArchInstruction *); -/* Renseigne sur les propriétés liées à un générateur. */ -static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *, size_t, size_t); +/* Fournit la quantité d'instructions pointant vers une autre. */ +static size_t _g_arch_instruction_count_links(const GArchInstruction *, compact_ins_link_t); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +/* Fournit les détails d'un lien donné avec une instruction. */ +static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *, size_t, compact_ins_link_t, InstructionLinkType *); -/* Imprime dans une ligne de rendu le contenu représenté. */ -static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Charge un objet depuis un flux de données. */ +static bool g_arch_instruction_load(GSerializableObject *, GObjectStorage *, int); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_arch_instruction_store(const GSerializableObject *, GObjectStorage *, int); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION GENERIQUE D'INSTRUCTION */ +/* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour une instruction d'architecture. */ -G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_init) - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init)); +G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_THICK_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_arch_instruction_ui_token_generator_iface_init)); + /****************************************************************************** @@ -139,28 +130,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT, static void g_arch_instruction_class_init(GArchInstructionClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchInstructionClass *instr; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose; - object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize; - - instr = G_ARCH_INSTRUCTION_CLASS(klass); - - instr->print = (print_instruction_fc)_g_arch_instruction_print; - - instr->load = (load_instruction_fc)_g_arch_instruction_load; - instr->store = (store_instruction_fc)_g_arch_instruction_store; + object->dispose = g_arch_instruction_dispose; + object->finalize = g_arch_instruction_finalize; } /****************************************************************************** * * -* Paramètres : instr = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance d'instruction d'architecture. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -168,27 +151,19 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) * * ******************************************************************************/ -static void g_arch_instruction_init(GArchInstruction *instr) +static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *iface) { - instr_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - INIT_GOBJECT_EXTRA_LOCK(extra); - - instr->operands = NULL; - - instr->from = NULL; - instr->to = NULL; + iface->load = g_arch_instruction_load; + iface->store = g_arch_instruction_store; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : instr = instance à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de génération. * +* Description : Initialise une instance d'instruction d'architecture. * * * * Retour : - * * * @@ -196,42 +171,22 @@ static void g_arch_instruction_init(GArchInstruction *instr) * * ******************************************************************************/ -static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface) +static void g_arch_instruction_init(GArchInstruction *instr) { - iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines; -#ifdef INCLUDE_GTK_SUPPORT - iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor; - iface->contain = (linegen_contain_fc)g_arch_instruction_contain_cursor; -#endif - iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2; - iface->print = (linegen_print_fc)g_arch_instruction_print; - -} + instr->rel_area = NULL; + instr->link_count = 0; -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * -* Description : Procède à l'initialisation de l'interface de sérialisation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + instr->links = NULL; -static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface) -{ - iface->load = (load_serializable_object_cb)g_arch_instruction_load; - iface->store = (store_serializable_object_cb)g_arch_instruction_store; + instr->operands = NULL; } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -241,43 +196,38 @@ static void g_arch_instruction_serializable_init(GSerializableObjectInterface *i * * ******************************************************************************/ -static void g_arch_instruction_dispose(GArchInstruction *instr) +static void g_arch_instruction_dispose(GObject *object) { + GArchInstruction *instr; /* Version spécialisée */ size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande à manipuler */ - g_arch_instruction_lock_operands(instr); + instr = G_ARCH_INSTRUCTION(object); + + g_clear_object(&instr->rel_area); - count = _g_arch_instruction_count_operands(instr); + g_arch_instruction_delete_all_links(instr); + + g_thick_object_lock(G_THICK_OBJECT(instr)); + + count = g_arch_instruction_count_operands(instr); for (i = 0; i < count; i++) { - op = _g_arch_instruction_get_operand(instr, 0); + op = g_arch_instruction_get_operand(instr, 0); rem_item_from_flat_array(&instr->operands, 0, sizeof(GArchOperand *)); /** * Une fois pour l'obtention, une autre pour la libération ! */ - g_object_unref(G_OBJECT(op)); - g_object_unref(G_OBJECT(op)); + unref_object(op); + unref_object(op); } - g_arch_instruction_unlock_operands(instr); - -#ifndef NDEBUG - g_arch_instruction_lock_src(instr); - assert(count_flat_array_items(instr->from) == 0); - g_arch_instruction_unlock_src(instr); -#endif - -#ifndef NDEBUG - g_arch_instruction_lock_dest(instr); - assert(count_flat_array_items(instr->to) == 0); - g_arch_instruction_unlock_dest(instr); -#endif + g_thick_object_unlock(G_THICK_OBJECT(instr)); G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr)); @@ -286,7 +236,7 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -296,38 +246,26 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) * * ******************************************************************************/ -static void g_arch_instruction_finalize(GArchInstruction *instr) +static void g_arch_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); - -} + GArchInstruction *instr; /* Version spécialisée */ + instr = G_ARCH_INSTRUCTION(object); -/****************************************************************************** -* * -* Paramètres : instr = instruction quelconque à consulter. * -* * -* Description : Indique l'encodage d'une instruction de façon détaillée. * -* * -* Retour : Description humaine de l'encodage utilisé. * -* * -* Remarques : - * -* * -******************************************************************************/ + if (instr->links != NULL) + free(instr->links); -const char *g_arch_instruction_get_encoding(const GArchInstruction *instr) -{ - return G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_encoding(instr); + G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * -* flag = drapeau d'information complémentaire à planter. * +* Paramètres : instr = instance à initialiser pleinement. * +* tid = identifiant associé au type d'instructions ciblé. * * * -* Description : Ajoute une information complémentaire à une instruction. * +* Description : Met en place une instruction d'architecture. * * * * Retour : Bilan de l'opération. * * * @@ -335,22 +273,18 @@ const char *g_arch_instruction_get_encoding(const GArchInstruction *instr) * * ******************************************************************************/ -bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) +bool g_arch_instruction_create(GArchInstruction *instr, itid_t tid) { bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ + instruction_extra_data_t extra; /* Données insérées à modifier */ - assert(flag <= AIF_HIGH_USER); + result = true; extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = !(extra->flags & flag); - - extra->flags |= flag; + extra.tid = tid; - UNLOCK_GOBJECT_EXTRA(extra); + SET_ARCH_INSTR_EXTRA(instr, &extra); return result; @@ -359,33 +293,24 @@ bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * -* flag = drapeau d'information complémentaire à planter. * +* Paramètres : instr = instruction quelconque à consulter. * * * -* Description : Retire une information complémentaire à une instruction. * +* Description : Fournit l'identifiant correspondant à un type d'instructions.* * * -* Retour : Bilan de l'opération. * +* Retour : Identifiant unique par type d'instruction et architecture. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag) +itid_t g_arch_instruction_get_type_id(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - assert(flag <= AIF_HIGH_USER); + itid_t result; /* Numéro à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - extra->flags &= ~flag; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.tid; return result; @@ -395,30 +320,23 @@ bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag) /****************************************************************************** * * * Paramètres : instr = instruction quelconque à consulter. * -* flag = drapeau d'information à rechercher. * * * -* Description : Détermine si une instruction possède un fanion particulier. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Bilan de la détection. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag flag) +char *g_arch_instruction_get_encoding(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - assert(flag <= AIF_HIGH_USER); - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Encodage à retourner */ + GArchInstructionClass *class; /* Classe des instructions */ - result = (extra->flags & flag); + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - UNLOCK_GOBJECT_EXTRA(extra); + result = class->get_encoding(instr); return result; @@ -427,28 +345,24 @@ bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag fl /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Fournit les informations complémentaires d'une instruction. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Eventuels drapeaux d'information complémentaire à plantés. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) +char *g_arch_instruction_get_keyword(const GArchInstruction *instr) { - ArchInstrFlag result; /* Fanions à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Etiquette à retourner */ + GArchInstructionClass *class; /* Classe des instructions */ - result = extra->flags; + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - UNLOCK_GOBJECT_EXTRA(extra); + result = class->get_keyword(instr); return result; @@ -457,10 +371,12 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * -* uid = identifiant unique par type d'instruction. * +* Paramètres : instr = instruction quelconque à compléter. * +* area = portion de binaire incluant l'instruction. * +* start = adresse virtuelle et/ou position physique. * +* length = taille de l'instruction. * * * -* Description : Définit l'identifiant unique pour un ensemble d'instructions.* +* Description : Calcule la localisation d'une instruction. * * * * Retour : - * * * @@ -468,45 +384,56 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) * * ******************************************************************************/ -void g_arch_instruction_set_unique_id(GArchInstruction *instr, itid_t uid) +void g_arch_instruction_compute_range(GArchInstruction *instr, GBinaryPortion *area, const vmpa2t *start, phys_t length) { - instr_extra_data_t *extra; /* Données insérées à modifier */ + const mrange_t *a_range; /* Couverture de la portion */ + phys_t diff; /* Décalage à appliquer */ - extra = GET_ARCH_INSTR_EXTRA(instr); + a_range = g_binary_portion_get_range(area); + + assert(mrange_contains_addr(a_range, start)); - LOCK_GOBJECT_EXTRA(extra); + diff = compute_vmpa_diff(get_mrange_addr(a_range), start); - extra->uid = uid; + instr->rel_area = area; + ref_object(area); - UNLOCK_GOBJECT_EXTRA(extra); + init_rel_mrange(&instr->rel_range, diff, length); } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * +* Paramètres : instr = instruction quelconque à consulter. * +* range = localisation de l'instruction. [OUT] * * * -* Description : Fournit l'identifiant unique pour un ensemble d'instructions.* +* Description : Fournit la place mémoire d'une instruction. * * * -* Retour : Identifiant unique par type d'instruction et architecture. * +* Retour : Validité de la localisation : existence d'une définition ? * * * * Remarques : - * * * ******************************************************************************/ -itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr) +bool g_arch_instruction_get_range(const GArchInstruction *instr, mrange_t *range) { - itid_t result; /* Numéro à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ + bool result; /* Statut à retourner */ + const mrange_t *a_range; /* Couverture de la portion */ + vmpa2t start; /* Position de départ complète */ - extra = GET_ARCH_INSTR_EXTRA(instr); + result = (instr->rel_area != NULL); + + if (result) + { + a_range = g_binary_portion_get_range(instr->rel_area); - LOCK_GOBJECT_EXTRA(extra); + copy_vmpa(&start, get_mrange_addr(a_range)); + advance_vmpa(&start, get_rel_mrange_offset(&instr->rel_range)); - result = extra->uid; + init_mrange(range, &start, get_rel_mrange_length(&instr->rel_range)); - UNLOCK_GOBJECT_EXTRA(extra); + } return result; @@ -515,234 +442,259 @@ itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à traiter. * -* type = type de procédure à utiliser. * -* proc = représentation de l'architecture utilisée. * -* context = contexte associé à la phase de désassemblage. * -* format = accès aux données du binaire d'origine. * +* Paramètres : instr = instruction à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * * * -* Description : Complète un désassemblage accompli pour une instruction. * +* Description : Ajoute une information complémentaire à une instruction. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format) +bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstructionFlag flag) { - GArchInstructionClass *class; /* Classe des instructions */ + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + assert(flag <= AIF_HIGH_USER); - if (class->call_hook != NULL) - class->call_hook(instr, type, proc, context, format); + extra = GET_ARCH_INSTR_EXTRA(instr); + + result = !(extra.flags & flag); + + extra.flags |= flag; + + SET_ARCH_INSTR_EXTRA(instr, &extra); + + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * -* address = adresse virtuelle et/ou position physique. * -* length = taille de l'instruction. * +* Paramètres : instr = instruction à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * * * -* Description : Définit la localisation d'une instruction. * +* Description : Retire une information complémentaire à une instruction. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_set_range(GArchInstruction *instr, const mrange_t *range) +bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstructionFlag flag) { - copy_mrange(&instr->range, range); + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ + + assert(flag <= AIF_HIGH_USER); + + extra = GET_ARCH_INSTR_EXTRA(instr); + + result = (extra.flags & flag); + + extra.flags &= ~flag; + + SET_ARCH_INSTR_EXTRA(instr, &extra); + + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * +* Paramètres : instr = instruction à venir consulter. * +* flag = drapeau d'information à rechercher. * * * -* Description : Fournit la place mémoire d'une instruction. * +* Description : Détermine si une instruction possède un fanion particulier. * * * -* Retour : Zone mémoire couverte par l'instruction. * +* Retour : Bilan de la détection. * * * * Remarques : - * * * ******************************************************************************/ -const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr) +bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstructionFlag flag) { - return &instr->range; + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ -} + assert(flag <= AIF_HIGH_USER); + + extra = GET_ARCH_INSTR_EXTRA(instr); + + result = (extra.flags & flag); + + return result; +} /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * -* offset = position physique dans le code binaire/NULL. [OUT] * -* length = taille de l'instruction ou NULL. [OUT] * -* address = adresse virtuelle ou position physique/NULL. [OUT] * +* Paramètres : instr = instruction à venir consulter. * * * -* Description : Fournit la localisation d'une instruction. * +* Description : Fournit les particularités de l'instruction. * * * -* Retour : - * +* Retour : Somme de tous les fanions associés à l'opérande. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offset, off_t *length, vmpa_t *address) +ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *instr) { - //if (offset != NULL) *offset = instr->offset; - //if (length != NULL) *length = instr->length; + ArchInstructionFlag result; /* Fanions à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + result = extra.flags; - //if (address != NULL) *address = instr->address; + return result; } +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : instr = instruction à consulter. * -* rregs = liste des rgistres lus. [OUT] * -* rcount = nombre de registres lus. [OUT] * -* wregs = liste des rgistres écrits. [OUT] * -* wcount = nombre de registres écrits. [OUT] * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction du lien recherché. * +* type = type de lien à détecter. * * * -* Description : Liste les registres lus et écrits par l'instruction. * +* Description : Détermine si un type de lien existe dans une instruction. * * * -* Retour : - * +* Retour : Bilan du statut courant de l'instruction. * * * -* Remarques : Les compteurs de références sont à décrémenter après usage ! * +* Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount) +static bool _g_arch_instruction_has_link(const GArchInstruction *instr, compact_ins_link_t dir, InstructionLinkType type) { -#if 0 - - size_t i; /* Boucle de parcours */ - - *rregs = NULL; - *rcount = 0; - *wregs = NULL; - *wcount = 0; + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ - instr->get_rw_regs(instr, rregs, rcount, wregs, wcount); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - for (i = 0; i < *rcount; i++) - g_object_ref(G_OBJECT((*rregs)[i])); + result = false; - for (i = 0; i < *wcount; i++) - g_object_ref(G_OBJECT((*wregs)[i])); + for (i = 0; i < instr->link_count && !result; i++) + result = COMPACT_INS_LINK_DIR(instr->links[i]) == dir; -#endif + return result; } - -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATION DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction à mettre à jour. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* type = type de lien à détecter. * * * -* Description : Verrouille les accès à la liste des opérandes. * +* Description : Détermine si un type de lien amène à une instruction. * * * -* Retour : - * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_lock_operands(GArchInstruction *instr) +bool g_arch_instruction_has_src_link(const GArchInstruction *instr, InstructionLinkType type) { - lock_flat_array(&instr->operands); + bool result; /* Bilan à retourner */ + + result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_FROM, type); + + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction à mettre à jour. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* type = type de lien à détecter. * * * -* Description : Déverrouille les accès à la liste des opérandes. * +* Description : Détermine si un type de lien émerge d'une instruction. * * * -* Retour : - * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_unlock_operands(GArchInstruction *instr) +bool g_arch_instruction_has_dest_link(const GArchInstruction *instr, InstructionLinkType type) { - unlock_flat_array(&instr->operands); + bool result; /* Bilan à retourner */ + + result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_TO, type); + + return result; } /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* operand = instruction à venir associer. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction du lien recherché. * +* linked = seconde instruction à considérer. * * * -* Description : Attache un opérande supplémentaire à une instruction. * +* Description : Détermine si un lien existe entre deux instructions. * * * -* Retour : - * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand) +static bool _g_arch_instruction_has_link_with(const GArchInstruction *instr, compact_ins_link_t dir, const GArchInstruction *linked) { - GSingletonFactory *factory; /* Unise à instances uniques */ - GArchOperand *singleton; /* Instance retenue */ - - factory = get_operands_factory(); - - singleton = G_ARCH_OPERAND(g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand))); + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ - g_object_unref(G_OBJECT(operand)); - g_object_unref(G_OBJECT(factory)); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - g_arch_instruction_lock_operands(instr); + result = false; - add_item_to_flat_array(&instr->operands, &singleton, sizeof(GArchOperand *)); + for (i = 0; i < instr->link_count && !result; i++) + result = COMPACT_INS_LINK_PTR(instr->links[i]) == linked; - g_arch_instruction_unlock_operands(instr); + return result; } /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* src = seconde instruction à considérer. * * * -* Description : Indique la quantité d'opérandes présents dans l'instruction. * +* Description : Détermine si une instruction est source d'une autre. * * * -* Retour : Nombre d'opérandes attachés. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -size_t _g_arch_instruction_count_operands(const GArchInstruction *instr) +bool g_arch_instruction_has_src_link_with(const GArchInstruction *instr, const GArchInstruction *src) { - size_t result; /* Décompte à retourner */ + bool result; /* Bilan à retourner */ - result = count_flat_array_items(instr->operands); + result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_FROM, src); return result; @@ -751,27 +703,22 @@ size_t _g_arch_instruction_count_operands(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * -* index = indice de l'opérande concerné. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dest = seconde instruction à considérer. * * * -* Description : Fournit un opérande donné d'une instruction. * +* Description : Détermine si une instruction est destination d'une autre. * * * -* Retour : Opérande trouvée. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index) +bool g_arch_instruction_has_dest_link_with(const GArchInstruction *instr, const GArchInstruction *dest) { - GArchOperand *result; /* Opérande à retourner */ - GArchOperand **ptr; /* Adresse dans le tableau */ - - ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *)); - - result = *ptr; + bool result; /* Bilan à retourner */ - g_object_ref(G_OBJECT(result)); + result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_TO, dest); return result; @@ -780,173 +727,165 @@ GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, siz /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* old = ancienne opérande à détacher. * -* new = nouvelle opérande à attacher. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * +* dest = ligne visée par la liaison (côté destination). * +* type = type de lien à construire. * * * -* Description : Remplace un opérande d'une instruction par un autre. * +* Description : Etablit un lien entre deux instructions. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) +void g_arch_instruction_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ - - result = false; - - count = _g_arch_instruction_count_operands(instr); + compact_ins_link_t new_from; /* Nouvel enregistrement #1 */ + compact_ins_link_t new_to; /* Nouvel enregistrement #2 */ - for (i = 0; i < count && !result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); + new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type); + ref_object(instr); - result = (op == old); + new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type); + ref_object(dest); - g_object_unref(G_OBJECT(op)); + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - } + dest->links = realloc(dest->links, ++dest->link_count * sizeof(compact_ins_link_t)); - if (result) - { - rpl_item_in_flat_array(instr->operands, i - 1, &new, sizeof(GArchOperand *)); + dest->links[dest->link_count - 1] = new_from; - g_object_unref(G_OBJECT(old)); + instr->links = realloc(instr->links, ++instr->link_count * sizeof(compact_ins_link_t)); - } + instr->links[instr->link_count - 1] = new_to; - return result; + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* target = instruction à venir dissocier. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * +* dest = ligne visée par la liaison (côté destination). * +* type = type de lien à construire. * * * -* Description : Détache un opérande liée d'une instruction. * +* Description : Supprime un lien entre deux instructions. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target) +void g_arch_instruction_unlink(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ + compact_ins_link_t old_from; /* Ancien enregistrement #1 */ + compact_ins_link_t old_to; /* Ancien enregistrement #2 */ + uint16_t i_from; /* Boucle de parcours #1 */ + uint16_t i_to; /* Boucle de parcours #2 */ + bool status; /* Bilan des recherches */ - result = false; + old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type); - count = _g_arch_instruction_count_operands(instr); + old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type); - for (i = 0; i < count && !result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - result = (op == target); + for (i_from = 0; i_from < dest->link_count; i_from++) + if (dest->links[i_from] == old_from) + break; - g_object_unref(G_OBJECT(op)); + for (i_to = 0; i_to < instr->link_count; i_to++) + if (instr->links[i_to] == old_to) + break; - } + assert((i_from < dest->link_count && i_to < instr->link_count) + || (i_from == dest->link_count && i_to == instr->link_count)); - if (result) + status = (i_from < dest->link_count && i_to < instr->link_count); + + if (status) { - rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *)); + if ((i_from + 1) < dest->link_count) + memmove(&dest->links[i_from], &dest->links[i_from + 1], + (dest->link_count - i_from - 1) * sizeof(compact_ins_link_t)); + + dest->links = realloc(dest->links, --dest->link_count * sizeof(compact_ins_link_t)); - g_object_unref(G_OBJECT(target)); + if ((i_to + 1) < instr->link_count) + memmove(&instr->links[i_to], &instr->links[i_to + 1], + (instr->link_count - i_to - 1) * sizeof(compact_ins_link_t)); + + instr->links = realloc(instr->links, --instr->link_count * sizeof(compact_ins_link_t)); } - return result; + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * -* target = instruction à venir retrouver. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * +* dest = ligne visée par la liaison (côté destination). * +* old = ancien type de lien construit. * +* new = nouveau type de lien à construire. * * * -* Description : Détermine le chemin conduisant à un opérande. * +* Description : Change la nature d'un lien entre deux instructions. * * * -* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * +* Retour : true pour une mise à jour réussie, false sinon. * * * -* Remarques : - * +* Remarques : Le verrou doit être posé sur les destinations de 'instr'. * * * ******************************************************************************/ -char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target) +bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new) { - char *result; /* Chemin à retourner */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ - int ret; /* Bilan d'une construction */ - char *sub_path; /* Sous-chemin emprunté */ - - result = NULL; - - g_arch_instruction_lock_operands(instr); + bool result; /* Bilan à retourner */ + compact_ins_link_t old_from; /* Ancien enregistrement #1 */ + compact_ins_link_t new_from; /* Nouvel enregistrement #1 */ + compact_ins_link_t old_to; /* Ancien enregistrement #2 */ + compact_ins_link_t new_to; /* Nouvel enregistrement #2 */ + uint16_t i_from; /* Boucle de parcours #1 */ + uint16_t i_to; /* Boucle de parcours #2 */ - count = _g_arch_instruction_count_operands(instr); + old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, old); + new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, new); - /* Première passe : accès direct */ + old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, old); + new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, new); - for (i = 0; i < count && result == NULL; i++) - { - op = _g_arch_instruction_get_operand(instr, i); + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - if (op == target) - { - ret = asprintf(&result, "%zu", i); - if (ret == -1) - { - LOG_ERROR_N("asprintf"); - result = NULL; - } - } + for (i_from = 0; i_from < dest->link_count; i_from++) + if (dest->links[i_from] == old_from) + break; - g_object_unref(G_OBJECT(op)); + for (i_to = 0; i_to < instr->link_count; i_to++) + if (instr->links[i_to] == old_to) + break; - } + assert((i_from < dest->link_count && i_to < instr->link_count) + || (i_from == dest->link_count && i_to == instr->link_count)); - /* Seconde passe : accès profond */ + result = (i_from < dest->link_count && i_to < instr->link_count); - for (i = 0; i < count && result == NULL; i++) + if (result) { - op = _g_arch_instruction_get_operand(instr, i); - - sub_path = g_arch_operand_find_inner_operand_path(op, target); - - if (sub_path != NULL) - { - ret = asprintf(&result, "%zu:%s", i, sub_path); - if (ret == -1) - { - LOG_ERROR_N("asprintf"); - result = NULL; - } - - free(sub_path); - - } - - g_object_unref(G_OBJECT(op)); - + dest->links[i_from] = new_from; + instr->links[i_to] = new_to; } - g_arch_instruction_unlock_operands(instr); + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; @@ -955,135 +894,127 @@ char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchO /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * -* path = chemin d'accès à un opérande à retrouver. * +* Paramètres : instr = instruction dont les informations sont à traiter. * * * -* Description : Obtient l'opérande correspondant à un chemin donné. * +* Description : Supprime tous les liens établis avec d'autres instructions. * * * -* Retour : Opérande trouvé ou NULL en cas d'échec. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path) +void g_arch_instruction_delete_all_links(GArchInstruction *instr) { - GArchOperand *result; /* Opérande trouvée à renvoyer */ - size_t index; /* Indice de l'opérande visé */ - char *end; /* Poursuite du parcours ? */ - GArchOperand *found; /* Opérande trouvé */ + GArchInstruction *linked; /* Autre instruction liée */ + InstructionLinkType type; /* Type de liaison */ - result = NULL; + g_thick_object_lock(G_THICK_OBJECT(instr)); - g_arch_instruction_lock_operands(instr); + while (g_arch_instruction_count_src_links(instr) > 0) + { + linked = g_arch_instruction_get_linked_source(instr, 0, &type); - /* Recherche au premier niveau */ + g_thick_object_unlock(G_THICK_OBJECT(instr)); - index = strtoul(path, &end, 10); + g_arch_instruction_unlink(linked, instr, type); - if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL)) - { - LOG_ERROR_N("strtoul"); - goto done; - } + g_thick_object_lock(G_THICK_OBJECT(instr)); - found = _g_arch_instruction_get_operand(instr, index); - if (found == NULL) goto done; + unref_object(linked); - if (*end == '\0') - { - result = found; - goto done; } - /* Recherche en profondeur */ + while (g_arch_instruction_count_dest_links(instr) > 0) + { + linked = g_arch_instruction_get_linked_destination(instr, 0, &type); - assert(*end == ':'); + g_thick_object_unlock(G_THICK_OBJECT(instr)); - result = g_arch_operand_get_inner_operand_from_path(found, end + 1); + g_arch_instruction_unlink(instr, linked, type); - g_object_unref(G_OBJECT(found)); + g_thick_object_lock(G_THICK_OBJECT(instr)); - done: + unref_object(linked); - g_arch_instruction_unlock_operands(instr); + } - return result; + g_thick_object_unlock(G_THICK_OBJECT(instr)); } - -/* ---------------------------------------------------------------------------------- */ -/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction à mettre à jour. * -* src = sélection de l'extrémité à traiter. * -* lock = indique le sens du verrouillage à mener. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction des liens à considérer. * * * -* Description : Met à disposition un encadrement des accès aux liens. * +* Description : Fournit la quantité d'instructions pointant vers une autre. * * * -* Retour : - * +* Retour : Nombre de ces liens. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock) +static size_t _g_arch_instruction_count_links(const GArchInstruction *instr, compact_ins_link_t dir) { - flat_array_t **array; /* Choix du tableau ciblé */ + size_t result; /* Nombre de liens à renvoyer */ + uint16_t i; /* Boucle de parcours */ + + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - array = (src ? &instr->from : &instr->to); + result = 0; - if (lock) - lock_flat_array(array); - else - unlock_flat_array(array); + for (i = 0; i < instr->link_count; i++) + if (COMPACT_INS_LINK_DIR(instr->links[i]) == dir) + result++; + + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* type = type de lien à détecter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * * * -* Description : Détermine si un type de lien existe dans une instruction. * +* Description : Fournit la quantité d'instructions placées en source. * * * -* Retour : Bilan du statut courant de l'instruction. * +* Retour : Nombre de ces liens. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType type) +size_t g_arch_instruction_count_src_links(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const instr_link_t *dlink; /* Définition de destination */ - - result = false; + size_t result; /* Nombre de liens à renvoyer */ - g_arch_instruction_lock_dest(instr); + result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_FROM); - count = g_arch_instruction_count_destinations(instr); + return result; - for (i = 0; i < count && !result; i++) - { - dlink = g_arch_instruction_get_destination(instr, i); +} - result = (dlink->type == type); - unref_instr_link(dlink); +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* * +* Description : Fournit la quantité d'instructions placées en destination. * +* * +* Retour : Nombre de ces liens. * +* * +* Remarques : - * +* * +******************************************************************************/ - } +size_t g_arch_instruction_count_dest_links(const GArchInstruction *instr) +{ + size_t result; /* Nombre de liens à renvoyer */ - g_arch_instruction_unlock_dest(instr); + result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_TO); return result; @@ -1092,41 +1023,47 @@ bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType ty /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* dest = ligne visée par la liaison (côté destination). * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* index = indice de l'élément à retrouver. * +* dir = direction des liens à considérer. * +* type = type de lien enregistré. [OUT] * * * -* Description : Détermine si un lien est déjà établi entre deux instructions.* +* Description : Fournit les détails d'un lien donné avec une instruction. * * * -* Retour : Bilan de l'état actuel des liaisons. * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest) +static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *instr, size_t index, compact_ins_link_t dir, InstructionLinkType *type) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const instr_link_t *dlink; /* Définition de destination */ - - result = false; + GArchInstruction *result; /* Instance ciblée à renvoyer */ + uint16_t i; /* Boucle de parcours */ - g_arch_instruction_lock_dest(instr); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - count = g_arch_instruction_count_destinations(instr); + result = NULL; + *type = ILT_COUNT; - for (i = 0; i < count && !result; i++) + for (i = 0; i < instr->link_count; i++) { - dlink = g_arch_instruction_get_destination(instr, i); + if (COMPACT_INS_LINK_DIR(instr->links[i]) != dir) + continue; - result = (dlink->linked == dest); + if (index == 0) + { + result = COMPACT_INS_LINK_PTR(instr->links[i]); + *type = COMPACT_INS_LINK_TYPE(instr->links[i]); + } - unref_instr_link(dlink); + else + index--; } - g_arch_instruction_unlock_dest(instr); + if (result != NULL) + ref_object(result); return result; @@ -1135,131 +1072,79 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* dest = ligne visée par la liaison (côté destination). * -* type = type de lien à construire. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* index = indice de l'élément à retrouver. * +* type = type de lien enregistré. [OUT] * * * -* Description : Etablit un lien entre deux instructions. * +* Description : Fournit les détails d'une source donnée d'une instruction. * * * -* Retour : - * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) +GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *instr, size_t index, InstructionLinkType *type) { - instr_link_t new_src; /* Nouveau lien à définir #1 */ - instr_link_t new_dst; /* Nouveau lien à définir #2 */ - - /* Côté destination */ - - new_src.linked = instr; - new_src.type = type; - - ref_instr_link((&new_src)); - - /* Côté point de départ */ + GArchInstruction *result; /* Instance ciblée à renvoyer */ - new_dst.linked = dest; - new_dst.type = type; + result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_FROM, type); - ref_instr_link((&new_dst)); - - /* Ajout dans le respect d'une cohérence globale */ - - g_arch_instruction_lock_src(dest); - g_arch_instruction_lock_dest(instr); - - add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t)); - - add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t)); - - g_arch_instruction_unlock_dest(instr); - g_arch_instruction_unlock_src(dest); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* dest = ligne visée par la liaison (côté destination). * -* old = ancien type de lien construit. * -* new = nouveau type de lien à construire. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* index = indice de l'élément à retrouver. * +* type = type de lien enregistré. [OUT] * * * -* Description : Change la nature d'un lien entre deux instructions. * +* Description : Fournit les détails d'une destination donnée d'une instruct. * * * -* Retour : true pour une mise à jour réussie, false sinon. * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * -* Remarques : Le verrou doit être posé sur les destinations de 'instr'. * +* Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new) +GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *instr, size_t index, InstructionLinkType *type) { - bool result; /* Bilan à retourner */ - size_t count; /* Raccourci pour la lecture */ - size_t i; /* Boucle de parcours */ - instr_link_t *slink; /* Définition de source */ - instr_link_t *dlink; /* Définition de destination */ - - result = false; - - /** - * Note : pour la récupération des liens de sources et de destinations, - * on n'utilise pas les fonctions g_arch_instruction_get_(source|destination)(), - * qui renvoient un pointeur non modifiable. - * - * On a en effet besoin de modifier le type de lien. - */ - - - g_arch_instruction_lock_src(dest); - - /* Côté destination */ - - count = g_arch_instruction_count_sources(dest); - - for (i = 0; i < count; i++) - { - slink = get_flat_array_item(dest->from, i, sizeof(instr_link_t)); - - if (slink->linked == instr && slink->type == old) - break; - - } - - if (i == count) - goto gaicl_exit; + GArchInstruction *result; /* Instance ciblée à renvoyer */ - /* Côté point de départ */ + result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_TO, type); - count = g_arch_instruction_count_destinations(instr); - - for (i = 0; i < count; i++) - { - dlink = get_flat_array_item(instr->to, i, sizeof(instr_link_t)); + return result; - if (dlink->linked == dest && dlink->type == old) - break; +} - } - if (i == count) - goto gaicl_exit; - /* Si les deux extrémités sont raccord... */ +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ - slink->type = new; - dlink->type = new; +/****************************************************************************** +* * +* Paramètres : instr = instance à consulter. * +* * +* Description : Indique la quantité d'opérandes présents dans l'instruction. * +* * +* Retour : Nombre d'opérandes attachés. * +* * +* Remarques : - * +* * +******************************************************************************/ - result = true; +size_t g_arch_instruction_count_operands(const GArchInstruction *instr) +{ + size_t result; /* Décompte à retourner */ - gaicl_exit: + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - g_arch_instruction_unlock_src(dest); + result = count_flat_array_items(instr->operands); return result; @@ -1268,9 +1153,10 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à traiter. * +* Paramètres : instr = instance à mettre à jour. * +* operand = instruction à venir associer. * * * -* Description : Supprime tous les liens établis avec d'autres instructions. * +* Description : Attache un opérande supplémentaire à une instruction. * * * * Retour : - * * * @@ -1278,190 +1164,83 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d * * ******************************************************************************/ -void g_arch_instruction_delete_all_links(GArchInstruction *instr) +void g_arch_instruction_attach_operand(GArchInstruction *instr, GArchOperand *operand) { - instr_link_t *link_src; /* Lien à supprimer #2 */ - GArchInstruction *other; /* Instruction de l'autre bout */ - size_t count; /* Quantié de liens présents */ - size_t i; /* Boucle de parcours */ - instr_link_t *link_dst; /* Lien à supprimer #1 */ - - /* Coté sources */ - - g_arch_instruction_lock_src(instr); - - while (count_flat_array_items(instr->from) > 0) - { - link_src = get_flat_array_item(instr->from, 0, sizeof(instr_link_t)); - - other = link_src->linked; - - g_arch_instruction_lock_dest(other); - - count = count_flat_array_items(other->to); - - for (i = 0; i < count; i++) - { - link_dst = get_flat_array_item(other->to, i, sizeof(instr_link_t)); - - if (link_dst->linked == instr && link_dst->type == link_src->type) - { - unref_instr_link(link_dst); - - rem_item_from_flat_array(&other->to, i, sizeof(instr_link_t)); - - break; - - } - - } - - assert(i < count); - - g_arch_instruction_unlock_dest(other); - - unref_instr_link(link_src); - - rem_item_from_flat_array(&instr->from, 0, sizeof(instr_link_t)); - - } - - g_arch_instruction_unlock_src(instr); - - /* Coté destinations */ - - g_arch_instruction_lock_dest(instr); - - while (count_flat_array_items(instr->to) > 0) - { - link_dst = get_flat_array_item(instr->to, 0, sizeof(instr_link_t)); - - other = link_dst->linked; - - g_arch_instruction_lock_src(other); - - count = count_flat_array_items(other->from); - - for (i = 0; i < count; i++) - { - link_src = get_flat_array_item(other->from, i, sizeof(instr_link_t)); - - if (link_src->linked == instr && link_src->type == link_dst->type) - { - unref_instr_link(link_src); - - rem_item_from_flat_array(&other->from, i, sizeof(instr_link_t)); - - break; - - } - - } + GSingletonFactory *factory; /* Unise à instances uniques */ + GSingletonCandidate *singleton; /* Instance retenue */ + GArchOperand *stored; /* Forme d'opérande conservée */ - assert(i < count); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - g_arch_instruction_unlock_src(other); + factory = get_operands_factory(); - unref_instr_link(link_dst); + singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand)); - rem_item_from_flat_array(&instr->to, 0, sizeof(instr_link_t)); + unref_object(factory); - } + stored = G_ARCH_OPERAND(singleton); - g_arch_instruction_unlock_dest(instr); + add_item_to_flat_array(&instr->operands, &stored, sizeof(GArchOperand *)); } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instance à mettre à jour. * +* old = ancienne opérande à détacher. * +* new = nouvelle opérande à attacher. * * * -* Description : Fournit la quantité d'instructions pointant vers une autre. * +* Description : Remplace un opérande d'une instruction par un autre. * * * -* Retour : Nombre de ces origines. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -size_t g_arch_instruction_count_sources(const GArchInstruction *instr) +bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) { - size_t result; /* Nombre de liens à renvoyer */ - - result = count_flat_array_items(instr->from); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* index = indice de l'élément à retrouver. * -* * -* Description : Fournit les détails d'une origine d'une instruction donnée. * -* * -* Retour : Lien déterminé vers une instruction d'origine. * -* * -* Remarques : - * -* * -******************************************************************************/ + bool result; /* Bilan à retourner */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + GSingletonFactory *factory; /* Unise à instances uniques */ + GSingletonCandidate *singleton; /* Instance retenue */ + GArchOperand *stored; /* Forme d'opérande conservée */ -const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index) -{ - instr_link_t *result; /* Détails présents à renvoyer */ + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - result = get_flat_array_item(instr->from, index, sizeof(instr_link_t)); + result = false; - ref_instr_link(result); + count = g_arch_instruction_count_operands(instr); - return result; + for (i = 0; i < count && !result; i++) + { + op = g_arch_instruction_get_operand(instr, i); -} + result = (op == old); + unref_object(op); -/****************************************************************************** -* * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* count = quantié de liens présents. [OUT] * -* * -* Description : Fournit tous les détails d'origine d'une instruction donnée. * -* * -* Retour : Liens vers des instructions d'origine à libérer. * -* * -* Remarques : - * -* * -******************************************************************************/ + } -instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *count) -{ - instr_link_t *result; /* Détails présents à renvoyer */ - size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien à fournir */ + if (result) + { + factory = get_operands_factory(); - g_arch_instruction_lock_src(instr); + singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(new)); - *count = g_arch_instruction_count_sources(instr); + unref_object(factory); - if (*count == 0) - result = NULL; + stored = G_ARCH_OPERAND(singleton); - else - { - result = (instr_link_t *)malloc(*count * sizeof(instr_link_t)); + rpl_item_in_flat_array(instr->operands, i - 1, &stored, sizeof(GArchOperand *)); - for (i = 0; i < *count; i++) - { - link = g_arch_instruction_get_source(instr, i); - memcpy(&result[i], link, sizeof(instr_link_t)); - } + unref_object(old); } - g_arch_instruction_unlock_src(instr); - return result; } @@ -1469,47 +1248,47 @@ instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *co /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instance à mettre à jour. * +* target = instruction à venir dissocier. * * * -* Description : Donne le nombre d'instructions non naturellement suivantes. * +* Description : Détache un opérande liée d'une instruction. * * * -* Retour : Nombre de ces destinations. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -size_t g_arch_instruction_count_destinations(const GArchInstruction *instr) +bool g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target) { - size_t result; /* Nombre de liens à renvoyer */ + bool result; /* Bilan à retourner */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ - result = count_flat_array_items(instr->to); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - return result; + result = false; -} + count = g_arch_instruction_count_operands(instr); + for (i = 0; i < count && !result; i++) + { + op = g_arch_instruction_get_operand(instr, i); -/****************************************************************************** -* * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* index = indice de l'élément à retrouver. * -* * -* Description : Fournit les détails d'une destination d'une instruction. * -* * -* Retour : Lien déterminé vers une instruction de destination. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = (op == target); -const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index) -{ - instr_link_t *result; /* Détails présents à renvoyer */ + unref_object(op); - result = get_flat_array_item(instr->to, index, sizeof(instr_link_t)); + } - ref_instr_link(result); + if (result) + { + rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *)); + + unref_object(target); + + } return result; @@ -1518,45 +1297,29 @@ const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* type = type de lien recherché. * +* Paramètres : instr = instance à consulter. * +* index = indice de l'opérande concerné. * * * -* Description : Fournit la destination d'une instruction et d'un type donné. * +* Description : Fournit un opérande donné d'une instruction. * * * -* Retour : Instruction de destination trouvée ou NULL. * +* Retour : Opérande trouvée. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type) +GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index) { - GArchInstruction *result; /* Résultat à remonter */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const instr_link_t *dest; /* Destination à étudier */ - - result = NULL; - - g_arch_instruction_lock_dest(instr); - - count = g_arch_instruction_count_destinations(instr); - - for (i = 0; i < count && result == NULL; i++) - { - dest = g_arch_instruction_get_destination(instr, i); + GArchOperand *result; /* Opérande à retourner */ + GArchOperand **ptr; /* Adresse dans le tableau */ - if (dest->type == type) - { - result = dest->linked; - g_object_ref(G_OBJECT(result)); - } + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - unref_instr_link(dest); + ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *)); - } + result = *ptr; - g_arch_instruction_unlock_dest(instr); + ref_object(result); return result; @@ -1565,97 +1328,78 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* count = quantié de liens présents. [OUT] * +* Paramètres : instr = instance à consulter. * +* target = instruction à venir retrouver. * * * -* Description : Fournit tous les détails de destination d'une instruction. * +* Description : Détermine le chemin conduisant à un opérande. * * * -* Retour : Liens vers des instructions de destination à libérer. * +* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * * * * Remarques : - * * * ******************************************************************************/ -instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_t *count) +char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target) { - instr_link_t *result; /* Détails présents à renvoyer */ + char *result; /* Chemin à retourner */ + size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien à fournir */ + GArchOperand *op; /* Opérande à manipuler */ + int ret; /* Bilan d'une construction */ + char *sub_path; /* Sous-chemin emprunté */ - g_arch_instruction_lock_dest(instr); + result = NULL; - *count = g_arch_instruction_count_destinations(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); - if (*count == 0) - result = NULL; + count = g_arch_instruction_count_operands(instr); - else + /* Première passe : accès direct */ + + for (i = 0; i < count && result == NULL; i++) { - result = (instr_link_t *)malloc(*count * sizeof(instr_link_t)); + op = g_arch_instruction_get_operand(instr, i); - for (i = 0; i < *count; i++) + if (op == target) { - link = g_arch_instruction_get_destination(instr, i); - memcpy(&result[i], link, sizeof(instr_link_t)); + ret = asprintf(&result, "%zu", i); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result = NULL; + } } - } - - g_arch_instruction_unlock_dest(instr); + unref_object(op); - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = é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_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - uleb128_t count; /* Nombre de liens à charger */ - uleb128_t i; /* Boucle de parcours */ - GArchInstruction *linked; /* Lien vers une instruction */ - uleb128_t type; /* Valeur ULEB128 à charger */ + /* Seconde passe : accès profond */ - g_arch_instruction_lock_dest(instr); + for (i = 0; i < count && result == NULL; i++) + { + op = g_arch_instruction_get_operand(instr, i); - result = unpack_uleb128(&count, pbuf); + sub_path = NULL;//g_arch_operand_find_inner_operand_path(op, target); - for (i = 0; i < count && result; i++) - { - linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf)); - if (linked == NULL) + if (sub_path != NULL) { - result = false; - break; - } + ret = asprintf(&result, "%zu:%s", i, sub_path); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result = NULL; + } + + free(sub_path); - result = unpack_uleb128(&type, pbuf); - if (!result) - { - g_object_unref(G_OBJECT(linked)); - break; } - g_arch_instruction_link_with(instr, linked, type); - g_object_unref(G_OBJECT(linked)); + unref_object(op); } - g_arch_instruction_unlock_dest(instr); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; @@ -1664,70 +1408,58 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter.* -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instance à consulter. * +* path = chemin d'accès à un opérande à retrouver. * * * -* Description : Sauvegarde toutes les destinations d'une instruction. * +* Description : Obtient l'opérande correspondant à un chemin donné. * * * -* Retour : Bilan de l'opération. * +* Retour : Opérande trouvé ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre d'éléments à traiter */ - size_t kept; /* Nombre de liens conservés */ - size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien vers une instruction */ + GArchOperand *result; /* Opérande trouvée à renvoyer */ + size_t index; /* Indice de l'opérande visé */ + char *end; /* Poursuite du parcours ? */ + GArchOperand *found; /* Opérande trouvé */ - g_arch_instruction_lock_dest(instr); + result = NULL; - count = g_arch_instruction_count_destinations(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); - /** - * Le type de lien ILT_REF n'est mis en place que lors de la création - * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place - * dynamiquement lors de la restauration de ces derniers. - */ + /* Recherche au premier niveau */ - kept = 0; + index = strtoul(path, &end, 10); - for (i = 0; i < count; i++) + if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL)) { - link = g_arch_instruction_get_destination(instr, i); - - if (link->type != ILT_REF) - kept++; - - unref_instr_link(link); - + LOG_ERROR_N("strtoul"); + goto done; } - result = pack_uleb128((uleb128_t []){ kept }, pbuf); + found = g_arch_instruction_get_operand(instr, index); + if (found == NULL) goto done; - for (i = 0; i < count && result; i++) + if (*end == '\0') { - link = g_arch_instruction_get_destination(instr, i); + result = found; + goto done; + } - if (link->type != ILT_REF) - { - result = g_object_storage_pack_object(storage, "instructions", - G_SERIALIZABLE_OBJECT(link->linked), pbuf); + /* Recherche en profondeur */ - if (result) - result = pack_uleb128((uleb128_t []){ link->type }, pbuf); + assert(*end == ':'); - } + result = NULL;//g_arch_operand_get_inner_operand_from_path(found, end + 1); - unref_instr_link(link); + unref_object(found); - } + done: - g_arch_instruction_unlock_dest(instr); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; @@ -1736,57 +1468,37 @@ bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStora /* ---------------------------------------------------------------------------------- */ -/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Fournit le nom humain de l'instruction manipulée. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : Mot clef de bas niveau. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_arch_instruction_get_keyword(GArchInstruction *instr) +static bool g_arch_instruction_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - const char *result; /* Désignation à retourner */ - - result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* * -* Description : Construit un petit résumé concis de l'instruction. * -* * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ + bool result; /* Bilan à retourner */ + uleb128_t extra; /* Données embarquées */ -char *g_arch_instruction_build_tooltip(const GArchInstruction *instr) -{ - char *result; /* Description à retourner */ - GArchInstructionClass *class; /* Classe des instructions */ + /* Propriétés internes */ - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + result = load_uleb128(&extra, fd); - if (class->build_tooltip != NULL) - result = class->build_tooltip(instr); + if (result) + g_thick_object_set_extra(G_THICK_OBJECT(object), extra); - else - result = NULL; + /* Liaisons avec d'autres instructions */ return result; @@ -1795,420 +1507,217 @@ char *g_arch_instruction_build_tooltip(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Fournit une description pour l'instruction manipulée. * +* Description : Sauvegarde un objet dans un flux de données. * * * -* Retour : Chaîne de caractères avec balises éventuelles. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_arch_instruction_get_description(const GArchInstruction *instr) +static bool g_arch_instruction_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { - const char *result; /* Description à retourner */ - - result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_desc(instr); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : instr = générateur à consulter. * -* * -* Description : Indique le nombre de ligne prêtes à être générées. * -* * -* Retour : Nombre de lignes devant apparaître au final. * -* * -* Remarques : - * -* * -******************************************************************************/ + bool result; /* Bilan à retourner */ + GArchInstruction *instr; /* Version spécialisée */ + size_t src_count; /* Quantité de sources */ + size_t dest_count; /* Quantité de destinations */ + off64_t *ins_offsets; /* Emplacements d'instructions */ + size_t i; /* Boucle de parcours */ + GArchInstruction *linked; /* Instruction liée */ + size_t op_count; /* Quantité d'opérandes */ + off64_t *op_offsets; /* Emplacements d'opérandes */ + GArchOperand *op; /* Opérande à traiter */ + guint extra; /* Données embarquées */ + InstructionLinkType type; /* Type de lien */ -static size_t g_arch_instruction_count_lines(const GArchInstruction *instr) -{ - return 1; + assert(g_thick_object_check_lock(G_THICK_OBJECT(object))); -} + /* Préparation des références aux instructions liées */ + instr = G_ARCH_INSTRUCTION(object); -#ifdef INCLUDE_GTK_SUPPORT + src_count = g_arch_instruction_count_src_links(instr); + dest_count = g_arch_instruction_count_dest_links(instr); + ins_offsets = malloc((src_count + dest_count) * sizeof(off64_t)); -/****************************************************************************** -* * -* Paramètres : instr = générateur à consulter. * -* x = position géographique sur la ligne concernée. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à constituer. [OUT] * -* * -* Description : Retrouve l'emplacement correspondant à une position donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + for (i = 0; i < src_count && result; i++) + { + linked = g_arch_instruction_get_linked_source(instr, i, (InstructionLinkType []) { 0 }); -static void g_arch_instruction_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor) -{ - *cursor = g_binary_cursor_new(); + result = g_object_storage_store_object(storage, "instructions", + G_SERIALIZABLE_OBJECT(linked), &ins_offsets[i]); - g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range)); + unref_object(linked); -} + } + for (i = 0; i < dest_count && result; i++) + { + linked = g_arch_instruction_get_linked_destination(instr, i, (InstructionLinkType []) { 0 }); -/****************************************************************************** -* * -* Paramètres : instr = générateur à consulter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à analyser. * -* * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * -* * -* Retour : Bilan de la détermination, utilisable en comparaisons. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = g_object_storage_store_object(storage, "instructions", + G_SERIALIZABLE_OBJECT(linked), &ins_offsets[src_count + i]); -static int g_arch_instruction_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor) -{ - int result; /* Conclusion à retourner */ - vmpa2t addr; /* Autre emplacement à comparer*/ + unref_object(linked); - assert(G_IS_BINARY_CURSOR(cursor)); + } - g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + if (!result) + goto exit_with_ins_off; - result = cmp_mrange_with_vmpa(&instr->range, &addr); + /* Préparation des références aux opérandes embarqués */ - return result; + op_count = g_arch_instruction_count_operands(instr); -} + op_offsets = malloc(op_count * sizeof(off64_t)); + for (i = 0; i < op_count && result; i++) + { + op = g_arch_instruction_get_operand(instr, i); -#endif + result = g_object_storage_store_object(storage, "operandss", + G_SERIALIZABLE_OBJECT(op), &op_offsets[i]); + unref_object(op); -/****************************************************************************** -* * -* Paramètres : instr = générateur à consulter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* * -* Description : Renseigne sur les propriétés liées à un générateur. * -* * -* Retour : Propriétés particulières associées. * -* * -* Remarques : - * -* * -******************************************************************************/ + } -static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat) -{ - return BLF_HAS_CODE; + if (!result) + goto exit_with_op_off; -} + /* Propriétés internes */ + extra = g_thick_object_get_extra(G_THICK_OBJECT(object)); -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à représenter. * -* line = ligne de rendu à compléter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + result = store_uleb128((uleb128_t []) { extra }, fd); + if (!result) goto exit; -static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) -{ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ + /* Liaisons avec d'autres instructions */ - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range)); + instr = G_ARCH_INSTRUCTION(object); - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range)); + src_count = g_arch_instruction_count_src_links(instr); + dest_count = g_arch_instruction_count_dest_links(instr); - g_buffer_line_fill_content(line, DLC_BINARY, content, &instr->range, VMPA_NO_PHYSICAL); + result = store_uleb128((uleb128_t []) { src_count }, fd); + if (!result) goto exit; - /* Instruction proprement dite */ + result = store_uleb128((uleb128_t []) { dest_count }, fd); + if (!result) goto exit; - key = g_arch_instruction_get_keyword(instr); - klen = strlen(key); + for (i = 0; i < src_count && result; i++) + { + linked = g_arch_instruction_get_linked_source(instr, i, &type); - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, G_OBJECT(instr)); + result = store_uleb128((uleb128_t []) { type }, fd); - /* Liste des opérandes */ + unref_object(linked); - g_arch_instruction_lock_operands(instr); + if (result) + result = store_uleb128((uleb128_t []) { ins_offsets[i] }, fd); - count = _g_arch_instruction_count_operands(instr); + } - if (count > 0) + for (i = 0; i < dest_count && result; i++) { - op = _g_arch_instruction_get_operand(instr, 0); - g_arch_operand_print(op, line); - g_object_unref(G_OBJECT(op)); - - for (i = 1; i < count; i++) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + linked = g_arch_instruction_get_linked_destination(instr, i, &type); - op = _g_arch_instruction_get_operand(instr, i); + result = store_uleb128((uleb128_t []) { type }, fd); - g_arch_operand_print(op, line); + unref_object(linked); - g_object_unref(G_OBJECT(op)); - - } + if (result) + result = store_uleb128((uleb128_t []) { ins_offsets[src_count + i] }, fd); } - g_arch_instruction_unlock_operands(instr); + /* Opérandes embarqués */ -} + result = store_uleb128((uleb128_t []) { op_count }, fd); + if (!result) goto exit; + for (i = 0; i < op_count && result; i++) + result = store_uleb128((uleb128_t []) { op_offsets[i] }, fd); -/****************************************************************************** -* * -* Paramètres : instr = générateur à utiliser pour l'impression. * -* line = ligne de rendu à compléter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * -* * -* Description : Imprime dans une ligne de rendu le contenu représenté. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + exit: + exit_with_op_off: -static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) -{ - G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content); + free(op_offsets); -} + exit_with_ins_off: + free(ins_offsets); + return result; -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ -/* ---------------------------------------------------------------------------------- */ +} -/****************************************************************************** -* * -* Paramètres : instr = é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_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ - uleb128_t value; /* Valeur ULEB128 à charger */ - uleb128_t count; /* Nombre d'éléments à traiter */ - uleb128_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à traiter */ - extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - result = unpack_uleb128(&value, pbuf); - if (result) - extra->uid = value; - if (result) - { - result = unpack_uleb128(&value, pbuf); - if (result) - extra->flags = value; - } - UNLOCK_GOBJECT_EXTRA(extra); - if (result) - result = unpack_mrange(&instr->range, pbuf); - if (result) - { - result = unpack_uleb128(&count, pbuf); - for (i = 0; i < count && result; i++) - { - op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf)); - result = (op != NULL); - if (result) - g_arch_instruction_attach_extra_operand(instr, op); - } - } - if (result) - result = g_arch_instruction_load_destinations(instr, storage, pbuf); +#if 0 - return result; -} /****************************************************************************** * * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : instr = instruction quelconque à traiter. * +* type = type de procédure à utiliser. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = accès aux données du binaire d'origine. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Complète un désassemblage accompli pour une instruction. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *class; /* Classe à activer */ + GArchInstructionClass *class; /* Classe des instructions */ class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - result = class->load(instr, storage, pbuf); - - return result; + if (class->call_hook != NULL) + class->call_hook(instr, type, proc, context, format); } -/****************************************************************************** -* * -* Paramètres : instr = é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_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ - size_t count; /* Nombre d'éléments à traiter */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à traiter */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf); - if (result) - result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); - - UNLOCK_GOBJECT_EXTRA(extra); - - if (result) - result = pack_mrange(&instr->range, pbuf); - - if (result) - { - g_arch_instruction_lock_operands(instr); - count = _g_arch_instruction_count_operands(instr); - - result = pack_uleb128((uleb128_t []){ count }, pbuf); - - for (i = 0; i < count && result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); - - result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf); - - g_object_unref(G_OBJECT(op)); - - } - - g_arch_instruction_unlock_operands(instr); +#endif - } - if (result) - result = g_arch_instruction_store_destinations(instr, storage, pbuf); - return result; - -} -/****************************************************************************** -* * -* Paramètres : instr = é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_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchInstructionClass *class; /* Classe à activer */ - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - result = class->store(instr, storage, pbuf); - return result; -} diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 3c9c149..98bc73e 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction.h - prototypes pour la gestion générique des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,194 +25,118 @@ #define _ARCH_INSTRUCTION_H -#include +#include +#include -#include "context.h" #include "operand.h" -#include "register.h" #include "vmpa.h" -#include "../analysis/type.h" -#include "../common/packed.h" -#include "../format/executable.h" +#include "../glibext/helpers.h" +#include "../glibext/portion.h" -#define G_TYPE_ARCH_INSTRUCTION g_arch_instruction_get_type() -#define G_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction)) -#define G_IS_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type())) -#define G_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass)) -#define G_IS_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_INSTRUCTION)) -#define G_ARCH_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass)) +/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */ -/* Définition générique d'une instruction d'architecture (instance) */ -typedef struct _GArchInstruction GArchInstruction; +#define G_TYPE_ARCH_INSTRUCTION (g_arch_instruction_get_type()) -/* Définition générique d'une instruction d'architecture (classe) */ -typedef struct _GArchInstructionClass GArchInstructionClass; +DECLARE_GTYPE(GArchInstruction, g_arch_instruction, G, ARCH_INSTRUCTION); -/* Drapeaux pour informations complémentaires */ - -#define AIF_USER_BIT 4 - -typedef enum _ArchInstrFlag -{ - AIF_NONE = (0 << 0), /* Aucune information */ - AIF_ROUTINE_START = (1 << 0), /* Début de routine */ - AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */ - AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */ - AIF_CALL = (1 << 3), /* Instruction d'appel */ - - AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */ - AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */ - -} ArchInstrFlag; - /* Type pour les types d'instructions */ typedef uint16_t itid_t; -/* Types de crochet de traitement */ -typedef enum _InstrProcessHook -{ - IPH_FETCH, /* Itinéraire de désassemblage */ - IPH_LINK, /* Edition des liens */ - IPH_POST, /* Résolution des symboles */ - - IPH_COUNT - -} InstrProcessHook; - - -/* Indique le type défini pour une instruction d'architecture. */ -GType g_arch_instruction_get_type(void); +/* Fournit l'identifiant correspondant à un type d'instructions. */ +itid_t g_arch_instruction_get_type_id(const GArchInstruction *); /* Indique l'encodage d'une instruction de façon détaillée. */ -const char *g_arch_instruction_get_encoding(const GArchInstruction *); - -/* Ajoute une information complémentaire à une instruction. */ -bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag); +char *g_arch_instruction_get_encoding(const GArchInstruction *); -/* Retire une information complémentaire à une instruction. */ -bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstrFlag); - -/* Détermine si une instruction possède un fanion particulier. */ -bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstrFlag); +/* Fournit le nom humain de l'instruction manipulée. */ +char *g_arch_instruction_get_keyword(const GArchInstruction *); -/* Fournit les informations complémentaires d'une instruction. */ -ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *); -/* Définit l'identifiant unique pour un ensemble d'instructions. */ -void g_arch_instruction_set_unique_id(GArchInstruction *, itid_t); + /* Type de masques pour les encodages d'instructions */ +typedef enum _InstructionBytesMask +{ + /** + * Correspond aux bits fixes : pas de valeurs de registre ni de valeur entière. + */ + IBM_LOOSE, -/* Fournit l'identifiant unique pour un ensemble d'instructions. */ -itid_t g_arch_instruction_get_unique_id(const GArchInstruction *); + /** + * Dissimulation des références à des éléments externes pouvant varier avec + * entre compilations : adresses de saut ou d'appel, références vers des tables, + * etc. + */ + IBM_LOCAL, + /** + * Dissimulation des déplacements à partir d'une base. + */ + IBM_STRICT, -/** - * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut - * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références - * circulaires. - * - * On procède donc à une seconde déclaration, en attendant éventuellement mieux. - */ + /** + * Conservation de toutes les valeurs immédiates et dissimulation des registres. + */ + IBM_LARGE, -/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */ -typedef struct _GArchProcessor GArchProcessor; + IBM_COUNT +} InstructionBytesMask; -/* Complète un désassemblage accompli pour une instruction. */ -typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); - -/* Complète un désassemblage accompli pour une instruction. */ -void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); -/* Définit la localisation d'une instruction. */ -void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *); +/* Calcule la localisation d'une instruction. */ +void g_arch_instruction_compute_range(GArchInstruction *, GBinaryPortion *, const vmpa2t *, phys_t); /* Fournit la place mémoire d'une instruction. */ -const mrange_t *g_arch_instruction_get_range(const GArchInstruction *); - - - -/* Fournit la localisation d'une instruction. */ -void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *, vmpa_t *) __attribute__ ((deprecated)); +bool g_arch_instruction_get_range(const GArchInstruction *, mrange_t *); +#define AIF_USER_BIT 4 -/* Liste les registres lus et écrits par l'instruction. */ -void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated)); +typedef enum _ArchInstructionFlag +{ + AIF_NONE = (0 << 0), /* Aucune information */ + AIF_ROUTINE_START = (1 << 0), /* Début de routine */ + AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */ + AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */ + AIF_CALL = (1 << 3), /* Instruction d'appel */ + AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */ + AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */ +} ArchInstructionFlag; -/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ +#define AIF_USER_FLAG(n) (1 << (AIF_USER_BIT + n)) -/* Verrouille les accès à la liste des opérandes. */ -void g_arch_instruction_lock_operands(GArchInstruction *); +/* Ajoute une information complémentaire à une instruction. */ +bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstructionFlag); -/* Déverrouille les accès à la liste des opérandes. */ -void g_arch_instruction_unlock_operands(GArchInstruction *); +/* Retire une information complémentaire à une instruction. */ +bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstructionFlag); -/* Attache un opérande supplémentaire à une instruction. */ -void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *); +/* Détermine si une instruction possède un fanion particulier. */ +bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstructionFlag); -/* Indique la quantité d'opérandes présents dans l'instruction. */ -size_t _g_arch_instruction_count_operands(const GArchInstruction *); +/* Fournit les particularités de l'instruction. */ +ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *); -/* Fournit un opérande donné d'une instruction. */ -GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t); -/* Remplace un opérande d'une instruction par un autre. */ -bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *); +/* Types de crochet de traitement */ +typedef enum _InstrProcessHook +{ + IPH_FETCH, /* Itinéraire de désassemblage */ + IPH_LINK, /* Edition des liens */ + IPH_POST, /* Résolution des symboles */ -/* Détache un opérande liée d'une instruction. */ -bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); - - -#define g_arch_instruction_count_operands(ins) \ - ({ \ - size_t __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_count_operands(ins); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_get_operand(ins, idx) \ - ({ \ - GArchOperand *__result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_get_operand(ins, idx); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_replace_operand(ins, o, n) \ - ({ \ - bool __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_replace_operand(ins, o, n); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_detach_operand(ins, o) \ - ({ \ - bool __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_detach_operand(ins, o); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) + IPH_COUNT +} InstrProcessHook; -/* Détermine le chemin conduisant à un opérande. */ -char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *); -/* Obtient l'opérande correspondant à un chemin donné. */ -GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *); @@ -236,30 +160,24 @@ typedef enum _InstructionLinkType } InstructionLinkType; -/* Déscription d'une liaison entre deux instructions */ -typedef struct _instr_link_t -{ - GArchInstruction *linked; /* Autre instruction liée */ - InstructionLinkType type; /* Type de liaison */ - -} instr_link_t; - -#define ref_instr_link(l) g_object_ref(G_OBJECT(l->linked)); -#define unref_instr_link(l) g_object_unref(G_OBJECT(l->linked)); +/* Détermine si un type de lien amène à une instruction. */ +bool g_arch_instruction_has_src_link(const GArchInstruction *, InstructionLinkType); +/* Détermine si un type de lien émerge d'une instruction. */ +bool g_arch_instruction_has_dest_link(const GArchInstruction *, InstructionLinkType); -/* Met à disposition un encadrement des accès aux liens. */ -void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool); +/* Détermine si une instruction est source d'une autre. */ +bool g_arch_instruction_has_src_link_with(const GArchInstruction *, const GArchInstruction *); -/* Détermine si un type de lien existe dans une instruction. */ -bool g_arch_instruction_has_link(GArchInstruction *, InstructionLinkType); - -/* Détermine si un lien est déjà établi entre deux instructions. */ -bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *); +/* Détermine si une instruction est destination d'une autre. */ +bool g_arch_instruction_has_dest_link_with(const GArchInstruction *, const GArchInstruction *); /* Etablit un lien entre deux instructions. */ -void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType); +void g_arch_instruction_link(GArchInstruction *, GArchInstruction *, InstructionLinkType); + +/* Supprime un lien entre deux instructions. */ +void g_arch_instruction_unlink(GArchInstruction *, GArchInstruction *, InstructionLinkType); /* Change la nature d'un lien entre deux instructions. */ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType); @@ -267,46 +185,72 @@ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, Inst /* Supprime tous les liens établis avec d'autres instructions. */ void g_arch_instruction_delete_all_links(GArchInstruction *); -#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true) -#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false) +/* Fournit la quantité d'instructions placées en source. */ +size_t g_arch_instruction_count_src_links(const GArchInstruction *); -/* Fournit la quantité d'instructions pointant vers une autre. */ -size_t g_arch_instruction_count_sources(const GArchInstruction *); +/* Fournit la quantité d'instructions placées en destination. */ +size_t g_arch_instruction_count_dest_links(const GArchInstruction *); -/* Fournit les détails d'une origine d'une instruction donnée. */ -const instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t); +/* Fournit les détails d'une source donnée d'une instruction. */ +GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *, size_t, InstructionLinkType *); -/* Fournit tous les détails d'origine d'une instruction donnée. */ -instr_link_t *g_arch_instruction_get_sources(GArchInstruction *, size_t *); +/* Fournit les détails d'une destination donnée d'une instruction. */ +GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *, size_t, InstructionLinkType *); -#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true) -#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false) -/* Donne le nombre d'instructions non naturellement suivantes. */ -size_t g_arch_instruction_count_destinations(const GArchInstruction *); -/* Fournit les détails d'une destination d'une instruction. */ -const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t); +/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ -/* Fournit la destination d'une instruction et d'un type donné. */ -GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType); -/* Fournit tous les détails de destination d'une instruction. */ -instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *, size_t *); +/* Indique la quantité d'opérandes présents dans l'instruction. */ +size_t g_arch_instruction_count_operands(const GArchInstruction *); +/* Attache un opérande supplémentaire à une instruction. */ +void g_arch_instruction_attach_operand(GArchInstruction *, GArchOperand *); +/* Remplace un opérande d'une instruction par un autre. */ +bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *); -/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */ +/* Détache un opérande liée d'une instruction. */ +bool g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); +/* Fournit un opérande donné d'une instruction. */ +GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *, size_t); + +/* Détermine le chemin conduisant à un opérande. */ +char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *); + +/* Obtient l'opérande correspondant à un chemin donné. */ +GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *); + + + + +#if 0 + + + +/** + * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut + * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références + * circulaires. + * + * On procède donc à une seconde déclaration, en attendant éventuellement mieux. + */ + +/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */ +typedef struct _GArchProcessor GArchProcessor; + + +/* Complète un désassemblage accompli pour une instruction. */ +typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); -/* Fournit le nom humain de l'instruction manipulée. */ -const char *g_arch_instruction_get_keyword(GArchInstruction *); -/* Construit un petit résumé concis de l'instruction. */ -char *g_arch_instruction_build_tooltip(const GArchInstruction *); -/* Fournit une description pour l'instruction manipulée. */ -const char *g_arch_instruction_get_description(const GArchInstruction *); +#endif diff --git a/src/arch/instructions/Makefile.am b/src/arch/instructions/Makefile.am index 28cf90f..d6fc4bd 100644 --- a/src/arch/instructions/Makefile.am +++ b/src/arch/instructions/Makefile.am @@ -1,12 +1,19 @@ -noinst_LTLIBRARIES = libarchinstructions.la +noinst_LTLIBRARIES = libarchinstructions.la libarchinstructionsui.la libarchinstructions_la_SOURCES = \ + raw-int.h \ raw.h raw.c \ undefined-int.h \ undefined.h undefined.c -libarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarchinstructions_la_CFLAGS = $(LIBGOBJ_CFLAGS) + +libarchinstructionsui_la_SOURCES = \ + raw-ui.h raw-ui.c \ + undefined-ui.h undefined-ui.c + +libarchinstructionsui_la_CFLAGS = $(LIBGTK4_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) diff --git a/src/arch/instructions/raw-int.h b/src/arch/instructions/raw-int.h new file mode 100644 index 0000000..4a5e64b --- /dev/null +++ b/src/arch/instructions/raw-int.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-int.h - prototypes pour la définition interne des instructions de données brutes + * + * 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_INSTRUCTIONS_RAW_INT_H +#define _ARCH_INSTRUCTIONS_RAW_INT_H + + +#include "raw.h" +#include "../instruction-int.h" + + + +/* Définition générique d'une instruction brute d'architecture (instance) */ +struct _GRawInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + +}; + +/* Définition générique d'une instruction brute d'architecture (instance) */ +struct _GRawInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une instruction de type 'db/dw/etc' simple. */ +bool g_raw_instruction_create_value(GRawInstruction *, GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t); + +/* Met en place une instruction de type 'db/dw/etc' étendue. */ +bool g_raw_instruction_create_array(GRawInstruction *, GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian); + + + +#endif /* _ARCH_INSTRUCTIONS_RAW_INT_H */ diff --git a/src/arch/instructions/raw-ui.c b/src/arch/instructions/raw-ui.c new file mode 100644 index 0000000..1026dfb --- /dev/null +++ b/src/arch/instructions/raw-ui.c @@ -0,0 +1,261 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-ui.c - opérandes représentant des instructions de données brutes 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 "raw-ui.h" + + +#include +#include +#include + + +#include "raw.h" +#include "../operand-ui.h" +#include "../operands/immediate.h" +#include "../../glibext/objhole.h" +#include "../../glibext/options/asm.h" + + + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_raw_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + iface->populate = g_raw_instruction_ui_populate_line; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_raw_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée #1 */ + GRawInstruction *raw; /* Version spécialisée #2 */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + phys_t max_displayed_len; /* Quantité de code affichée */ + char *key; /* Mot clef principal */ + char *string; /* Chaîne reconstituée */ + size_t iter; /* Tête d'écriture */ + bool first; /* Mémorise une énumération */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + GImmediateOperand *imm; /* Version opérande de valeur */ + char byte; /* Octet à afficher (ou pas) */ +#ifndef NDEBUG + bool status; /* Bilan d'une récupération */ +#endif + + instr = G_ARCH_INSTRUCTION(generator); + raw = G_RAW_INSTRUCTION(instr); + content = G_BIN_CONTENT(data); + + g_thick_object_lock(G_THICK_OBJECT(instr)); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + /* Localisation */ + + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + /* Contenu */ + + if (g_raw_instruction_is_padding(raw)) + max_displayed_len = 0; + + else if (g_raw_instruction_is_string(raw)) + max_displayed_len = 1; + + else + { + max_displayed_len = get_mrange_length(&range); + max_displayed_len /= g_arch_instruction_count_operands(instr); + } + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, max_displayed_len); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr)); + + free(key); + + /* Contenu sous forme d'opérandes */ + + if (g_raw_instruction_is_padding(raw)) + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL("..."), NULL, NULL); + + else + { + string = NULL; + iter = 0; + + first = true; + + count = g_arch_instruction_count_operands(instr); + + for (i = 0; i < count; i++) + { + op = g_arch_instruction_get_operand(instr, i); + + if (!G_IS_IMMEDIATE_OPERAND(op)) + goto fallback; + + imm = G_IMMEDIATE_OPERAND(op); + + if (g_immediate_operand_get_size(imm) != MDS_8_BITS) + goto fallback; + + if (!g_raw_instruction_is_string(raw) && g_immediate_operand_get_display(imm) != IOD_CHAR) + goto fallback; + +#ifndef NDEBUG + status = g_immediate_operand_get_value(imm, MDS_8_BITS, &byte); + assert(status); +#else + g_immediate_operand_get_value(imm, MDS_8_BITS, &byte); +#endif + + /* Si le caractère doit apparaître en hexadécimal... */ + + if (!isprint(byte)) + goto fallback; + + /* Impression de l'octet */ + + if (string == NULL) + { + string = calloc(count + 3, sizeof(char)); + + strcpy(string, "\""); + iter = 1; + + } + + string[iter++] = byte; + + unref_object(op); + + continue; + + fallback: + + /* Si une chaîne précède */ + + if (string != NULL && iter > 1) + { + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + else + first = false; + + string[iter++] = '"'; + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL); + + iter = 1; + + } + + /* Intégration en tant qu'opérande classique */ + + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + else + first = false; + + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + + unref_object(op); + + } + + /* Si au final une chaîne traine encore */ + + if (string != NULL && iter > 1) + { + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + + string[iter++] = '"'; + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL); + + } + + if (string != NULL) + free(string); + + } + + g_thick_object_unlock(G_THICK_OBJECT(instr)); + +} diff --git a/src/arch/instructions/raw-ui.h b/src/arch/instructions/raw-ui.h new file mode 100644 index 0000000..cd604e6 --- /dev/null +++ b/src/arch/instructions/raw-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-ui.h - prototypes pour les opérandes représentant des instructions de données brutes 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_RAW_UI_H +#define _ARCH_OPERANDS_RAW_UI_H + + +#include "../../glibext/generator-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_OPERANDS_RAW_UI_H */ diff --git a/src/arch/instructions/raw.c b/src/arch/instructions/raw.c index 26282fa..87297f1 100644 --- a/src/arch/instructions/raw.c +++ b/src/arch/instructions/raw.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * raw.c - instructions pures vues de l'esprit * - * Copyright (C) 2014-2020 Cyrille Bagard + * Copyright (C) 2014-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,36 +25,19 @@ #include -#include #include #include -#include "../instruction-int.h" +#include "raw-int.h" #include "../operands/immediate.h" -#include "../operands/target.h" -#include "../../core/columns.h" +//#include "../operands/target.h" // FIXME -/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ - - -/* Définition générique d'une instruction brute d'architecture (instance) */ -struct _GRawInstruction -{ - GArchInstruction parent; /* A laisser en premier */ - -}; - -/* Définition générique d'une instruction brute d'architecture (classe) */ -struct _GRawInstructionClass -{ - GArchInstructionClass parent; /* A laisser en premier */ - -}; +/* --------------------- INSTRUCTION AVEC JEU DE DONNEES BRUTES --------------------- */ /* Initialise la classe des instructions brutes d'architecture. */ @@ -64,40 +47,26 @@ static void g_raw_instruction_class_init(GRawInstructionClass *); static void g_raw_instruction_init(GRawInstruction *); /* Supprime toutes les références externes. */ -static void g_raw_instruction_dispose(GRawInstruction *); +static void g_raw_instruction_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_raw_instruction_finalize(GRawInstruction *); - -/* Indique l'encodage d'une instruction de façon détaillée. */ -static const char *g_raw_instruction_get_encoding(const GRawInstruction *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static const char *g_raw_instruction_get_keyword(const GRawInstruction *); +static void g_raw_instruction_finalize(GObject *); -/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Charge une instruction depuis une mémoire tampon. */ -static bool g_raw_instruction_unserialize(GRawInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *); - -/* Sauvegarde une instruction dans une mémoire tampon. */ -static bool g_raw_instruction_serialize(GRawInstruction *, GAsmStorage *, packed_buffer_t *); - - - -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ - +/* Indique l'encodage d'une instruction de façon détaillée. */ +static char *g_raw_instruction_get_encoding(const GArchInstruction *); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +/* Fournit le nom humain de l'instruction manipulée. */ +static char *g_raw_instruction_get_keyword(const GArchInstruction *); /* ---------------------------------------------------------------------------------- */ -/* INSTRUCTION INCONNUE / DONNEES */ +/* INSTRUCTION AVEC JEU DE DONNEES BRUTES */ /* ---------------------------------------------------------------------------------- */ @@ -124,18 +93,13 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_raw_instruction_dispose; - object->finalize = (GObjectFinalizeFunc)g_raw_instruction_finalize; + object->dispose = g_raw_instruction_dispose; + object->finalize = g_raw_instruction_finalize; instr = G_ARCH_INSTRUCTION_CLASS(klass); - instr->get_encoding = (get_instruction_encoding_fc)g_raw_instruction_get_encoding; - instr->get_keyword = (get_instruction_keyword_fc)g_raw_instruction_get_keyword; - - instr->unserialize = (unserialize_instruction_fc)g_raw_instruction_unserialize; - instr->serialize = (serialize_instruction_fc)g_raw_instruction_serialize; - - instr->print = (print_instruction_fc)g_raw_instruction_print; + instr->get_encoding = g_raw_instruction_get_encoding; + instr->get_keyword = g_raw_instruction_get_keyword; } @@ -160,7 +124,7 @@ static void g_raw_instruction_init(GRawInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -170,16 +134,16 @@ static void g_raw_instruction_init(GRawInstruction *instr) * * ******************************************************************************/ -static void g_raw_instruction_dispose(GRawInstruction *instr) +static void g_raw_instruction_dispose(GObject *object) { - G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(G_OBJECT(instr)); + G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -189,16 +153,17 @@ static void g_raw_instruction_dispose(GRawInstruction *instr) * * ******************************************************************************/ -static void g_raw_instruction_finalize(GRawInstruction *instr) +static void g_raw_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(G_OBJECT(instr)); + G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(object); } /****************************************************************************** * * -* Paramètres : addr = position à associer à l'instruction. * +* Paramètres : area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * * size = taille de l'opérande souhaitée. * * value = valeur sur x bits à venir récupérer. * * * @@ -210,127 +175,106 @@ static void g_raw_instruction_finalize(GRawInstruction *instr) * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDataSize size, uint64_t value) +GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value) { GArchInstruction *result; /* Instruction à retourner */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - operand = g_imm_operand_new_from_value(size, value); - if (operand == NULL) goto error; + if (!g_raw_instruction_create_value(G_RAW_INSTRUCTION(result), area, addr, size, value)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser pleinement. * +* area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * +* size = taille de chacun des éléments à représenter. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Met en place une instruction de type 'db/dw/etc' simple. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_raw_instruction_create_value(GRawInstruction *instr, GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value) +{ + bool result; /* Bilan à retourner */ + GArchOperand *operand; /* Octet non décodé à afficher */ + uint16_t length; /* Taille de l'instruction */ + + result = false; + + operand = g_immediate_operand_new_from_value(size, value); + if (operand == NULL) goto exit; g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - g_arch_instruction_attach_extra_operand(result, operand); + g_thick_object_lock(G_THICK_OBJECT(instr)); + + g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand); + unref_object(operand); + + g_thick_object_unlock(G_THICK_OBJECT(instr)); switch (size) { case MDS_8_BITS_UNSIGNED: case MDS_8_BITS_SIGNED: - init_mrange(&range, addr, 1); + length = 1; break; case MDS_16_BITS_UNSIGNED: case MDS_16_BITS_SIGNED: - init_mrange(&range, addr, 2); + length = 2; break; case MDS_32_BITS_UNSIGNED: case MDS_32_BITS_SIGNED: - init_mrange(&range, addr, 4); + length = 4; break; case MDS_64_BITS_UNSIGNED: case MDS_64_BITS_SIGNED: - init_mrange(&range, addr, 8); + length = 8; break; default: assert(false); - goto error; + goto exit; break; } - g_arch_instruction_set_range(result, &range); + g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, addr, length); - return result; - - error: - - g_object_unref(G_OBJECT(result)); - - return NULL; - -} + result = true; - -/****************************************************************************** -* * -* Paramètres : content = flux de données à analyser. * -* addr = position courante dans ce flux. [OUT] * -* * -* Description : Crée une instruction de type 'db/dw/etc' pour un uleb128. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *addr) -{ - GArchInstruction *result; /* Instruction à retourner */ - vmpa2t start; /* Départ original de lecture */ - uleb128_t value; /* Valeur uleb128 à représenter*/ - phys_t diff; /* Couverture de la lecture */ - MemoryDataSize leb_size; /* Taille de la valeur */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ - - result = NULL; - - copy_vmpa(&start, addr); - - if (!g_binary_content_read_uleb128(content, addr, &value)) - goto error; - - diff = compute_vmpa_diff(&start, addr); - - leb_size = MDS_FROM_BYTES(diff); - assert(leb_size != MDS_UNDEFINED); - - result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - - init_mrange(&range, &start, diff); - g_arch_instruction_set_range(result, &range); - - operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value); - if (operand == NULL) goto error; - - g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - - g_arch_instruction_attach_extra_operand(result, operand); + exit: return result; - error: - - g_clear_object(&result); - - return NULL; - } /****************************************************************************** * * -* Paramètres : content = flux de données à analyser. * -* addr = position courante dans ce flux. [OUT] * +* Paramètres : area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * +* size = taille de chacun des éléments à représenter. * +* content = flux de données à analyser. * +* count = nombre de ces éléments. * +* endian = ordre des bits dans la source. * * * -* Description : Crée une instruction de type 'db/dw/etc' pour un sleb128. * +* Description : Crée une instruction de type 'db/dw/etc' étendue. * * * * Retour : Instruction mise en place. * * * @@ -338,256 +282,174 @@ GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *addr) +GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian) { GArchInstruction *result; /* Instruction à retourner */ - vmpa2t start; /* Départ original de lecture */ - uleb128_t value; /* Valeur uleb128 à représenter*/ - phys_t diff; /* Couverture de la lecture */ - MemoryDataSize leb_size; /* Taille de la valeur */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ - - result = NULL; - - copy_vmpa(&start, addr); - - if (!g_binary_content_read_uleb128(content, addr, &value)) - goto error; - - diff = compute_vmpa_diff(&start, addr); - - leb_size = MDS_FROM_BYTES(diff) | MDS_SIGN; - assert(leb_size != MDS_SIGN); result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - init_mrange(&range, &start, diff); - g_arch_instruction_set_range(result, &range); - - operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value); - if (operand == NULL) goto error; - - g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - - g_arch_instruction_attach_extra_operand(result, operand); + if (!g_raw_instruction_create_array(G_RAW_INSTRUCTION(result), area, addr, size, content, count, endian)) + g_clear_object(&result); return result; - error: - - g_clear_object(&result); - - return NULL; - } /****************************************************************************** * * -* Paramètres : content = flux de données à analyser. * +* Paramètres : instr = instance à initialiser pleinement. * +* area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * * size = taille de chacun des éléments à représenter. * +* content = flux de données à analyser. * * count = nombre de ces éléments. * -* addr = position courante dans ce flux. [OUT] * * endian = ordre des bits dans la source. * * * -* Description : Crée une instruction de type 'db/dw/etc' étendue. * +* Description : Met en place une instruction de type 'db/dw/etc' étendue. * * * -* Retour : Instruction mise en place. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, MemoryDataSize size, size_t count, vmpa2t *addr, SourceEndian endian) +bool g_raw_instruction_create_array(GRawInstruction *instr, GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian) { - GArchInstruction *result; /* Instruction à retourner */ - vmpa2t old; /* Sauvegarde de la position */ + bool result; /* Bilan à retourner */ + vmpa2t start; /* Sauvegarde de la position */ size_t i; /* Boucle de parcours */ GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ + phys_t diff; /* Décalage à appliquer */ + + result = false; /* Par soucis de cohérence */ - if (count == 0) return NULL; + if (count == 0) + goto exit; - result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); + copy_vmpa(&start, addr); - copy_vmpa(&old, addr); + g_thick_object_lock(G_THICK_OBJECT(instr)); for (i = 0; i < count; i++) { - operand = g_imm_operand_new_from_data(size, content, addr, endian); - if (operand == NULL) goto error; + operand = g_immediate_operand_new_from_data(size, content, addr, (bool []){ false /* unused */ }, endian); + if (operand == NULL) break; g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - g_arch_instruction_attach_extra_operand(result, operand); + g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand); + unref_object(operand); } - init_mrange(&range, &old, compute_vmpa_diff(addr, &old)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); - g_arch_instruction_set_range(result, &range); + if (i < count) + goto exit; - return result; + diff = compute_vmpa_diff(addr, &start); + + g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, &start, diff); - error: + result = true; - g_object_unref(G_OBJECT(result)); + exit: - return NULL; + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * +* Paramètres : instr = instruction à traiter. * +* is_padding = nouveau statut à associer au contenu. * * * -* Description : Indique l'encodage d'une instruction de façon détaillée. * +* Description : Marque l'instruction comme ne contenant que du bourrage. * * * -* Retour : Description humaine de l'encodage utilisé. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static const char *g_raw_instruction_get_encoding(const GRawInstruction *instr) +void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding) { - const char *result; /* Description à retourner */ - - if (g_raw_instruction_is_string(instr)) - result = _("String"); + if (is_padding) + g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); else - result = _("Raw"); - - return result; + g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); } /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : instr = instruction à traiter. * +* is_padding = nouveau statut à associer au contenu. * * * -* Description : Fournit le nom humain de l'instruction manipulée. * +* Description : Indique si le contenu de l'instruction est du bourrage. * * * -* Retour : Mot clef de bas niveau. * +* Retour : Statut du contenu de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr) +bool g_raw_instruction_is_padding(const GRawInstruction *instr) { - GArchOperand *operand; /* Octet décodé à afficher */ - MemoryDataSize size; /* Taille de valeur associée */ - - static char *defines[] = { "dn", "db", "dw", "dd", "dq" }; - - operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0); - - if (G_IS_TARGET_OPERAND(operand)) - size = g_target_operand_get_size(G_TARGET_OPERAND(operand)); - else - size = g_imm_operand_get_size(G_IMM_OPERAND(operand)); + bool result; /* Indication à retourner */ - g_object_unref(G_OBJECT(operand)); + result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - return defines[MDS_RANGE(size)]; + return result; } - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction à traiter. * +* is_string = nouveau statut à associer au contenu. * * * -* Description : Charge une instruction depuis une mémoire tampon. * +* Description : Marque l'instruction comme contenant une chaîne de texte. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_raw_instruction_unserialize(GRawInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); - - result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); - - if (result) - { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - - if (result) - g_raw_instruction_mark_as_padding(instr, (boolean == 1)); - - } - - if (result) - { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - - if (result) - g_raw_instruction_mark_as_string(instr, (boolean == 1)); - - } - - return result; + if (is_string) + g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); + else + g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); } /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction à traiter. * +* is_string = nouveau statut à associer au contenu. * * * -* Description : Sauvegarde une instruction dans une mémoire tampon. * +* Description : Indique si le contenu de l'instruction est un texte. * * * -* Retour : Bilan de l'opération. * +* Retour : Statut du contenu de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) +bool g_raw_instruction_is_string(const GRawInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); - - result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - boolean = (g_raw_instruction_is_padding(instr) ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - } + bool result; /* Indication à retourner */ - if (result) - { - boolean = (g_raw_instruction_is_string(instr) ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - } + result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); return result; @@ -596,285 +458,73 @@ static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *sto /* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à représenter. * -* line = ligne de rendu à compléter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * +* Paramètres : instr = instruction quelconque à consulter. * * * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : - * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +static char *g_raw_instruction_get_encoding(const GArchInstruction *instr) { - GArchInstruction *base; /* Autre version de l'instance */ - phys_t max_displayed_len; /* Quantité de code affichée */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - char *string; /* Chaîne reconstituée */ - size_t iter; /* Tête d'écriture */ - bool first; /* Mémorise une énumération */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ - GImmOperand *imm; /* Version opérande de valeur */ - char byte; /* Octet à afficher (ou pas) */ -#ifndef NDEBUG - bool status; /* Bilan d'une récupération */ -#endif - - base = G_ARCH_INSTRUCTION(instr); - - /* Localisation */ - - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - /* Contenu */ - - if (g_raw_instruction_is_padding(instr)) - max_displayed_len = 0; - - else if (g_raw_instruction_is_string(instr)) - max_displayed_len = 1; - - else - { - max_displayed_len = get_mrange_length(&base->range); - max_displayed_len /= g_arch_instruction_count_operands(base); - } - - g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, max_displayed_len); - - /* Zone du code d'assemblage */ + char *result; /* Description à retourner */ + GRawInstruction *raw; /* Version spécialisée */ - key = g_arch_instruction_get_keyword(base); - klen = strlen(key); - - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); - - if (g_raw_instruction_is_padding(instr)) - g_buffer_line_append_text(line, DLC_ASSEMBLY, "...", 3, RTT_RAW, NULL); + raw = G_RAW_INSTRUCTION(instr); + if (g_raw_instruction_is_string(raw)) + result = strdup(_("String")); else - { - string = NULL; - iter = 0; - - first = true; - - g_arch_instruction_lock_operands(base); - - count = _g_arch_instruction_count_operands(base); - - for (i = 0; i < count; i++) - { - op = _g_arch_instruction_get_operand(base, i); - - if (!G_IS_IMM_OPERAND(op)) - goto grip_fallback; - - imm = G_IMM_OPERAND(op); - - if (g_imm_operand_get_size(imm) != MDS_8_BITS) - goto grip_fallback; - - if (!g_raw_instruction_is_string(instr) && g_imm_operand_get_display(imm) != IOD_CHAR) - goto grip_fallback; - -#ifndef NDEBUG - status = g_imm_operand_get_value(imm, MDS_8_BITS, &byte); - assert(status); -#else - g_imm_operand_get_value(imm, MDS_8_BITS, &byte); -#endif - - /* Si le caractère doit apparaître en hexadécimal... */ - - if (!isprint(byte)) - goto grip_fallback; - - /* Impression de l'octet */ - - if (string == NULL) - { - string = (char *)calloc(count + 3, sizeof(char)); - - strcpy(string, "\""); - iter = 1; - - } - - string[iter++] = byte; - - g_object_unref(G_OBJECT(op)); - - continue; - - grip_fallback: - - /* Si une chaîne précède */ - - if (string != NULL && iter > 1) - { - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - else - first = false; - - string[iter++] = '"'; - - g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL); - - iter = 1; - - } - - /* Intégration en tant qu'opérande classique */ - - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - else - first = false; - - g_arch_operand_print(op, line); - - g_object_unref(G_OBJECT(op)); - - } - - /* Si au final une chaîne traine encore */ - - if (string != NULL && iter > 1) - { - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - - string[iter++] = '"'; - - g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL); - - } + result = strdup(_("Raw")); - g_arch_instruction_unlock_operands(base); - - if (string != NULL) - free(string); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_padding = nouveau statut à associer au contenu. * -* * -* Description : Marque l'instruction comme ne contenant que du bourrage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding) -{ - if (is_padding) - g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - else - g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction à traiter. * -* is_padding = nouveau statut à associer au contenu. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Indique si le contenu de l'instruction est du bourrage. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Statut du contenu de l'instruction. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -bool g_raw_instruction_is_padding(const GRawInstruction *instr) +static char *g_raw_instruction_get_keyword(const GArchInstruction *instr) { - bool result; /* Indication à retourner */ - - result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - - return result; - -} + char *result; /* Désignation à retourner */ + GArchOperand *operand; /* Octet décodé à afficher */ + MemoryDataSize size; /* Taille de valeur associée */ + static char *defines[] = { "dn", "db", "dw", "dd", "dq" }; -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_string = nouveau statut à associer au contenu. * -* * -* Description : Marque l'instruction comme contenant une chaîne de texte. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + g_thick_object_lock(G_THICK_OBJECT(instr)); -void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string) -{ - if (is_string) - g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); - else - g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); - -} + operand = g_arch_instruction_get_operand(instr, 0); + /*if (G_IS_TARGET_OPERAND(operand)) FIXME + size = g_target_operand_get_size(G_TARGET_OPERAND(operand)); + else*/ + size = g_immediate_operand_get_size(G_IMMEDIATE_OPERAND(operand)); -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_string = nouveau statut à associer au contenu. * -* * -* Description : Indique si le contenu de l'instruction est un texte. * -* * -* Retour : Statut du contenu de l'instruction. * -* * -* Remarques : - * -* * -******************************************************************************/ + unref_object(operand); -bool g_raw_instruction_is_string(const GRawInstruction *instr) -{ - bool result; /* Indication à retourner */ + g_thick_object_unlock(G_THICK_OBJECT(instr)); - result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); + result = strdup(defines[MDS_RANGE(size)]); return result; diff --git a/src/arch/instructions/raw.h b/src/arch/instructions/raw.h index 4e92cd4..712f877 100644 --- a/src/arch/instructions/raw.h +++ b/src/arch/instructions/raw.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * raw.h - prototypes pour les instructions pures vues de l'esprit + * raw.h - prototypes pour les instructions de données brutes * - * Copyright (C) 2014-2020 Cyrille Bagard + * Copyright (C) 2014-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,46 +25,24 @@ #define _ARCH_INSTRUCTIONS_RAW_H -#include - - #include "../instruction.h" #include "../vmpa.h" +#include "../../analysis/content.h" +#include "../../glibext/helpers.h" -/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ - - -#define G_TYPE_RAW_INSTRUCTION g_raw_instruction_get_type() -#define G_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RAW_INSTRUCTION, GRawInstruction)) -#define G_IS_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RAW_INSTRUCTION)) -#define G_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass)) -#define G_IS_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RAW_INSTRUCTION)) -#define G_RAW_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass)) - +#define G_TYPE_RAW_INSTRUCTION (g_raw_instruction_get_type()) -/* Définition générique d'une instruction brute d'architecture (instance) */ -typedef struct _GRawInstruction GRawInstruction; +DECLARE_GTYPE(GRawInstruction, g_raw_instruction, G, RAW_INSTRUCTION); -/* Définition générique d'une instruction brute d'architecture (classe) */ -typedef struct _GRawInstructionClass GRawInstructionClass; - - -/* Indique le type défini pour une instruction inconnue d'architecture. */ -GType g_raw_instruction_get_type(void); /* Crée une instruction de type 'db/dw/etc' simple. */ -GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *, MemoryDataSize, uint64_t); +GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t); -/* Crée une instruction de type 'db/dw/etc' pour un uleb128. */ -GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *); +/* Crée une instruction de type 'db/dw/etc' étendue. */ +GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian); -/* Crée une instruction de type 'db/dw/etc' pour un sleb128. */ -GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *); - -/* Crée une instruction de type 'db/dw/etc' étendue. */ -GArchInstruction *g_raw_instruction_new_array(const GBinContent *, MemoryDataSize, size_t, vmpa2t *, SourceEndian); /* Drapeaux pour informations complémentaires */ typedef enum _RawInstrFlag @@ -74,6 +52,7 @@ typedef enum _RawInstrFlag } RawInstrFlag; + /* Marque l'instruction comme ne contenant que du bourrage. */ void g_raw_instruction_mark_as_padding(GRawInstruction *, bool); diff --git a/src/arch/instructions/undefined-int.h b/src/arch/instructions/undefined-int.h index a9b7627..faf0b4b 100644 --- a/src/arch/instructions/undefined-int.h +++ b/src/arch/instructions/undefined-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * undefined-int.h - prototypes pour la définition générique interne des instructions au comportement non défini + * undefined-int.h - prototypes pour la définition interne des instructions au comportement non défini * - * Copyright (C) 2019 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -27,42 +27,18 @@ #include "undefined.h" #include "../instruction-int.h" -#include "../../glibext/objhole.h" -/* Informations glissées dans la structure GObject de GArchInstruction */ -typedef struct _undef_extra_data_t -{ - /** - * Le champ uid de la structure parente attendue conduit à une taille - * alignée sur 2 octets, donc à une taille totale de 4 octets ce qui - * représente la limite maximale de taille supportée. - * - * Pour 3 octets à la base, qui devraient laisser 8 - 1 octets disponbibles - * en incluant le bit de verrouillage. - * - * On reproduit donc la structure instr_extra_data_t ici, en basculant - * l'énumération InstrExpectedBehavior en champ de bits. - */ - - itid_t uid; /* Identifiant unique du type */ - ArchInstrFlag flags; /* Informations complémentaires*/ - - unsigned int behavior : 2; /* Conséquences réelles */ - -} undef_extra_data_t; - - /* Définition générique d'une instruction au comportement non défini (instance) */ -struct _GUndefInstruction +struct _GUndefinedInstruction { GArchInstruction parent; /* A laisser en premier */ }; /* Définition générique d'une instruction au comportement non défini (classe) */ -struct _GUndefInstructionClass +struct _GUndefinedInstructionClass { GArchInstructionClass parent; /* A laisser en premier */ @@ -73,15 +49,25 @@ struct _GUndefInstructionClass * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ +/* Informations glissées dans la structure GObject de GArchInstruction */ +typedef struct _undef_extra_data_t +{ + ARCH_INSTRUCTION_EXTRA_DATA + + unsigned int behavior : 2; /* Conséquences réelles */ + +} undef_extra_data_t; + -# define GET_UNDEF_INSTR_EXTRA(ins) ((undef_extra_data_t *)&((GArchInstruction *)ins)->extra) +#define GET_UNDEF_INSTR_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, undef_extra_data_t) -#else +#define SET_UNDEF_INSTR_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, undef_extra_data_t, data) -# define GET_UNDEF_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), undef_extra_data_t) -#endif +/* Met en place une instruction au comportement indéfini. */ +bool g_undefined_instruction_create(GUndefinedInstruction *, InstrExpectedBehavior); diff --git a/src/arch/instructions/undefined-ui.c b/src/arch/instructions/undefined-ui.c new file mode 100644 index 0000000..fbc0452 --- /dev/null +++ b/src/arch/instructions/undefined-ui.c @@ -0,0 +1,102 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined-ui.c - opérandes représentant des instructions indéfinies 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 "undefined-ui.h" + + +#include "../instruction.h" +#include "../../glibext/options/asm.h" + + + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + iface->populate = g_undefined_instruction_ui_populate_line; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + char *key; /* Mot clef principal */ + + instr = G_ARCH_INSTRUCTION(generator); + content = G_BIN_CONTENT(data); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_ERROR, SL(key), NULL, G_OBJECT(instr)); + + free(key); + +} diff --git a/src/arch/instructions/undefined-ui.h b/src/arch/instructions/undefined-ui.h new file mode 100644 index 0000000..8bc2d67 --- /dev/null +++ b/src/arch/instructions/undefined-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined-ui.h - prototypes pour les opérandes représentant des instructions indéfinies 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_UNDEFINED_UI_H +#define _ARCH_OPERANDS_UNDEFINED_UI_H + + +#include "../../glibext/generator-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_OPERANDS_UNDEFINED_UI_H */ diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c index 15c63e7..75df493 100644 --- a/src/arch/instructions/undefined.c +++ b/src/arch/instructions/undefined.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.c - instructions au comportement non défini * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,63 +25,42 @@ #include +#include #include #include "undefined-int.h" -#include "../../core/columns.h" +#include "../../glibext/serialize-int.h" +/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ + + /* Initialise la classe des instructions non définies. */ -static void g_undef_instruction_class_init(GUndefInstructionClass *); +static void g_undefined_instruction_class_init(GUndefinedInstructionClass *); /* Initialise une instance d'instruction non définie. */ -static void g_undef_instruction_init(GUndefInstruction *); +static void g_undefined_instruction_init(GUndefinedInstruction *); /* Supprime toutes les références externes. */ -static void g_undef_instruction_dispose(GUndefInstruction *); +static void g_undefined_instruction_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_undef_instruction_finalize(GUndefInstruction *); - -/* Indique l'encodage d'une instruction de façon détaillée. */ -static const char *g_undef_instruction_get_encoding(const GUndefInstruction *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static const char *g_undef_instruction_get_keyword(const GUndefInstruction *); - - - -/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ - - -/* Charge une instruction depuis une mémoire tampon. */ -static bool g_undef_instruction_unserialize(GUndefInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *); - -/* Sauvegarde une instruction dans une mémoire tampon. */ -static bool g_undef_instruction_serialize(GUndefInstruction *, GAsmStorage *, packed_buffer_t *); - - - -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ - - -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +static void g_undefined_instruction_finalize(GObject *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static char *g_undefined_instruction_get_encoding(const GArchInstruction *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); +/* Fournit le nom humain de l'instruction manipulée. */ +static char *g_undefined_instruction_get_keyword(const GArchInstruction *); @@ -91,7 +70,9 @@ static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, pac /* Indique le type défini pour une instruction au comportement non défini. */ -G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION); +G_DEFINE_TYPE_WITH_CODE(GUndefinedInstruction, g_undefined_instruction, G_TYPE_ARCH_INSTRUCTION, + G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_undefined_instruction_ui_token_generator_iface_init)); + /****************************************************************************** @@ -106,28 +87,20 @@ G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION); * * ******************************************************************************/ -static void g_undef_instruction_class_init(GUndefInstructionClass *klass) +static void g_undefined_instruction_class_init(GUndefinedInstructionClass *klass) { GObjectClass *object; /* Autre version de la classe */ GArchInstructionClass *instr; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_undef_instruction_dispose; - object->finalize = (GObjectFinalizeFunc)g_undef_instruction_finalize; + object->dispose = g_undefined_instruction_dispose; + object->finalize = g_undefined_instruction_finalize; instr = G_ARCH_INSTRUCTION_CLASS(klass); - instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding; - instr->get_keyword = (get_instruction_keyword_fc)g_undef_instruction_get_keyword; - - instr->unserialize = (unserialize_instruction_fc)g_undef_instruction_unserialize; - instr->serialize = (serialize_instruction_fc)g_undef_instruction_serialize; - - instr->print = (print_instruction_fc)g_undef_instruction_print; - - instr->load = (load_instruction_fc)g_undef_instruction_load; - instr->store = (store_instruction_fc)g_undef_instruction_store; + instr->get_encoding = g_undefined_instruction_get_encoding; + instr->get_keyword = g_undefined_instruction_get_keyword; } @@ -144,16 +117,22 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass) * * ******************************************************************************/ -static void g_undef_instruction_init(GUndefInstruction *instr) +static void g_undefined_instruction_init(GUndefinedInstruction *instr) { - GET_UNDEF_INSTR_EXTRA(instr)->behavior = IEB_UNDEFINED; + undef_extra_data_t extra; /* Données insérées à consulter*/ + + extra = GET_UNDEF_INSTR_EXTRA(instr); + + extra.behavior = IEB_UNDEFINED; + + SET_UNDEF_INSTR_EXTRA(instr, &extra); } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -163,16 +142,16 @@ static void g_undef_instruction_init(GUndefInstruction *instr) * * ******************************************************************************/ -static void g_undef_instruction_dispose(GUndefInstruction *instr) +static void g_undefined_instruction_dispose(GObject *object) { - G_OBJECT_CLASS(g_undef_instruction_parent_class)->dispose(G_OBJECT(instr)); + G_OBJECT_CLASS(g_undefined_instruction_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -182,9 +161,9 @@ static void g_undef_instruction_dispose(GUndefInstruction *instr) * * ******************************************************************************/ -static void g_undef_instruction_finalize(GUndefInstruction *instr) +static void g_undefined_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_undef_instruction_parent_class)->finalize(G_OBJECT(instr)); + G_OBJECT_CLASS(g_undefined_instruction_parent_class)->finalize(object); } @@ -201,16 +180,14 @@ static void g_undef_instruction_finalize(GUndefInstruction *instr) * * ******************************************************************************/ -GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior) +GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior behavior) { GArchInstruction *result; /* Instruction à retourner */ - undef_extra_data_t *extra; /* Données insérées à modifier */ - result = g_object_new(G_TYPE_UNDEF_INSTRUCTION, NULL); + result = g_object_new(G_TYPE_UNDEFINED_INSTRUCTION, NULL); - extra = GET_UNDEF_INSTR_EXTRA(result); - - extra->behavior = behavior; + if (!g_undefined_instruction_create(G_UNDEFINED_INSTRUCTION(result), behavior)) + g_clear_object(&result); return result; @@ -219,90 +196,10 @@ GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * -* * -* Description : Indique l'encodage d'une instruction de façon détaillée. * -* * -* Retour : Description humaine de l'encodage utilisé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const char *g_undef_instruction_get_encoding(const GUndefInstruction *instr) -{ - const char *result; /* Description à retourner */ - - result = _("Undefined"); - - return result; - -} - - -/****************************************************************************** +* Paramètres : instr = instance à initialiser pleinement. * +* behavior = état réel du CPU après une passe de l'instruction.* * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* * -* Description : Fournit le nom humain de l'instruction manipulée. * -* * -* Retour : Mot clef de bas niveau. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr) -{ - const char *result; /* Désignation à retourner */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_UNDEF_INSTR_EXTRA(instr); - - switch (extra->behavior) - { - case IEB_NOP: - result = "nop"; - break; - - case IEB_UNDEFINED: - result = "undefined"; - break; - - case IEB_UNPREDICTABLE: - result = "unpredictable"; - break; - - case IEB_RESERVED: - result = "reserved"; - break; - - default: - assert(false); - result = NULL; - break; - - } - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge une instruction depuis une mémoire tampon. * +* Description : Met en place une instruction au comportement indéfini. * * * * Retour : Bilan de l'opération. * * * @@ -310,122 +207,24 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr) * * ******************************************************************************/ -static bool g_undef_instruction_unserialize(GUndefInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +bool g_undefined_instruction_create(GUndefinedInstruction *instr, InstrExpectedBehavior behavior) { bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + undef_extra_data_t extra; /* Données insérées à modifier */ - result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + result = true; - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - extra->behavior = val; - - UNLOCK_GOBJECT_EXTRA(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde une instruction dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_undef_instruction_serialize(GUndefInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); - - result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false); + extra = GET_UNDEF_INSTR_EXTRA(instr); - UNLOCK_GOBJECT_EXTRA(extra); + extra.behavior = behavior; - } + SET_UNDEF_INSTR_EXTRA(instr, &extra); return result; } - -/* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à représenter. * -* line = ligne de rendu à compléter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) -{ - GArchInstruction *base; /* Version de base */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - - base = G_ARCH_INSTRUCTION(instr); - - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, VMPA_NO_PHYSICAL); - - /* Instruction proprement dite */ - - key = g_arch_instruction_get_keyword(base); - klen = strlen(key); - - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL); - -} - - /****************************************************************************** * * * Paramètres : instr = instruction à consulter. * @@ -438,18 +237,14 @@ static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *lin * * ******************************************************************************/ -InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *instr) +InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *instr) { InstrExpectedBehavior result; /* Comportement à retourner */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ + undef_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_UNDEF_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->behavior; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.behavior; return result; @@ -464,41 +259,21 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction * /****************************************************************************** * * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : instr = instruction quelconque à consulter. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Bilan de l'opération. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +static char *g_undefined_instruction_get_encoding(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); - - result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Description à retourner */ - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - extra->behavior = val; - - UNLOCK_GOBJECT_EXTRA(extra); - - } + result = strdup(_("Undefined")); return result; @@ -507,37 +282,45 @@ static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *s /****************************************************************************** * * -* Paramètres : instr = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Bilan de l'opération. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +static char *g_undefined_instruction_get_keyword(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + char *result; /* Désignation à retourner */ + undef_extra_data_t extra; /* Données insérées à consulter*/ - result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf); + extra = GET_UNDEF_INSTR_EXTRA(instr); - if (result) + switch (extra.behavior) { - extra = GET_UNDEF_INSTR_EXTRA(instr); + case IEB_NOP: + result = strdup("nop"); + break; - LOCK_GOBJECT_EXTRA(extra); + case IEB_UNDEFINED: + result = strdup("undefined"); + break; - result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false); + case IEB_UNPREDICTABLE: + result = strdup("unpredictable"); + break; - UNLOCK_GOBJECT_EXTRA(extra); + case IEB_RESERVED: + result = strdup("reserved"); + break; + + default: + assert(false); + result = NULL; + break; } diff --git a/src/arch/instructions/undefined.h b/src/arch/instructions/undefined.h index 8f35f35..d4b35f4 100644 --- a/src/arch/instructions/undefined.h +++ b/src/arch/instructions/undefined.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.h - prototypes pour les instructions au comportement non défini * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,27 +25,14 @@ #define _ARCH_INSTRUCTIONS_UNDEFINED_H -#include - - #include "../instruction.h" -#include "../vmpa.h" - +#include "../../glibext/helpers.h" -#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type() -#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstruction)) -#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UNDEF_INSTRUCTION)) -#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) -#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION)) -#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) +#define G_TYPE_UNDEFINED_INSTRUCTION (g_undefined_instruction_get_type()) -/* Définition générique d'une instruction au comportement non défini (instance) */ -typedef struct _GUndefInstruction GUndefInstruction; - -/* Définition générique d'une instruction au comportement non défini (classe) */ -typedef struct _GUndefInstructionClass GUndefInstructionClass; +DECLARE_GTYPE(GUndefinedInstruction, g_undefined_instruction, G, UNDEFINED_INSTRUCTION); /* Etat précis de l'instruction */ @@ -59,14 +46,11 @@ typedef enum _InstrExpectedBehavior } InstrExpectedBehavior; -/* Indique le type défini pour une instruction au comportement non défini. */ -GType g_undef_instruction_get_type(void); - /* Crée une instruction au comportement nominalement indéfini. */ -GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior); +GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior); /* Indique le type de conséquences réél de l'instruction. */ -InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *); +InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *); diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 8a9b961..7a11deb 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -296,4 +296,33 @@ char *mrange_length_to_string(const mrange_t *, MemoryDataSize, char [VMPA_MAX_L +/* ------------------- DEFINITION D'UN ESPACE RELATIVE EN MEMOIRE ------------------- */ + + +/* Couverture mémoire */ +typedef struct _rel_mrange_t +{ + uint32_t offset; /* Décalage depuis une ref. */ + uint16_t length; /* Taille de la couverture */ + +} rel_mrange_t; + + +#define init_rel_mrange(rr, o, l) \ + do \ + { \ + (rr)->offset = o; \ + (rr)->length = l; \ + } \ + while (0); + + +#define get_rel_mrange_offset(rr) \ + (rr)->offset + +#define get_rel_mrange_length(rr) \ + (rr)->length + + + #endif /* _ARCH_VMPA_H */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index d09b661..1056cb2 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -47,6 +47,7 @@ endif libcommon4_la_SOURCES = \ + array.h array.c \ asm.h asm.c \ bits.h bits.c \ compiler.h \ diff --git a/src/common/cpp.h b/src/common/cpp.h index 9616db3..4ebad82 100644 --- a/src/common/cpp.h +++ b/src/common/cpp.h @@ -48,6 +48,8 @@ */ #define SL(str) str, strlen(str) +#define STCSL(str) str, STATIC_STR_SIZE(str) + /** * Détermine la taille de la plus longue chaîne de caractères diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 17fd2bf..15ed866 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -20,7 +20,8 @@ libcore4_la_SOURCES = \ logs.h logs.c \ nox.h nox.c \ nproc.h nproc.c \ - paths.h paths.c + paths.h paths.c \ + processors.h processors.c libcore4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS) diff --git a/src/core/core.c b/src/core/core.c index 8fe12f5..c730fad 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -25,6 +25,7 @@ #include "global.h" +#include "processors.h" @@ -61,6 +62,14 @@ bool load_core_components(AvailableCoreComponent flags) } + if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0) + { + register_arch_gtypes(); + + init_operands_factory(); + + } + return result; } @@ -80,6 +89,12 @@ bool load_core_components(AvailableCoreComponent flags) void unload_core_components(AvailableCoreComponent flags) { + if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0) + { + exit_operands_factory(); + + } + if ((flags & ACC_GLOBAL_VARS) != 0 && (__loaded & ACC_GLOBAL_VARS) == 0) { set_work_queue(NULL); @@ -111,7 +126,6 @@ void unload_core_components(AvailableCoreComponent flags) #include "demanglers.h" #include "global.h" #include "params.h" -#include "processors.h" #include "queue.h" #include "../analysis/scan/core.h" #ifdef INCLUDE_MAGIC_SUPPORT @@ -195,9 +209,6 @@ bool load_all_core_components(bool cs) if (result) result = init_segment_content_hash_table(); - register_arch_gtypes(); - init_operands_factory(); - } } @@ -223,8 +234,6 @@ void unload_all_core_components(bool cs) { if (cs) { - exit_operands_factory(); - exit_segment_content_hash_table(); unload_demanglers_definitions(); diff --git a/src/core/core.h b/src/core/core.h index e5f0a60..640476a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -34,9 +34,10 @@ typedef enum _AvailableCoreComponent { ACC_NONE = (0 << 0), /* Statut initial */ ACC_GLOBAL_VARS = (1 << 0), /* Singletons globaux */ - ACC_SCAN_FEATURES = (1 << 1), /* Espace de noms pour scan */ + ACC_CODE_ANALYSIS = (1 << 1), /* Désassemblage de code */ + ACC_SCAN_FEATURES = (1 << 2), /* Espace de noms pour scan */ - ACC_ALL_COMPONENTS = (1 << 2) - 1 + ACC_ALL_COMPONENTS = (1 << 3) - 1 } AvailableCoreComponent; diff --git a/src/core/processors.c b/src/core/processors.c index e4a558f..056fc23 100644 --- a/src/core/processors.c +++ b/src/core/processors.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * processors.c - enregistrement et fourniture des architectures supportées * - * Copyright (C) 2015-2020 Cyrille Bagard + * Copyright (C) 2015-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -29,13 +29,13 @@ #include #include - +#if 0 #include "../arch/instructions/raw.h" #include "../arch/instructions/undefined.h" #include "../arch/operands/immediate.h" #include "../arch/operands/register.h" #include "../arch/operands/target.h" - +#endif /* Cache des singletons d'opérandes */ @@ -77,12 +77,12 @@ static proc_t *find_processor_by_key(const char *); void register_arch_gtypes(void) { - g_type_ensure(G_TYPE_RAW_INSTRUCTION); - g_type_ensure(G_TYPE_UNDEF_INSTRUCTION); + //g_type_ensure(G_TYPE_RAW_INSTRUCTION); + //g_type_ensure(G_TYPE_UNDEF_INSTRUCTION); - g_type_ensure(G_TYPE_IMM_OPERAND); - g_type_ensure(G_TYPE_REGISTER_OPERAND); - g_type_ensure(G_TYPE_TARGET_OPERAND); + //g_type_ensure(G_TYPE_IMM_OPERAND); + //g_type_ensure(G_TYPE_REGISTER_OPERAND); + //g_type_ensure(G_TYPE_TARGET_OPERAND); } @@ -126,7 +126,7 @@ GSingletonFactory *get_operands_factory(void) result = __operands_factory; - g_object_ref(G_OBJECT(result)); + ref_object(result); return result; @@ -154,7 +154,7 @@ void exit_operands_factory(void) } - +#if 0 /****************************************************************************** * * * Paramètres : type = type GLib représentant le type à instancier. * @@ -206,7 +206,7 @@ bool register_processor_type(GType type) done: - g_object_unref(G_OBJECT(proc)); + unref_object(proc); return result; @@ -341,3 +341,4 @@ GArchProcessor *get_arch_processor_for_key(const char *key) return result; } +#endif diff --git a/src/core/processors.h b/src/core/processors.h index 6aa2d1e..b622305 100644 --- a/src/core/processors.h +++ b/src/core/processors.h @@ -29,7 +29,7 @@ #include -#include "../arch/processor.h" +//#include "../arch/processor.h" #include "../glibext/singleton.h" @@ -45,7 +45,7 @@ GSingletonFactory *get_operands_factory(void); /* Supprime le fournisseur d'instances uniques d'opérandes. */ void exit_operands_factory(void); - +#if 0 /* Enregistre un processeur pour une architecture donnée. */ bool register_processor_type(GType); @@ -57,7 +57,7 @@ char **get_all_processor_keys(size_t *); /* Fournit le processeur d'architecture correspondant à un nom. */ GArchProcessor *get_arch_processor_for_key(const char *); - +#endif #endif /* _CORE_PROCESSORS_H */ diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c index 4862e9f..e3fb27b 100644 --- a/src/glibext/bufferline.c +++ b/src/glibext/bufferline.c @@ -24,14 +24,16 @@ #include "bufferline.h" +#include +#include + + #include "bufferline-int.h" #if 0 -#include -#include #include @@ -273,158 +275,12 @@ bool g_buffer_line_create(GBufferLine *line, size_t col_count) } - - - - - - - -/****************************************************************************** -* * -* Paramètres : line = ligne à venir compléter. * -* column = colonne de la ligne visée par l'insertion. * -* tag = type de décorateur à utiliser. * -* text = texte à insérer dans l'existant. * -* length = taille du texte à traiter. * -* style = gestionnaire de paramètres de rendu à consulter. * -* creator = instance GLib quelconque à associer. * -* * -* Description : Ajoute du texte à formater dans une ligne donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator) -{ - size_t index; /* Indice d'insertion */ - //content_origin *origin; /* Définition d'une origine */ - - assert(column < line->col_count); - assert(length > 0); - - index = append_text_to_line_column(&line->columns[column], tag, text, length, style); - - /* - if (creator != NULL) - { - line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin)); - - origin = &line->origins[line->ocount - 1]; - - origin->coord.column = column; - origin->coord.index = index; - - origin->creator = creator; - g_object_ref(G_OBJECT(creator)); - - } - */ - -} - - - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : line = ligne de texte à manipuler. * -* cr = contexte graphique dédié à la procédure. * -* column = (première) colonne à traiter. * -* y = ordonnée du point d'impression. * -* style = style de rendu pour les bribes de texte. * -* * -* Description : Imprime la ligne de texte représentée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style) -{ -#if 0 - GBufferLineClass *class; /* Stockage de briques de base */ - bool has_src_surface; /* Note une présence définie */ -#endif - size_t max_column; /* Borne de fin des colonnes */ - int x; /* Point de départ d'impression*/ - size_t i; /* Boucle de parcours */ - - /* - if (line->flags != BLF_NONE) - { - class = G_BUFFER_LINE_GET_CLASS(line); - - if (line->flags & BLF_ENTRYPOINT) - { - cairo_set_source_surface(cairo, class->entrypoint_img, 5, y); - has_src_surface = true; - } - else if (line->flags & BLF_BOOKMARK) - { - cairo_set_source_surface(cairo, class->bookmark_img, 5, y); - has_src_surface = true; - } - else - has_src_surface = false; - - if (has_src_surface) - cairo_paint(cairo); - - } - */ - - - /* Détermination de l'éventail des colonnes à traiter */ - - if (column == line->merge_start) - max_column = line->col_count; - - else if (column > line->merge_start) - max_column = 0; - - else - max_column = column + 1; - - /* Dessin du contenu de ces colonnes */ - - x = 0; - - for (i = column; i < max_column; i++) - draw_line_column(&line->columns[i], cr, &x, y, style); - -} - - - - - - - - - - -#if 0 - - /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* col = indice de la colonne à constituer. * -* size = taille souhaitée de l'impression des positions. * -* addr = localisation physique à venir représenter. * +* Paramètres : line = ligne à venir compléter. * +* column = indice de la colonne visée par l'insertion. * +* size = taille souhaitée de l'impression des positions. * +* addr = localisation physique à venir représenter. * * * * Description : Construit le tronc commun d'une ligne autour de sa position. * * * @@ -434,7 +290,7 @@ void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int * * ******************************************************************************/ -void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr) +void g_buffer_line_fill_physical(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr) { VMPA_BUFFER(position); /* Emplacement au format texte */ size_t len; /* Taille de l'élément inséré */ @@ -448,20 +304,22 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, if (i == len) i = len - 1; + assert(column < line->col_count); + if (i > 0) - g_buffer_line_append_text(line, col, position, i, RTT_PHYS_ADDR_PAD, NULL); + g_buffer_line_append_text(line, column, TRT_PHYS_ADDR_PAD, position, i, NULL, NULL); - g_buffer_line_append_text(line, col, &position[i], len - i, RTT_PHYS_ADDR, NULL); + g_buffer_line_append_text(line, column, TRT_PHYS_ADDR, &position[i], len - i, NULL, NULL); } /****************************************************************************** * * -* Paramètres : line = ligne à venir compléter. * -* col = indice de la colonne à constituer. * -* size = taille souhaitée de l'impression des positions. * -* addr = localisation virtuelle à venir représenter. * +* Paramètres : line = ligne à venir compléter. * +* column = indice de la colonne visée par l'insertion. * +* size = taille souhaitée de l'impression des positions. * +* addr = localisation virtuelle à venir représenter. * * * * Description : Construit le tronc commun d'une ligne autour de sa position. * * * @@ -471,7 +329,7 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, * * ******************************************************************************/ -void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr) +void g_buffer_line_fill_virtual(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr) { VMPA_BUFFER(position); /* Emplacement au format texte */ size_t len; /* Taille de l'élément inséré */ @@ -479,6 +337,8 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, vmpa2_virt_to_string(addr, size, position, &len); + assert(column < line->col_count); + if (has_virt_addr(addr)) { for (i = 2; i < len; i++) @@ -488,14 +348,14 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, i = len - 1; if (i > 0) - g_buffer_line_append_text(line, col, position, i, RTT_VIRT_ADDR_PAD, NULL); + g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, i, NULL, NULL); - g_buffer_line_append_text(line, col, &position[i], len - i, RTT_VIRT_ADDR, NULL); + g_buffer_line_append_text(line, column, TRT_VIRT_ADDR, &position[i], len - i, NULL, NULL); } else - g_buffer_line_append_text(line, col, position, len, RTT_VIRT_ADDR_PAD, NULL); + g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, len, NULL, NULL); } @@ -503,7 +363,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, /****************************************************************************** * * * Paramètres : line = ligne à venir compléter. * -* col = indice de la colonne à constituer. * +* column = indice de la colonne visée par l'insertion. * * content = contenu binaire global à venir lire. * * range = localisation des données à venir lire et présenter.* * max = taille maximale de la portion binaire en octets. * @@ -516,7 +376,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, * * ******************************************************************************/ -void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent *content, const mrange_t *range, phys_t max) +void g_buffer_line_fill_content(GBufferLine *line, size_t column, const GBinContent *content, const mrange_t *range, phys_t max) { phys_t length; /* Taille de la couverture */ bool truncated; /* Indique si le code est coupé*/ @@ -548,7 +408,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent if (required <= sizeof(static_buffer)) bin_code = static_buffer; else - bin_code = (char *)calloc(required, sizeof(char)); + bin_code = calloc(required, sizeof(char)); /* Code brut */ @@ -589,7 +449,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent /* Conclusion */ - g_buffer_line_append_text(line, col, bin_code, iter - bin_code, RTT_RAW_CODE, NULL); + g_buffer_line_append_text(line, column, TRT_RAW_CODE, bin_code, iter - bin_code, NULL, NULL); if (bin_code != static_buffer) free(bin_code); @@ -599,6 +459,146 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent /****************************************************************************** * * +* Paramètres : line = ligne à venir compléter. * +* column = colonne de la ligne visée par l'insertion. * +* tag = type de décorateur à utiliser. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* style = gestionnaire de paramètres de rendu à consulter. * +* creator = instance GLib quelconque à associer. * +* * +* Description : Ajoute du texte à formater dans une ligne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator) +{ + size_t index; /* Indice d'insertion */ + //content_origin *origin; /* Définition d'une origine */ + + assert(column < line->col_count); + assert(length > 0); + + index = append_text_to_line_column(&line->columns[column], tag, text, length, style); + + /* + if (creator != NULL) + { + line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin)); + + origin = &line->origins[line->ocount - 1]; + + origin->coord.column = column; + origin->coord.index = index; + + origin->creator = creator; + g_object_ref(G_OBJECT(creator)); + + } + */ + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : line = ligne de texte à manipuler. * +* cr = contexte graphique dédié à la procédure. * +* column = (première) colonne à traiter. * +* y = ordonnée du point d'impression. * +* style = style de rendu pour les bribes de texte. * +* * +* Description : Imprime la ligne de texte représentée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style) +{ +#if 0 + GBufferLineClass *class; /* Stockage de briques de base */ + bool has_src_surface; /* Note une présence définie */ +#endif + size_t max_column; /* Borne de fin des colonnes */ + int x; /* Point de départ d'impression*/ + size_t i; /* Boucle de parcours */ + + /* + if (line->flags != BLF_NONE) + { + class = G_BUFFER_LINE_GET_CLASS(line); + + if (line->flags & BLF_ENTRYPOINT) + { + cairo_set_source_surface(cairo, class->entrypoint_img, 5, y); + has_src_surface = true; + } + else if (line->flags & BLF_BOOKMARK) + { + cairo_set_source_surface(cairo, class->bookmark_img, 5, y); + has_src_surface = true; + } + else + has_src_surface = false; + + if (has_src_surface) + cairo_paint(cairo); + + } + */ + + + /* Détermination de l'éventail des colonnes à traiter */ + + if (column == line->merge_start) + max_column = line->col_count; + + else if (column > line->merge_start) + max_column = 0; + + else + max_column = column + 1; + + /* Dessin du contenu de ces colonnes */ + + x = 0; + + for (i = column; i < max_column; i++) + draw_line_column(&line->columns[i], cr, &x, y, style); + +} + + + + + + + + + + +#if 0 + + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir consulter. * * column = indice de la colonne visée par les recherches. * * * diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h index d6a2e2d..e95ee2b 100644 --- a/src/glibext/bufferline.h +++ b/src/glibext/bufferline.h @@ -30,6 +30,8 @@ #include "helpers.h" #include "tokenstyle.h" +#include "../arch/vmpa.h" +#include "../analysis/content.h" @@ -45,8 +47,6 @@ #ifdef INCLUDE_GTK_SUPPORT # include "widthtracker.h" #endif -#include "../analysis/content.h" -#include "../arch/vmpa.h" @@ -75,6 +75,9 @@ typedef struct _GBufferLineClass GBufferLineClass; + + + #define G_TYPE_BUFFER_LINE (g_buffer_line_get_type()) DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE); @@ -98,7 +101,14 @@ typedef enum _BufferLineFlags /* Crée une nouvelle représentation de fragments de texte. */ GBufferLine *g_buffer_line_new(size_t); +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_physical(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *); + +/* Construit le tronc commun d'une ligne autour de sa position. */ +void g_buffer_line_fill_virtual(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *); +/* Construit le tronc commun d'une ligne autour de son contenu. */ +void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, const mrange_t *, phys_t); /* Ajoute du texte à formater dans une ligne donnée. */ void g_buffer_line_append_text(GBufferLine *, size_t, TokenRenderingTag, const char *, size_t, const GTokenStyle *, GObject *); diff --git a/src/glibext/options/asm.h b/src/glibext/options/asm.h index e916083..d7a2c86 100644 --- a/src/glibext/options/asm.h +++ b/src/glibext/options/asm.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * disass.h - prototypes pour les options de rendus de code désassemblé + * asm.h - prototypes pour les options de rendus de code désassemblé * * Copyright (C) 2025 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _GLIBEXT_OPTIONS_DISASS_H -#define _GLIBEXT_OPTIONS_DISASS_H +#ifndef _GLIBEXT_OPTIONS_ASM_H +#define _GLIBEXT_OPTIONS_ASM_H #include "../helpers.h" @@ -32,14 +32,23 @@ /* Liste des colonnes en options */ typedef enum _DisassColumnOptions { - ACO_OFFSET, /* Position */ + ACO_PHYSICAL, /* Position physique */ + ACO_VIRTUAL, /* Adresse virtuelle */ + ACO_BINARY, /* Contenu sous forme binaire */ ACO_COUNT } DisassColumnOptions; -#define ACO_ASSEMBLY (ACO_COUNT + 0) /* Code pour assembleur */ +#define ACO_ASSEMBLY_LABEL (ACO_COUNT + 0) /* Etiquette dans les données */ +#define ACO_ASSEMBLY_HEAD (ACO_COUNT + 1) /* Instruction pour assembleur */ +#define ACO_ASSEMBLY (ACO_COUNT + 2) /* Code pour assembleur */ +#define ACO_COMMENTS (ACO_COUNT + 3) /* Commentaires éventuels */ + + + + #if 0 diff --git a/tests/arch/instruction.py b/tests/arch/instruction.py new file mode 100644 index 0000000..da4d8c1 --- /dev/null +++ b/tests/arch/instruction.py @@ -0,0 +1,52 @@ + +import pychrysalide +from chrysacase import ChrysalideTestCase +from pychrysalide.arch import ArchInstruction + + +class TestProcessor(ChrysalideTestCase): + """TestCase for arch.ArchProcessor.""" + + + def testAbstractClass(self): + """Forbid instruction class instance.""" + + with self.assertRaisesRegex(RuntimeError, 'pychrysalide.arch.ArchInstruction is an abstract class'): + ins = ArchInstruction() + + + def testInstructionBasicImplementation(self): + """Implement basic custom instructions.""" + + + class TodoInstruction(ArchInstruction): + + def __init__(self): + super().__init__(0x123) + + + ins = TodoInstruction() + + with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as encoding'): + print(ins.encoding) + + with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as keyword'): + print(ins.keyword) + + + class CustomInstruction(ArchInstruction): + + def __init__(self): + super().__init__(0x123) + + def _get_encoding(self): + return 'custom' + + def _get_keyword(self): + return 'kw' + + + ins = CustomInstruction() + + self.assertEqual('custom', ins.encoding) + self.assertEqual('kw', ins.keyword) -- cgit v0.11.2-87-g4458