diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-07-17 16:36:21 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-07-17 16:36:21 (GMT) |
commit | 24d3836fcf8d443eb654b981f65478cd9923b8f1 (patch) | |
tree | 7672a28b864127e8958c3c6cce751dcf646d2fbe /plugins/pychrysa/format | |
parent | a61f089babe336b012da31a494b0f7470b6e1a9a (diff) |
Updated the Python bindings.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@552 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'plugins/pychrysa/format')
-rw-r--r-- | plugins/pychrysa/format/Makefile.am | 3 | ||||
-rw-r--r-- | plugins/pychrysa/format/dex/class.c | 91 | ||||
-rw-r--r-- | plugins/pychrysa/format/dex/class.h | 3 | ||||
-rw-r--r-- | plugins/pychrysa/format/dex/dex.c | 99 | ||||
-rw-r--r-- | plugins/pychrysa/format/dex/dex.h | 5 | ||||
-rw-r--r-- | plugins/pychrysa/format/dex/module.c | 36 | ||||
-rw-r--r-- | plugins/pychrysa/format/elf/elf.c | 94 | ||||
-rw-r--r-- | plugins/pychrysa/format/elf/elf.h | 5 | ||||
-rw-r--r-- | plugins/pychrysa/format/elf/module.c | 36 | ||||
-rw-r--r-- | plugins/pychrysa/format/executable.c | 97 | ||||
-rw-r--r-- | plugins/pychrysa/format/executable.h | 5 | ||||
-rw-r--r-- | plugins/pychrysa/format/format.c | 505 | ||||
-rw-r--r-- | plugins/pychrysa/format/format.h | 19 | ||||
-rw-r--r-- | plugins/pychrysa/format/module.c | 42 | ||||
-rw-r--r-- | plugins/pychrysa/format/symbol.c | 720 | ||||
-rw-r--r-- | plugins/pychrysa/format/symbol.h | 42 |
16 files changed, 1501 insertions, 301 deletions
diff --git a/plugins/pychrysa/format/Makefile.am b/plugins/pychrysa/format/Makefile.am index 0adbe0f..5733e39 100644 --- a/plugins/pychrysa/format/Makefile.am +++ b/plugins/pychrysa/format/Makefile.am @@ -4,7 +4,8 @@ noinst_LTLIBRARIES = libpychrysaformat.la libpychrysaformat_la_SOURCES = \ executable.h executable.c \ format.h format.c \ - module.h module.c + module.h module.c \ + symbol.h symbol.c libpychrysaformat_la_LIBADD = \ dex/libpychrysaformatdex.la \ diff --git a/plugins/pychrysa/format/dex/class.c b/plugins/pychrysa/format/dex/class.c index 538fd25..1741b52 100644 --- a/plugins/pychrysa/format/dex/class.c +++ b/plugins/pychrysa/format/dex/class.c @@ -31,48 +31,48 @@ #include <format/dex/class.h> -#include "../../quirks.h" - - - -/* Crée un nouvel objet Python de type 'DexClass'. */ -static PyObject *py_dex_class_new(PyTypeObject *, PyObject *, PyObject *); - - /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * -* args = arguments fournis à l'appel. * -* kwds = arguments de type key=val fournis. * +* Paramètres : - * * * -* Description : Crée un nouvel objet Python de type 'DexClass'. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : Instance Python mise en place. * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_dex_class_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +PyTypeObject *get_python_dex_class_type(void) { - Py_RETURN_NONE; - -} - - - - + static PyMethodDef py_dex_class_methods[] = { + { NULL } + }; + static PyGetSetDef py_dex_class_getseters[] = { + { NULL } + }; + static PyTypeObject py_dex_class_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "pychrysalide.format.dex.DexClass", + .tp_basicsize = sizeof(PyGObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "PyChrysalide Dex class.", + .tp_methods = py_dex_class_methods, + .tp_getset = py_dex_class_getseters + }; + return &py_dex_class_type; +} /****************************************************************************** @@ -89,49 +89,26 @@ static PyObject *py_dex_class_new(PyTypeObject *type, PyObject *args, PyObject * bool register_python_dex_class(PyObject *module) { - PyObject *pygobj_mod; /* Module Python-GObject */ + PyTypeObject *py_dex_class_type; /* Type Python 'DexClass' */ int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - static PyMethodDef py_dex_class_methods[] = { - { NULL } - }; - - static PyGetSetDef py_dex_class_getseters[] = { - { NULL } - }; - - static PyTypeObject py_dex_class_type = { - - PyObject_HEAD_INIT(NULL) - - .tp_name = "pychrysalide.format.dex.DexClass", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyChrysalide Dex class", - - .tp_methods = py_dex_class_methods, - .tp_getset = py_dex_class_getseters, - .tp_new = (newfunc)py_dex_class_new - - }; - - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; + py_dex_class_type = get_python_dex_class_type(); - py_dex_class_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); + py_dex_class_type->tp_base = &PyGObject_Type; + py_dex_class_type->tp_basicsize = py_dex_class_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_dex_class_type) < 0) + if (PyType_Ready(py_dex_class_type) != 0) return false; - Py_INCREF(&py_dex_class_type); - ret = PyModule_AddObject(module, "DexClass", (PyObject *)&py_dex_class_type); + Py_INCREF(py_dex_class_type); + ret = PyModule_AddObject(module, "DexClass", (PyObject *)py_dex_class_type); + if (ret != 0) return false; - pygobject_register_class(module, "GDexClass", G_TYPE_DEX_CLASS, &py_dex_class_type, - Py_BuildValue("(O)", py_dex_class_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "DexClass", G_TYPE_DEX_CLASS, py_dex_class_type, + Py_BuildValue("(O)", py_dex_class_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/format/dex/class.h b/plugins/pychrysa/format/dex/class.h index d767d12..9bfcde2 100644 --- a/plugins/pychrysa/format/dex/class.h +++ b/plugins/pychrysa/format/dex/class.h @@ -31,6 +31,9 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_dex_class_type(void); + /* Prend en charge l'objet 'pychrysalide.format.dex.DexClass'. */ bool register_python_dex_class(PyObject *module); diff --git a/plugins/pychrysa/format/dex/dex.c b/plugins/pychrysa/format/dex/dex.c index 6f422a4..a11af52 100644 --- a/plugins/pychrysa/format/dex/dex.c +++ b/plugins/pychrysa/format/dex/dex.c @@ -28,11 +28,12 @@ #include <pygobject.h> -#include <format/dex/dex-int.h> +#include <format/dex/class.h> +#include <format/dex/dex.h> -#include "class.h" -#include "../../quirks.h" +#include "../executable.h" +#include "../../glibext/bincontent.h" @@ -64,19 +65,23 @@ static PyObject *py_dex_format_get_class(PyObject *, PyObject *); static PyObject *py_dex_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *result; /* Instance à retourner */ - const bin_t *content; /* Données binaires */ - int length; /* Quantité de ces données */ + PyObject *content_obj; /* Objet pour le contenu */ int ret; /* Bilan de lecture des args. */ - GBinFormat *format; /* Version GLib du format */ + GBinContent *content; /* Instance GLib correspondante*/ + GBinFormat *format; /* Création GLib à transmettre */ - ret = PyArg_ParseTuple(args, "s#", &content, &length); - if (!ret) Py_RETURN_NONE; + ret = PyArg_ParseTuple(args, "O", &content_obj); + if (!ret) return NULL; + + ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type()); + if (!ret) return NULL; - format = g_dex_format_new(content, length); - if (format == NULL) Py_RETURN_NONE; + content = G_BIN_CONTENT(pygobject_get(content_obj)); + format = g_dex_format_new(/* FIXME */(bin_t *)content, 0/*content*/); result = pygobject_new(G_OBJECT(format)); - //g_object_unref(format); + + g_object_unref(format); return (PyObject *)result; @@ -149,38 +154,30 @@ static PyObject *py_dex_format_get_class(PyObject *self, PyObject *args) } - - - - - /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexFormat'. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : Bilan de l'opération. * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -bool register_python_dex_format(PyObject *module) +PyTypeObject *get_python_dex_format_type(void) { - PyObject *parent_mod; /* Accès au module parent */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_dex_format_methods[] = { { "count_classes", (PyCFunction)py_dex_format_count_classes, METH_NOARGS, - "Count the quantity of loaded Dex classes." + "count_classes($self, /)\n--\n\nCount the quantity of loaded Dex classes." }, { "get_class", (PyCFunction)py_dex_format_get_class, METH_VARARGS, - "Provide a given loaded Dex class." + "get_class($self, index, /)\n--\n\nProvide a given loaded Dex class." }, { NULL } }; @@ -191,12 +188,12 @@ bool register_python_dex_format(PyObject *module) static PyTypeObject py_dex_format_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.format.dex.DexFormat", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide Dex format", @@ -206,27 +203,45 @@ bool register_python_dex_format(PyObject *module) }; - parent_mod = PyImport_ImportModule("pychrysalide.format"); - if (parent_mod == NULL) return false; + return &py_dex_format_type; + +} - py_dex_format_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "ExeFormat"); - Py_DECREF(parent_mod); - if (PyType_Ready(&py_dex_format_type) < 0) - return false; +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexFormat'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_dex_format(PyObject *module) +{ + PyTypeObject *py_dex_format_type; /* Type Python 'DexFormat' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - Py_INCREF(&py_dex_format_type); - ret = PyModule_AddObject(module, "DexFormat", (PyObject *)&py_dex_format_type); + py_dex_format_type = get_python_dex_format_type(); - parent_mod = PyImport_ImportModule("pychrysalide.format"); - if (parent_mod == NULL) return false; + py_dex_format_type->tp_base = get_python_executable_format_type(); + py_dex_format_type->tp_basicsize = py_dex_format_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_dex_format_type) != 0) + return false; - pygobject_register_class(module, "GDexFormat", G_TYPE_DEX_FORMAT, &py_dex_format_type, - Py_BuildValue("(OO)", py_dex_format_type.tp_base, - PyObject_GetAttrString(parent_mod, "BinFormat"))); + Py_INCREF(py_dex_format_type); + ret = PyModule_AddObject(module, "DexFormat", (PyObject *)py_dex_format_type); + if (ret != 0) return false; - Py_DECREF(parent_mod); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "DexFormat", G_TYPE_DEX_FORMAT, py_dex_format_type, + Py_BuildValue("(O)", py_dex_format_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/format/dex/dex.h b/plugins/pychrysa/format/dex/dex.h index 9a4c481..9d524bb 100644 --- a/plugins/pychrysa/format/dex/dex.h +++ b/plugins/pychrysa/format/dex/dex.h @@ -31,8 +31,11 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_dex_format_type(void); + /* Prend en charge l'objet 'pychrysalide.format.dex.DexFormat'. */ -bool register_python_dex_format(PyObject *module); +bool register_python_dex_format(PyObject *); diff --git a/plugins/pychrysa/format/dex/module.c b/plugins/pychrysa/format/dex/module.c index 43f0dbb..41f48c4 100644 --- a/plugins/pychrysa/format/dex/module.c +++ b/plugins/pychrysa/format/dex/module.c @@ -44,27 +44,43 @@ bool add_format_dex_module_to_python_module(PyObject *super) { - bool result; - PyObject *module; + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyMethodDef py_format_dex_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_dex_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.format.dex", + .m_doc = "Python module for Chrysalide.format.dex", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.format.dex", py_format_dex_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_dex_module); if (module == NULL) return false; - Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.format.dex", module); + ret = PyState_AddModule(super, &py_chrysalide_dex_module); + if (ret != 0) goto loading_failed; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.format.dex"); + if (ret != 0) goto loading_failed; - result = (ret == 0); + Py_INCREF(module); + ret = PyModule_AddObject(super, "dex", module); + if (ret != 0) goto loading_failed; - if (ret != 0) /* ... */; + result = true; result &= register_python_dex_class(module); result &= register_python_dex_format(module); - return true; + loading_failed: + + return result; } diff --git a/plugins/pychrysa/format/elf/elf.c b/plugins/pychrysa/format/elf/elf.c index 3ae8f53..87988ee 100644 --- a/plugins/pychrysa/format/elf/elf.c +++ b/plugins/pychrysa/format/elf/elf.c @@ -28,10 +28,11 @@ #include <pygobject.h> -#include <format/elf/elf-int.h> +#include <format/elf/elf.h> -#include "../../quirks.h" +#include "../executable.h" +#include "../../glibext/bincontent.h" @@ -57,48 +58,43 @@ static PyObject *py_elf_format_new(PyTypeObject *, PyObject *, PyObject *); static PyObject *py_elf_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *result; /* Instance à retourner */ - const bin_t *content; /* Données binaires */ - int length; /* Quantité de ces données */ + PyObject *content_obj; /* Objet pour le contenu */ int ret; /* Bilan de lecture des args. */ - GBinFormat *format; /* Version GLib du format */ + GBinContent *content; /* Instance GLib correspondante*/ + GBinFormat *format; /* Création GLib à transmettre */ - ret = PyArg_ParseTuple(args, "s#", &content, &length); - if (!ret) Py_RETURN_NONE; + ret = PyArg_ParseTuple(args, "O", &content_obj); + if (!ret) return NULL; - format = NULL;//g_elf_format_new(content, length); - if (format == NULL) Py_RETURN_NONE; + ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type()); + if (!ret) return NULL; + + content = G_BIN_CONTENT(pygobject_get(content_obj)); + format = g_elf_format_new(content); result = pygobject_new(G_OBJECT(format)); - //g_object_unref(format); + + g_object_unref(format); return (PyObject *)result; } - - - - - - /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : Bilan de l'opération. * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -bool register_python_elf_format(PyObject *module) +PyTypeObject *get_python_elf_format_type(void) { - PyObject *parent_mod; /* Accès au module parent */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_elf_format_methods[] = { { NULL } }; @@ -109,12 +105,12 @@ bool register_python_elf_format(PyObject *module) static PyTypeObject py_elf_format_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.format.elf.ElfFormat", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide Elf format", @@ -124,27 +120,45 @@ bool register_python_elf_format(PyObject *module) }; - parent_mod = PyImport_ImportModule("pychrysalide.format"); - if (parent_mod == NULL) return false; + return &py_elf_format_type; + +} - py_elf_format_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "ExeFormat"); - Py_DECREF(parent_mod); - if (PyType_Ready(&py_elf_format_type) < 0) - return false; +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_elf_format(PyObject *module) +{ + PyTypeObject *py_elf_format_type; /* Type Python 'ElfFormat' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - Py_INCREF(&py_elf_format_type); - ret = PyModule_AddObject(module, "ElfFormat", (PyObject *)&py_elf_format_type); + py_elf_format_type = get_python_elf_format_type(); - parent_mod = PyImport_ImportModule("pychrysalide.format"); - if (parent_mod == NULL) return false; + py_elf_format_type->tp_base = get_python_executable_format_type(); + py_elf_format_type->tp_basicsize = py_elf_format_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_elf_format_type) != 0) + return false; - pygobject_register_class(module, "GElfFormat", G_TYPE_ELF_FORMAT, &py_elf_format_type, - Py_BuildValue("(OO)", py_elf_format_type.tp_base, - PyObject_GetAttrString(parent_mod, "BinFormat"))); + Py_INCREF(py_elf_format_type); + ret = PyModule_AddObject(module, "ElfFormat", (PyObject *)py_elf_format_type); + if (ret != 0) return false; - Py_DECREF(parent_mod); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ElfFormat", G_TYPE_ELF_FORMAT, py_elf_format_type, + Py_BuildValue("(O)", py_elf_format_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/format/elf/elf.h b/plugins/pychrysa/format/elf/elf.h index 658e58b..d037942 100644 --- a/plugins/pychrysa/format/elf/elf.h +++ b/plugins/pychrysa/format/elf/elf.h @@ -31,8 +31,11 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_elf_format_type(void); + /* Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. */ -bool register_python_elf_format(PyObject *module); +bool register_python_elf_format(PyObject *); diff --git a/plugins/pychrysa/format/elf/module.c b/plugins/pychrysa/format/elf/module.c index d701cfd..ebd34d9 100644 --- a/plugins/pychrysa/format/elf/module.c +++ b/plugins/pychrysa/format/elf/module.c @@ -43,26 +43,42 @@ bool add_format_elf_module_to_python_module(PyObject *super) { - bool result; - PyObject *module; + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyMethodDef py_format_elf_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_elf_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.format.elf", + .m_doc = "Python module for Chrysalide.format.elf", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.format.elf", py_format_elf_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_elf_module); if (module == NULL) return false; - Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.format.elf", module); + ret = PyState_AddModule(super, &py_chrysalide_elf_module); + if (ret != 0) goto loading_failed; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.format.elf"); + if (ret != 0) goto loading_failed; - result = (ret == 0); + Py_INCREF(module); + ret = PyModule_AddObject(super, "elf", module); + if (ret != 0) goto loading_failed; - if (ret != 0) /* ... */; + result = true; result &= register_python_elf_format(module); - return true; + loading_failed: + + return result; } diff --git a/plugins/pychrysa/format/executable.c b/plugins/pychrysa/format/executable.c index 21da818..e7e218d 100644 --- a/plugins/pychrysa/format/executable.c +++ b/plugins/pychrysa/format/executable.c @@ -31,55 +31,58 @@ #include <format/format.h> -#include "../quirks.h" - - - -/* Crée un nouvel objet Python de type 'BinFormat'. */ -static PyObject *py_executable_format_new(PyTypeObject *, PyObject *, PyObject *); - - - - -#define _(str) str - +#include "format.h" /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * -* args = arguments fournis à l'appel. * -* kwds = arguments de type key=val fournis. * +* Paramètres : - * * * -* Description : Crée un nouvel objet Python de type 'BinFormat'. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : Instance Python mise en place. * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_executable_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +PyTypeObject *get_python_executable_format_type(void) { - PyErr_SetString(PyExc_ValueError, - _("pychrysalide.format.ExeFormat can not be instanciated directly")); + static PyMethodDef py_exe_format_methods[] = { + { NULL } + }; - return NULL; + static PyGetSetDef py_exe_format_getseters[] = { + { NULL } + }; -} + static PyTypeObject py_exe_format_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.ExeFormat", + .tp_basicsize = sizeof(PyGObject), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_doc = "PyChrysalide executable format", + .tp_methods = py_exe_format_methods, + .tp_getset = py_exe_format_getseters, + }; + return &py_exe_format_type; + +} /****************************************************************************** * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Prend en charge l'objet 'pychrysalide.gui.panels.BinFormat'. * +* Description : Prend en charge l'objet 'pychrysalide.format.ExeFormat'. * * * * Retour : Bilan de l'opération. * * * @@ -89,46 +92,26 @@ static PyObject *py_executable_format_new(PyTypeObject *type, PyObject *args, Py bool register_python_executable_format(PyObject *module) { - PyObject *parent_mod; /* Accès au module parent */ + PyTypeObject *py_exe_format_type; /* Type Python 'ExeFormat' */ int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - static PyMethodDef py_executable_format_methods[] = { - { NULL } - }; - - static PyGetSetDef py_executable_format_getseters[] = { - { NULL } - }; - - static PyTypeObject py_executable_format_type = { - - PyObject_HEAD_INIT(NULL) - - .tp_name = "pychrysalide.format.ExeFormat", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyChrysalide executable format", - - .tp_methods = py_executable_format_methods, - .tp_getset = py_executable_format_getseters, - .tp_new = (newfunc)py_executable_format_new - - }; + py_exe_format_type = get_python_executable_format_type(); - parent_mod = PyImport_ImportModule("pychrysalide.format"); - if (parent_mod == NULL) return false; + py_exe_format_type->tp_base = get_python_binary_format_type(); + py_exe_format_type->tp_basicsize = py_exe_format_type->tp_base->tp_basicsize; - py_executable_format_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "BinFormat"); - Py_DECREF(parent_mod); - - if (PyType_Ready(&py_executable_format_type) < 0) + if (PyType_Ready(py_exe_format_type) != 0) return false; - Py_INCREF(&py_executable_format_type); - ret = PyModule_AddObject(module, "ExeFormat", (PyObject *)&py_executable_format_type); + Py_INCREF(py_exe_format_type); + ret = PyModule_AddObject(module, "ExeFormat", (PyObject *)py_exe_format_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ExeFormat", G_TYPE_EXE_FORMAT, py_exe_format_type, + Py_BuildValue("(O)", py_exe_format_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/format/executable.h b/plugins/pychrysa/format/executable.h index 40b5dcf..64b03f7 100644 --- a/plugins/pychrysa/format/executable.h +++ b/plugins/pychrysa/format/executable.h @@ -31,8 +31,11 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_executable_format_type(void); + /* Prend en charge l'objet 'pychrysalide.format.ExeFormat'. */ -bool register_python_executable_format(PyObject *module); +bool register_python_executable_format(PyObject *); diff --git a/plugins/pychrysa/format/format.c b/plugins/pychrysa/format/format.c index 423e94e..290b189 100644 --- a/plugins/pychrysa/format/format.c +++ b/plugins/pychrysa/format/format.c @@ -31,39 +31,139 @@ #include <format/format.h> -#include "../quirks.h" +#include "../helpers.h" +#include "../arch/vmpa.h" +/* ------------------------ PARCOURS DE SYMBOLES DE BINAIRES ------------------------ */ +/* Parcours des symboles présents dans un binaire */ +typedef struct _pyBinSymbolIterator +{ + PyObject_HEAD /* A laisser en premier */ + + GBinFormat *format; /* Format binaire à consulter */ + size_t next; /* Symbole binaire à présenter */ + +} pyBinSymbolIterator; + + +/* Prend acte d'un compteur de référence à 0. */ +static void py_binary_symbol_iterator_dealloc(PyObject *); + +/* Fournit un itérateur pour symboles de format binaire. */ +static PyObject *py_binary_symbol_iterator_next(PyObject *); + +/* Initialise un objet Python de type 'BinSymbolIterator'. */ +static int py_binary_symbol_iterator_init(PyObject *, PyObject *, PyObject *); + + + +/* ---------------------------- FORMAT BINAIRE GENERIQUE ---------------------------- */ + + +/* Recherche le symbole correspondant à une étiquette. */ +static PyObject *py_binary_format_find_symbol_by_label(PyObject *, PyObject *); + +/* Recherche le symbole suivant celui lié à une adresse. */ +static PyObject *py_binary_format_find_symbol_at(PyObject *, PyObject *); + +/* Recherche le symbole suivant celui lié à une adresse. */ +static PyObject *py_binary_format_find_next_symbol_at(PyObject *, PyObject *); + +/* Recherche le symbole correspondant à une adresse. */ +static PyObject *py_binary_format_resolve_symbol(PyObject *, PyObject *); + +/* Fournit la liste de tous les symboles détectés. */ +static PyObject *py_binary_format_get_symbols(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS DE SYMBOLES DE BINAIRES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = instance Python à libérer de la mémoire. * +* * +* Description : Prend acte d'un compteur de référence à 0. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ -#define _(str) str +static void py_binary_symbol_iterator_dealloc(PyObject *self) +{ + pyBinSymbolIterator *iterator; /* Références pour le parcours */ + /** + * Il aurait été sans doute mieux de reposer ici sur .tp_finalize, + * mais cela semble impliquer de mettre en place tous les mécanismes de GC... + * + * cf. https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation + */ + iterator = (pyBinSymbolIterator *)self; + g_object_unref(G_OBJECT(iterator->format)); + Py_TYPE(self)->tp_free((PyObject *)self); -/* Crée un nouvel objet Python de type 'BinFormat'. */ -static PyObject *py_binary_format_new(PyTypeObject *, PyObject *, PyObject *); +} -/* Recherche une position dans une routine selon une adresse. */ -static PyObject *py_binary_format_resolve_relative_routine(PyObject *, PyObject *); +/****************************************************************************** +* * +* Paramètres : self = itérateur à manipuler. * +* * +* Description : Fournit un itérateur pour symboles de format binaire. * +* * +* Retour : Instance Python prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ -/* Fournit le prototype de toutes les routines détectées. */ -static PyObject *py_binary_format_get_routines(PyObject *, void *); +static PyObject *py_binary_symbol_iterator_next(PyObject *self) +{ + PyObject *result; /* Instance à retourner */ + pyBinSymbolIterator *iterator; /* Références pour le parcours */ + size_t count; /* Nombre de symboles présents */ + GBinSymbol **symbols; /* Liste de ces mêmes symboles */ + + iterator = (pyBinSymbolIterator *)self; + + symbols = g_binary_format_get_symbols(iterator->format, &count); + + if (iterator->next < count) + { + result = pygobject_new(G_OBJECT(symbols[iterator->next])); + iterator->next++; + } + else + { + PyErr_SetNone(PyExc_StopIteration); + result = NULL; + } + return result; +} /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet instancié à initialiser. * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'BinFormat'. * +* Description : Initialise un objet Python de type 'BinSymbolIterator'. * * * * Retour : Instance Python mise en place. * * * @@ -71,168 +171,431 @@ static PyObject *py_binary_format_get_routines(PyObject *, void *); * * ******************************************************************************/ -static PyObject *py_binary_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_binary_symbol_iterator_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + pyBinSymbolIterator *iterator; /* Références pour le parcours */ + PyObject *format; /* Format binaire en Python */ + int ret; /* Bilan de lecture des args. */ + + ret = PyArg_ParseTuple(args, "O", &format); + if (!ret) return -1; + + ret = PyObject_IsInstance(format, (PyObject *)get_python_binary_format_type()); + if (!ret) return -1; + + iterator = (pyBinSymbolIterator *)self; + + iterator->format = G_BIN_FORMAT(pygobject_get(format)); + g_object_ref(G_OBJECT(iterator->format)); + + iterator->next = 0; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_symbol_iterator_type(void) { - PyErr_SetString(PyExc_ValueError, - _("pychrysalide.format.BinFormat can not be instanciated directly")); + static PyTypeObject py_binary_symbol_iterator_type = { - return NULL; + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.BinSymbolIterator", + .tp_basicsize = sizeof(pyBinSymbolIterator), + + .tp_dealloc = py_binary_symbol_iterator_dealloc, + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "Iterator for binary symbols", + + .tp_iter = PyObject_SelfIter, + .tp_iternext = py_binary_symbol_iterator_next, + + .tp_init = py_binary_symbol_iterator_init, + + .tp_new = PyType_GenericNew, + + }; + + return &py_binary_symbol_iterator_type; } +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide...BinSymbolIterator'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_symbol_iterator(PyObject *module) +{ + PyTypeObject *py_binary_symbol_iterator_type; /* Type Python 'BinSymbolIterator' */ + int ret; /* Bilan d'un appel */ + + py_binary_symbol_iterator_type = get_python_binary_symbol_iterator_type(); + py_binary_symbol_iterator_type->tp_base = &PyBaseObject_Type; + if (PyType_Ready(py_binary_symbol_iterator_type) != 0) + return false; + Py_INCREF(py_binary_symbol_iterator_type); + ret = PyModule_AddObject(module, "BinSymbolIterator", (PyObject *)py_binary_symbol_iterator_type); + if (ret != 0) return false; + return true; +} +/* ---------------------------------------------------------------------------------- */ +/* FORMAT BINAIRE GENERIQUE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : self = classe représentant un format binaire. * +* Paramètres : self = classe représentant un binaire. * * args = arguments fournis à l'appel. * * * -* Description : Recherche une position dans une routine selon une adresse. * +* Description : Recherche le symbole correspondant à une étiquette. * * * -* Retour : Tuple (nom, décallage) ou Py_None. * +* Retour : Symbol trouvé si l'opération a été un succès, None sinon. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_binary_format_resolve_relative_routine(PyObject *self, PyObject *args) +static PyObject *py_binary_format_find_symbol_by_label(PyObject *self, PyObject *args) { - PyObject *result; /* Tuple à retourner */ - GBinFormat *format; /* Format à manipuler */ - vmpa_t addr; /* Adresse demandée en visuel */ + PyObject *result; /* Valeur à retourner */ + PyObject *label; /* Etiquette à retrouver */ int ret; /* Bilan de lecture des args. */ - bool found; /* Bilan de la résolution */ - const char *label; /* Désignation de la trouvaille*/ + GBinFormat *format; /* Format de binaire manipulé */ + GBinSymbol *symbol; /* Enventuel symbole trouvé */ + bool found; - format = G_BIN_FORMAT(pygobject_get(self)); + ret = PyArg_ParseTuple(args, "O", &label); + if (!ret) return NULL; + + ret = PyUnicode_Check(label); + if (!ret) return NULL; - ret = PyArg_ParseTuple(args, "K", &addr); - if (!ret) Py_RETURN_NONE; + format = G_BIN_FORMAT(pygobject_get(self)); - found = g_binary_format_resolve_relative_routine(format, &label, &addr); - if (!found) Py_RETURN_NONE; + found = g_binary_format_find_symbol_by_label(format, PyUnicode_DATA(label), &symbol); - result = PyTuple_New(2); - PyTuple_SetItem(result, 0, PyString_FromString(label)); - PyTuple_SetItem(result, 1, PyLong_FromLongLong(addr)); + if (found) + result = pygobject_new(G_OBJECT(symbol)); + else + { + result = Py_None; + Py_INCREF(result); + } return result; } +/****************************************************************************** +* * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Recherche le symbole suivant celui lié à une adresse. * +* * +* Retour : Symbol trouvé si l'opération a été un succès, None sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ +static PyObject *py_binary_format_find_symbol_at(PyObject *self, PyObject *args) +{ + PyObject *result; /* Valeur à retourner */ + PyObject *py_vmpa; /* Localisation version Python */ + int ret; /* Bilan de lecture des args. */ + GBinFormat *format; /* Format de binaire manipulé */ + GBinSymbol *symbol; /* Enventuel symbole trouvé */ + bool found; + + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + format = G_BIN_FORMAT(pygobject_get(self)); + + found = g_binary_format_find_symbol_at(format, get_internal_vmpa(py_vmpa), &symbol); + + if (found) + result = pygobject_new(G_OBJECT(symbol)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} /****************************************************************************** * * -* Paramètres : self = classe représentant un format binaire. * -* closure = adresse non utilisée ici. * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * * * -* Description : Fournit le prototype de toutes les routines détectées. * +* Description : Recherche le symbole suivant celui lié à une adresse. * * * -* Retour : Liste de routine, vide ou non. * +* Retour : Symbol trouvé si l'opération a été un succès, None sinon. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_binary_format_get_routines(PyObject *self, void *closure) +static PyObject *py_binary_format_find_next_symbol_at(PyObject *self, PyObject *args) { - PyObject *result; /* Tuple à retourner */ - GBinFormat *format; /* Format à manipuler */ - GBinRoutine **routines; /* Routines binaires présentes */ - size_t count; /* Quantité de ces routines */ - size_t i; /* Boucle de parcours */ + PyObject *result; /* Valeur à retourner */ + PyObject *py_vmpa; /* Localisation version Python */ + int ret; /* Bilan de lecture des args. */ + GBinFormat *format; /* Format de binaire manipulé */ + GBinSymbol *symbol; /* Enventuel symbole trouvé */ + bool found; + + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; format = G_BIN_FORMAT(pygobject_get(self)); - routines = g_binary_format_get_routines(format, &count); - result = PyTuple_New(count); + found = g_binary_format_find_next_symbol_at(format, get_internal_vmpa(py_vmpa), &symbol); - for (i = 0; i < count; i++) - PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(routines[i]))); + if (found) + result = pygobject_new(G_OBJECT(symbol)); + else + { + result = Py_None; + Py_INCREF(result); + } return result; } +/****************************************************************************** +* * +* Paramètres : self = classe représentant un format binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Recherche le symbole correspondant à une adresse. * +* * +* Retour : Tuple (nom, décallage) ou Py_None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_format_resolve_symbol(PyObject *self, PyObject *args) +{ + PyObject *result; /* Valeur à retourner */ + PyObject *py_vmpa; /* Localisation version Python */ + int ret; /* Bilan de lecture des args. */ + GBinFormat *format; /* Format de binaire manipulé */ + GBinSymbol *symbol; /* Enventuel symbole trouvé */ + phys_t diff; /* Décallage éventuel mesuré */ + bool found; + + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + format = G_BIN_FORMAT(pygobject_get(self)); + + found = g_binary_format_resolve_symbol(format, get_internal_vmpa(py_vmpa), &symbol, &diff); + + if (found) + { + result = PyTuple_New(2); + PyTuple_SetItem(result, 0, pygobject_new(G_OBJECT(symbol))); + PyTuple_SetItem(result, 1, PyLong_FromUnsignedLongLong(diff)); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : self = classe représentant un format binaire. * +* closure = adresse non utilisée ici. * * * -* Description : Prend en charge l'objet 'pychrysalide.gui.panels.BinFormat'. * +* Description : Fournit la liste de tous les symboles détectés. * * * -* Retour : Bilan de l'opération. * +* Retour : Tableau créé ou NULL si aucun symbole trouvé. * * * * Remarques : - * * * ******************************************************************************/ -bool register_python_binary_format(PyObject *module) +static PyObject *py_binary_format_get_symbols(PyObject *self, void *closure) { - PyObject *parent_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ + PyObject *result; /* Instance à retourner */ + PyTypeObject *iterator_type; /* Type Python de l'itérateur */ + PyObject *args_list; /* Arguments de mise en place */ - static PyMethodDef py_binary_format_methods[] = { + iterator_type = get_python_binary_symbol_iterator_type(); + + Py_INCREF(self); + + args_list = Py_BuildValue("(O)", self); + result = PyObject_CallObject((PyObject *)iterator_type, args_list); + + Py_DECREF(args_list); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_format_type(void) +{ + static PyMethodDef py_bin_format_methods[] = { + { + "find_symbol_by_label", py_binary_format_find_symbol_by_label, + METH_VARARGS, + "find_symbol_by_label($self, label, /)\n--\n\nFind a symbol by its label." + }, + { + "find_symbol_at", py_binary_format_find_symbol_at, + METH_VARARGS, + "find_symbol_at($self, addr, /)\n--\n\nFind a symbol at a given address." + }, { - "resolve_relative_routine", (PyCFunction)py_binary_format_resolve_relative_routine, + "find_next_symbol_at", py_binary_format_find_next_symbol_at, METH_VARARGS, - "Search a position inside a routine by a given address." + "find_next_symbol_at($self, addr, /)\n--\n\nFind the symbol next to the one found at a given address." + }, + { + "resolve_symbol", py_binary_format_resolve_symbol, + METH_VARARGS, + "resolve_symbol($self, addr, /)\n--\n\nSearch a position inside a routine by a given address." }, { NULL } }; - static PyGetSetDef py_binary_format_getseters[] = { + static PyGetSetDef py_bin_format_getseters[] = { { - "routines", (getter)py_binary_format_get_routines, (setter)NULL, - "Provide the list of all detected routines in the binary format.", NULL + "symbols", py_binary_format_get_symbols, NULL, + "Iterable list of all symbols found in the binary format.", NULL }, { NULL } }; - static PyTypeObject py_binary_format_type = { + static PyTypeObject py_bin_format_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.format.BinFormat", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, .tp_doc = "PyChrysalide binary format", - .tp_methods = py_binary_format_methods, - .tp_getset = py_binary_format_getseters, - .tp_new = (newfunc)py_binary_format_new + .tp_methods = py_bin_format_methods, + .tp_getset = py_bin_format_getseters }; - parent_mod = PyImport_ImportModule("gobject"); - if (parent_mod == NULL) return false; + return &py_bin_format_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.BinFormat'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_format(PyObject *module) +{ + PyTypeObject *py_bin_format_type; /* Type Python 'BinFormat' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - py_binary_format_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "GObject"); - Py_DECREF(parent_mod); + py_bin_format_type = get_python_binary_format_type(); - if (PyType_Ready(&py_binary_format_type) < 0) + py_bin_format_type->tp_base = &PyGObject_Type; + py_bin_format_type->tp_basicsize = py_bin_format_type->tp_base->tp_basicsize; + + APPLY_ABSTRACT_FLAG(py_bin_format_type); + + if (PyType_Ready(py_bin_format_type) != 0) return false; - Py_INCREF(&py_binary_format_type); - ret = PyModule_AddObject(module, "BinFormat", (PyObject *)&py_binary_format_type); + Py_INCREF(py_bin_format_type); + ret = PyModule_AddObject(module, "BinFormat", (PyObject *)py_bin_format_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BinFormat", G_TYPE_BIN_FORMAT, py_bin_format_type, + Py_BuildValue("(O)", py_bin_format_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/format/format.h b/plugins/pychrysa/format/format.h index 3a2c401..50ec47a 100644 --- a/plugins/pychrysa/format/format.h +++ b/plugins/pychrysa/format/format.h @@ -31,8 +31,25 @@ +/* ------------------------ PARCOURS DE SYMBOLES DE BINAIRES ------------------------ */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_symbol_iterator_type(void); + +/* Prend en charge l'objet 'pychrysalide...BinSymbolIterator'. */ +bool register_python_binary_symbol_iterator(PyObject *); + + + +/* ---------------------------- FORMAT BINAIRE GENERIQUE ---------------------------- */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_format_type(void); + /* Prend en charge l'objet 'pychrysalide.format.BinFormat'. */ -bool register_python_binary_format(PyObject *module); +bool register_python_binary_format(PyObject *); diff --git a/plugins/pychrysa/format/module.c b/plugins/pychrysa/format/module.c index efaade6..bd81187 100644 --- a/plugins/pychrysa/format/module.c +++ b/plugins/pychrysa/format/module.c @@ -25,15 +25,17 @@ #include "module.h" +#include <assert.h> + + #include "executable.h" #include "format.h" +#include "symbol.h" #include "dex/module.h" #include "elf/module.h" - - /****************************************************************************** * * * Paramètres : module = module dont la définition est à compléter. * @@ -48,28 +50,50 @@ bool add_format_module_to_python_module(PyObject *super) { - bool result; - PyObject *module; + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyMethodDef py_format_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_format_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.format", + .m_doc = "Python module for Chrysalide.format", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.format", py_format_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_format_module); if (module == NULL) return false; + ret = PyState_AddModule(super, &py_chrysalide_format_module); + if (ret != 0) goto loading_failed; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.format"); + if (ret != 0) goto loading_failed; + Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.format", module); + ret = PyModule_AddObject(super, "format", module); + if (ret != 0) goto loading_failed; - result = (ret == 0); + result = true; + result &= register_python_binary_symbol_iterator(module); result &= register_python_binary_format(module); result &= register_python_executable_format(module); + result &= register_python_binary_symbol(module); result &= add_format_dex_module_to_python_module(module); result &= add_format_elf_module_to_python_module(module); + loading_failed: + + assert(result); + return result; } diff --git a/plugins/pychrysa/format/symbol.c b/plugins/pychrysa/format/symbol.c new file mode 100644 index 0000000..1fc868e --- /dev/null +++ b/plugins/pychrysa/format/symbol.c @@ -0,0 +1,720 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symbol.c - équivalent Python du fichier "format/symbol.h" + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "symbol.h" + + +#include <pygobject.h> + + +#include <i18n.h> + + +#include <format/symbol.h> + + +#include "../helpers.h" +#include "../analysis/routine.h" +#include "../analysis/db/items/comment.h" +#include "../arch/instruction.h" +#include "../arch/vmpa.h" + + + +/* Effectue une comparaison avec un objet Python 'BinSymbol'. */ +static PyObject *py_binary_symbol_richcompare(PyObject *, PyObject *, int); + +/* Définit un autre nom pour le symbole. */ +static PyObject *py_binary_symbol_set_alt_label(PyObject *, PyObject *); + +/* Raffine la définition de l'emplacement d'un symbole. */ +static PyObject *py_binary_symbol_fix_range(PyObject *, PyObject *); + +/* Attache la routine associée au symbole. */ +static PyObject *py_binary_symbol_attach_routine(PyObject *, PyObject *); + +/* Attache l'instruction associée au symbole. */ +static PyObject *py_binary_symbol_attach_instruction(PyObject *, PyObject *); + +/* Fournit le type du symbole. */ +static PyObject *py_binary_symbol_get_target_type(PyObject *, void *); + +/* Fournit un étiquette pour viser un symbole. */ +static PyObject *py_binary_symbol_get_label(PyObject *, void *); + +/* Fournit l'emplacement où se situe un symbole. */ +static PyObject *py_binary_symbol_get_range(PyObject *, void *); + +/* Fournit l'éventuelle routine associée au symbole. */ +static PyObject *py_binary_symbol_get_routine(PyObject *, void *); + +/* Fournit l'éventuelle instruction associée au symbole. */ +static PyObject *py_binary_symbol_get_instruction(PyObject *, void *); + +/* Fournit l'éventuel commentaire associé au symbole. */ +static PyObject *py_binary_symbol_get_comment(PyObject *, void *); + +/* Ajoute un commentaire facultatif au symbole. */ +static int py_binary_symbol_set_comment(PyObject *, PyObject *, void *); + +/* Définit les constantes pour les symboles binaires. */ +static bool py_binary_symbol_define_constants(PyTypeObject *); + + + +/****************************************************************************** +* * +* Paramètres : obj = objet Python à tenter de convertir. * +* addr = structure équivalente pour Chrysalide. * +* * +* Description : Effectue une comparaison avec un objet Python 'BinSymbol'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_richcompare(PyObject *a, PyObject *b, int op) +{ + PyObject *result; /* Chaîne à retourner */ + int ret; /* Bilan de lecture des args. */ + const GBinSymbol *sym_a; /* Premier élément à traiter */ + const GBinSymbol *sym_b; /* Second élément à traiter */ + int status; /* Résultat d'une comparaison */ + + ret = PyObject_IsInstance(b, (PyObject *)get_python_binary_symbol_type()); + if (!ret) + { + result = Py_NotImplemented; + goto cmp_done; + } + + sym_a = G_BIN_SYMBOL(pygobject_get(a)); + sym_a = G_BIN_SYMBOL(pygobject_get(b)); + + status = g_binary_symbol_cmp(&sym_a, &sym_b); + + switch (op) + { + case Py_LT: + result = status < 0 ? Py_True : Py_False; + break; + + case Py_LE: + result = status <= 0 ? Py_True : Py_False; + break; + + case Py_EQ: + result = status == 0 ? Py_True : Py_False; + break; + + case Py_NE: + result = status != 0 ? Py_True : Py_False; + break; + + case Py_GT: + result = status > 0 ? Py_True : Py_False; + break; + + case Py_GE: + result = status >= 0 ? Py_True : Py_False; + break; + + default: + result = Py_NotImplemented; + break; + + } + + cmp_done: + + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de l'objet à instancier. * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Crée un nouvel objet Python de type 'DbComment'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Bilan à retourner */ + SymbolType stype; /* Type prévu pour le symbole */ + int ret; /* Bilan de lecture des args. */ + GBinSymbol *symbol; /* Version GLib du symble */ + + ret = PyArg_ParseTuple(args, "l", &stype); + if (!ret) return NULL; + + if (stype >= STP_COUNT) + { + PyErr_SetString(PyExc_ValueError, _("Invalid type of message")); + return NULL; + } + + symbol = g_binary_symbol_new(stype); + + result = pygobject_new(G_OBJECT(symbol)); + g_object_unref(symbol); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Définit un autre nom pour le symbole. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_set_alt_label(PyObject *self, PyObject *args) +{ + const char *alt; /* Etiquette alternative */ + int ret; /* Bilan de lecture des args. */ + GBinSymbol *symbol; /* Elément à consulter */ + + ret = PyArg_ParseTuple(args, "s", &alt); + if (!ret) return NULL; + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + + g_binary_symbol_set_alt_label(symbol, alt); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Raffine la définition de l'emplacement d'un symbole. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_fix_range(PyObject *self, PyObject *args) +{ + PyObject *py_vmpa; /* Localisation version Python */ + int ret; /* Bilan de lecture des args. */ + GBinSymbol *symbol; /* Elément à consulter */ + + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + g_binary_symbol_fix_range(symbol, get_internal_vmpa(py_vmpa)); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Attache la routine associée au symbole. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_attach_routine(PyObject *self, PyObject *args) +{ + PyObject *py_routine; /* Routine version Python */ + int ret; /* Bilan de lecture des args. */ + GBinSymbol *symbol; /* Elément à consulter */ + GBinRoutine *routine; /* Routine à attacher */ + + ret = PyArg_ParseTuple(args, "O", &py_routine); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_routine, (PyObject *)get_python_binary_routine_type()); + if (!ret) return NULL; + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + routine = G_BIN_ROUTINE(pygobject_get(py_routine)); + + g_binary_symbol_attach_routine(symbol, routine); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Attache l'instruction associée au symbole. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_attach_instruction(PyObject *self, PyObject *args) +{ + PyObject *py_instr; /* Instruction version Python */ + int ret; /* Bilan de lecture des args. */ + GBinSymbol *symbol; /* Elément à consulter */ + GArchInstruction *instr; /* Instruction à attacher */ + + ret = PyArg_ParseTuple(args, "O", &py_instr); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_instr, (PyObject *)get_python_arch_instruction_type()); + if (!ret) return NULL; + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + instr = G_ARCH_INSTRUCTION(pygobject_get(py_instr)); + + g_binary_symbol_attach_instruction(symbol, instr); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le type du symbole. * +* * +* Retour : Type de symbole représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_target_type(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + SymbolType type; /* Type de symbole représenté */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + type = g_binary_symbol_get_target_type(symbol); + + result = PyLong_FromLong(type); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit un étiquette pour viser un symbole. * +* * +* Retour : Chaîne de caractères renvoyant au symbole. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_label(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + const char *label; /* Désignation courante */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + label = g_binary_symbol_get_label(symbol); + + result = PyUnicode_FromString(label); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'emplacement où se situe un symbole. * +* * +* Retour : Zone mémoire couverte par le symbole. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_range(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + const mrange_t *range; /* Couverture courante */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + range = g_binary_symbol_get_range(symbol); + + result = build_from_internal_mrange(range); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'éventuelle routine associée au symbole. * +* * +* Retour : Instance en place ou None si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_routine(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + GBinRoutine *routine; /* Routine attachée */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + routine = g_binary_symbol_get_routine(symbol); + + result = pygobject_new(G_OBJECT(routine)); + + return result; + +} + + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'éventuelle instruction associée au symbole. * +* * +* Retour : Instance en place ou None si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_instruction(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + GArchInstruction *instr; /* Routine attachée */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + instr = g_binary_symbol_get_instruction(symbol); + + result = pygobject_new(G_OBJECT(instr)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'éventuel commentaire associé au symbole. * +* * +* Retour : Instance Python du commentaire GLib ou None si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_symbol_get_comment(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinSymbol *symbol; /* Elément à consulter */ + GDbComment *comment; /* Commentaire à associé */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + comment = g_binary_symbol_get_comment(symbol); + + if (comment != NULL) + result = pygobject_new(G_OBJECT(comment)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * +* * +* Description : Ajoute un commentaire facultatif au symbole. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_symbol_set_comment(PyObject *self, PyObject *value, void *closure) +{ + GBinSymbol *symbol; /* Elément à consulter */ + int ret; /* Bilan de lecture des args. */ + GDbComment *comment; /* Commentaire à associer */ + + symbol = G_BIN_SYMBOL(pygobject_get(self)); + + if (value == Py_None) + g_binary_symbol_set_comment(symbol, NULL); + + else + { + ret = PyObject_IsInstance(value, (PyObject *)get_python_db_comment_type()); + if (!ret) return -1; + + comment = G_DB_COMMENT(pygobject_get(value)); + + g_binary_symbol_set_comment(symbol, comment); + + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les symboles binaires. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_symbol_define_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + result &= PyDict_AddIntMacro(obj_type, STP_DATA); + result &= PyDict_AddIntMacro(obj_type, STP_ROUTINE); + result &= PyDict_AddIntMacro(obj_type, STP_CODE_LABEL); + result &= PyDict_AddIntMacro(obj_type, STP_OBJECT); + result &= PyDict_AddIntMacro(obj_type, STP_FUNCTION); + result &= PyDict_AddIntMacro(obj_type, STP_ENTRY_POINT); + result &= PyDict_AddIntMacro(obj_type, STP_STRING); + result &= PyDict_AddIntMacro(obj_type, STP_RO_STRING); + result &= PyDict_AddIntMacro(obj_type, STP_COUNT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_symbol_type(void) +{ + static PyMethodDef py_bin_symbol_methods[] = { + { + "set_alt_label", py_binary_symbol_set_alt_label, + METH_VARARGS, + "set_alt_label($self, alt, /)\n--\n\nSet an alternative label for the symbol." + }, + { + "fix_range", py_binary_symbol_fix_range, + METH_VARARGS, + "fix_range($self, range, /)\n--\n\nRefine the location of the current symbol." + }, + { + "attach_routine", py_binary_symbol_attach_routine, + METH_VARARGS, + "attach_routine($self, instr, /)\n--\n\nAttach a provided routine to the current symbol." + }, + { + "attach_instruction", py_binary_symbol_attach_instruction, + METH_VARARGS, + "attach_instruction($self, instr, /)\n--\n\nAttach a provided instruction to the current symbol." + }, + { NULL } + }; + + static PyGetSetDef py_bin_symbol_getseters[] = { + { + "target_type", py_binary_symbol_get_target_type, NULL, + "Type of the current symbol.", NULL + }, + { + "label", py_binary_symbol_get_label, NULL, + "Label of the symbol, provided by the internal component or by an alternative label.", NULL + }, + { + "range", py_binary_symbol_get_range, NULL, + "Range covered by the symbol.", NULL + }, + { + "routine", py_binary_symbol_get_routine, NULL, + "Potential routine attached to the symbol.", NULL + }, + { + "instruction", py_binary_symbol_get_instruction, NULL, + "Potential instruction attached to the symbol.", NULL + }, + { + "comment", py_binary_symbol_get_comment, py_binary_symbol_set_comment, + "Optional comment linked to the symbol.", NULL + }, + { NULL } + }; + + static PyTypeObject py_bin_symbol_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.BinSymbol", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide binary symbol", + + .tp_richcompare = py_binary_symbol_richcompare, + + .tp_methods = py_bin_symbol_methods, + .tp_getset = py_bin_symbol_getseters, + .tp_new = (newfunc)py_binary_symbol_new + + }; + + return &py_bin_symbol_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.BinSymbol'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_symbol(PyObject *module) +{ + PyTypeObject *py_bin_symbol_type; /* Type Python 'BinSymbol' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_bin_symbol_type = get_python_binary_symbol_type(); + + py_bin_symbol_type->tp_base = &PyGObject_Type; + py_bin_symbol_type->tp_basicsize = py_bin_symbol_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_bin_symbol_type) != 0) + return false; + + if (!py_binary_symbol_define_constants(py_bin_symbol_type)) + return false; + + Py_INCREF(py_bin_symbol_type); + ret = PyModule_AddObject(module, "BinSymbol", (PyObject *)py_bin_symbol_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BinSymbol", G_TYPE_BIN_SYMBOL, py_bin_symbol_type, + Py_BuildValue("(O)", py_bin_symbol_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/format/symbol.h b/plugins/pychrysa/format/symbol.h new file mode 100644 index 0000000..c094c75 --- /dev/null +++ b/plugins/pychrysa/format/symbol.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symbol.h - prototypes pour l'équivalent Python du fichier "format/symbol.h" + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSA_FORMAT_SYMBOL_H +#define _PLUGINS_PYCHRYSA_FORMAT_SYMBOL_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_symbol_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.BinSymbol'. */ +bool register_python_binary_symbol(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSA_FORMAT_EXECUTABLE_H */ |