diff options
Diffstat (limited to 'plugins/pychrysalide/arch/operand.c')
-rw-r--r-- | plugins/pychrysalide/arch/operand.c | 476 |
1 files changed, 275 insertions, 201 deletions
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c index 0aee4f7..42bd247 100644 --- a/plugins/pychrysalide/arch/operand.c +++ b/plugins/pychrysalide/arch/operand.c @@ -30,23 +30,32 @@ #include <i18n.h> #include <arch/operand-int.h> -#include <plugins/dt.h> +#include <glibext/strbuilder-int.h> #include "../access.h" #include "../helpers.h" +#include "../glibext/comparable.h" +#include "../glibext/hashable.h" +#include "../glibext/objhole.h" +#include "../glibext/serialize.h" #include "../glibext/singleton.h" +#include "../glibext/strbuilder.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_arch_operand_new(PyTypeObject *, PyObject *, PyObject *); - /* Initialise la classe générique des opérandes. */ -static void py_arch_operand_init_gclass(GArchOperandClass *, gpointer); +static int py_arch_operand_init_gclass(GArchOperandClass *, PyTypeObject *); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_operand, G_TYPE_ARCH_OPERAND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_arch_operand_init(PyObject *, PyObject *, PyObject *); + +#if 0 /* Compare un opérande avec un autre. */ static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *, bool); @@ -57,14 +66,6 @@ static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand /* Obtient l'opérande correspondant à un chemin donné. */ static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *, const char *); -/* Traduit un opérande en version humainement lisible. */ -static void py_arch_operand_print_wrapper(const GArchOperand *, GBufferLine *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Construit un petit résumé concis de l'opérande. */ -static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const GLoadedBinary *); - #endif @@ -72,6 +73,9 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const G /* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ +#if 0 + + /* Effectue une comparaison avec un objet Python 'ArchOperand'. */ static PyObject *py_arch_operand_richcompare(PyObject *, PyObject *, int); @@ -81,6 +85,15 @@ static PyObject *py_arch_operand_find_inner_operand_path(PyObject *, PyObject *) /* Obtient l'opérande correspondant à un chemin donné. */ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObject *); +#endif + + +/* Ajoute une information complémentaire à un opérande. */ +static PyObject *py_arch_operand_set_flag(PyObject *, PyObject *); + +/* Retire une information complémentaire à un opérande. */ +static PyObject *py_arch_operand_unset_flag(PyObject *, PyObject *); + /* ---------------------------------------------------------------------------------- */ @@ -90,113 +103,109 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObjec /****************************************************************************** * * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* Paramètres : gclass = classe GLib à initialiser. * +* pyclass = classe Python à initialiser. * * * -* Description : Accompagne la création d'une instance dérivée en Python. * +* Description : Initialise la classe générique des opérandes. * * * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* Retour : 0 pour indiquer un succès de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_arch_operand_init_gclass(GArchOperandClass *gclass, PyTypeObject *pyclass) { - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type de base à dériver */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ -#define ARCH_OPERAND_DOC \ - "The ArchOperand object aims to get subclassed to create" \ - " operands of any kind for new architectures.\n" \ - "\n" \ - "Calls to the *__init__* constructor of this abstract object expect"\ - " no particular argument.\n" \ - "\n" \ - "The following methods have to be defined for new classes:\n" \ - "* pychrysalide.arch.ArchRegister.__cmp__();\n" \ - "* pychrysalide.arch.ArchRegister._print();\n" \ - "* pychrysalide.arch.ArchRegister._build_tooltip().\n" \ - "\n" \ - "Some extra method definitions are optional for new classes:\n" \ - "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \ - "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\ - "\n" \ - "Chrysalide creates an internal glue to provide rich comparisons" \ - " for operands based on the old-style *__cmp__* function." +#if 0 + GStringBuilderInterface *iface; /* Interface utilisée */ - /* Validations diverses */ + iface = g_type_interface_peek(gclass, G_TYPE_STRING_BUILDER); - base = get_python_arch_operand_type(); - if (type == base) - { - result = NULL; - PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); - goto exit; - } + /* + printf("???????? init Python Operand ?????????????? -> class: %p '%s' - strbuilder iface: %p\n", + gclass, g_type_name(G_TYPE_FROM_CLASS(gclass)), iface); + */ - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); +#endif - gtype = build_dynamic_type(G_TYPE_ARCH_OPERAND, type->tp_name, - (GClassInitFunc)py_arch_operand_init_gclass, NULL, NULL); +#if 0 - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); + class->compare = py_arch_operand___cmp___wrapper; + class->find_inner = py_arch_operand_find_inner_operand_path_wrapper; + class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper; - if (!status) - { - result = NULL; - goto exit; - } - } +#endif - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - result = PyType_GenericNew(type, args, kwds); - exit: + //PY_CLASS_SET_WRAPPER(gclass->xxx, py_arch_operand_xxx_wrapper); - return result; + return 0; } /****************************************************************************** * * -* Paramètres : class = classe à initialiser. * -* unused = données non utilisées ici. * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * * * -* Description : Initialise la classe générique des opérandes. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : - * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unused) +static int py_arch_operand_init(PyObject *self, PyObject *args, PyObject *kwds) { - class->compare = py_arch_operand___cmp___wrapper; - class->find_inner = py_arch_operand_find_inner_operand_path_wrapper; - class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper; + //unsigned int endianness; /* Boutisme du processeur */ + int ret; /* Bilan de lecture des args. */ + //GArchProcessor *proc; /* Processeur à manipuler */ - class->print = py_arch_operand_print_wrapper; -#ifdef INCLUDE_GTK_SUPPORT - class->build_tooltip = py_arch_operand_build_tooltip_wrapper; -#endif +#define ARCH_OPERAND_DOC \ + "The ArchOperand object aims to get subclassed to create" \ + " operands of any kind for new architectures.\n" \ + "\n" \ + "Calls to the *__init__* constructor of this abstract object expect"\ + " no particular argument.\n" \ + "\n" \ + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.arch.ArchRegister.__cmp__();\n" \ + "* pychrysalide.arch.ArchRegister._print();\n" \ + "* pychrysalide.arch.ArchRegister._build_tooltip().\n" \ + "\n" \ + "Some extra method definitions are optional for new classes:\n" \ + "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \ + "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\ + "\n" \ + "Chrysalide creates an internal glue to provide rich comparisons" \ + " for operands based on the old-style *__cmp__* function." + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + //proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + //proc->endianness = endianness; + + return 0; } + +#if 0 + /****************************************************************************** * * * Paramètres : a = premier opérande à consulter. * @@ -410,126 +419,6 @@ static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const G } -/****************************************************************************** -* * -* Paramètres : operand = registre visé par la procédure. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void py_arch_operand_print_wrapper(const GArchOperand *operand, GBufferLine *line) -{ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_OPERAND_PRINT_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _print, "$self, line, /", \ - METH_VARARGS, \ - "Abstract method used to print the operand into a rendering" \ - " line, which is a provided pychrysalide.glibext.BufferLine" \ - " instance." \ -) - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(operand)); - - if (has_python_method(pyobj, "_print")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); - - pyret = run_python_method(pyobj, "_print", args); - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * -* * -* Description : Construit un petit résumé concis de l'opérande. * -* * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand, const GLoadedBinary *binary) -{ - char *result; /* Description à retourner */ - PyGILState_STATE gstate; /* Sauvegarde d'environnement */ - PyObject *pyobj; /* Objet Python concerné */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *pyret; /* Bilan de consultation */ - -#define ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER PYTHON_WRAPPER_DEF \ -( \ - _build_tooltip, "$self, line, /", \ - METH_VARARGS, \ - "Abstract method used to build a tooltip text shown when the" \ - " mouse is over the operand.\n" \ - "\n" \ - "A pychrysalide.analysis.LoadedBinary instance is provided in" \ - " case of need." \ -) - - result = NULL; - - gstate = PyGILState_Ensure(); - - pyobj = pygobject_new(G_OBJECT(operand)); - - if (has_python_method(pyobj, "_build_tooltip")) - { - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary))); - - pyret = run_python_method(pyobj, "_build_tooltip", args); - - if (pyret != NULL) - { - if (PyUnicode_Check(pyret)) - result = strdup(PyUnicode_AsUTF8(pyret)); - } - - Py_XDECREF(pyret); - - Py_DECREF(args); - - } - - Py_DECREF(pyobj); - - PyGILState_Release(gstate); - - return result; - -} - #endif @@ -540,6 +429,9 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand, /* ---------------------------------------------------------------------------------- */ + +#if 0 + /****************************************************************************** * * * Paramètres : a = premier object Python à consulter. * @@ -701,6 +593,164 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyO } +#endif + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Ajoute une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_set_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_SET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + set_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Add some flags to the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to apply to the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* for operation" \ + " success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_set_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Retire une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_unset_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_UNSET_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + unset_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Remove some flags from the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to delete from the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* for operation" \ + " success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_unset_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Détermine si un opérande possède un fanion particulier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_operand_has_flag(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + unsigned int flag; /* Fanion(s) à appliquer */ + int ret; /* Bilan de lecture des args. */ + GArchOperand *operand; /* Opérande manipulé */ + bool status; /* Bilan à transmettre */ + +#define ARCH_OPERAND_HAS_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + has_flag, "$self, flag, /", \ + METH_VARARGS, py_arch_operand, \ + "Tell if some flags are set for the operand.\n" \ + "\n" \ + "This *flag* argument is an integer value containing" \ + " bits to test for the operand state.\n" \ + "\n" \ + "The result is an boolean status: *True* if the bits" \ + " are active, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + operand = G_ARCH_OPERAND(pygobject_get(self)); + + status = g_arch_operand_has_flag(operand, flag); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + /****************************************************************************** * * @@ -717,6 +767,11 @@ static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyO PyTypeObject *get_python_arch_operand_type(void) { static PyMethodDef py_arch_operand_methods[] = { + ARCH_OPERAND_SET_FLAG_METHOD, + ARCH_OPERAND_UNSET_FLAG_METHOD, + ARCH_OPERAND_HAS_FLAG_METHOD, + + /* ARCH_OPERAND_CMP_WRAPPER, ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER, ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER, @@ -726,6 +781,7 @@ PyTypeObject *get_python_arch_operand_type(void) #endif ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD, ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD, + */ { NULL } }; @@ -744,11 +800,12 @@ PyTypeObject *get_python_arch_operand_type(void) .tp_doc = ARCH_OPERAND_DOC, - .tp_richcompare = py_arch_operand_richcompare, + //.tp_richcompare = py_arch_operand_richcompare, .tp_methods = py_arch_operand_methods, .tp_getset = py_arch_operand_getseters, + .tp_init = py_arch_operand_init, .tp_new = py_arch_operand_new, }; @@ -784,9 +841,26 @@ bool ensure_python_arch_operand_is_registered(void) dict = PyModule_GetDict(module); + if (!ensure_python_thick_object_is_registered()) + return false; + + if (!ensure_python_comparable_object_is_registered()) + return false; + + if (!ensure_python_hashable_object_is_registered()) + return false; + + if (!ensure_python_serializable_object_is_registered()) + return false; + if (!ensure_python_singleton_candidate_is_registered()) return false; + if (!ensure_python_string_builder_is_registered()) + return false; + + pyg_register_class_init(G_TYPE_ARCH_OPERAND, (PyGClassInitFunc)py_arch_operand_init_gclass); + if (!register_class_for_pygobject(dict, G_TYPE_ARCH_OPERAND, type)) return false; |