diff options
Diffstat (limited to 'plugins/pychrysalide/arch')
| -rw-r--r-- | plugins/pychrysalide/arch/processor.c | 10 | ||||
| -rw-r--r-- | plugins/pychrysalide/arch/register.c | 407 | 
2 files changed, 393 insertions, 24 deletions
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c index 37f97a4..557e7a7 100644 --- a/plugins/pychrysalide/arch/processor.c +++ b/plugins/pychrysalide/arch/processor.c @@ -677,6 +677,8 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces      PyObject *pyins;                        /* Instruction en objet Python */      int ret;                                /* Bilan d'une conversion      */ +    result = NULL; +      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(proc)); @@ -696,10 +698,7 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces          Py_DECREF(args); -        if (pyins == NULL) -            result = NULL; - -        else +        if (pyins != NULL)          {              ret = convert_to_arch_instruction(pyins, &result); @@ -721,9 +720,6 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces      } -    else -        result = NULL; -      PyGILState_Release(gstate);      return result; diff --git a/plugins/pychrysalide/arch/register.c b/plugins/pychrysalide/arch/register.c index 7ecdb0e..84d3180 100644 --- a/plugins/pychrysalide/arch/register.c +++ b/plugins/pychrysalide/arch/register.c @@ -48,17 +48,35 @@ static PyObject *py_arch_register_new(PyTypeObject *, PyObject *, PyObject *);  /* Initialise la classe des descriptions de fichier binaire. */  static void py_arch_register_init_gclass(GArchRegisterClass *, gpointer); +/* Produit une empreinte à partir d'un registre. */ +static guint py_arch_register___hash___wrapper(const GArchRegister *); + +/* Compare un registre avec un autre. */ +static int py_arch_register___cmp___wrapper(const GArchRegister *, const GArchRegister *); + +/* Traduit un registre en version humainement lisible. */ +static void py_arch_register_print_wrapper(const GArchRegister *, GBufferLine *); +  /* Indique si le registre correspond à ebp ou similaire. */ -static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *); +static bool py_arch_register_is_base_pointer_wrapper(const GArchRegister *); + +/* Indique si le registre correspond à esp ou similaire. */ +static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *);  /* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */ +/* Effectue une comparaison avec un objet Python 'ArchRegister'. */ +static PyObject *py_arch_register_richcompare(PyObject *, PyObject *, int); +  /* Indique si le registre correspond à ebp ou similaire. */  static PyObject *py_arch_register_is_base_pointer(PyObject *, void *); +/* Indique si le registre correspond à esp ou similaire. */ +static PyObject *py_arch_register_is_stack_pointer(PyObject *, void *); +  /* ---------------------------------------------------------------------------------- */ @@ -88,6 +106,23 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje      GType gtype;                            /* Nouveau type de registre    */      bool status;                            /* Bilan d'un enregistrement   */ +#define ARCH_REGISTER_DOC                                               \ +    "The ArchRegister object aims to get subclassed to create"          \ +    " registers suitable for new architectures.\n"                      \ +    "\n"                                                                \ +    "Calls to the *__init__* constructor of this abstract object expect"\ +    " no particular argument.\n"                                        \ +    "\n"                                                                \ +    "The following methods have to be defined for new classes:\n"       \ +    "* pychrysalide.arch.ArchRegister.__hash__();\n"                    \ +    "* pychrysalide.arch.ArchRegister.__cmp__();\n"                     \ +    "* pychrysalide.arch.ArchRegister._print();\n"                      \ +    "* pychrysalide.arch.ArchRegister._is_base_pointer();\n"            \ +    "* pychrysalide.arch.ArchRegister._is_stack_pointer().\n"           \ +    "\n"                                                                \ +    "Chrysalide creates an internal glue to provide rich comparisons"   \ +    " for registers based on the old-style *__cmp__* function." +      /* Validations diverses */      base = get_python_arch_register_type(); @@ -144,7 +179,182 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje  static void py_arch_register_init_gclass(GArchRegisterClass *class, gpointer unused)  { -    class->is_bp = g_arch_register_is_base_pointer_wrapper; +    class->hash = py_arch_register___hash___wrapper; +    class->compare = py_arch_register___cmp___wrapper; +    class->print = py_arch_register_print_wrapper; +    class->is_bp = py_arch_register_is_base_pointer_wrapper; +    class->is_sp = py_arch_register_is_stack_pointer_wrapper; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : reg = registre visé par la procédure.                        * +*                                                                             * +*  Description : Produit une empreinte à partir d'un registre.                * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static guint py_arch_register___hash___wrapper(const GArchRegister *reg) +{ +    guint result;                           /* Empreinte à retourner       */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ + +#define ARCH_REGISTER_HASH_WRAPPER PYTHON_WRAPPER_DEF           \ +(                                                               \ +    __hash__, "$self, /",                                       \ +    METH_NOARGS,                                                \ +    "Abstract method used to produce a hash of the object. The" \ +    " result must be an integer value."                         \ +) + +    result = 0; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(reg)); + +    if (has_python_method(pyobj, "__hash__")) +    { +        pyret = run_python_method(pyobj, "__hash__", NULL); + +        if (pyret != NULL) +        { +            if (PyLong_Check(pyret)) +                result = PyLong_AsUnsignedLong(pyret); + +            Py_DECREF(pyret); + +        } + +    } + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : a = premier opérande à consulter.                            * +*                b = second opérande à consulter.                             * +*                                                                             * +*  Description : Compare un registre avec un autre.                           * +*                                                                             * +*  Retour      : Bilan de la comparaison.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_arch_register___cmp___wrapper(const GArchRegister *a, const GArchRegister *b) +{ +    int result;                             /* Empreinte à retourner       */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ + +#define ARCH_REGISTER_CMP_WRAPPER PYTHON_WRAPPER_DEF            \ +(                                                               \ +    __cmp__, "$self, other, /",                                 \ +    METH_VARARGS,                                               \ +    "Abstract method used to produce a compare the register"    \ +    " with another one. This second object is always an"        \ +    " pychrysalide.arch.ArchRegister instance.\n"               \ +    "\n"                                                        \ +    " This is the old-style comparison method, but Chrysalide"  \ +    " provides a glue to automatically build a rich version of" \ +    " this function."                                           \ +) + +    result = 0; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(a)); + +    if (has_python_method(pyobj, "__cmp__")) +    { +        args = PyTuple_New(1); +        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(b))); + +        pyret = run_python_method(pyobj, "__cmp__", args); + +        if (pyret != NULL) +        { +            if (PyLong_Check(pyret)) +                result = PyLong_AsLong(pyret); +        } + +        Py_DECREF(args); + +        Py_XDECREF(pyret); + +    } + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : reg = registre visé par la procédure.                        * +*                                                                             * +*  Description : Traduit un registre en version humainement lisible.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void py_arch_register_print_wrapper(const GArchRegister *reg, 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_REGISTER_PRINT_WRAPPER PYTHON_WRAPPER_DEF              \ +(                                                                   \ +    _print, "$self, line, /",                                       \ +    METH_VARARGS,                                                   \ +    "Abstract method used to print the register into a rendering"   \ +    " line, which is a provided pychrysalide.glibext.BufferLine"    \ +    " instance."                                                    \ +) + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(reg)); + +    if (has_python_method(pyobj, "_print")) +    { +        args = PyTuple_New(1); +        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); + +        pyret = run_python_method(pyobj, "_print", args); + +        Py_DECREF(args); + +        Py_XDECREF(pyret); + +    } + +    PyGILState_Release(gstate);  } @@ -161,21 +371,96 @@ static void py_arch_register_init_gclass(GArchRegisterClass *class, gpointer unu  *                                                                             *  ******************************************************************************/ -static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *reg) +static bool py_arch_register_is_base_pointer_wrapper(const GArchRegister *reg) +{ +    bool result;                            /* Bilan à renvoyer            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ + +#define ARCH_REGISTER_IS_BASE_POINTER_WRAPPER PYTHON_WRAPPER_DEF    \ +(                                                                   \ +    _is_base_pointer, "$self, /",                                   \ +    METH_NOARGS,                                                    \ +    "Abstract method used to tell if the register is handling a"    \ +    " base pointer. The result must be a boolean value."            \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(reg)); + +    if (has_python_method(pyobj, "_is_base_pointer")) +    { +        pyret = run_python_method(pyobj, "_is_base_pointer", NULL); + +        if (pyret != NULL) +        { +            result = (pyret == Py_True); + +            Py_DECREF(pyret); + +        } + +    } + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : reg = registre visé par la procédure.                        * +*                                                                             * +*  Description : Indique si le registre correspond à esp ou similaire.        * +*                                                                             * +*  Retour      : true si la correspondance est avérée, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *reg)  {      bool result;                            /* Bilan à renvoyer            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *pyret;                        /* Bilan de consultation       */ +#define ARCH_REGISTER_IS_STACK_POINTER_WRAPPER PYTHON_WRAPPER_DEF   \ +(                                                                   \ +    _is_stack_pointer, "$self, /",                                  \ +    METH_NOARGS,                                                    \ +    "Abstract method used to tell if the register is handling a"    \ +    " stack pointer. The result must be a boolean value."           \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); +      pyobj = pygobject_new(G_OBJECT(reg)); -    assert(has_python_method(pyobj, "_is_base_pointer")); +    if (has_python_method(pyobj, "_is_stack_pointer")) +    { +        pyret = run_python_method(pyobj, "_is_stack_pointer", NULL); + +        if (pyret != NULL) +        { +            result = (pyret == Py_True); -    pyret = run_python_method(pyobj, "_is_base_pointer", NULL); +            Py_DECREF(pyret); -    result = (pyret == Py_True); +        } + +    } -    Py_XDECREF(pyret); +    PyGILState_Release(gstate);      return result; @@ -190,6 +475,51 @@ static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *reg)  /******************************************************************************  *                                                                             * +*  Paramètres  : a  = premier object Python à consulter.                      * +*                b  = second object Python à consulter.                       * +*                op = type de comparaison menée.                              * +*                                                                             * +*  Description : Effectue une comparaison avec un objet Python 'ArchRegister'.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_arch_register_richcompare(PyObject *a, PyObject *b, int op) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    int ret;                                /* Bilan de lecture des args.  */ +    const GArchRegister *reg_a;             /* Premier élément à traiter   */ +    const GArchRegister *reg_b;             /* Second élément à traiter    */ +    int status;                             /* Résultat d'une comparaison  */ + +    ret = PyObject_IsInstance(b, (PyObject *)get_python_arch_register_type()); +    if (!ret) +    { +        result = Py_NotImplemented; +        goto cmp_done; +    } + +    reg_a = G_ARCH_REGISTER(pygobject_get(a)); +    reg_b = G_ARCH_REGISTER(pygobject_get(b)); + +    status = py_arch_register___cmp___wrapper(reg_a, reg_b); + +    result = status_to_rich_cmp_state(status, op); + + cmp_done: + +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : self    = objet Python concerné par l'appel.                 *  *                closure = non utilisé ici.                                   *  *                                                                             * @@ -207,6 +537,12 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)      GArchRegister *reg;                     /* Registre visé               */      bool status;                            /* Bilan de consultation       */ +#define ARCH_REGISTER_IS_BASE_POINTER_ATTRIB PYTHON_IS_DEF_FULL     \ +(                                                                   \ +    base_pointer, py_arch_register,                                 \ +    "Tell if the register is a base pointer or not."                \ +) +      reg = G_ARCH_REGISTER(pygobject_get(self));      status = g_arch_register_is_base_pointer(reg); @@ -221,6 +557,43 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)  /******************************************************************************  *                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Indique si le registre correspond à esp ou similaire.        * +*                                                                             * +*  Retour      : True si la correspondance est avérée, False sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_arch_register_is_stack_pointer(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Instance Python à retourner */ +    GArchRegister *reg;                     /* Registre visé               */ +    bool status;                            /* Bilan de consultation       */ + +#define ARCH_REGISTER_IS_STACK_POINTER_ATTRIB PYTHON_IS_DEF_FULL    \ +(                                                                   \ +    stack_pointer, py_arch_register,                                \ +    "Tell if the register is a stack pointer or not."               \ +) + +    reg = G_ARCH_REGISTER(pygobject_get(self)); + +    status = g_arch_register_is_stack_pointer(reg); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : -                                                            *  *                                                                             *  *  Description : Fournit un accès à une définition de type à diffuser.        * @@ -234,19 +607,17 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)  PyTypeObject *get_python_arch_register_type(void)  {      static PyMethodDef py_arch_register_methods[] = { -        { -            "_is_base_pointer", not_yet_implemented_method, -            METH_NOARGS, -            "_is_base_pointer($self, /)\n--\n\nDefine an implementation to provide the relative member value." -        }, +        ARCH_REGISTER_HASH_WRAPPER, +        ARCH_REGISTER_CMP_WRAPPER, +        ARCH_REGISTER_PRINT_WRAPPER, +        ARCH_REGISTER_IS_BASE_POINTER_WRAPPER, +        ARCH_REGISTER_IS_STACK_POINTER_WRAPPER,          { NULL }      };      static PyGetSetDef py_arch_register_getseters[] = { -        { -            "is_base_pointer", py_arch_register_is_base_pointer, NULL, -            "Tell if the register is a base pointer or not.", NULL -        }, +        ARCH_REGISTER_IS_BASE_POINTER_ATTRIB, +        ARCH_REGISTER_IS_STACK_POINTER_ATTRIB,          { NULL }      }; @@ -259,7 +630,9 @@ PyTypeObject *get_python_arch_register_type(void)          .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, -        .tp_doc         = "PyChrysalide register for a given architecture.", +        .tp_doc         = ARCH_REGISTER_DOC, + +        .tp_richcompare = py_arch_register_richcompare,          .tp_methods     = py_arch_register_methods,          .tp_getset      = py_arch_register_getseters,  | 
