diff options
110 files changed, 6243 insertions, 1811 deletions
@@ -1,3 +1,143 @@ +15-07-17 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + * plugins/pychrysa/analysis/binaries/file.c: + * plugins/pychrysa/analysis/binaries/module.c: + * plugins/pychrysa/analysis/binary.c: + * plugins/pychrysa/analysis/block.c: + * plugins/pychrysa/analysis/block.h: + * plugins/pychrysa/analysis/blocks/flow.c: + * plugins/pychrysa/analysis/blocks/flow.h: + * plugins/pychrysa/analysis/blocks/module.c: + * plugins/pychrysa/analysis/blocks/module.h: + * plugins/pychrysa/analysis/blocks/virtual.c: + * plugins/pychrysa/analysis/blocks/virtual.h: + * plugins/pychrysa/analysis/db/items/comment.c: + * plugins/pychrysa/analysis/db/items/module.c: + * plugins/pychrysa/analysis/db/Makefile.am: + * plugins/pychrysa/analysis/db/module.c: + * plugins/pychrysa/analysis/Makefile.am: + * plugins/pychrysa/analysis/module.c: + Update the Python bindings. + + * plugins/pychrysa/analysis/roptions.c: + * plugins/pychrysa/analysis/roptions.h: + Deleted entries. + + * plugins/pychrysa/analysis/routine.c: + * plugins/pychrysa/analysis/routine.h: + Update the Python bindings. + + * plugins/pychrysa/arch/arm/instruction.c: + * plugins/pychrysa/arch/arm/instruction.h: + * plugins/pychrysa/arch/arm/Makefile.am: + * plugins/pychrysa/arch/arm/module.c: + * plugins/pychrysa/arch/arm/module.h: + * plugins/pychrysa/arch/arm/processor.c: + * plugins/pychrysa/arch/arm/processor.h: + * plugins/pychrysa/arch/arm/v7/instruction.c: + * plugins/pychrysa/arch/arm/v7/instruction.h: + * plugins/pychrysa/arch/arm/v7/Makefile.am: + * plugins/pychrysa/arch/arm/v7/module.c: + * plugins/pychrysa/arch/arm/v7/module.h: + * plugins/pychrysa/arch/arm/v7/processor.c: + * plugins/pychrysa/arch/arm/v7/processor.h: + Added entries. + + * plugins/pychrysa/arch/instruction.c: + * plugins/pychrysa/arch/instruction.h: + * plugins/pychrysa/arch/Makefile.am: + * plugins/pychrysa/arch/module.c: + * plugins/pychrysa/arch/processor.c: + * plugins/pychrysa/arch/processor.h: + * plugins/pychrysa/arch/vmpa.c: + * plugins/pychrysa/arch/vmpa.h: + Update the Python bindings. + + * plugins/pychrysa/common/fnv1a.c: + * plugins/pychrysa/common/fnv1a.h: + * plugins/pychrysa/common/Makefile.am: + * plugins/pychrysa/common/module.c: + * plugins/pychrysa/common/module.h: + Added entries. + + * plugins/pychrysa/core/module.c: + * plugins/pychrysa/core/params.c: + * plugins/pychrysa/format/dex/class.c: + * plugins/pychrysa/format/dex/class.h: + * plugins/pychrysa/format/dex/dex.c: + * plugins/pychrysa/format/dex/dex.h: + * plugins/pychrysa/format/dex/module.c: + * plugins/pychrysa/format/elf/elf.c: + * plugins/pychrysa/format/elf/elf.h: + * plugins/pychrysa/format/elf/module.c: + * plugins/pychrysa/format/executable.c: + * plugins/pychrysa/format/executable.h: + * plugins/pychrysa/format/format.c: + * plugins/pychrysa/format/format.h: + * plugins/pychrysa/format/Makefile.am: + * plugins/pychrysa/format/module.c: + Update the Python bindings. + + * plugins/pychrysa/format/symbol.c: + * plugins/pychrysa/format/symbol.h: + * plugins/pychrysa/glibext/bincontent.c: + * plugins/pychrysa/glibext/bincontent.h: + Added entries. + + * plugins/pychrysa/glibext/bufferline.c: + * plugins/pychrysa/glibext/bufferline.h: + * plugins/pychrysa/glibext/codebuffer.c: + * plugins/pychrysa/glibext/codebuffer.h: + * plugins/pychrysa/glibext/configuration.c: + * plugins/pychrysa/glibext/Makefile.am: + * plugins/pychrysa/glibext/module.c: + * plugins/pychrysa/gtkext/blockview.c: + * plugins/pychrysa/gtkext/blockview.h: + Update the Python bindings. + + * plugins/pychrysa/gtkext/bufferview.c: + * plugins/pychrysa/gtkext/bufferview.h: + Added entries. + + * plugins/pychrysa/gtkext/Makefile.am: + * plugins/pychrysa/gtkext/module.c: + * plugins/pychrysa/gtkext/viewpanel.c: + * plugins/pychrysa/gtkext/viewpanel.h: + * plugins/pychrysa/gui/editem.c: + * plugins/pychrysa/gui/editem.h: + * plugins/pychrysa/gui/module.c: + * plugins/pychrysa/gui/panels/log.c: + * plugins/pychrysa/gui/panels/log.h: + * plugins/pychrysa/gui/panels/module.c: + * plugins/pychrysa/gui/panels/module.h: + * plugins/pychrysa/gui/panels/panel.c: + * plugins/pychrysa/gui/panels/panel.h: + * plugins/pychrysa/helpers.c: + * plugins/pychrysa/helpers.h: + Update the Python bindings. + + * plugins/pychrysa/linsyscalls/oidapgi.py: + Deleted entry. + + * plugins/pychrysa/Makefile.am: + * plugins/pychrysa/pychrysa.c: + Update the Python bindings. + + * src/analysis/binary.c: + * src/analysis/disass/area.c: + * src/arch/instruction.c: + * src/arch/processor.c: + * src/arch/vmpa.c: + * src/arch/vmpa.h: + * src/format/dex/dex.h: + * src/format/symbol.c: + * src/format/symbol.h: + * src/glibext/delayed.c: + * src/glibext/gbufferline.h: + * src/gtkext/gtkextstatusbar.c: + Update code. + 15-07-16 Cyrille Bagard <nocbos@gmail.com> * plugins/ropgadgets/finder.c: diff --git a/configure.ac b/configure.ac index bd15448..eed6c5b 100644 --- a/configure.ac +++ b/configure.ac @@ -272,6 +272,9 @@ AC_CONFIG_FILES([Makefile plugins/pychrysa/analysis/db/Makefile plugins/pychrysa/analysis/db/items/Makefile plugins/pychrysa/arch/Makefile + plugins/pychrysa/arch/arm/Makefile + plugins/pychrysa/arch/arm/v7/Makefile + plugins/pychrysa/common/Makefile plugins/pychrysa/core/Makefile plugins/pychrysa/debug/Makefile plugins/pychrysa/format/Makefile diff --git a/plugins/pychrysa/Makefile.am b/plugins/pychrysa/Makefile.am index 8c59c10..e4b9739 100644 --- a/plugins/pychrysa/Makefile.am +++ b/plugins/pychrysa/Makefile.am @@ -1,6 +1,7 @@ -pkglib_LTLIBRARIES = pychrysa.la pychrysalide.la +pkglib_LTLIBRARIES = pychrysalide.la +# -------- %< -------- %< -------- %< -------- %< -------- pychrysa_la_SOURCES = \ helpers.h helpers.c \ plugin.h plugin.c \ @@ -20,20 +21,25 @@ pychrysa_la_LDFLAGS = -module -avoid-version $(LIBGTK_LIBS) $(LIBXML_LIBS) $(LIB $(LIBPYGOBJECT_LIBS) \ -L../../src/.libs -L../../src/gui/.libs -lchrysagui -lchrysadisass -lchrysagtkext \ -L../../src/plugins/.libs -lplugins - +# -------- %< -------- %< -------- %< -------- %< -------- pychrysalide_la_SOURCES = \ + helpers.h helpers.c \ pychrysa.h pychrysa.c pychrysalide_la_LIBADD = \ analysis/libpychrysaanalysis.la \ arch/libpychrysaarch.la \ + common/libpychrysacommon.la \ core/libpychrysacore.la \ - glibext/libpychrysaglibext.la + format/libpychrysaformat.la \ + glibext/libpychrysaglibext.la \ + gtkext/libpychrysagtkext.la \ + gui/libpychrysagui.la pychrysalide_la_LDFLAGS = -module -avoid-version \ $(LIBPYTHON_LIBS) $(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS) \ - -L../../src/.libs -lchrysadisass -lchrysagtkext -lchrysacore \ + -L../../src/.libs -lchrysadisass -lchrysagui -lchrysagtkext -lchrysacore \ -L../../src/plugins/.libs -lplugins @@ -43,4 +49,5 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJE AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = analysis arch core debug format glibext gtkext gui +SUBDIRS = analysis arch common core format glibext gtkext gui +#SUBDIRS = analysis arch common core debug format glibext gtkext gui diff --git a/plugins/pychrysa/analysis/Makefile.am b/plugins/pychrysa/analysis/Makefile.am index 7e18757..8b0609d 100644 --- a/plugins/pychrysa/analysis/Makefile.am +++ b/plugins/pychrysa/analysis/Makefile.am @@ -3,21 +3,14 @@ noinst_LTLIBRARIES = libpychrysaanalysis.la libpychrysaanalysis_la_SOURCES = \ binary.h binary.c \ - module.h module.c + block.h block.c \ + module.h module.c \ + routine.h routine.c libpychrysaanalysis_la_LIBADD = \ - binaries/libpychrysaanalysisbinaries.la - -# libpychrysaanalysis_la_SOURCES = \ -# binary.h binary.c \ -# block.h block.c \ -# module.h module.c \ -# roptions.h roptions.c \ -# routine.h routine.c - -# libpychrysaanalysis_la_LIBADD = \ -# binaries/libpychrysaanalysisbinaries.la \ -# blocks/libpychrysaanalysisblocks.la + binaries/libpychrysaanalysisbinaries.la \ + blocks/libpychrysaanalysisblocks.la \ + db/libpychrysaanalysisdb.la libpychrysaanalysis_la_LDFLAGS = diff --git a/plugins/pychrysa/analysis/binaries/file.c b/plugins/pychrysa/analysis/binaries/file.c index af285d9..40463ba 100644 --- a/plugins/pychrysa/analysis/binaries/file.c +++ b/plugins/pychrysa/analysis/binaries/file.c @@ -60,7 +60,7 @@ static PyObject *py_binary_file_get_filename(PyObject *, void *); static PyObject *py_binary_file_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *result; /* Instance à retourner */ - char *filename; /* Nom du fichier à charger */ + const char *filename; /* Nom du fichier à charger */ int ret; /* Bilan de lecture des args. */ GLoadedBinary *binary; /* Version GLib du format */ diff --git a/plugins/pychrysa/analysis/binaries/module.c b/plugins/pychrysa/analysis/binaries/module.c index c2adddf..b43d24f 100644 --- a/plugins/pychrysa/analysis/binaries/module.c +++ b/plugins/pychrysa/analysis/binaries/module.c @@ -25,6 +25,9 @@ #include "module.h" +#include <assert.h> + + #include "file.h" @@ -47,7 +50,7 @@ bool add_analysis_binaries_module_to_python_module(PyObject *super) PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyModuleDef py_chrysalide_arch_module = { + static PyModuleDef py_chrysalide_binaries_module = { .m_base = PyModuleDef_HEAD_INIT, @@ -60,31 +63,26 @@ bool add_analysis_binaries_module_to_python_module(PyObject *super) result = false; - module = PyModule_Create(&py_chrysalide_arch_module); + module = PyModule_Create(&py_chrysalide_binaries_module); if (module == NULL) return false; - ret = PyState_AddModule(super, &py_chrysalide_arch_module); - if (ret != 0) goto aabmtpm_exit; + ret = PyState_AddModule(super, &py_chrysalide_binaries_module); + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.analysis.binaries"); - if (ret != 0) goto aabmtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "binaries", module); - if (ret != 0) goto aabmtpm_exit; + if (ret != 0) goto loading_failed; result = true; result &= register_python_binary_file(module); - aabmtpm_exit: - - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ + loading_failed: - } + assert(result); return result; diff --git a/plugins/pychrysa/analysis/binary.c b/plugins/pychrysa/analysis/binary.c index 1a513eb..fad84cd 100644 --- a/plugins/pychrysa/analysis/binary.c +++ b/plugins/pychrysa/analysis/binary.c @@ -28,138 +28,62 @@ #include <pygobject.h> +#include <analysis/binary.h> +#include "../helpers.h" +/* Lance l'analyse d'un élément binaire chargé. */ +static PyObject *py_loaded_binary_analyse(PyObject *, PyObject *); +/* Fournit le nom associé à l'élément binaire. */ +static PyObject *py_loaded_binary_get_name(PyObject *, void *); -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_loaded_binary_type(void) -{ - static PyTypeObject py_loaded_binary_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.analysis.LoadedBinary", - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyChrysalide loaded binary", - - }; - - return &py_loaded_binary_type; - -} - +/* Fournit le format de fichier reconnu dans le contenu binaire. */ +static PyObject *py_loaded_binary_get_format(PyObject *, void *); +/* Fournit le processeur de l'architecture liée au binaire. */ +static PyObject *py_loaded_binary_get_processor(PyObject *, void *); -#include <analysis/binary.h> - +/* Fournit le tampon associé au contenu assembleur d'un binaire. */ +static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *, void *); /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : self = contenu binaire à manipuler. * +* args = non utilisé ici. * * * -* Description : Prend en charge l'objet 'pychrysalide.arch.loaded_binary'. * +* Description : Lance l'analyse d'un élément binaire chargé. * * * -* Retour : Bilan de l'opération. * +* Retour : Rien (None). * * * * Remarques : - * * * ******************************************************************************/ -bool register_python_loaded_binary(PyObject *module) +static PyObject *py_loaded_binary_analyse(PyObject *self, PyObject *args) { - PyTypeObject *py_loaded_binary_type; /* Type Python 'LoadedBinary' */ - int ret; /* Bilan d'un appel */ - PyObject *dict; /* Dictionnaire du module */ + GLoadedBinary *binary; /* Version GLib du format */ - py_loaded_binary_type = get_python_loaded_binary_type(); - - py_loaded_binary_type->tp_base = &PyGObject_Type; - py_loaded_binary_type->tp_basicsize = py_loaded_binary_type->tp_base->tp_basicsize; + binary = G_LOADED_BINARY(pygobject_get(self)); - if (PyType_Ready(py_loaded_binary_type) != 0) - return false; + g_loaded_binary_analyse(binary); - Py_INCREF(py_loaded_binary_type); - ret = PyModule_AddObject(module, "LoadedBinary", (PyObject *)py_loaded_binary_type); - if (ret != 0) return false; - - dict = PyModule_GetDict(module); - pygobject_register_class(dict, "LoadedBinary", G_TYPE_LOADED_BINARY, py_loaded_binary_type, - Py_BuildValue("(O)", py_loaded_binary_type->tp_base)); - - return true; + Py_RETURN_NONE; } - - - - - - - - - - -#if 0 - - -#include <pygobject.h> - - -#include <analysis/binary.h> - - -#include "../quirks.h" -#include "../arch/instruction.h" -#include "../format/executable.h" -#include "../glibext/codebuffer.h" - - - -/* Fournit le fichier correspondant à l'élément binaire. */ -static PyObject *py_loaded_binary_get_filename(PyObject *self, PyObject *args); - -/* Fournit le format de fichier reconnu dans le contenu binaire. */ -static PyObject *py_loaded_binary_get_format(PyObject *, PyObject *); - -/* Fournit les instructions issues du désassemblage. */ -static PyObject *py_loaded_binary_get_instructions(PyObject *, PyObject *); - - - -/* Fournit le tampon associé au contenu assembleur d'un binaire. */ -static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *, void *); - - - - /****************************************************************************** * * -* Paramètres : self = classe représentant un binaire. * -* args = arguments fournis à l'appel. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Fournit le fichier correspondant à l'élément binaire. * +* Description : Fournit le nom associé à l'élément binaire. * * * * Retour : Nom de fichier avec chemin absolu. * * * @@ -167,17 +91,17 @@ static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *, void *); * * ******************************************************************************/ -static PyObject *py_loaded_binary_get_name(PyObject *self, PyObject *args) +static PyObject *py_loaded_binary_get_name(PyObject *self, void *closure) { PyObject *result; /* Trouvailles à retourner */ GLoadedBinary *binary; /* Version native */ - const char *filename; /* Fichier associé au binaire */ + const char *name; /* Désignation du binaire */ binary = G_LOADED_BINARY(pygobject_get(self)); - filename = g_loaded_binary_get_name(binary, true); + name = g_loaded_binary_get_name(binary, true); - result = PyString_FromString(filename); + result = PyUnicode_FromString(name); return result; @@ -186,28 +110,30 @@ static PyObject *py_loaded_binary_get_name(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : self = classe représentant un binaire. * -* args = arguments fournis à l'appel. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * * Description : Fournit le format de fichier reconnu dans le contenu binaire.* * * -* Retour : Nom de fichier avec chemin absolu. * +* Retour : Instance du format reconnu. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_loaded_binary_get_format(PyObject *self, PyObject *args) +static PyObject *py_loaded_binary_get_format(PyObject *self, void *closure) { - PyObject *result; /* Trouvailles à retourner */ - GLoadedBinary *binary; /* Version native */ - GExeFormat *format; /* Format du binaire physique */ + PyObject *result; /* Instance Python à retourner */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ + GExeFormat *format; /* Format du binaire lié */ binary = G_LOADED_BINARY(pygobject_get(self)); format = g_loaded_binary_get_format(binary); result = pygobject_new(G_OBJECT(format)); + //g_object_unref(G_OBJECT(format)); + return result; } @@ -215,37 +141,35 @@ static PyObject *py_loaded_binary_get_format(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : self = classe représentant un binaire. * -* args = arguments fournis à l'appel. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Fournit les instructions issues du désassemblage. * +* Description : Fournit le processeur de l'architecture liée au binaire. * * * -* Retour : Instructions issues du désassemblage. * +* Retour : Instance du processeur associé. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_loaded_binary_get_instructions(PyObject *self, PyObject *args) +static PyObject *py_loaded_binary_get_processor(PyObject *self, void *closure) { - PyObject *result; /* Trouvailles à retourner */ - GLoadedBinary *binary; /* Version native */ - GArchInstruction *instr; /* Première instruction */ + PyObject *result; /* Instance Python à retourner */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ + GArchProcessor *proc; /* Architecture visée */ binary = G_LOADED_BINARY(pygobject_get(self)); + proc = g_loaded_binary_get_processor(binary); - instr = g_loaded_binary_get_instructions(binary); + result = pygobject_new(G_OBJECT(proc)); - result = pygobject_new(G_OBJECT(instr)); + g_object_unref(G_OBJECT(proc)); return result; } - - - /****************************************************************************** * * * Paramètres : self = classe représentant une instruction. * @@ -275,88 +199,106 @@ static PyObject *py_loaded_binary_get_disassembled_buffer(PyObject *self, void * } - - - - - - - /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.analysis.LoadedBinary'.* +* 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_loaded_binary(PyObject *module) +PyTypeObject *get_python_loaded_binary_type(void) { - PyObject *pygobj_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_loaded_binary_methods[] = { { - "get_filename", (PyCFunction)py_loaded_binary_get_filename, + "analyse", py_loaded_binary_analyse, METH_NOARGS, - "Provide the filename of the loaded binary." - }, - { - "get_format", (PyCFunction)py_loaded_binary_get_format, - METH_NOARGS, - "Provide the file format recognized in the binary content." - }, - { - "get_instructions", (PyCFunction)py_loaded_binary_get_instructions, - METH_NOARGS, - "Give access to all disassembled instructions." + "analyse(/)\n--\n\nStart the analysis of the loaded binary and " \ + "send a \"disassembly-done\" signal when done." }, { NULL } }; static PyGetSetDef py_loaded_binary_getseters[] = { { - "disassembled_buffer", (getter)py_loaded_binary_get_disassembled_buffer, (setter)NULL, - "Give access to the disassembled code buffer.", NULL + "name", py_loaded_binary_get_name, NULL, + "Name of the loaded binary.", NULL + }, + { + "format", py_loaded_binary_get_format, NULL, + "File format recognized in the binary content.", NULL + }, + { + "processor", py_loaded_binary_get_processor, NULL, + "Handler for the current binary processor.", NULL + }, + { + "disassembled_buffer", py_loaded_binary_get_disassembled_buffer, NULL, + "Disassembled code buffer.", NULL }, { NULL } }; static PyTypeObject py_loaded_binary_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.analysis.LoadedBinary", - .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 loaded binary", .tp_methods = py_loaded_binary_methods, - .tp_getset = py_loaded_binary_getseters + .tp_getset = py_loaded_binary_getseters, }; - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; + return &py_loaded_binary_type; - py_loaded_binary_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); +} - if (PyType_Ready(&py_loaded_binary_type) < 0) - return false; - Py_INCREF(&py_loaded_binary_type); - ret = PyModule_AddObject(module, "LoadedBinary", (PyObject *)&py_loaded_binary_type); +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis.LoadedBinary'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - return (ret == 0); +bool register_python_loaded_binary(PyObject *module) +{ + PyTypeObject *py_loaded_binary_type; /* Type Python 'LoadedBinary' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ -} + py_loaded_binary_type = get_python_loaded_binary_type(); + + py_loaded_binary_type->tp_base = &PyGObject_Type; + py_loaded_binary_type->tp_basicsize = py_loaded_binary_type->tp_base->tp_basicsize; + + APPLY_ABSTRACT_FLAG(py_loaded_binary_type); + + if (PyType_Ready(py_loaded_binary_type) != 0) + return false; -#endif + Py_INCREF(py_loaded_binary_type); + ret = PyModule_AddObject(module, "LoadedBinary", (PyObject *)py_loaded_binary_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "LoadedBinary", G_TYPE_LOADED_BINARY, py_loaded_binary_type, + Py_BuildValue("(O)", py_loaded_binary_type->tp_base)); + return true; + +} diff --git a/plugins/pychrysa/analysis/block.c b/plugins/pychrysa/analysis/block.c index bd8684d..4cbc353 100644 --- a/plugins/pychrysa/analysis/block.c +++ b/plugins/pychrysa/analysis/block.c @@ -54,7 +54,7 @@ static PyObject *py_instructions_block_visit(PyObject *, PyObject *); static PyObject *py_instructions_block_get_links_block(PyObject *, PyObject *); /* Définit les constantes pour les blocs basiques. */ -static bool py_instructions_block_define_constants(PyObject *); +static bool py_instructions_block_define_constants(PyTypeObject *); @@ -82,7 +82,7 @@ static bool py_block_visitor_glue(GInstrBlock *block, BlockVisitOrder order, py_ args = PyTuple_New(3); PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(block))); - PyTuple_SetItem(args, 1, PyInt_FromLong(order)); + PyTuple_SetItem(args, 1, PyLong_FromLong(order)); PyTuple_SetItem(args, 2, data->user); value = _run_python_method(data->func, args); @@ -96,6 +96,7 @@ static bool py_block_visitor_glue(GInstrBlock *block, BlockVisitOrder order, py_ } + /****************************************************************************** * * * Paramètres : self = classe représentant un binaire. * @@ -120,6 +121,8 @@ static PyObject *py_instructions_block_visit(PyObject *self, PyObject *args) ret = PyArg_ParseTuple(args, "OO", &data.func, &data.user); if (!ret) Py_RETURN_NONE; + if (PyCallable_Check(data.func) != 1) return NULL; + block = G_INSTR_BLOCK(pygobject_get(self)); status = g_instr_block_visit(block, (instr_block_visitor_cb)py_block_visitor_glue, &data); @@ -162,7 +165,7 @@ static PyObject *py_instructions_block_get_links_block(PyObject *self, PyObject /****************************************************************************** * * -* Paramètres : dict = dictionnaire à compléter. * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * * * * Description : Définit les constantes pour les blocs basiques. * * * @@ -172,90 +175,110 @@ static PyObject *py_instructions_block_get_links_block(PyObject *self, PyObject * * ******************************************************************************/ -static bool py_instructions_block_define_constants(PyObject *dict) +static bool py_instructions_block_define_constants(PyTypeObject *obj_type) { - int ret; /* Bilan d'un ajout */ - - ret = PyDict_SetItemString(dict, "BVO_IN", PyInt_FromLong(BVO_IN)); - if (ret == -1) return false; + bool result; /* Bilan à retourner */ - ret = PyDict_SetItemString(dict, "BVO_PENDING", PyInt_FromLong(BVO_PENDING)); - if (ret == -1) return false; + result = true; - ret = PyDict_SetItemString(dict, "BVO_OUT", PyInt_FromLong(BVO_OUT)); - if (ret == -1) return false; + result &= PyDict_AddIntMacro(obj_type, BVO_IN); + result &= PyDict_AddIntMacro(obj_type, BVO_PENDING); + result &= PyDict_AddIntMacro(obj_type, BVO_OUT); - return true; + return result; } /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.analysis.InstrBlock'. * +* 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_instructions_block(PyObject *module) +PyTypeObject *get_python_instr_block_type(void) { - PyObject *parent_mod; /* Module de la classe parente */ - int ret; /* Bilan d'un appel */ - - static PyMethodDef py_instructions_block_methods[] = { + static PyMethodDef py_instr_block_methods[] = { { "visit", (PyCFunction)py_instructions_block_visit, METH_VARARGS, - "Visit all the basic blocks, starting at the provided one." + "visit($self, cb, data, /)\n--\n\nVisit all the basic blocks, starting at the provided one." }, { "get_links_block", (PyCFunction)py_instructions_block_get_links_block, METH_VARARGS, - "Get the block containing all blocks linked to the caller." + "get_links_block($self, /)\n--\n\nGet the block containing all blocks linked to the caller." }, { NULL } }; - static PyGetSetDef py_instructions_block_getseters[] = { + static PyGetSetDef py_instr_block_getseters[] = { { NULL } }; - static PyTypeObject py_instructions_block_type = { + static PyTypeObject py_instr_block_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.analysis.InstrBlock", - .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = "PyChrysalide basic block", - .tp_methods = py_instructions_block_methods, - .tp_getset = py_instructions_block_getseters + .tp_methods = py_instr_block_methods, + .tp_getset = py_instr_block_getseters, }; - parent_mod = PyImport_ImportModule("gobject"); - if (parent_mod == NULL) return false; + return &py_instr_block_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis.InstrBlock'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_instr_block(PyObject *module) +{ + PyTypeObject *py_instr_block_type; /* Type Python 'InstrBlock' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_instr_block_type = get_python_instr_block_type(); - py_instructions_block_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "GObject"); - Py_DECREF(parent_mod); + py_instr_block_type->tp_base = &PyGObject_Type; + py_instr_block_type->tp_basicsize = py_instr_block_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_instructions_block_type) < 0) + if (PyType_Ready(py_instr_block_type) != 0) return false; - if (!py_instructions_block_define_constants(py_instructions_block_type.tp_dict)) + if (!py_instructions_block_define_constants(py_instr_block_type)) return false; - Py_INCREF(&py_instructions_block_type); - ret = PyModule_AddObject(module, "InstrBlock", (PyObject *)&py_instructions_block_type); + Py_INCREF(py_instr_block_type); + ret = PyModule_AddObject(module, "InstrBlock", (PyObject *)py_instr_block_type); + if (ret != 0) return false; - return (ret == 0); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "InstrBlock", G_TYPE_INSTR_BLOCK, py_instr_block_type, + Py_BuildValue("(O)", py_instr_block_type->tp_base)); + + return true; } diff --git a/plugins/pychrysa/analysis/block.h b/plugins/pychrysa/analysis/block.h index 4752b9a..71e3160 100644 --- a/plugins/pychrysa/analysis/block.h +++ b/plugins/pychrysa/analysis/block.h @@ -31,8 +31,11 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_instr_block_type(void); + /* Prend en charge l'objet 'pychrysalide.analysis.InstrBlock'. */ -bool register_python_instructions_block(PyObject *); +bool register_python_instr_block(PyObject *); diff --git a/plugins/pychrysa/analysis/blocks/flow.c b/plugins/pychrysa/analysis/blocks/flow.c index a5ee99c..626d5c8 100644 --- a/plugins/pychrysa/analysis/blocks/flow.c +++ b/plugins/pychrysa/analysis/blocks/flow.c @@ -31,12 +31,15 @@ #include <analysis/blocks/flow.h> +#include "../block.h" +#if 0 + /* Fournit les adresses limites d'un bloc d'exécution. */ static PyObject *py_flow_block_get_boundary_addresses(PyObject *, void *); @@ -180,3 +183,103 @@ bool register_python_flow_block(PyObject *module) return (ret == 0); } + +#endif + + + + + + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_flow_block_type(void) +{ + static PyMethodDef py_flow_block_methods[] = { + { NULL } + }; + + static PyGetSetDef py_flow_block_getseters[] = { + { NULL } + }; + + static PyTypeObject py_flow_block_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.blocks.FlowBlock", + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide flow block", + + .tp_methods = py_flow_block_methods, + .tp_getset = py_flow_block_getseters, + + }; + + return &py_flow_block_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide...blocks.FlowBlock'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_flow_block(PyObject *module) +{ + PyTypeObject *py_flow_block_type; /* Type Python 'FlowBlock' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_flow_block_type = get_python_flow_block_type(); + + py_flow_block_type->tp_base = get_python_instr_block_type(); + py_flow_block_type->tp_basicsize = py_flow_block_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_flow_block_type) != 0) + return false; + + Py_INCREF(py_flow_block_type); + ret = PyModule_AddObject(module, "FlowBlock", (PyObject *)py_flow_block_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "FlowBlock", G_TYPE_FLOW_BLOCK, py_flow_block_type, + Py_BuildValue("(O)", py_flow_block_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/analysis/blocks/flow.h b/plugins/pychrysa/analysis/blocks/flow.h index 20d649e..69b6c24 100644 --- a/plugins/pychrysa/analysis/blocks/flow.h +++ b/plugins/pychrysa/analysis/blocks/flow.h @@ -31,6 +31,9 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_flow_block_type(void); + /* Prend en charge l'objet 'pychrysalide.analysis.blocks.FlowBlock'. */ bool register_python_flow_block(PyObject *); diff --git a/plugins/pychrysa/analysis/blocks/module.c b/plugins/pychrysa/analysis/blocks/module.c index 881ebc7..4968e90 100644 --- a/plugins/pychrysa/analysis/blocks/module.c +++ b/plugins/pychrysa/analysis/blocks/module.c @@ -25,6 +25,9 @@ #include "module.h" +#include <assert.h> + + #include "flow.h" #include "virtual.h" @@ -42,27 +45,47 @@ * * ******************************************************************************/ -bool add_blocks_module_to_python_module(PyObject *super) +bool add_analysis_blocks_module_to_python_module(PyObject *super) { bool result; /* Bilan à retourner */ - PyObject *module; /* Module Python mis en place */ + PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyMethodDef py_blocks_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_blocks_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.analysis.blocks", + .m_doc = "Python module for Chrysalide.analysis.blocks", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.analysis.blocks", py_blocks_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_blocks_module); if (module == NULL) return false; + ret = PyState_AddModule(super, &py_chrysalide_blocks_module); + if (ret != 0) goto loading_failed; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.analysis.blocks"); + if (ret != 0) goto loading_failed; + Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.analysis.blocks", module); + ret = PyModule_AddObject(super, "blocks", module); + if (ret != 0) goto loading_failed; - result = (ret == 0); + result = true; result &= register_python_flow_block(module); result &= register_python_virtual_block(module); + loading_failed: + + assert(result); + return result; } diff --git a/plugins/pychrysa/analysis/blocks/module.h b/plugins/pychrysa/analysis/blocks/module.h index 395be19..dc2d17c 100644 --- a/plugins/pychrysa/analysis/blocks/module.h +++ b/plugins/pychrysa/analysis/blocks/module.h @@ -32,7 +32,7 @@ /* Ajoute le module 'blocks' au module Python. */ -bool add_blocks_module_to_python_module(PyObject *); +bool add_analysis_blocks_module_to_python_module(PyObject *); diff --git a/plugins/pychrysa/analysis/blocks/virtual.c b/plugins/pychrysa/analysis/blocks/virtual.c index 4f15371..bdc81b0 100644 --- a/plugins/pychrysa/analysis/blocks/virtual.c +++ b/plugins/pychrysa/analysis/blocks/virtual.c @@ -31,35 +31,24 @@ #include <analysis/blocks/virtual.h> - - - - - - - - - +#include "../block.h" /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.....VirtualBlock'. * +* 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_virtual_block(PyObject *module) +PyTypeObject *get_python_virtual_block_type(void) { - PyObject *parent_mod; /* Module de la classe parente */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_virtual_block_methods[] = { { NULL } }; @@ -70,35 +59,58 @@ bool register_python_virtual_block(PyObject *module) static PyTypeObject py_virtual_block_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.analysis.blocks.VirtualBlock", - .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "PyChrysalide basic virtual block", + .tp_doc = "PyChrysalide virtual block", .tp_methods = py_virtual_block_methods, - .tp_getset = py_virtual_block_getseters + .tp_getset = py_virtual_block_getseters, }; - parent_mod = PyImport_ImportModule("pychrysalide.analysis"); - if (parent_mod == NULL) return false; + return &py_virtual_block_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide...blocks.VirtualBlock'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_virtual_block(PyObject *module) +{ + PyTypeObject *py_virtual_block_type; /* Type Python 'VirtualBlock' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_virtual_block_type = get_python_virtual_block_type(); - py_virtual_block_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "InstrBlock"); - Py_DECREF(parent_mod); + py_virtual_block_type->tp_base = get_python_instr_block_type(); + py_virtual_block_type->tp_basicsize = py_virtual_block_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_virtual_block_type) < 0) + if (PyType_Ready(py_virtual_block_type) != 0) return false; - Py_INCREF(&py_virtual_block_type); - ret = PyModule_AddObject(module, "VirtualBlock", (PyObject *)&py_virtual_block_type); + Py_INCREF(py_virtual_block_type); + ret = PyModule_AddObject(module, "VirtualBlock", (PyObject *)py_virtual_block_type); + if (ret != 0) return false; - pygobject_register_class(module, "GVirtualBlock", G_TYPE_VIRTUAL_BLOCK, &py_virtual_block_type, - Py_BuildValue("(O)", py_virtual_block_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "VirtualBlock", G_TYPE_VIRTUAL_BLOCK, py_virtual_block_type, + Py_BuildValue("(O)", py_virtual_block_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/analysis/blocks/virtual.h b/plugins/pychrysa/analysis/blocks/virtual.h index 1c70b34..0bfaf82 100644 --- a/plugins/pychrysa/analysis/blocks/virtual.h +++ b/plugins/pychrysa/analysis/blocks/virtual.h @@ -31,6 +31,9 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_virtual_block_type(void); + /* Prend en charge l'objet 'pychrysalide.analysis.blocks.VirtualBlock'. */ bool register_python_virtual_block(PyObject *); diff --git a/plugins/pychrysa/analysis/db/Makefile.am b/plugins/pychrysa/analysis/db/Makefile.am index e33130f..2de2a16 100644 --- a/plugins/pychrysa/analysis/db/Makefile.am +++ b/plugins/pychrysa/analysis/db/Makefile.am @@ -6,7 +6,8 @@ libpychrysaanalysisdb_la_SOURCES = \ item.h item.c \ module.h module.c -libpychrysaanalysisdb_la_LDFLAGS = +libpychrysaanalysisdb_la_LDFLAGS = \ + items/libpychrysaanalysisdbitems.la AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ diff --git a/plugins/pychrysa/analysis/db/items/comment.c b/plugins/pychrysa/analysis/db/items/comment.c index 1bb2863..951f6ce 100644 --- a/plugins/pychrysa/analysis/db/items/comment.c +++ b/plugins/pychrysa/analysis/db/items/comment.c @@ -75,6 +75,9 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject ret = PyArg_ParseTuple(args, "Osp", &py_vmpa, &text, &is_volatile); if (!ret) Py_RETURN_NONE; + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + addr = get_internal_vmpa(py_vmpa); if (py_vmpa == NULL) Py_RETURN_NONE; @@ -114,7 +117,7 @@ static PyObject *py_db_comment_get_text(PyObject *self, void *closure) } -/*********************d********************************************************* +/****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * value = valeur fournie à intégrer ou prendre en compte. * diff --git a/plugins/pychrysa/analysis/db/items/module.c b/plugins/pychrysa/analysis/db/items/module.c index 3c634e3..009e823 100644 --- a/plugins/pychrysa/analysis/db/items/module.c +++ b/plugins/pychrysa/analysis/db/items/module.c @@ -25,6 +25,9 @@ #include "module.h" +#include <assert.h> + + #include "comment.h" @@ -64,27 +67,22 @@ bool add_analysis_db_items_module_to_python_module(PyObject *super) if (module == NULL) return false; ret = PyState_AddModule(super, &py_chrysalide_items_module); - if (ret != 0) goto aadimtpm_exit; + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.analysis.db.items"); - if (ret != 0) goto aadimtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "items", module); - if (ret != 0) goto aadimtpm_exit; + if (ret != 0) goto loading_failed; result = true; result &= register_python_db_comment(module); - aadimtpm_exit: - - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ + loading_failed: - } + assert(result); return result; diff --git a/plugins/pychrysa/analysis/db/module.c b/plugins/pychrysa/analysis/db/module.c index 8c527a9..08c408c 100644 --- a/plugins/pychrysa/analysis/db/module.c +++ b/plugins/pychrysa/analysis/db/module.c @@ -25,8 +25,12 @@ #include "module.h" +#include <assert.h> + + #include "collection.h" #include "item.h" +#include "items/module.h" @@ -65,28 +69,25 @@ bool add_analysis_db_module_to_python_module(PyObject *super) if (module == NULL) return false; ret = PyState_AddModule(super, &py_chrysalide_db_module); - if (ret != 0) goto aadmtpm_exit; + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.analysis.db"); - if (ret != 0) goto aadmtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "db", module); - if (ret != 0) goto aadmtpm_exit; + if (ret != 0) goto loading_failed; result = true; result &= register_python_db_collection(module); result &= register_python_db_item(module); - aadmtpm_exit: + result &= add_analysis_db_items_module_to_python_module(module); - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ + loading_failed: - } + assert(result); return result; diff --git a/plugins/pychrysa/analysis/module.c b/plugins/pychrysa/analysis/module.c index e13c8f8..d45a3f1 100644 --- a/plugins/pychrysa/analysis/module.c +++ b/plugins/pychrysa/analysis/module.c @@ -25,8 +25,15 @@ #include "module.h" +#include <assert.h> + + #include "binary.h" +#include "block.h" +#include "routine.h" #include "binaries/module.h" +#include "blocks/module.h" +#include "db/module.h" @@ -48,7 +55,7 @@ bool add_analysis_module_to_python_module(PyObject *super) PyObject *module; /* Sous-module mis en place */ int ret; /* Bilan d'un appel */ - static PyModuleDef py_chrysalide_arch_module = { + static PyModuleDef py_chrysalide_analysis_module = { .m_base = PyModuleDef_HEAD_INIT, @@ -61,106 +68,33 @@ bool add_analysis_module_to_python_module(PyObject *super) result = false; - module = PyModule_Create(&py_chrysalide_arch_module); + module = PyModule_Create(&py_chrysalide_analysis_module); if (module == NULL) return false; - ret = PyState_AddModule(super, &py_chrysalide_arch_module); - if (ret != 0) goto aamtpm_exit; + ret = PyState_AddModule(super, &py_chrysalide_analysis_module); + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.analysis"); - if (ret != 0) goto aamtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "analysis", module); - if (ret != 0) goto aamtpm_exit; + if (ret != 0) goto loading_failed; result = true; result &= register_python_loaded_binary(module); + result &= register_python_instr_block(module); + result &= register_python_binary_routine(module); result &= add_analysis_binaries_module_to_python_module(module); + result &= add_analysis_blocks_module_to_python_module(module); + result &= add_analysis_db_module_to_python_module(module); - aamtpm_exit: - - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ - - } - - return result; - -} - - - - - - - - - - - - - - - - - - - - - - + loading_failed: -#if 0 -#include "binary.h" -#include "block.h" -#include "routine.h" -#include "binaries/module.h" -#include "blocks/module.h" - - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Ajoute le module 'analysis' au module Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool add_analysis_module_to_python_module(PyObject *super) -{ - bool result; - PyObject *module; - int ret; /* Bilan d'un appel */ - - static PyMethodDef py_analysis_methods[] = { - { NULL } - }; - - module = Py_InitModule("pychrysalide.analysis", py_analysis_methods); - if (module == NULL) return false; - - Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.analysis", module); - - result = (ret == 0); - - result &= register_python_loaded_binary(module); - result &= register_python_binary_routine(module); - result &= register_python_instructions_block(module); - result &= add_binaries_module_to_python_module(module); - result &= add_blocks_module_to_python_module(module); + assert(result); return result; } -#endif diff --git a/plugins/pychrysa/analysis/roptions.c b/plugins/pychrysa/analysis/roptions.c deleted file mode 100644 index 72e99e5..0000000 --- a/plugins/pychrysa/analysis/roptions.c +++ /dev/null @@ -1,276 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * roptions.c - équivalent Python du fichier "analysis/roptions.h" - * - * Copyright (C) 2010-2013 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 "roptions.h" - - -#include <pygobject.h> - - -#include "../format/executable.h" - - - - -/* Classe 'analysis.roptions' pour Python */ -typedef struct _py_rendering_options -{ - PyObject_HEAD - - GRenderingOptions *glib; /* Options réelles manipulées */ - -} py_rendering_options; - - - - -/* Crée un nouvel objet Python de type 'py_rendering_options'. */ -static PyObject *py_rendering_options_new(PyTypeObject *, PyObject *, PyObject *); - - - -/* Indique si les adresses des instructions sont à afficher. */ -static PyObject *py_rendering_options_get_show_address(PyObject *, void *); - -/* Affiche (ou non) les adresses des instructions. */ -static int py_rendering_options_set_show_address(PyObject *, PyObject *, void *); - - - - -/* Affiche (ou non) le code des instructions. */ -static PyObject *py_rendering_options_show_code(PyObject *, PyObject *); - - - - - -/****************************************************************************** -* * -* 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 'py_rendering_options'. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_rendering_options_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - py_rendering_options *result; /* Instance à retourner */ - PyObject *executable; /* Format d'exécutable joint */ - int ret; /* Bilan de lecture des args. */ - GExeFormat *_executable; /* Version GLib du format */ - - ret = PyArg_ParseTuple(args, "O", &executable); - if (!ret) Py_RETURN_NONE; - - result = (py_rendering_options *)type->tp_alloc(type, 0); - - _executable = G_EXE_FORMAT(pygobject_get(executable)); - if (_executable == NULL) return NULL; - - g_object_ref(G_OBJECT(_executable)); - result->glib = g_rendering_options_new(_executable); - - return (PyObject *)result; - -} - - -/****************************************************************************** -* * -* Paramètres : roptions = instance Python dont la référence est à donner. * -* * -* Description : Fournit l'instance GLib d'une instance Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GRenderingOptions *py_rendering_options_get_glib_instance(PyObject *roptions) -{ - return ((py_rendering_options *)roptions)->glib; - -} - - - - -/****************************************************************************** -* * -* Paramètres : self = classe présentant des options de représentation. * -* data = adresse non utilisée ici. * -* * -* Description : Indique si les adresses des instructions sont à afficher. * -* * -* Retour : Valeur booléenne indiquant le statut d'une option. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_rendering_options_get_show_address(PyObject *self, void *data) -{ - - printf(" -->> get address\n"); - - return Py_BuildValue("i", true); - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe présentant des options de représentation. * -* value = nouvelle valeur affectée. * -* data = adresse non utilisée ici. * -* * -* Description : Affiche (ou non) les adresses des instructions. * -* * -* Retour : Bilan de la mise à jour. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_rendering_options_set_show_address(PyObject *self, PyObject *value, void *data) -{ - printf(" -->> set address\n"); - - return 0; - -} - - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : self = classe assurant le lien avec l'éditeur de messages. * -* args = arguments fournis à l'appel. * -* * -* Description : Affiche (ou non) le code des instructions. * -* * -* Retour : Rien en équivalent Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_rendering_options_show_code(PyObject *self, PyObject *args) -{ - int state; /* Nouveau statut d'affichage */ - - if (!PyArg_ParseTuple(args, "i", &state)) - return NULL; - - - - - printf("show code :: %d\n", state); - - Py_RETURN_NONE; - -} - - - - - - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Ajoute l'objet 'analysis.roptions' au module Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool add_analysis_roptions_to_python_module(PyObject *module) -{ - int ret; /* Bilan d'un appel */ - - static PyMethodDef py_rendering_options_methods[] = { - { - "show_code", (PyCFunction)py_rendering_options_show_code, - METH_VARARGS, - "Define if the binary code has to be processed or not." - }, - { NULL } - }; - - static PyGetSetDef py_rendering_options_getset[] = { - { - "show_address", - (getter)py_rendering_options_get_show_address, - (setter)py_rendering_options_set_show_address, - "Define or retrieve if the instruction address need to be shown." - }, - { NULL } - }; - - static PyTypeObject py_rendering_options_type = { - - PyObject_HEAD_INIT(NULL) - - .tp_name = "pyoida.analysis.RenderingOptions", - .tp_basicsize = sizeof(py_rendering_options), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyOIDA rendering options", - - .tp_methods = py_rendering_options_methods, - .tp_getset = py_rendering_options_getset, - .tp_new = (newfunc)py_rendering_options_new - - }; - - if (PyType_Ready(&py_rendering_options_type) < 0) - return false; - - Py_INCREF(&py_rendering_options_type); - ret = PyModule_AddObject(module, "RenderingOptions", (PyObject *)&py_rendering_options_type); - - return (ret == 0); - -} diff --git a/plugins/pychrysa/analysis/routine.c b/plugins/pychrysa/analysis/routine.c index 5cd56f5..2ca3560 100644 --- a/plugins/pychrysa/analysis/routine.c +++ b/plugins/pychrysa/analysis/routine.c @@ -25,25 +25,31 @@ #include "routine.h" +#include <string.h> #include <pygobject.h> -#include <analysis/routine.h> +#include <i18n.h> +#include <analysis/routine.h> -/* Crée un nouvel objet Python de type 'BinaryRoutine'. */ -static PyObject *py_binary_routine_new(PyTypeObject *, PyObject *, PyObject *); +#include "block.h" -/* Fournit les blocs basiques de la routine. */ -static PyObject *py_binary_routine_get_basic_blocks(PyObject *, void *); +/* Crée un nouvel objet Python de type 'BinRoutine'. */ +static PyObject *py_binary_routine_new(PyTypeObject *, PyObject *, PyObject *); -/* Décrit le prototype de la routine sous forme de caractères. */ -static PyObject *py_binary_routine_str(PyObject *); +/* Fournit le nom humain d'une routine. */ +static PyObject *py_binary_routine_get_name(PyObject *, void *); +/* Définit le nom humain d'une routine. */ +static int py_binary_routine_set_name(PyObject *, PyObject *, void *); + +/* Fournit les blocs basiques de la routine. */ +static PyObject *py_binary_routine_get_basic_blocks(PyObject *, void *); @@ -72,7 +78,75 @@ static PyObject *py_binary_routine_new(PyTypeObject *type, PyObject *args, PyObj } +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le nom humain d'une routine. * +* * +* Retour : Désignation humainement lisible ou None si non définie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_routine_get_name(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinRoutine *routine; /* Elément à consulter */ + const char *name; /* Désignation courante */ + + routine = G_BIN_ROUTINE(pygobject_get(self)); + name = g_binary_routine_get_name(routine); + + if (name != NULL) + result = PyUnicode_FromString(name); + 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 : Définit le nom humain d'une routine. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_routine_set_name(PyObject *self, PyObject *value, void *closure) +{ + GBinRoutine *routine; /* Elément à consulter */ + + if (!PyUnicode_Check(value) && value != Py_None) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string.")); + return -1; + } + + routine = G_BIN_ROUTINE(pygobject_get(self)); + + if (!PyUnicode_Check(value)) + g_binary_routine_set_name(routine, strdup(PyUnicode_DATA(value))); + else + g_binary_routine_set_name(routine, NULL); + return 0; + +} /****************************************************************************** @@ -104,78 +178,76 @@ static PyObject *py_binary_routine_get_basic_blocks(PyObject *self, void *closur } - - - /****************************************************************************** * * -* Paramètres : self = classe représentant une routine binaire. * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * * * -* Description : Décrit le prototype de la routine sous forme de caractères. * +* Description : Définit les blocs basiques de la routine. * * * -* Retour : Chaîne de caractères. * +* Retour : Bilan de l'opération pour Python. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_binary_routine_str(PyObject *self) +static int py_binary_routine_set_basic_blocks(PyObject *self, PyObject *value, void *closure) { - PyObject *result; /* Chaîne à retourner */ - GBinRoutine *routine; /* Version native */ - char *string; /* Description à libérer */ + GBinRoutine *routine; /* Elément à consulter */ + int ret; /* Bilan de lecture des args. */ + GInstrBlock *blocks; /* Blocs basiques à intégrer */ - routine = G_BIN_ROUTINE(pygobject_get(self)); - string = g_binary_routine_to_string(routine); + ret = PyObject_IsInstance(value, (PyObject *)get_python_instr_block_type()); + if (!ret) return -1; - result = PyString_FromString(string); + routine = G_BIN_ROUTINE(pygobject_get(self)); + blocks = G_INSTR_BLOCK(pygobject_get(value)); - free(string); + g_binary_routine_set_basic_blocks(routine, blocks); - return result; + return 0; } /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.analysis.LoadedBinary'.* +* 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_binary_routine(PyObject *module) +PyTypeObject *get_python_binary_routine_type(void) { - PyObject *pygobj_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_binary_routine_methods[] = { { NULL } }; static PyGetSetDef py_binary_routine_getseters[] = { { - "basic_blocks", (getter)py_binary_routine_get_basic_blocks, (setter)NULL, - "Provide the basic blocks of the binary routine.", NULL + "name", py_binary_routine_get_name, py_binary_routine_set_name, + "Name of the current routine.", NULL + }, + { + "basic_blocks", py_binary_routine_get_basic_blocks, py_binary_routine_set_basic_blocks, + "Basic blocks of the binary routine.", NULL }, { NULL } }; static PyTypeObject py_binary_routine_type = { - PyObject_HEAD_INIT(NULL) - - .tp_name = "pychrysalide.analysis.BinaryRoutine", - .tp_basicsize = sizeof(PyGObject), + PyVarObject_HEAD_INIT(NULL, 0) - .tp_str = py_binary_routine_str, + .tp_name = "pychrysalide.analysis.BinRoutine", - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide binary routine", @@ -185,21 +257,45 @@ bool register_python_binary_routine(PyObject *module) }; - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; + return &py_binary_routine_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis.BinRoutine'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_routine(PyObject *module) +{ + PyTypeObject *py_binary_routine_type; /* Type Python 'BinRoutine' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_binary_routine_type = get_python_binary_routine_type(); - py_binary_routine_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); + py_binary_routine_type->tp_base = &PyGObject_Type; + py_binary_routine_type->tp_basicsize = py_binary_routine_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_binary_routine_type) < 0) + if (PyType_Ready(py_binary_routine_type) != 0) return false; - Py_INCREF(&py_binary_routine_type); - ret = PyModule_AddObject(module, "BinaryRoutine", (PyObject *)&py_binary_routine_type); + Py_INCREF(py_binary_routine_type); + ret = PyModule_AddObject(module, "BinRoutine", (PyObject *)py_binary_routine_type); + if (ret != 0) return false; - pygobject_register_class(module, "GBinRoutine", G_TYPE_BIN_ROUTINE, &py_binary_routine_type, - Py_BuildValue("(O)", py_binary_routine_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BinRoutine", G_TYPE_BIN_ROUTINE, py_binary_routine_type, + Py_BuildValue("(O)", py_binary_routine_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/analysis/routine.h b/plugins/pychrysa/analysis/routine.h index 7c72fa4..ec61466 100644 --- a/plugins/pychrysa/analysis/routine.h +++ b/plugins/pychrysa/analysis/routine.h @@ -31,7 +31,10 @@ -/* Prend en charge l'objet 'pychrysalide.analysis.BinaryRoutine'. */ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_routine_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.BinRoutine'. */ bool register_python_binary_routine(PyObject *); diff --git a/plugins/pychrysa/arch/Makefile.am b/plugins/pychrysa/arch/Makefile.am index 54b9261..7607ed8 100644 --- a/plugins/pychrysa/arch/Makefile.am +++ b/plugins/pychrysa/arch/Makefile.am @@ -2,9 +2,14 @@ noinst_LTLIBRARIES = libpychrysaarch.la libpychrysaarch_la_SOURCES = \ + instruction.h instruction.c \ module.h module.c \ + processor.h processor.c \ vmpa.h vmpa.c +libpychrysaarch_la_LIBADD = \ + arm/libpychrysaarcharm.la + # libpychrysaarch_la_SOURCES = \ # archbase.h archbase.c \ # instruction.h instruction.c \ @@ -19,3 +24,5 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJE -I../../../src AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = arm diff --git a/plugins/pychrysa/arch/arm/Makefile.am b/plugins/pychrysa/arch/arm/Makefile.am new file mode 100644 index 0000000..b081061 --- /dev/null +++ b/plugins/pychrysa/arch/arm/Makefile.am @@ -0,0 +1,20 @@ + +noinst_LTLIBRARIES = libpychrysaarcharm.la + +libpychrysaarcharm_la_SOURCES = \ + instruction.h instruction.c \ + module.h module.c \ + processor.h processor.c + +libpychrysaarcharm_la_LIBADD = \ + v7/libpychrysaarcharmv7.la + +libpychrysaarcharm_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I../../../../src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = v7 diff --git a/plugins/pychrysa/arch/arm/instruction.c b/plugins/pychrysa/arch/arm/instruction.c new file mode 100644 index 0000000..ed53386 --- /dev/null +++ b/plugins/pychrysa/arch/arm/instruction.c @@ -0,0 +1,120 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.c - équivalent Python du fichier "arch/arm/instruction.c" + * + * 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 "instruction.h" + + +#include <pygobject.h> + + +#include <arch/arm/instruction.h> + + +#include "../instruction.h" +#include "../../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_arm_instruction_type(void) +{ + static PyMethodDef py_arm_instruction_methods[] = { + { NULL } + }; + + static PyGetSetDef py_arm_instruction_getseters[] = { + { NULL } + }; + + static PyTypeObject py_arm_instruction_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.arm.ArmInstruction", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide instruction for an ARM architecture.", + + .tp_methods = py_arm_instruction_methods, + .tp_getset = py_arm_instruction_getseters, + + }; + + return &py_arm_instruction_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide....arm.ArmInstruction'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_arm_instruction(PyObject *module) +{ + PyTypeObject *py_arm_instruction_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_arm_instruction_type = get_python_arm_instruction_type(); + + py_arm_instruction_type->tp_base = get_python_arch_instruction_type(); + py_arm_instruction_type->tp_basicsize = py_arm_instruction_type->tp_base->tp_basicsize; + + APPLY_ABSTRACT_FLAG(py_arm_instruction_type); + + if (PyType_Ready(py_arm_instruction_type) != 0) + return false; + + Py_INCREF(py_arm_instruction_type); + ret = PyModule_AddObject(module, "ArmInstruction", (PyObject *)py_arm_instruction_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArmInstruction", G_TYPE_ARM_INSTRUCTION, py_arm_instruction_type, + Py_BuildValue("(O)", py_arm_instruction_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/arch/arm/instruction.h b/plugins/pychrysa/arch/arm/instruction.h new file mode 100644 index 0000000..daec429 --- /dev/null +++ b/plugins/pychrysa/arch/arm/instruction.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour l'équivalent Python du fichier "arch/arm/instruction.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_PYCHRYSALIDE_ARCH_ARM_INSTRUCTION_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_INSTRUCTION_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_arm_instruction_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.arm.ArmInstruction'. */ +bool register_python_arm_instruction(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_INSTRUCTION_H */ diff --git a/plugins/pychrysa/arch/arm/module.c b/plugins/pychrysa/arch/arm/module.c new file mode 100644 index 0000000..d1d7adc --- /dev/null +++ b/plugins/pychrysa/arch/arm/module.c @@ -0,0 +1,96 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire arm en tant que module + * + * 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 "module.h" + + +#include "instruction.h" +#include "processor.h" +#include "v7/module.h" + + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Ajoute le module 'arm' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_arch_arm_module_to_python_module(PyObject *super) +{ + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ + int ret; /* Bilan d'un appel */ + + static PyModuleDef py_chrysalide_arm_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.arch.arm", + .m_doc = "Python module for Chrysalide.arch.arm", + + .m_size = -1, + + }; + + result = false; + + module = PyModule_Create(&py_chrysalide_arm_module); + if (module == NULL) return false; + + ret = PyState_AddModule(super, &py_chrysalide_arm_module); + if (ret != 0) goto aaamtpm_exit; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.arch.arm"); + if (ret != 0) goto aaamtpm_exit; + + Py_INCREF(module); + ret = PyModule_AddObject(super, "arm", module); + if (ret != 0) goto aaamtpm_exit; + + result = true; + + result &= register_python_arm_instruction(module); + result &= register_python_arm_processor(module); + + result &= add_arch_arm_v7_module_to_python_module(module); + + aaamtpm_exit: + + if (!result) + { + printf("something went wrong in %s...\n", __FUNCTION__); + /* ... */ + + } + + return result; + +} diff --git a/plugins/pychrysa/arch/arm/module.h b/plugins/pychrysa/arch/arm/module.h new file mode 100644 index 0000000..eed753f --- /dev/null +++ b/plugins/pychrysa/arch/arm/module.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire arm en tant que module + * + * 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_PYCHRYSALIDE_ARCH_ARM_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'arm' au module Python. */ +bool add_arch_arm_module_to_python_module(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_MODULE_H */ diff --git a/plugins/pychrysa/arch/arm/processor.c b/plugins/pychrysa/arch/arm/processor.c new file mode 100644 index 0000000..049dcb3 --- /dev/null +++ b/plugins/pychrysa/arch/arm/processor.c @@ -0,0 +1,120 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.c - équivalent Python du fichier "arch/arm/processor.c" + * + * 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 "processor.h" + + +#include <pygobject.h> + + +#include <arch/arm/processor.h> + + +#include "../processor.h" +#include "../../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_arm_processor_type(void) +{ + static PyMethodDef py_arm_processor_methods[] = { + { NULL } + }; + + static PyGetSetDef py_arm_processor_getseters[] = { + { NULL } + }; + + static PyTypeObject py_arm_processor_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.arm.ArmProcessor", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide processor for an ARM architecture.", + + .tp_methods = py_arm_processor_methods, + .tp_getset = py_arm_processor_getseters, + + }; + + return &py_arm_processor_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.arm.ArmProcessor'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_arm_processor(PyObject *module) +{ + PyTypeObject *py_arm_processor_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_arm_processor_type = get_python_arm_processor_type(); + + py_arm_processor_type->tp_base = get_python_arch_processor_type(); + py_arm_processor_type->tp_basicsize = py_arm_processor_type->tp_base->tp_basicsize; + + APPLY_ABSTRACT_FLAG(py_arm_processor_type); + + if (PyType_Ready(py_arm_processor_type) != 0) + return false; + + Py_INCREF(py_arm_processor_type); + ret = PyModule_AddObject(module, "ArmProcessor", (PyObject *)py_arm_processor_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArmProcessor", G_TYPE_ARM_PROCESSOR, py_arm_processor_type, + Py_BuildValue("(O)", py_arm_processor_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/arch/arm/processor.h b/plugins/pychrysa/arch/arm/processor.h new file mode 100644 index 0000000..594f0e6 --- /dev/null +++ b/plugins/pychrysa/arch/arm/processor.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.h - prototypes pour l'équivalent Python du fichier "arch/arm/processor.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_PYCHRYSALIDE_ARCH_ARM_PROCESSOR_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_PROCESSOR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_arm_processor_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.arm.ArmProcessor'. */ +bool register_python_arm_processor(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_PROCESSOR_H */ diff --git a/plugins/pychrysa/arch/arm/v7/Makefile.am b/plugins/pychrysa/arch/arm/v7/Makefile.am new file mode 100644 index 0000000..d95aff3 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/Makefile.am @@ -0,0 +1,16 @@ + +noinst_LTLIBRARIES = libpychrysaarcharmv7.la + +libpychrysaarcharmv7_la_SOURCES = \ + instruction.h instruction.c \ + module.h module.c \ + processor.h processor.c + + +libpychrysaarcharmv7_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I../../../../../src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/pychrysa/arch/arm/v7/instruction.c b/plugins/pychrysa/arch/arm/v7/instruction.c new file mode 100644 index 0000000..8a19259 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/instruction.c @@ -0,0 +1,117 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.c - équivalent Python du fichier "arch/arm/v7/instruction.c" + * + * 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 "instruction.h" + + +#include <pygobject.h> + + +#include <arch/arm/v7/instruction.h> + + +#include "../instruction.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_armv7_instruction_type(void) +{ + static PyMethodDef py_armv7_instruction_methods[] = { + { NULL } + }; + + static PyGetSetDef py_armv7_instruction_getseters[] = { + { NULL } + }; + + static PyTypeObject py_armv7_instruction_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.arm.v7.ArmV7Instruction", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide instruction for an ARMv7 architecture.", + + .tp_methods = py_armv7_instruction_methods, + .tp_getset = py_armv7_instruction_getseters, + + }; + + return &py_armv7_instruction_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide....arm.ArmInstruction'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_armv7_instruction(PyObject *module) +{ + PyTypeObject *py_armv7_instruction_type;/* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_armv7_instruction_type = get_python_armv7_instruction_type(); + + py_armv7_instruction_type->tp_base = get_python_arm_instruction_type(); + py_armv7_instruction_type->tp_basicsize = py_armv7_instruction_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_armv7_instruction_type) != 0) + return false; + + Py_INCREF(py_armv7_instruction_type); + ret = PyModule_AddObject(module, "ArmV7Instruction", (PyObject *)py_armv7_instruction_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArmV7Instruction", G_TYPE_ARMV7_INSTRUCTION, py_armv7_instruction_type, + Py_BuildValue("(O)", py_armv7_instruction_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/arch/arm/v7/instruction.h b/plugins/pychrysa/arch/arm/v7/instruction.h new file mode 100644 index 0000000..9eac361 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/instruction.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour l'équivalent Python du fichier "arch/arm/v7/instruction.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_PYCHRYSALIDE_ARCH_ARM_V7_INSTRUCTION_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_INSTRUCTION_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_armv7_instruction_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.arm.v7.ArmV7Instruction'. */ +bool register_python_armv7_instruction(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_INSTRUCTION_H */ diff --git a/plugins/pychrysa/arch/arm/v7/module.c b/plugins/pychrysa/arch/arm/v7/module.c new file mode 100644 index 0000000..7c0aabf --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/module.c @@ -0,0 +1,93 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire v7 en tant que module + * + * 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 "module.h" + + +#include "instruction.h" +#include "processor.h" + + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Ajoute le module 'arm' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_arch_arm_v7_module_to_python_module(PyObject *super) +{ + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ + int ret; /* Bilan d'un appel */ + + static PyModuleDef py_chrysalide_v7_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.arch.arm.v7", + .m_doc = "Python module for Chrysalide.arch.arm.v7", + + .m_size = -1, + + }; + + result = false; + + module = PyModule_Create(&py_chrysalide_v7_module); + if (module == NULL) return false; + + ret = PyState_AddModule(super, &py_chrysalide_v7_module); + if (ret != 0) goto aaamtpm_exit; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.arch.arm.v7"); + if (ret != 0) goto aaamtpm_exit; + + Py_INCREF(module); + ret = PyModule_AddObject(super, "v7", module); + if (ret != 0) goto aaamtpm_exit; + + result = true; + + result &= register_python_armv7_instruction(module); + result &= register_python_armv7_processor(module); + + aaamtpm_exit: + + if (!result) + { + printf("something went wrong in %s...\n", __FUNCTION__); + /* ... */ + + } + + return result; + +} diff --git a/plugins/pychrysa/arch/arm/v7/module.h b/plugins/pychrysa/arch/arm/v7/module.h new file mode 100644 index 0000000..61ad126 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/module.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire v7 en tant que module + * + * 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_PYCHRYSALIDE_ARCH_ARM_V7_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'arm' au module Python. */ +bool add_arch_arm_v7_module_to_python_module(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_MODULE_H */ diff --git a/plugins/pychrysa/arch/arm/v7/processor.c b/plugins/pychrysa/arch/arm/v7/processor.c new file mode 100644 index 0000000..1844066 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/processor.c @@ -0,0 +1,117 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.c - équivalent Python du fichier "arch/arm/v7/processor.c" + * + * 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 "processor.h" + + +#include <pygobject.h> + + +#include <arch/arm/v7/processor.h> + + +#include "../processor.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_armv7_processor_type(void) +{ + static PyMethodDef py_armv7_processor_methods[] = { + { NULL } + }; + + static PyGetSetDef py_armv7_processor_getseters[] = { + { NULL } + }; + + static PyTypeObject py_armv7_processor_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.arm.v7.ArmV7Processor", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide processor for an ARMv7 architecture.", + + .tp_methods = py_armv7_processor_methods, + .tp_getset = py_armv7_processor_getseters, + + }; + + return &py_armv7_processor_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.arm.ArmProcessor'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_armv7_processor(PyObject *module) +{ + PyTypeObject *py_armv7_processor_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_armv7_processor_type = get_python_armv7_processor_type(); + + py_armv7_processor_type->tp_base = get_python_arm_processor_type(); + py_armv7_processor_type->tp_basicsize = py_armv7_processor_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_armv7_processor_type) != 0) + return false; + + Py_INCREF(py_armv7_processor_type); + ret = PyModule_AddObject(module, "ArmV7Processor", (PyObject *)py_armv7_processor_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArmV7Processor", G_TYPE_ARMV7_PROCESSOR, py_armv7_processor_type, + Py_BuildValue("(O)", py_armv7_processor_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/arch/arm/v7/processor.h b/plugins/pychrysa/arch/arm/v7/processor.h new file mode 100644 index 0000000..268a025 --- /dev/null +++ b/plugins/pychrysa/arch/arm/v7/processor.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.h - prototypes pour l'équivalent Python du fichier "arch/arm/v7/processor.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_PYCHRYSALIDE_ARCH_ARM_V7_PROCESSOR_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_PROCESSOR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_armv7_processor_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.arm.v7.ArmV7Processor'. */ +bool register_python_armv7_processor(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_ARM_V7_PROCESSOR_H */ diff --git a/plugins/pychrysa/arch/instruction.c b/plugins/pychrysa/arch/instruction.c index efbdaa5..d675226 100644 --- a/plugins/pychrysa/arch/instruction.c +++ b/plugins/pychrysa/arch/instruction.c @@ -25,6 +25,384 @@ #include "instruction.h" +#include <assert.h> +#include <pygobject.h> + + +#include <arch/instruction.h> + + +#include "vmpa.h" +#include "../helpers.h" + + + + +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ + + + + + +/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */ + + + +/* Fournit la place mémoire d'une instruction. */ +static PyObject *py_arch_instruction_get_range(PyObject *, void *); + +/* Définit la localisation d'une instruction. */ +static int py_arch_instruction_set_range(PyObject *, PyObject *, void *); + + + +/* Fournit le nom humain de l'instruction manipulée. */ +static PyObject *py_arch_instruction_get_keyword(PyObject *, void *); + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + + + +/* Fournit les origines d'une instruction donnée. */ +static PyObject *py_arch_instruction_get_sources(PyObject *, PyObject *); + +/* Fournit les destinations d'une instruction donnée. */ +static PyObject *py_arch_instruction_get_destinations(PyObject *, PyObject *); + + + + +/****************************************************************************** +* * +* Paramètres : self = instruction d'architecture à manipuler. * +* args = liste d'arguments non utilisée ici. * +* * +* Description : Fournit les origines d'une instruction donnée. * +* * +* Retour : Nombre de ces origines. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_get_sources(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + GArchInstruction *instr; /* Version native */ + GArchInstruction **dests; /* Destination des liens */ + InstructionLinkType *types; /* Nature de ces liens */ + size_t count; /* Nombre de liens présents */ + size_t i; /* Boucle de parcours */ + PyObject *dest; /* Destination de lien Python */ + PyObject *type; /* Nature du lien en Python */ + int ret; /* Bilan d'une écriture d'arg. */ + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + + count = g_arch_instruction_get_sources(instr, &dests, &types); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + dest = pygobject_new(G_OBJECT(dests[i])); + type = PyLong_FromLong(types[i]); + + ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", dest, type)); + assert(ret == 0); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instruction d'architecture à manipuler. * +* args = liste d'arguments non utilisée ici. * +* * +* Description : Fournit les destinations d'une instruction donnée. * +* * +* Retour : Nombre de ces destinations. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_get_destinations(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + GArchInstruction *instr; /* Version native */ + GArchInstruction **dests; /* Destination des liens */ + InstructionLinkType *types; /* Nature de ces liens */ + size_t count; /* Nombre de liens présents */ + size_t i; /* Boucle de parcours */ + PyObject *dest; /* Destination de lien Python */ + PyObject *type; /* Nature du lien en Python */ + int ret; /* Bilan d'une écriture d'arg. */ + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + + count = g_arch_instruction_get_destinations(instr, &dests, &types, NULL); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + dest = pygobject_new(G_OBJECT(dests[i])); + type = PyLong_FromLong(types[i]); + + ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", dest, type)); + assert(ret == 0); + + } + + return result; + +} + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une instruction. * +* closure = adresse non utilisée ici. * +* * +* Description : Fournit la place mémoire d'une instruction. * +* * +* Retour : Valeur associée à la propriété consultée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_get_range(PyObject *self, void *closure) +{ + PyObject *result; /* Conversion à retourner */ + GArchInstruction *instr; /* Version native */ + const mrange_t *range; /* Espace mémoire à exporter */ + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + range = g_arch_instruction_get_range(instr); + + result = build_from_internal_mrange(range); + + return result; + +} + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = adresse non utilisée ici. * +* * +* Description : Définit la localisation d'une instruction. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_arch_instruction_set_range(PyObject *self, PyObject *value, void *closure) +{ + int ret; /* Bilan d'analyse */ + mrange_t *range; /* Espace mémoire à manipuler */ + GArchInstruction *instr; /* Version native */ + + ret = PyObject_IsInstance(value, (PyObject *)get_python_mrange_type()); + if (!ret) return -1; + + range = get_internal_mrange(value); + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + g_arch_instruction_set_range(instr, range); + + return 0; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une instruction. * +* unused = adresse non utilisée ici. * +* * +* Description : Fournit le nom humain de l'instruction manipulée. * +* * +* Retour : Valeur associée à la propriété consultée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused) +{ + PyObject *result; /* Trouvailles à retourner */ + GArchInstruction *instr; /* Version native */ + const char *kw; /* Valeur récupérée */ + + instr = G_ARCH_INSTRUCTION(pygobject_get(self)); + kw = g_arch_instruction_get_keyword(instr, 0/* FIXME*/); + + result = PyUnicode_FromString(kw); + + return result; + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_arch_instruction_type(void) +{ + static PyMethodDef py_arch_instruction_methods[] = { + { "get_sources", py_arch_instruction_get_sources, + METH_NOARGS, + "get_sources(, /)\n--\n\nProvide the instructions list driving to the current instruction." + }, + { "get_destinations", py_arch_instruction_get_destinations, + METH_NOARGS, + "get_destinations(, /)\n--\n\nProvide the instructions list following the current instruction." + }, + { NULL } + }; + + static PyGetSetDef py_arch_instruction_getseters[] = { + { + "range", py_arch_instruction_get_range, py_arch_instruction_set_range, + "Give access to the memory range covered by the current instruction.", NULL + }, + { + "keyword", (getter)py_arch_instruction_get_keyword, (setter)NULL, + "Give le name of the assembly instruction.", NULL + }, + { NULL } + }; + + static PyTypeObject py_arch_instruction_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.ArchInstruction", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide instruction for a given architecture.", + + .tp_methods = py_arch_instruction_methods, + .tp_getset = py_arch_instruction_getseters, + + }; + + return &py_arch_instruction_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.ArchInstruction'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_arch_instruction(PyObject *module) +{ + PyTypeObject *py_arch_instruction_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_arch_instruction_type = get_python_arch_instruction_type(); + + py_arch_instruction_type->tp_base = &PyGObject_Type; + py_arch_instruction_type->tp_basicsize = py_arch_instruction_type->tp_base->tp_basicsize; + + APPLY_ABSTRACT_FLAG(py_arch_instruction_type); + + if (PyType_Ready(py_arch_instruction_type) != 0) + return false; + + Py_INCREF(py_arch_instruction_type); + ret = PyModule_AddObject(module, "ArchInstruction", (PyObject *)py_arch_instruction_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArchInstruction", G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_type, + Py_BuildValue("(O)", py_arch_instruction_type->tp_base)); + + return true; + +} + + + + + + + +#if 0 + + #include <pygobject.h> #include <stdbool.h> #include <string.h> @@ -330,34 +708,6 @@ static PyObject *py_arch_instruction_get_location(PyObject *self, char *name) } -/****************************************************************************** -* * -* Paramètres : self = classe représentant une instruction. * -* unused = adresse non utilisée ici. * -* * -* Description : Fournit le nom humain de l'instruction manipulée. * -* * -* Retour : Valeur associée à la propriété consultée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused) -{ - PyObject *result; /* Trouvailles à retourner */ - GArchInstruction *instr; /* Version native */ - const char *kw; /* Valeur récupérée */ - - instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - kw = g_arch_instruction_get_keyword(instr); - - result = PyString_FromString(kw); - - return result; - -} - /****************************************************************************** * * @@ -438,3 +788,6 @@ bool register_python_arch_instruction(PyObject *module) return (ret == 0); } + + +#endif diff --git a/plugins/pychrysa/arch/instruction.h b/plugins/pychrysa/arch/instruction.h index 7b81d65..c3f8bd9 100644 --- a/plugins/pychrysa/arch/instruction.h +++ b/plugins/pychrysa/arch/instruction.h @@ -31,16 +31,8 @@ -/* --------------------- ITERATEUR POUR BOUCLE SUR INSTRUCTIONS --------------------- */ - - -/* Permet une itération de 'pychrysalide.arch.ArchInstruction'. */ -bool register_python_arch_instruction_iterator(PyObject *); - - - -/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */ - +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_arch_instruction_type(void); /* Prend en charge l'objet 'pychrysalide.arch.ArchInstruction'. */ bool register_python_arch_instruction(PyObject *); diff --git a/plugins/pychrysa/arch/module.c b/plugins/pychrysa/arch/module.c index 92172e0..6df56a9 100644 --- a/plugins/pychrysa/arch/module.c +++ b/plugins/pychrysa/arch/module.c @@ -25,7 +25,13 @@ #include "module.h" +#include <assert.h> + + +#include "instruction.h" +#include "processor.h" #include "vmpa.h" +#include "arm/module.h" @@ -64,27 +70,27 @@ bool add_arch_module_to_python_module(PyObject *super) if (module == NULL) return false; ret = PyState_AddModule(super, &py_chrysalide_arch_module); - if (ret != 0) goto aamtpm_exit; + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.arch"); - if (ret != 0) goto aamtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "arch", module); - if (ret != 0) goto aamtpm_exit; + if (ret != 0) goto loading_failed; result = true; + result &= register_python_arch_instruction(module); + result &= register_python_arch_processor(module); result &= register_python_vmpa(module); + result &= register_python_mrange(module); - aamtpm_exit: + result &= add_arch_arm_module_to_python_module(module); - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ + loading_failed: - } + assert(result); return result; diff --git a/plugins/pychrysa/arch/processor.c b/plugins/pychrysa/arch/processor.c index 6a275d4..0a9ae3a 100644 --- a/plugins/pychrysa/arch/processor.c +++ b/plugins/pychrysa/arch/processor.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * processor.h - prototypes pour l'équivalent Python du fichier "arch/processor.h" + * processor.c - équivalent Python du fichier "arch/processor.c" * - * Copyright (C) 2010-2013 Cyrille Bagard + * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,22 +25,21 @@ #include "processor.h" -#include "../../../src/arch/processor.h" +#include <pygobject.h> +#include <i18n.h> -/* ------------------------- TYPAGE DES ENUMERATIONS PYTHON ------------------------- */ +#include <arch/processor.h> -/* Définit les constantes pour les types de processeur. */ -bool py_arch_processor_type_define_constants(PyObject *); -/* Ajoute l'objet 'arch.processor.ArchProcessorType' au module. */ -bool add_arch_processor_type_to_python_module(PyObject *); +#include "instruction.h" +#include "vmpa.h" +#include "../helpers.h" -/* ------------------------- PARTIE STATIQUE DE PROCESSEURS ------------------------- */ @@ -48,12 +47,7 @@ bool add_arch_processor_type_to_python_module(PyObject *); -/* Classe 'analysis.roptions' pour Python */ -typedef struct _py_processor -{ - PyObject_HEAD -} py_processor; @@ -63,120 +57,246 @@ typedef struct _py_processor +/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */ + + + +/* Fournit les instructions désassemblées pour une architecture. */ +static PyObject *py_arch_processor_get_disass_instrs(PyObject *, void *); + +/* Recherche une instruction d'après son adresse. */ +static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *); + +/* Fournit l'instruction qui en précède une autre. */ +static PyObject *py_arch_processor_get_prev_instr(PyObject *, PyObject *); + +/* Fournit l'instruction qui en suit une autre. */ +static PyObject *py_arch_processor_get_next_instr(PyObject *, PyObject *); + + + + /* ---------------------------------------------------------------------------------- */ -/* TYPAGE DES ENUMERATIONS PYTHON */ +/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : dict = dictionnaire à compléter. * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * * * -* Description : Définit les constantes pour les types de processeur. * +* Description : Fournit les instructions désassemblées pour une architecture.* * * -* Retour : - * +* Retour : Liste des instructions désassemblées ou None si aucune. * * * * Remarques : - * * * ******************************************************************************/ -bool py_arch_processor_type_define_constants(PyObject *dict) +static PyObject *py_arch_processor_get_disass_instrs(PyObject *self, void *closure) { - int ret; /* Bilan d'un ajout */ + PyObject *result; /* Instance Python à retourner */ + GArchProcessor *proc; /* Architecture visée */ + GArchInstruction *instrs; /* Série d'instructions liées */ - ret = PyDict_SetItemString(dict, "APT_JVM", PyInt_FromLong(APT_JVM)); - if (ret == -1) return false; + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + instrs = g_arch_processor_get_disassembled_instructions(proc); - ret = PyDict_SetItemString(dict, "APT_MIPS", PyInt_FromLong(APT_MIPS)); - if (ret == -1) return false; + if (instrs != NULL) + result = pygobject_new(G_OBJECT(instrs)); + else + { + result = Py_None; + Py_INCREF(result); + } - ret = PyDict_SetItemString(dict, "APT_386", PyInt_FromLong(APT_386)); - if (ret == -1) return false; - - ret = PyDict_SetItemString(dict, "APT_COUNT", PyInt_FromLong(APT_COUNT)); - if (ret == -1) return false; - - return true; + return result; } -PyObject *__test; + /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * * * -* Description : Ajoute l'objet 'arch.processor.ArchProcessorType' au module. * +* Description : Note les instructions désassemblées avec une architecture. * * * -* Retour : - * +* Retour : Bilan de l'opération pour Python. * * * * Remarques : - * * * ******************************************************************************/ -bool add_arch_processor_type_to_python_module(PyObject *module) +static int py_arch_processor_set_disass_instrs(PyObject *self, PyObject *value, void *closure) { - int ret; /* Bilan d'un appel */ + GArchProcessor *proc; /* Architecture visée */ + GArchInstruction *instrs; /* Série d'instructions liées */ - static PyTypeObject py_arch_processor_type_type = { + if (!PyObject_TypeCheck(value, get_python_arch_instruction_type())) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be an instruction.")); + return -1; + } - PyObject_HEAD_INIT(NULL) + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + instrs = G_ARCH_INSTRUCTION(pygobject_get(value)); - .tp_name = "pyoida.arch.processor.ArchProcessorType", + g_arch_processor_set_disassembled_instructions(proc, instrs); - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + return 0; - .tp_doc = "PyOIDA version of the ArchProcessorType enumeration", +} - }; - if (PyType_Ready(&py_arch_processor_type_type) < 0) - return false; +/****************************************************************************** +* * +* Paramètres : self = processeur d'architecture à manipuler. * +* args = instruction représentant le point de départ. * +* * +* Description : Recherche une instruction d'après son adresse. * +* * +* Retour : Instruction trouvée à l'adresse donnée, None si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_processor_find_instr_by_addr(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + PyObject *addr_obj; /* Objet pour une localisation */ + int ret; /* Bilan de lecture des args. */ + GArchProcessor *proc; /* Processeur manipulé */ + vmpa2t *addr; /* Localisation à retrouver */ + GArchInstruction *found; /* Instruction liée trouvée */ + + ret = PyArg_ParseTuple(args, "O", &addr_obj); + if (!ret) return NULL; + + ret = PyObject_IsInstance(addr_obj, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + addr = get_internal_vmpa(addr_obj); - py_arch_processor_type_define_constants(py_arch_processor_type_type.tp_dict); + found = g_arch_processor_find_instr_by_address(proc, addr); - Py_INCREF(&py_arch_processor_type_type); - ret = PyModule_AddObject(module, "ArchProcessorType", (PyObject *)&py_arch_processor_type_type); + if (found != NULL) + result = pygobject_new(G_OBJECT(found)); - __test = (PyObject *)&py_arch_processor_type_type; + else + { + result = Py_None; + Py_INCREF(result); + } - return (ret == 0); + return result; } +/****************************************************************************** +* * +* Paramètres : self = processeur d'architecture à manipuler. * +* args = instruction représentant le point de départ. * +* * +* Description : Fournit l'instruction qui en précède une autre. * +* * +* Retour : Instruction précédente trouvée, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ -/* ---------------------------------------------------------------------------------- */ -/* PARTIE STATIQUE DE PROCESSEURS */ -/* ---------------------------------------------------------------------------------- */ +static PyObject *py_arch_processor_get_prev_instr(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + PyObject *instr_obj; /* Objet pour une instruction */ + int ret; /* Bilan de lecture des args. */ + GArchProcessor *proc; /* Processeur manipulé */ + GArchInstruction *instr; /* Instruction de référence */ + GArchInstruction *found; /* Instruction liée trouvée */ + ret = PyArg_ParseTuple(args, "O", &instr_obj); + if (!ret) return NULL; + ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type()); + if (!ret) return NULL; + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj)); + found = g_arch_processor_get_prev_instr(proc, instr); + if (found != NULL) + result = pygobject_new(G_OBJECT(found)); + else + { + result = Py_None; + Py_INCREF(result); + } + return result; +} +/****************************************************************************** +* * +* Paramètres : self = processeur d'architecture à manipuler. * +* args = instruction représentant le point de départ. * +* * +* Description : Fournit l'instruction qui en suit une autre. * +* * +* Retour : Instruction suivante trouvée, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ +static PyObject *py_arch_processor_get_next_instr(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + PyObject *instr_obj; /* Objet pour une instruction */ + int ret; /* Bilan de lecture des args. */ + GArchProcessor *proc; /* Processeur manipulé */ + GArchInstruction *instr; /* Instruction de référence */ + GArchInstruction *found; /* Instruction liée trouvée */ + ret = PyArg_ParseTuple(args, "O", &instr_obj); + if (!ret) return NULL; + ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type()); + if (!ret) return NULL; + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj)); + found = g_arch_processor_get_next_instr(proc, instr); + if (found != NULL) + result = pygobject_new(G_OBJECT(found)); + else + { + result = Py_None; + Py_INCREF(result); + } + return result; +} -/* ---------------------------------------------------------------------------------- */ -/* PARTIE GRAPHIQUE DES [DE]CHARGEMENTS */ -/* ---------------------------------------------------------------------------------- */ @@ -186,103 +306,107 @@ bool add_arch_processor_type_to_python_module(PyObject *module) -/* Crée un nouvel objet Python de type 'py_processor'. */ -static PyObject *py_processor_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 'py_processor'. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : - * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +PyTypeObject *get_python_arch_processor_type(void) { - py_processor *result; /* Instance à retourner */ - - result = (py_processor *)type->tp_alloc(type, 0); - - return (PyObject *)result; - -} - - + static PyMethodDef py_arch_processor_methods[] = { + { + "find_instr_by_addr", py_arch_processor_find_instr_by_addr, + METH_VARARGS, + "find_instr_by_addr($self, addr, /)\n--\n\nLook for an instruction located at a given address." + }, + { + "get_prev_instr", py_arch_processor_get_prev_instr, + METH_VARARGS, + "get_prev_instr($self, instr, /)\n--\n\nProvide the instruction preceding a given instruction." + }, + { + "get_next_instr", py_arch_processor_get_next_instr, + METH_VARARGS, + "get_next_instr($self, instr, /)\n--\n\nProvide the instruction following a given instruction." + }, + { NULL } + }; + static PyGetSetDef py_arch_processor_getseters[] = { + { + "disass_instrs", py_arch_processor_get_disass_instrs, py_arch_processor_set_disass_instrs, + "Give access to the disassembled instructions run by the current processor.", NULL + }, + { NULL } + }; + static PyTypeObject py_arch_processor_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "pychrysalide.arch.ArchProcessor", + .tp_basicsize = sizeof(PyGObject), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, + .tp_doc = "PyChrysalide processor for a given architecture.", + .tp_methods = py_arch_processor_methods, + .tp_getset = py_arch_processor_getseters, + }; + return &py_arch_processor_type; +} /****************************************************************************** * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Ajoute l'objet 'analysis.roptions' au module Python. * +* Description : Prend en charge l'objet 'pychrysalide.arch.ArchProcessor'. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -bool add_arch_processor_to_python_module(PyObject *module) +bool register_python_arch_processor(PyObject *module) { - bool result; /* Bilan à retourner */ + PyTypeObject *py_arch_processor_type; /* Type Python 'BinContent' */ int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - static PyMethodDef py_processor_methods[] = { - { NULL } - }; - - static PyGetSetDef py_processor_getset[] = { - { NULL } - }; - - static PyTypeObject py_processor_type = { + py_arch_processor_type = get_python_arch_processor_type(); - PyObject_HEAD_INIT(NULL) + py_arch_processor_type->tp_base = &PyGObject_Type; + py_arch_processor_type->tp_basicsize = py_arch_processor_type->tp_base->tp_basicsize; - .tp_name = "pyoida.arch.Processor", - .tp_basicsize = sizeof(py_processor), + APPLY_ABSTRACT_FLAG(py_arch_processor_type); - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyOIDA processor for a given architecture", - - .tp_methods = py_processor_methods, - .tp_getset = py_processor_getset, - .tp_new = (newfunc)py_processor_new - - }; - - if (PyType_Ready(&py_processor_type) < 0) + if (PyType_Ready(py_arch_processor_type) != 0) return false; - //printf("ret import = %p\n", PyImport_ImportModule("pyoida.arch.processor.ArchProcessorType")); + Py_INCREF(py_arch_processor_type); + ret = PyModule_AddObject(module, "ArchProcessor", (PyObject *)py_arch_processor_type); + if (ret != 0) return false; + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ArchProcessor", G_TYPE_ARCH_PROCESSOR, py_arch_processor_type, + Py_BuildValue("(O)", py_arch_processor_type->tp_base)); - - Py_INCREF(&py_processor_type); - ret = PyModule_AddObject(module, "Processor", (PyObject *)&py_processor_type); - - result = add_arch_processor_type_to_python_module(module); - - - return (ret == 0 && result); + return true; } diff --git a/plugins/pychrysa/arch/processor.h b/plugins/pychrysa/arch/processor.h index 6a74176..26837cb 100644 --- a/plugins/pychrysa/arch/processor.h +++ b/plugins/pychrysa/arch/processor.h @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_PYOIDA_ARCH_PROCESSOR_H -#define _PLUGINS_PYOIDA_ARCH_PROCESSOR_H +#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_PROCESSOR_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_PROCESSOR_H #include <Python.h> @@ -31,9 +31,12 @@ -/* Ajoute l'objet 'arch.processor' au module Python. */ -bool add_arch_processor_to_python_module(PyObject *); +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_arch_processor_type(void); +/* Prend en charge l'objet 'pychrysalide.arch.ArchProcessor'. */ +bool register_python_arch_processor(PyObject *); -#endif /* _PLUGINS_PYOIDA_ARCH_PROCESSOR_H */ + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_PROCESSOR_H */ diff --git a/plugins/pychrysa/arch/vmpa.c b/plugins/pychrysa/arch/vmpa.c index 43131b5..350f61b 100644 --- a/plugins/pychrysa/arch/vmpa.c +++ b/plugins/pychrysa/arch/vmpa.c @@ -28,11 +28,14 @@ #include <string.h> +#include "../helpers.h" +/* ---------------------- DEFINITION D'UNE POSITION EN MEMOIRE ---------------------- */ + typedef struct _py_vmpa_t @@ -49,7 +52,7 @@ typedef struct _py_vmpa_t /* Fournit une représentation d'une variable 'vmpa_t'. */ static PyObject *py_vmpa_to_str(PyObject *); -/* Effectue une conversion d'un objet Python en type 'vmpa_t'. */ +/* Effectue une comparaison avec un objet Python 'vmpa_t'. */ static PyObject *py_vmpa_richcompare(PyObject *, PyObject *, int); /* Fournit une partie du contenu de la position représentée. */ @@ -67,12 +70,74 @@ static bool convert_pyobj_to_vmpa(PyObject *, vmpa2t *); /* Effectue une opération de type 'add' avec le type 'vmpa'. */ static PyObject *py_vmpa_nb_add(PyObject *, PyObject *); +/* Définit les constantes pour les localisations. */ +static bool py_vmpa_define_constants(PyTypeObject *); + + + +/* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */ + + +/* Couverture mémoire */ +typedef struct _py_mrange_t +{ + PyObject_HEAD /* Préambule Python */ + + mrange_t range; /* Informations internes */ + +} py_mrange_t; + + +/* Fournit une représentation d'une variable 'mrange_t'. */ +static PyObject *py_mrange_to_str(PyObject *); + + + +/* Effectue une comparaison avec un objet Python 'mrange_t'. */ +static PyObject *py_mrange_richcompare(PyObject *, PyObject *, int); + + + +/* Indique si une zone en contient une autre ou non. */ +static PyObject *py_mrange_contains(PyObject *, PyObject *); + + + + +/* Fournit la position de départ de la zone mémoire représentée. */ +static PyObject *py_mrange_get_addr(PyObject *, void *); + +/* Définit la position de départ de la zone mémoire représentée. */ +static int py_mrange_set_addr(PyObject *, PyObject *, void *); + +/* Fournit la taille de la zone mémoire représentée. */ +static PyObject *py_mrange_get_length(PyObject *, void *); + +/* Définit la taille de la zone mémoire représentée. */ +static int py_mrange_set_length(PyObject *, PyObject *, void *); + +/* Calcule la position extérieure finale d'une couverture. */ +static PyObject *py_mrange_get_end_addr(PyObject *, void *); + + + +/* Crée un nouvel objet Python de type 'mrange'. */ +static PyObject *py_mrange_new(PyTypeObject *, PyObject *, PyObject *); + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UNE POSITION EN MEMOIRE */ +/* ---------------------------------------------------------------------------------- */ + + + + /****************************************************************************** * * * Paramètres : obj = objet Python à traiter. * @@ -119,7 +184,7 @@ static PyObject *py_vmpa_to_str(PyObject *obj) * Paramètres : obj = objet Python à tenter de convertir. * * addr = structure équivalente pour Chrysalide. * * * -* Description : Effectue une conversion d'un objet Python en type 'vmpa_t'. * +* Description : Effectue une comparaison avec un objet Python 'vmpa_t'. * * * * Retour : Bilan de l'opération. * * * @@ -184,7 +249,7 @@ static PyObject *py_vmpa_get_value(PyObject *self, void *closure) key = (char *)closure; - if (strcmp(key, "phy") == 0) + if (strcmp(key, "phys") == 0) { if (get_phy_addr(&vmpa->addr) == VMPA_NO_PHYSICAL) { @@ -236,7 +301,7 @@ static int py_vmpa_set_value(PyObject *self, PyObject *value, void *closure) key = (char *)closure; - if (strcmp(key, "phy") == 0) + if (strcmp(key, "phys") == 0) { if (value == Py_None) init_vmpa(&vmpa->addr, VMPA_NO_PHYSICAL, get_virt_addr(&vmpa->addr)); @@ -296,7 +361,7 @@ static int py_vmpa_set_value(PyObject *self, PyObject *value, void *closure) static PyObject *py_vmpa_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - py_vmpa_t *result; /* Instance à retourner */ + py_vmpa_t *result; /* Instance à retourner */ unsigned long long phy; /* Position physique */ unsigned long long virt; /* Adresse en mémoire virtuelle*/ int ret; /* Bilan de lecture des args. */ @@ -442,6 +507,32 @@ void change_editor_items_current_view_content(void/*GtkViewPanel*/ *view) /****************************************************************************** * * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les localisations. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_vmpa_define_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + result &= PyDict_AddIntMacro(obj_type, VMPA_NO_PHYSICAL); + result &= PyDict_AddIntMacro(obj_type, VMPA_NO_VIRTUAL); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -504,13 +595,13 @@ PyTypeObject *get_python_vmpa_type(void) static PyGetSetDef py_vmpa_getseters[] = { { - "phy", py_vmpa_get_value, py_vmpa_set_value, - "Give access to the physical offset of the location", "phy" + "phys", py_vmpa_get_value, py_vmpa_set_value, + "Give access to the physical offset of the location.", "phys" }, { "virt", py_vmpa_get_value, py_vmpa_set_value, - "Give access to the virtual address of the location", "virt" + "Give access to the virtual address of the location.", "virt" }, { NULL } @@ -529,7 +620,7 @@ PyTypeObject *get_python_vmpa_type(void) .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "Python object for vmpa_t", + .tp_doc = "Python object for vmpa_t.", .tp_richcompare = py_vmpa_richcompare, @@ -565,6 +656,9 @@ bool register_python_vmpa(PyObject *module) if (PyType_Ready(py_vmpa_type) != 0) return false; + if (!py_vmpa_define_constants(py_vmpa_type)) + return false; + Py_INCREF(py_vmpa_type); ret = PyModule_AddObject(module, "vmpa", (PyObject *)py_vmpa_type); @@ -595,3 +689,551 @@ vmpa2t *get_internal_vmpa(PyObject *obj) return &((py_vmpa_t *)obj)->addr; } + + +/****************************************************************************** +* * +* Paramètres : addr = structure interne à copier en objet Python. * +* * +* Description : Convertit une structure de type 'vmpa2t' en objet Python. * +* * +* Retour : Object Python résultant de la conversion opérée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *build_from_internal_vmpa(const vmpa2t *addr) +{ + py_vmpa_t *result; /* Instance à retourner */ + PyTypeObject *type; /* Type à instancier */ + + type = get_python_vmpa_type(); + + result = (py_vmpa_t *)type->tp_alloc(type, 0); + + copy_vmpa(&result->addr, addr); + + return (PyObject *)result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UNE ZONE EN MEMOIRE */ +/* ---------------------------------------------------------------------------------- */ + + + + + + + +/****************************************************************************** +* * +* Paramètres : obj = objet Python à traiter. * +* * +* Description : Fournit une représentation d'une variable 'mrange_t'. * +* * +* Retour : Chaîne de caractère pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_to_str(PyObject *obj) +{ + PyObject *result; /* Chaîne à retourner */ + + result = PyUnicode_FromFormat("<TODO!>"); + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : obj = objet Python à tenter de convertir. * +* addr = structure équivalente pour Chrysalide. * +* * +* Description : Effectue une comparaison avec un objet Python 'mrange_t'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_richcompare(PyObject *a, PyObject *b, int op) +{ + PyObject *result; /* Chaîne à retourner */ + mrange_t *range_a; /* Premier espace à traiter */ + mrange_t *range_b; /* Second espace à traiter */ + int status; /* Résultat d'une comparaison */ + + range_a = get_internal_mrange(a); + + range_b = get_internal_mrange(b); + if (range_b == NULL) return NULL; + + status = cmp_mrange(range_a, range_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; + + } + + Py_INCREF(result); + + return result; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : self = contenu binaire à manipuler. * +* args = non utilisé ici. * +* * +* Description : Indique si une zone en contient une autre ou non. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_contains(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à faire remonter */ + int ret; /* Bilan de lecture des args. */ + PyObject *range_obj; /* Objet pour un intervale */ + mrange_t *range; /* Région mémoire de contenance*/ + mrange_t *sub; /* Région mémoire contenue ? */ + + ret = PyArg_ParseTuple(args, "O", &range_obj); + if (!ret) return NULL; + + ret = PyObject_IsInstance(range_obj, (PyObject *)get_python_mrange_type()); + if (!ret) return NULL; + + range = get_internal_mrange(self); + sub = get_internal_mrange(range_obj); + + result = (mrange_contains_mrange(range, sub) ? Py_True : Py_False); + + Py_INCREF(result); + + return result; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : self = définition de l'espace visé par la procédure. * +* closure = élément non utilisé ici. * +* * +* Description : Fournit la position de départ de la zone mémoire représentée.* +* * +* Retour : Nouvelle objet mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_get_addr(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + mrange_t *range; /* Espace mémoire à manipuler */ + + range = get_internal_mrange(self); + + result = build_from_internal_vmpa(get_mrange_addr(range)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition de l'espace visé par la procédure. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = élément non utilisé ici. * +* * +* Description : Définit la position de départ de la zone mémoire représentée.* +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_mrange_set_addr(PyObject *self, PyObject *value, void *closure) +{ + int result; /* Bilan à faire remonter */ + vmpa2t *addr; /* Localisation version C */ + mrange_t *range; /* Espace mémoire à manipuler */ + + result = 0; + + addr = get_internal_vmpa(value); + if (addr == NULL) return -1; + + range = get_internal_mrange(self); + + init_mrange(range, addr, get_mrange_length(range)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition de l'espace visé par la procédure. * +* closure = élément non utilisé ici. * +* * +* Description : Fournit la taille de la zone mémoire représentée. * +* * +* Retour : Nouvelle objet mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_get_length(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + mrange_t *range; /* Espace mémoire à manipuler */ + + range = get_internal_mrange(self); + + result = Py_BuildValue("K", get_mrange_length(range)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition de l'espace visé par la procédure. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = élément non utilisé ici. * +* * +* Description : Définit la taille de la zone mémoire représentée. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_mrange_set_length(PyObject *self, PyObject *value, void *closure) +{ + int result; /* Bilan à faire remonter */ + mrange_t *range; /* Espace mémoire à manipuler */ + PY_LONG_LONG val; /* Valeur traduite génériquemt */ + int overflow; /* Détection d'une grosse val. */ + vmpa2t tmp; /* Copie pour recopie */ + + result = 0; + + range = get_internal_mrange(self); + + val = PyLong_AsLongLongAndOverflow(value, &overflow); + + if (val == -1 && (overflow == 1 || PyErr_Occurred())) + { + result = -1; + PyErr_Clear(); + } + else + { + copy_vmpa(&tmp, get_mrange_addr(range)); + init_mrange(range, &tmp, val); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition de l'espace visé par la procédure. * +* closure = élément non utilisé ici. * +* * +* Description : Calcule la position extérieure finale d'une couverture. * +* * +* Retour : Nouvelle objet mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_get_end_addr(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + mrange_t *range; /* Espace mémoire à manipuler */ + vmpa2t end; /* Adresse à reproduire */ + + range = get_internal_mrange(self); + compute_mrange_end_addr(range, &end); + + result = build_from_internal_vmpa(&end); + + 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 'mrange'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_mrange_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + py_mrange_t *result; /* Instance à retourner */ + PyObject *py_vmpa; /* Localisation version Python */ + unsigned long long length; /* Taille physique */ + int ret; /* Bilan de lecture des args. */ + vmpa2t *addr; /* Localisation version C */ + + ret = PyArg_ParseTuple(args, "OK", &py_vmpa, &length); + if (!ret) return NULL; + + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + addr = get_internal_vmpa(py_vmpa); + if (addr == NULL) return NULL; + + result = (py_mrange_t *)type->tp_alloc(type, 0); + + init_mrange(&result->range, addr, length); + + return (PyObject *)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_mrange_type(void) +{ + static PyMethodDef py_mrange_methods[] = { + { "contains", py_mrange_contains, + METH_VARARGS, + "contains($self, other, /)\n--\nTell if the current range contains another given range or address." + }, +#if 0 + { "read_u8", py_arch_instruction_read_u8, + METH_VARARGS, + "read_u8($self, addr, /)\n--\n\nRead an unsigned byte from a given position." + }, +#endif + { NULL } + }; + + static PyGetSetDef py_mrange_getseters[] = { + { + "addr", py_mrange_get_addr, py_mrange_set_addr, + "Give access to the start location of the memory range.", NULL + }, + { + "length", py_mrange_get_length, py_mrange_set_length, + "Give access to the length of the memory range.", NULL + }, + { + "end", py_mrange_get_end_addr, NULL, + "Provide the final external point of the memory range.", NULL + }, + { NULL } + }; + + static PyTypeObject py_mrange_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.mrange", + .tp_basicsize = sizeof(py_mrange_t), + + .tp_str = py_mrange_to_str, + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "Python object for mrange_t.", + + .tp_richcompare = py_mrange_richcompare, + + .tp_methods = py_mrange_methods, + .tp_getset = py_mrange_getseters, + .tp_new = (newfunc)py_mrange_new + + }; + + return &py_mrange_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.mrange'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_mrange(PyObject *module) +{ + PyTypeObject *py_mrange_type; /* Type Python pour 'mrange' */ + int ret; /* Bilan d'un appel */ + + py_mrange_type = get_python_mrange_type(); + + if (PyType_Ready(py_mrange_type) != 0) + return false; + + Py_INCREF(py_mrange_type); + ret = PyModule_AddObject(module, "mrange", (PyObject *)py_mrange_type); + + return (ret == 0); + +} + + +/****************************************************************************** +* * +* Paramètres : obj = objet Python à traiter. * +* * +* Description : Donne accès au coeur d'un objet 'pychrysalide.arch.mrange'. * +* * +* Retour : Localistion réelle ou NULL en cas de mauvaise conversion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +mrange_t *get_internal_mrange(PyObject *obj) +{ + int ret; /* Bilan d'analyse */ + + ret = PyObject_IsInstance(obj, (PyObject *)get_python_mrange_type()); + if (!ret) return NULL; + + return &((py_mrange_t *)obj)->range; + +} + + +/****************************************************************************** +* * +* Paramètres : range = structure interne à copier en objet Python. * +* * +* Description : Convertit une structure de type 'mrange_t' en objet Python. * +* * +* Retour : Object Python résultant de la conversion opérée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *build_from_internal_mrange(const mrange_t *range) +{ + py_mrange_t *result; /* Instance à retourner */ + PyTypeObject *type; /* Type à instancier */ + + type = get_python_mrange_type(); + + result = (py_mrange_t *)type->tp_alloc(type, 0); + + copy_mrange(&result->range, range); + + return (PyObject *)result; + +} diff --git a/plugins/pychrysa/arch/vmpa.h b/plugins/pychrysa/arch/vmpa.h index 8635b51..6c51d3e 100644 --- a/plugins/pychrysa/arch/vmpa.h +++ b/plugins/pychrysa/arch/vmpa.h @@ -43,6 +43,26 @@ bool register_python_vmpa(PyObject *); /* Donne accès au coeur d'un objet 'pychrysalide.arch.vmpa'. */ vmpa2t *get_internal_vmpa(PyObject *); +/* Convertit une structure de type 'vmpa2t' en objet Python. */ +PyObject *build_from_internal_vmpa(const vmpa2t *); + + + +/* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_mrange_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.mrange'. */ +bool register_python_mrange(PyObject *); + +/* Donne accès au coeur d'un objet 'pychrysalide.arch.mrange'. */ +mrange_t *get_internal_mrange(PyObject *); + +/* Convertit une structure de type 'mrange_t' en objet Python. */ +PyObject *build_from_internal_mrange(const mrange_t *); + #endif /* _PLUGINS_PYCHRYSALIDE_ARCH_VMPA_H */ diff --git a/plugins/pychrysa/common/Makefile.am b/plugins/pychrysa/common/Makefile.am new file mode 100644 index 0000000..38d1697 --- /dev/null +++ b/plugins/pychrysa/common/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libpychrysacommon.la + +libpychrysacommon_la_SOURCES = \ + fnv1a.h fnv1a.c \ + module.h module.c + + +libpychrysacommon_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I../../../src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/pychrysa/common/fnv1a.c b/plugins/pychrysa/common/fnv1a.c new file mode 100644 index 0000000..2befcbe --- /dev/null +++ b/plugins/pychrysa/common/fnv1a.c @@ -0,0 +1,145 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * fnv1a.c - équivalent Python du fichier "common/fnv1a.c" + * + * 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 "fnv1a.h" + + +#include <pygobject.h> + + +#include <common/fnv1a.h> + + + +/* Détermine l'empreinte FNV1a d'une chaîne de caractères. */ +static PyObject *py_fnv1a_hash(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = NULL car méthode statique. * +* args = non utilisé ici. * +* * +* Description : Détermine l'empreinte FNV1a d'une chaîne de caractères. * +* * +* Retour : Numéro de révision. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_fnv1a_hash(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + const char *str; /* Chaîne à traiter. */ + int ret; /* Bilan de lecture des args. */ + fnv64_t value; /* Empreinte calculée */ + + ret = PyArg_ParseTuple(args, "s", &str); + if (!ret) Py_RETURN_NONE; + + value = fnv_64a_hash(str); + + result = Py_BuildValue("K", (unsigned long long)value); + + 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_fnv1a_type(void) +{ + static PyMethodDef py_fnv1a_methods[] = { + + { "hash", py_fnv1a_hash, + METH_VARARGS | METH_STATIC, + "hash(str, /)\n--\n\nCompute the FNV-1a hash from a given string." + }, + { NULL } + + }; + + static PyTypeObject py_fnv1a_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.core.fnv1a", + .tp_basicsize = sizeof(PyObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT, + + .tp_doc = "Python version for Chrysalide of the Fowler-Noll-Vo hash function.", + + .tp_methods = py_fnv1a_methods + + }; + + return &py_fnv1a_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.core.fnv1a'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_fnv1a(PyObject *module) +{ + PyTypeObject *py_fnv1a_type; /* Type Python pour 'fnv1a' */ + int ret; /* Bilan d'un appel */ + + py_fnv1a_type = get_python_fnv1a_type(); + + //py_fnv1a_type->tp_new = PyType_GenericNew; + + if (PyType_Ready(py_fnv1a_type) != 0) + return false; + + Py_INCREF(py_fnv1a_type); + ret = PyModule_AddObject(module, "fnv1a", (PyObject *)py_fnv1a_type); + + return (ret == 0); + +} diff --git a/plugins/pychrysa/common/fnv1a.h b/plugins/pychrysa/common/fnv1a.h new file mode 100644 index 0000000..535abf1 --- /dev/null +++ b/plugins/pychrysa/common/fnv1a.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * fnv1a.h - prototypes pour l'équivalent Python du fichier "common/fnv1a.c" + * + * 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_PYCHRYSALIDE_COMMON_FNV1A_H +#define _PLUGINS_PYCHRYSALIDE_COMMON_FNV1A_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_fnv1a_type(void); + +/* Prend en charge l'objet 'pychrysalide.common.fnv1a'. */ +bool register_python_fnv1a(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_COMMON_FNV1A_H */ diff --git a/plugins/pychrysa/common/module.c b/plugins/pychrysa/common/module.c new file mode 100644 index 0000000..bb4d47f --- /dev/null +++ b/plugins/pychrysa/common/module.c @@ -0,0 +1,91 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire common en tant que module + * + * 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 "module.h" + + +#include "fnv1a.h" + + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Ajoute le module 'common' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_common_module_to_python_module(PyObject *super) +{ + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ + int ret; /* Bilan d'un appel */ + + static PyModuleDef py_chrysalide_common_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.common", + .m_doc = "Python module for Chrysalide.common", + + .m_size = -1, + + }; + + result = false; + + module = PyModule_Create(&py_chrysalide_common_module); + if (module == NULL) return false; + + ret = PyState_AddModule(super, &py_chrysalide_common_module); + if (ret != 0) goto acmtpm_exit; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.common"); + if (ret != 0) goto acmtpm_exit; + + Py_INCREF(module); + ret = PyModule_AddObject(super, "common", module); + if (ret != 0) goto acmtpm_exit; + + result = true; + + result &= register_python_fnv1a(module); + + acmtpm_exit: + + if (!result) + { + printf("something went wrong in %s...\n", __FUNCTION__); + /* ... */ + + } + + return result; + +} diff --git a/plugins/pychrysa/common/module.h b/plugins/pychrysa/common/module.h new file mode 100644 index 0000000..f1c1aa6 --- /dev/null +++ b/plugins/pychrysa/common/module.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire common en tant que module + * + * 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_PYCHRYSALIDE_COMMON_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_COMMON_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'common' au module Python. */ +bool add_common_module_to_python_module(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_COMMON_MODULE_H */ diff --git a/plugins/pychrysa/core/module.c b/plugins/pychrysa/core/module.c index 489f173..a866c05 100644 --- a/plugins/pychrysa/core/module.c +++ b/plugins/pychrysa/core/module.c @@ -25,6 +25,9 @@ #include "module.h" +#include <assert.h> + + #include "params.h" @@ -64,27 +67,22 @@ bool add_core_module_to_python_module(PyObject *super) if (module == NULL) return false; ret = PyState_AddModule(super, &py_chrysalide_core_module); - if (ret != 0) goto acmtpm_exit; + if (ret != 0) goto loading_failed; ret = _PyImport_FixupBuiltin(module, "pychrysalide.core"); - if (ret != 0) goto acmtpm_exit; + if (ret != 0) goto loading_failed; Py_INCREF(module); ret = PyModule_AddObject(super, "core", module); - if (ret != 0) goto acmtpm_exit; + if (ret != 0) goto loading_failed; result = true; result &= register_python_params(module); - acmtpm_exit: - - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ + loading_failed: - } + assert(result); return result; diff --git a/plugins/pychrysa/core/params.c b/plugins/pychrysa/core/params.c index 987bca6..5029304 100644 --- a/plugins/pychrysa/core/params.c +++ b/plugins/pychrysa/core/params.c @@ -31,12 +31,15 @@ #include <core/params.h> +#include "../helpers.h" + + /* Fournit la version du programme global. */ static PyObject *py_params_get_main_configuration(PyObject *, PyObject *); /* Définit les constantes pour les paramètres. */ -static bool py_params_define_constants(PyObject *); +static bool py_params_define_constants(PyTypeObject *); @@ -114,7 +117,7 @@ PyTypeObject *get_python_params_type(void) /****************************************************************************** * * -* Paramètres : dict = dictionnaire à compléter. * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * * * * Description : Définit les constantes pour les paramètres. * * * @@ -124,21 +127,19 @@ PyTypeObject *get_python_params_type(void) * * ******************************************************************************/ -static bool py_params_define_constants(PyObject *dict) +static bool py_params_define_constants(PyTypeObject *obj_type) { - int ret; /* Bilan d'un ajout */ + bool result; /* Bilan à retourner */ -#define DEF_STR_CONST(name) \ - ret = PyDict_SetItemString(dict, #name, PyUnicode_FromString(name)); \ - if (ret == -1) return false; + result = true; - DEF_STR_CONST(MPK_LAST_PROJECT); - DEF_STR_CONST(MPK_ELLIPSIS_HEADER); - DEF_STR_CONST(MPK_ELLIPSIS_TAB); - DEF_STR_CONST(MPK_KEYBINDINGS_EDIT); - DEF_STR_CONST(MPK_AUTO_SAVE); + result &= PyDict_AddStringMacro(obj_type, MPK_LAST_PROJECT); + result &= PyDict_AddStringMacro(obj_type, MPK_ELLIPSIS_HEADER); + result &= PyDict_AddStringMacro(obj_type, MPK_ELLIPSIS_TAB); + result &= PyDict_AddStringMacro(obj_type, MPK_KEYBINDINGS_EDIT); + result &= PyDict_AddStringMacro(obj_type, MPK_AUTO_SAVE); - return true; + return result; } @@ -167,7 +168,7 @@ bool register_python_params(PyObject *module) if (PyType_Ready(py_params_type) != 0) return false; - if (!py_params_define_constants(py_params_type->tp_dict)) + if (!py_params_define_constants(py_params_type)) return false; Py_INCREF(py_params_type); 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 */ diff --git a/plugins/pychrysa/glibext/Makefile.am b/plugins/pychrysa/glibext/Makefile.am index 8383434..0a61da2 100644 --- a/plugins/pychrysa/glibext/Makefile.am +++ b/plugins/pychrysa/glibext/Makefile.am @@ -1,12 +1,10 @@ noinst_LTLIBRARIES = libpychrysaglibext.la -# libpychrysaglibext_la_SOURCES = \ -# bufferline.h bufferline.c \ -# codebuffer.h codebuffer.c \ -# module.h module.c - libpychrysaglibext_la_SOURCES = \ + bincontent.h bincontent.c \ + bufferline.h bufferline.c \ + codebuffer.h codebuffer.c \ configuration.h configuration.c \ module.h module.c diff --git a/plugins/pychrysa/glibext/bincontent.c b/plugins/pychrysa/glibext/bincontent.c new file mode 100644 index 0000000..5c9856e --- /dev/null +++ b/plugins/pychrysa/glibext/bincontent.c @@ -0,0 +1,267 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bincontent.c - prototypes pour l'équivalent Python du fichier "glibext/gbincontent.c" + * + * 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 "bincontent.h" + + +#include <pygobject.h> + + +#include <glibext/gbincontent.h> + + +#include "../arch/vmpa.h" + + +/* Crée un nouvel objet Python de type 'BinContent'. */ +static PyObject *py_binary_content_new(PyTypeObject *, PyObject *, PyObject *); + +/* Fournit une empreinte unique (SHA256) pour les données. */ +static PyObject *py_binary_content_get_checksum(PyObject *, PyObject *); + +/* Lit un nombre non signé sur un octet. */ +static PyObject *py_binary_content_read_u8(PyObject *, PyObject *); + + + + + + + + + + + + + + +/****************************************************************************** +* * +* 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 'BinContent'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Instance à retourner */ + const char *filename; /* Nom du fichier à charger */ + int ret; /* Bilan de lecture des args. */ + GBinContent *content; /* Version GLib du contenu */ + + ret = PyArg_ParseTuple(args, "s", &filename); + if (!ret) Py_RETURN_NONE; + + content = g_binary_content_new_from_file(filename); + + result = pygobject_new(G_OBJECT(content)); + g_object_unref(content); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = contenu binaire à manipuler. * +* args = non utilisé ici. * +* * +* Description : Fournit une empreinte unique (SHA256) pour les données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_content_get_checksum(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + GBinContent *content; /* Version GLib du format */ + const gchar *checksum; /* Empreinte fournie */ + + content = G_BIN_CONTENT(pygobject_get(self)); + + checksum = g_binary_content_get_cheksum(content); + + result = PyUnicode_FromString(checksum); + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = contenu binaire à manipuler. * +* args = non utilisé ici. * +* * +* Description : Lit un nombre non signé sur un octet. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + GBinContent *content; /* Version GLib du format */ + int ret; /* Bilan de lecture des args. */ + PyObject *addr_obj; /* Objet pour une position */ + vmpa2t *addr; /* Position interne associée */ + uint8_t val; /* Valeur lue à faire suivre */ + bool status; /* Bilan de l'opération */ + + content = G_BIN_CONTENT(pygobject_get(self)); + + printf("Passage\n"); + + ret = PyArg_ParseTuple(args, "O", &addr_obj); + + printf("ret == %d\n", ret); + + if (!ret) return NULL; + + addr = get_internal_vmpa(addr_obj); + if (addr == NULL) /* ... */; + + status = g_binary_content_read_u8(content, addr, /*SourceEndian endian*/0, &val); + if (!status) return NULL; + + printf("val :: 0x%02hhx\n", val); + + result = PyBytes_FromStringAndSize((char *)&val, 1);; + //Py_INCREF(result); + + return result; + +} + + + + + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_content_type(void) +{ + static PyMethodDef py_binary_content_methods[] = { + { "get_cheksum", py_binary_content_get_checksum, + METH_NOARGS, + "Compute a SHA256 hash as chechsum of handled data." + }, + { "read_u8", py_binary_content_read_u8, + METH_VARARGS, + "read_u8($self, addr, /)\n--\n\nRead an unsigned byte from a given position." + }, + { NULL } + }; + + static PyGetSetDef py_binary_content_getseters[] = { + { NULL } + }; + + static PyTypeObject py_binary_content_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.BinContent", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide binary content", + + .tp_methods = py_binary_content_methods, + .tp_getset = py_binary_content_getseters, + .tp_new = (newfunc)py_binary_content_new + + }; + + return &py_binary_content_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.BinContent'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_content(PyObject *module) +{ + PyTypeObject *py_binary_content_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_binary_content_type = get_python_binary_content_type(); + + py_binary_content_type->tp_base = &PyGObject_Type; + py_binary_content_type->tp_basicsize = py_binary_content_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_binary_content_type) != 0) + return false; + + Py_INCREF(py_binary_content_type); + ret = PyModule_AddObject(module, "BinContent", (PyObject *)py_binary_content_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BinContent", G_TYPE_BIN_CONTENT, py_binary_content_type, + Py_BuildValue("(O)", py_binary_content_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/analysis/roptions.h b/plugins/pychrysa/glibext/bincontent.h index 76ad2fe..b6ae9a5 100644 --- a/plugins/pychrysa/analysis/roptions.h +++ b/plugins/pychrysa/glibext/bincontent.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * roptions.h - prototypes pour l'équivalent Python du fichier "analysis/roptions.h" + * bincontent.h - prototypes pour l'équivalent Python du fichier "glibext/gbincontent.h" * - * Copyright (C) 2010-2012 Cyrille Bagard + * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * @@ -22,24 +22,21 @@ */ -#ifndef _PLUGINS_PYOIDA_ANALYSIS_ROPTIONS_H -#define _PLUGINS_PYOIDA_ANALYSIS_ROPTIONS_H +#ifndef _PLUGINS_PYCHRYSA_GLIBEXT_BINCONTENT_H +#define _PLUGINS_PYCHRYSA_GLIBEXT_BINCONTENT_H #include <Python.h> #include <stdbool.h> -#include <analysis/roptions.h> +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_content_type(void); +/* Prend en charge l'objet 'pychrysalide.glibext.BinContent'. */ +bool register_python_binary_content(PyObject *); -/* Fournit l'instance GLib d'une instance Python. */ -GRenderingOptions *py_rendering_options_get_glib_instance(PyObject *); -/* Ajoute l'objet 'analysis.roptions' au module Python. */ -bool add_analysis_roptions_to_python_module(PyObject *); - - -#endif /* _PLUGINS_PYOIDA_ANALYSIS_ROPTIONS_H */ +#endif /* _PLUGINS_PYCHRYSA_GLIBEXT_BINCONTENT_H */ diff --git a/plugins/pychrysa/glibext/bufferline.c b/plugins/pychrysa/glibext/bufferline.c index d5b8b13..ce85cfb 100644 --- a/plugins/pychrysa/glibext/bufferline.c +++ b/plugins/pychrysa/glibext/bufferline.c @@ -29,16 +29,35 @@ #include <pygobject.h> +#include <i18n.h> + + #include <glibext/gbufferline.h> -#include "../quirks.h" +#include "../helpers.h" +#include "../arch/vmpa.h" /* Reconstruit et fournit le texte présent sur une ligne tampon. */ static PyObject *py_buffer_line_get_text(PyObject *, PyObject *); +/* Ajoute une propriété particulière à une ligne donnée. */ +static PyObject *py_buffer_line_add_flag(PyObject *, PyObject *); + +/* Retire une propriété particulière à une ligne donnée. */ +static PyObject *py_buffer_line_remove_flag(PyObject *, PyObject *); + +/* Fournit l'emplacement où se situe un symbole. */ +static PyObject *py_buffer_line_get_range(PyObject *, void *); + +/* Renseigne sur les propriétés particulières liées à une ligne. */ +static PyObject *py_buffer_line_get_flags(PyObject *, void *); + +/* Définit les constantes pour les lignes de tampon. */ +static bool py_buffer_line_define_constants(PyTypeObject *); + /****************************************************************************** @@ -57,13 +76,26 @@ static PyObject *py_buffer_line_get_text(PyObject *, PyObject *); static PyObject *py_buffer_line_get_text(PyObject *self, PyObject *args) { PyObject *result; /* Trouvailles à retourner */ + BufferLineColumn first; /* Première colonne à parcourir*/ + BufferLineColumn end; /* Dernière colonne à parcourir*/ + int markup; /* Besoin de décorations ? */ + int ret; /* Bilan de lecture des args. */ GBufferLine *line; /* Version native */ char *text; /* Texte reconstruit à libérer */ + ret = PyArg_ParseTuple(args, "IIp", &first, &end, &markup); + if (!ret) return NULL; + + if (first >= BLC_COUNT || end >= BLC_COUNT) + { + PyErr_SetString(PyExc_ValueError, _("Invalid range in arguments")); + return NULL; + } + line = G_BUFFER_LINE(pygobject_get(self)); - text = "";//g_buffer_line_get_text(line); + text = g_buffer_line_get_text(line, first, end, markup); - result = PyString_FromString(text); + result = PyUnicode_FromString(text); free(text); @@ -74,60 +106,278 @@ static PyObject *py_buffer_line_get_text(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : self = classe représentant une ligne de tampon. * +* args = arguments fournis à l'appel. * * * -* Description : Prend en charge l'objet 'pychrysalide.glibext.BufferLine'. * +* Description : Ajoute une propriété particulière à une ligne donnée. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool register_python_buffer_line(PyObject *module) +static PyObject *py_buffer_line_add_flag(PyObject *self, PyObject *args) { - PyObject *pygobj_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ + BufferLineFlags flag; /* Drapeau à considérer */ + int ret; /* Bilan de lecture des args. */ + GBufferLine *line; /* Version native */ + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + if ((flag & ~BLF_ALL) != 0) + { + PyErr_SetString(PyExc_ValueError, _("Invalid flag")); + return NULL; + } + + line = G_BUFFER_LINE(pygobject_get(self)); + g_buffer_line_add_flag(line, flag); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une ligne de tampon. * +* args = arguments fournis à l'appel. * +* * +* Description : Retire une propriété particulière à une ligne donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_buffer_line_remove_flag(PyObject *self, PyObject *args) +{ + BufferLineFlags flag; /* Drapeau à considérer */ + int ret; /* Bilan de lecture des args. */ + GBufferLine *line; /* Version native */ + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + if ((flag & ~BLF_ALL) != 0) + { + PyErr_SetString(PyExc_ValueError, _("Invalid flag")); + return NULL; + } + + line = G_BUFFER_LINE(pygobject_get(self)); + g_buffer_line_remove_flag(line, flag); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la zone mémoire où se situe la ligne. * +* * +* Retour : Emplacement mémoire virtuel ou physique. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_buffer_line_get_range(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBufferLine *line; /* Elément à consulter */ + const mrange_t *range; /* Couverture courante */ + + line = G_BUFFER_LINE(pygobject_get(self)); + range = g_buffer_line_get_range(line); + + result = build_from_internal_mrange(range); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Renseigne sur les propriétés particulières liées à une ligne.* +* * +* Retour : Propriétés intégrées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_buffer_line_get_flags(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBufferLine *line; /* Elément à consulter */ + BufferLineFlags flags; /* Drapeaux à exporter */ + + line = G_BUFFER_LINE(pygobject_get(self)); + flags = g_buffer_line_get_flags(line); + + result = PyLong_FromLong(flags); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les lignes de tampon. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_buffer_line_define_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + result &= PyDict_AddIntMacro(obj_type, BLC_PHYSICAL); + result &= PyDict_AddIntMacro(obj_type, BLC_VIRTUAL); + result &= PyDict_AddIntMacro(obj_type, BLC_BINARY); + result &= PyDict_AddIntMacro(obj_type, BLC_ASSEMBLY_HEAD); + result &= PyDict_AddIntMacro(obj_type, BLC_ASSEMBLY); + result &= PyDict_AddIntMacro(obj_type, BLC_COMMENTS); + result &= PyDict_AddIntMacro(obj_type, BLC_COUNT); + result &= PyDict_AddIntMacro(obj_type, BLC_LAST_USED); + result &= PyDict_AddIntMacro(obj_type, BLC_INVALID); + result &= PyDict_AddIntMacro(obj_type, BLC_MAIN); + result &= PyDict_AddIntMacro(obj_type, BLC_FIRST); + result &= PyDict_AddIntMacro(obj_type, BLC_DISPLAY); + + result &= PyDict_AddIntMacro(obj_type, BLF_NONE); + result &= PyDict_AddIntMacro(obj_type, BLF_HAS_CODE); + result &= PyDict_AddIntMacro(obj_type, BLF_ENTRYPOINT); + result &= PyDict_AddIntMacro(obj_type, BLF_BOOKMARK); + + 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_buffer_line_type(void) +{ static PyMethodDef py_buffer_line_methods[] = { { - "get_text", (PyCFunction)py_buffer_line_get_text, - METH_NOARGS, - "Rebuild and provide the text of a buffer line." + "get_text", py_buffer_line_get_text, + METH_VARARGS, + "get_text($self, first_col, last_col, markup, /)\n--\n\nProvide the text of a buffer line." + }, + { + "add_flag", py_buffer_line_add_flag, + METH_VARARGS, + "add_flag($self, flag, /)\n--\n\nAdd a flag to the buffer line." + }, + { + "remove_flag", py_buffer_line_remove_flag, + METH_VARARGS, + "remove_flag($self, flag, /)\n--\n\nRemove a flag from the buffer line." + }, + { NULL } + }; + + static PyGetSetDef py_buffer_line_getseters[] = { + { + "range", py_buffer_line_get_range, NULL, + "Range covered by the line.", NULL + }, + { + "flags", py_buffer_line_get_flags, NULL, + "Current flags of the buffer line.", NULL }, { NULL } }; static PyTypeObject py_buffer_line_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.glibext.BufferLine", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide buffer line", - .tp_methods = py_buffer_line_methods + .tp_methods = py_buffer_line_methods, + .tp_getset = py_buffer_line_getseters, }; - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; + return &py_buffer_line_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.BufferLine'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - py_buffer_line_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); +bool register_python_buffer_line(PyObject *module) +{ + PyTypeObject *py_buffer_line_type; /* Type Python 'BufferLine' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_buffer_line_type = get_python_buffer_line_type(); + + py_buffer_line_type->tp_base = &PyGObject_Type; + py_buffer_line_type->tp_basicsize = py_buffer_line_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_buffer_line_type) != 0) + return false; - if (PyType_Ready(&py_buffer_line_type) < 0) + if (!py_buffer_line_define_constants(py_buffer_line_type)) return false; - Py_INCREF(&py_buffer_line_type); - ret = PyModule_AddObject(module, "BufferLine", (PyObject *)&py_buffer_line_type); + Py_INCREF(py_buffer_line_type); + ret = PyModule_AddObject(module, "BufferLine", (PyObject *)py_buffer_line_type); + if (ret != 0) return false; - pygobject_register_class(module, "GBufferLine", G_TYPE_BUFFER_LINE, &py_buffer_line_type, - Py_BuildValue("(O)", py_buffer_line_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BufferLine", G_TYPE_BUFFER_LINE, py_buffer_line_type, + Py_BuildValue("(O)", py_buffer_line_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/glibext/bufferline.h b/plugins/pychrysa/glibext/bufferline.h index 282a61a..e02b05f 100644 --- a/plugins/pychrysa/glibext/bufferline.h +++ b/plugins/pychrysa/glibext/bufferline.h @@ -31,6 +31,9 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_buffer_line_type(void); + /* Prend en charge l'objet 'pychrysalide.glibext.BufferLine'. */ bool register_python_buffer_line(PyObject *); diff --git a/plugins/pychrysa/glibext/codebuffer.c b/plugins/pychrysa/glibext/codebuffer.c index 6368ee7..9d9bc96 100644 --- a/plugins/pychrysa/glibext/codebuffer.c +++ b/plugins/pychrysa/glibext/codebuffer.c @@ -31,7 +31,7 @@ #include <glibext/gcodebuffer.h> -#include "../quirks.h" +#include "../arch/vmpa.h" @@ -56,15 +56,22 @@ static PyObject *py_code_buffer_find_line_by_addr(PyObject *, PyObject *); static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args) { PyObject *result; /* Trouvailles à retourner */ - GCodeBuffer *buffer; /* Version native */ - vmpa_t addr; /* Adresse visée par l'opérat° */ + PyObject *py_vmpa; /* Localisation version Python */ int ret; /* Bilan de lecture des args. */ + vmpa2t *addr; /* Adresse visée par l'opérat° */ + GCodeBuffer *buffer; /* Version native */ GBufferLine *line; /* Ligne trouvée */ - buffer = G_CODE_BUFFER(pygobject_get(self)); + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; - ret = PyArg_ParseTuple(args, "K", &addr); - if (!ret) Py_RETURN_NONE; + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + addr = get_internal_vmpa(py_vmpa); + if (addr == NULL) return NULL; + + buffer = G_CODE_BUFFER(pygobject_get(self)); line = g_code_buffer_find_line_by_addr(buffer, addr, 0, NULL); if (line == NULL) Py_RETURN_NONE; @@ -78,60 +85,86 @@ static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.glibext.Codebuffer'. * +* 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_code_buffer(PyObject *module) +PyTypeObject *get_python_code_buffer_type(void) { - PyObject *pygobj_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_code_buffer_methods[] = { { "find_line_by_addr", (PyCFunction)py_code_buffer_find_line_by_addr, METH_VARARGS, - "Find a buffer line with a given address." + "find_line_by_addr($self, addr, /)\n--\n\nFind a buffer line with a given address." }, { NULL } }; + static PyGetSetDef py_code_buffer_getseters[] = { + { NULL } + }; + static PyTypeObject py_code_buffer_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.glibext.CodeBuffer", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide code buffer", - .tp_methods = py_code_buffer_methods + .tp_methods = py_code_buffer_methods, + .tp_getset = py_code_buffer_getseters, }; - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; + return &py_code_buffer_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_code_buffer(PyObject *module) +{ + PyTypeObject *py_code_buffer_type; /* Type Python 'CodeBuffer' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_code_buffer_type = get_python_code_buffer_type(); - py_code_buffer_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); + py_code_buffer_type->tp_base = &PyGObject_Type; + py_code_buffer_type->tp_basicsize = py_code_buffer_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_code_buffer_type) < 0) + if (PyType_Ready(py_code_buffer_type) != 0) return false; - Py_INCREF(&py_code_buffer_type); - ret = PyModule_AddObject(module, "CodeBuffer", (PyObject *)&py_code_buffer_type); + Py_INCREF(py_code_buffer_type); + ret = PyModule_AddObject(module, "CodeBuffer", (PyObject *)py_code_buffer_type); + if (ret != 0) return false; - pygobject_register_class(module, "GCodeBuffer", G_TYPE_CODE_BUFFER, &py_code_buffer_type, - Py_BuildValue("(O)", py_code_buffer_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "CodeBuffer", G_TYPE_CODE_BUFFER, py_code_buffer_type, + Py_BuildValue("(O)", py_code_buffer_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/glibext/codebuffer.h b/plugins/pychrysa/glibext/codebuffer.h index e921e36..83ec508 100644 --- a/plugins/pychrysa/glibext/codebuffer.h +++ b/plugins/pychrysa/glibext/codebuffer.h @@ -31,6 +31,9 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_code_buffer_type(void); + /* Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. */ bool register_python_code_buffer(PyObject *); diff --git a/plugins/pychrysa/glibext/configuration.c b/plugins/pychrysa/glibext/configuration.c index 9820af3..fd35b19 100644 --- a/plugins/pychrysa/glibext/configuration.c +++ b/plugins/pychrysa/glibext/configuration.c @@ -67,15 +67,10 @@ static bool py_config_param_define_constants(PyObject *); /* ----------------------------- PARCOURS DE PARAMETRES ----------------------------- */ - +/* Parcours des éléments de configuration */ typedef struct _pyConfigParamIterator { - - PyObject_HEAD - long int m; - long int i; - - + PyObject_HEAD /* A laisser en premier */ GGenConfig *config; /* Configuration à parcourir */ GList *params; /* Liste de paramètres */ @@ -85,15 +80,10 @@ typedef struct _pyConfigParamIterator } pyConfigParamIterator; - - /* Prend acte d'un compteur de référence à 0. */ static void py_config_param_iterator_dealloc(PyObject *); /* Fournit un itérateur pour paramètres de configuration. */ -static PyObject *py_config_param_iterator_iter(PyObject *); - -/* Fournit un itérateur pour paramètres de configuration. */ static PyObject *py_config_param_iterator_next(PyObject *); /* Initialise un objet Python de type 'ConfigParamIterator'. */ @@ -646,28 +636,7 @@ static void py_config_param_iterator_dealloc(PyObject *self) g_generic_config_runlock(iterator->config); g_object_unref(G_OBJECT(iterator->config)); - Py_TYPE(self)->tp_free((PyObject*)self); - -} - - -/****************************************************************************** -* * -* Paramètres : self = itérateur à manipuler. * -* * -* Description : Fournit un itérateur pour paramètres de configuration. * -* * -* Retour : Instance Python prête à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_config_param_iterator_iter(PyObject *self) -{ - Py_INCREF(self); - - return self; + Py_TYPE(self)->tp_free((PyObject *)self); } @@ -700,7 +669,7 @@ static PyObject *py_config_param_iterator_next(PyObject *self) if (item != NULL) { result = pygobject_new(G_OBJECT(item->data)); - Py_XINCREF(result); + Py_INCREF(result); } else { @@ -782,7 +751,7 @@ PyTypeObject *get_python_config_param_iterator_type(void) .tp_doc = "Iterator for configuration parameters", - .tp_iter = py_config_param_iterator_iter, + .tp_iter = PyObject_SelfIter, .tp_iternext = py_config_param_iterator_next, .tp_init = py_config_param_iterator_init, @@ -816,7 +785,6 @@ bool register_python_config_param_iterator(PyObject *module) py_config_param_iterator_type = get_python_config_param_iterator_type(); py_config_param_iterator_type->tp_base = &PyBaseObject_Type; - py_config_param_iterator_type->tp_basicsize = py_config_param_iterator_type->tp_base->tp_basicsize; if (PyType_Ready(py_config_param_iterator_type) != 0) return false; @@ -1063,7 +1031,7 @@ static PyObject *py_generic_config_list_params(PyObject *self, PyObject *args) PyObject *args_list; /* Arguments de mise en place */ iterator_type = get_python_config_param_iterator_type(); - + Py_INCREF(self); args_list = Py_BuildValue("(O)", self); diff --git a/plugins/pychrysa/glibext/module.c b/plugins/pychrysa/glibext/module.c index 9f3d3a8..0cb96a7 100644 --- a/plugins/pychrysa/glibext/module.c +++ b/plugins/pychrysa/glibext/module.c @@ -25,6 +25,12 @@ #include "module.h" +#include <assert.h> + + +#include "bincontent.h" +#include "bufferline.h" +#include "codebuffer.h" #include "configuration.h" @@ -75,18 +81,16 @@ bool add_glibext_module_to_python_module(PyObject *super) result = true; + result &= register_python_binary_content(module); + result &= register_python_buffer_line(module); + result &= register_python_code_buffer(module); result &= register_python_config_param(module); result &= register_python_config_param_iterator(module); result &= register_python_generic_config(module); agmtpm_exit: - if (!result) - { - printf("something went wrong in %s...\n", __FUNCTION__); - /* ... */ - - } + assert(result); return result; diff --git a/plugins/pychrysa/gtkext/Makefile.am b/plugins/pychrysa/gtkext/Makefile.am index 4849c7b..958f000 100644 --- a/plugins/pychrysa/gtkext/Makefile.am +++ b/plugins/pychrysa/gtkext/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libpychrysagtkext.la libpychrysagtkext_la_SOURCES = \ blockview.h blockview.c \ + bufferview.h bufferview.c \ viewpanel.h viewpanel.c \ module.h module.c diff --git a/plugins/pychrysa/gtkext/blockview.c b/plugins/pychrysa/gtkext/blockview.c index e076e3c..973538b 100644 --- a/plugins/pychrysa/gtkext/blockview.c +++ b/plugins/pychrysa/gtkext/blockview.c @@ -31,66 +31,51 @@ #include <gtkext/gtkblockview.h> -#include "../quirks.h" - - - -/* Crée un nouvel objet Python de type 'ViewPanel'. */ -static PyObject *py_block_view_new(PyTypeObject *, PyObject *, PyObject *); +#include "bufferview.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 'ViewPanel'. * +* 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_block_view_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +PyTypeObject *get_python_block_view_type(void) { -#if 0 - PyObject *result; /* Instance à retourner */ - const char *name; /* Désignation humaine */ - const char *lname; /* Nom version longue */ - PyGObject *widget; /* Composant visuel du panneau */ - const char *path; /* Placement à l'affichage */ - int ret; /* Bilan de lecture des args. */ - GEditorItem *item; /* Version GLib du format */ - - ret = PyArg_ParseTuple(args, "ssOs", &name, &lname, &widget, &path); - if (!ret) Py_RETURN_NONE; - - item = g_block_view_new(get_internal_ref(), name, lname, - GTK_WIDGET(pygobject_get(widget)), path); - - result = py_block_view_from_c(G_BLOCK_VIEW(item)); - g_object_unref(item); - - return (PyObject *)result; -#endif - - /* FIXME */ - + static PyMethodDef py_block_view_methods[] = { + { NULL } + }; - Py_RETURN_NONE; + static PyGetSetDef py_block_view_getseters[] = { + { NULL } + }; -} + static PyTypeObject py_block_view_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "pychrysalide.gtkext.BlockView", + .tp_basicsize = sizeof(PyGObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "PyChrysalide block view.", + .tp_methods = py_block_view_methods, + .tp_getset = py_block_view_getseters + }; + return &py_block_view_type; +} /****************************************************************************** @@ -107,50 +92,26 @@ static PyObject *py_block_view_new(PyTypeObject *type, PyObject *args, PyObject bool register_python_block_view(PyObject *module) { - PyObject *parent_mod; /* Module Python-EditorItem */ + PyTypeObject *py_block_view_type; /* Type Python 'BlockView' */ int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ - static PyMethodDef py_block_view_methods[] = { - { NULL } - }; - - static PyGetSetDef py_block_view_getseters[] = { - { NULL } - }; - - static PyTypeObject py_block_view_type = { - - PyObject_HEAD_INIT(NULL) - - .tp_name = "pychrysalide.gtkext.BlockView", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyChrysalide view panel", - - .tp_methods = py_block_view_methods, - .tp_getset = py_block_view_getseters, - .tp_new = (newfunc)py_block_view_new, - .tp_init = (initproc)pychrysalide_allow_args_for_gobjects - - }; - - parent_mod = PyImport_ImportModule("pychrysalide.gtkext"); - if (parent_mod == NULL) return false; + py_block_view_type = get_python_block_view_type(); - py_block_view_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "ViewPanel"); - Py_DECREF(parent_mod); + py_block_view_type->tp_base = get_python_buffer_view_type(); + py_block_view_type->tp_basicsize = py_block_view_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_block_view_type) < 0) + if (PyType_Ready(py_block_view_type) != 0) return false; - Py_INCREF(&py_block_view_type); - ret = PyModule_AddObject(module, "BlockView", (PyObject *)&py_block_view_type); + Py_INCREF(py_block_view_type); + ret = PyModule_AddObject(module, "BlockView", (PyObject *)py_block_view_type); + if (ret != 0) return false; - pygobject_register_class(module, "GtkBlockView", GTK_TYPE_BLOCK_VIEW, &py_block_view_type, - Py_BuildValue("(O)", py_block_view_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "BlockView", GTK_TYPE_BLOCK_VIEW, py_block_view_type, + Py_BuildValue("(O)", py_block_view_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/gtkext/blockview.h b/plugins/pychrysa/gtkext/blockview.h index a6cf3a0..1735ac3 100644 --- a/plugins/pychrysa/gtkext/blockview.h +++ b/plugins/pychrysa/gtkext/blockview.h @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_PYCHRYSA_GTKEXT_MODULE_BLOCK_VIEW_H -#define _PLUGINS_PYCHRYSA_GTKEXT_MODULE_BLOCK_VIEW_H +#ifndef _PLUGINS_PYCHRYSA_GTKEXT_BLOCKVIEW_H +#define _PLUGINS_PYCHRYSA_GTKEXT_BLOCKVIEW_H #include <Python.h> @@ -31,9 +31,12 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_block_view_type(void); + /* Prend en charge l'objet 'pychrysalide.gtkext.BlockView'. */ bool register_python_block_view(PyObject *module); -#endif /* _PLUGINS_PYCHRYSA_GTKEXT_MODULE_BLOCK_VIEW_H */ +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BLOCKVIEW_H */ diff --git a/plugins/pychrysa/gtkext/bufferview.c b/plugins/pychrysa/gtkext/bufferview.c new file mode 100644 index 0000000..a8b86e8 --- /dev/null +++ b/plugins/pychrysa/gtkext/bufferview.c @@ -0,0 +1,117 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferview.c - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferview.c" + * + * Copyright (C) 2012 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 "bufferview.h" + + +#include <pygobject.h> + + +#include <gtkext/gtkbufferview.h> + + +#include "viewpanel.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_buffer_view_type(void) +{ + static PyMethodDef py_buffer_view_methods[] = { + { NULL } + }; + + static PyGetSetDef py_buffer_view_getseters[] = { + { NULL } + }; + + static PyTypeObject py_buffer_view_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.gtkext.Bufferview", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide buffer view.", + + .tp_methods = py_buffer_view_methods, + .tp_getset = py_buffer_view_getseters + + }; + + return &py_buffer_view_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gtkext.Bufferview'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_buffer_view(PyObject *module) +{ + PyTypeObject *py_buffer_view_type; /* Type Python 'Bufferview' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_buffer_view_type = get_python_buffer_view_type(); + + py_buffer_view_type->tp_base = get_python_view_panel_type(); + py_buffer_view_type->tp_basicsize = py_buffer_view_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_buffer_view_type) != 0) + return false; + + Py_INCREF(py_buffer_view_type); + ret = PyModule_AddObject(module, "Bufferview", (PyObject *)py_buffer_view_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "Bufferview", GTK_TYPE_BUFFER_VIEW, py_buffer_view_type, + Py_BuildValue("(O)", py_buffer_view_type->tp_base)); + + return true; + +} diff --git a/plugins/pychrysa/gtkext/bufferview.h b/plugins/pychrysa/gtkext/bufferview.h new file mode 100644 index 0000000..7ef9995 --- /dev/null +++ b/plugins/pychrysa/gtkext/bufferview.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bufferview.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkbufferview.h" + * + * Copyright (C) 2012 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_GTKEXT_BUFFERVIEW_H +#define _PLUGINS_PYCHRYSA_GTKEXT_BUFFERVIEW_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_buffer_view_type(void); + +/* Prend en charge l'objet 'pychrysalide.gtkext.Bufferview'. */ +bool register_python_buffer_view(PyObject *module); + + + +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_BUFFERVIEW_H */ diff --git a/plugins/pychrysa/gtkext/module.c b/plugins/pychrysa/gtkext/module.c index ef006e2..507b3cb 100644 --- a/plugins/pychrysa/gtkext/module.c +++ b/plugins/pychrysa/gtkext/module.c @@ -25,7 +25,11 @@ #include "module.h" +#include <assert.h> + + #include "blockview.h" +#include "bufferview.h" #include "viewpanel.h" @@ -44,25 +48,46 @@ bool add_gtkext_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_gtkext_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_gtkext_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.gtkext", + .m_doc = "Python module for Chrysalide.gtkext", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.gtkext", py_gtkext_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_gtkext_module); if (module == NULL) return false; + ret = PyState_AddModule(super, &py_chrysalide_gtkext_module); + if (ret != 0) goto agmtpm_exit; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.gtkext"); + if (ret != 0) goto agmtpm_exit; + Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.gtkext", module); + ret = PyModule_AddObject(super, "gtkext", module); + if (ret != 0) goto agmtpm_exit; - result = (ret == 0); + result = true; result &= register_python_view_panel(module); + result &= register_python_buffer_view(module); result &= register_python_block_view(module); + agmtpm_exit: + + assert(result); + return result; } diff --git a/plugins/pychrysa/gtkext/viewpanel.c b/plugins/pychrysa/gtkext/viewpanel.c index f680487..8c85fbd 100644 --- a/plugins/pychrysa/gtkext/viewpanel.c +++ b/plugins/pychrysa/gtkext/viewpanel.c @@ -31,16 +31,22 @@ #include <gtkext/gtkviewpanel.h> -#include "../quirks.h" +#include "../helpers.h" +#include "../arch/vmpa.h" /* Crée un nouvel objet Python de type 'ViewPanel'. */ +#if 0 static PyObject *py_view_panel_new(PyTypeObject *, PyObject *, PyObject *); +#endif /* S'assure qu'une adresse donnée est visible à l'écran. */ static PyObject *py_view_panel_scroll_to_address(PyObject *, PyObject *); +/* Définit les constantes pour les panneaux de vue. */ +static bool py_view_panel_define_constants(PyTypeObject *); + /****************************************************************************** @@ -56,7 +62,7 @@ static PyObject *py_view_panel_scroll_to_address(PyObject *, PyObject *); * Remarques : - * * * ******************************************************************************/ - +#if 0 static PyObject *py_view_panel_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { #if 0 @@ -86,10 +92,7 @@ static PyObject *py_view_panel_new(PyTypeObject *type, PyObject *args, PyObject Py_RETURN_NONE; } - - - - +#endif /****************************************************************************** @@ -108,47 +111,75 @@ static PyObject *py_view_panel_new(PyTypeObject *type, PyObject *args, PyObject static PyObject *py_view_panel_scroll_to_address(PyObject *self, PyObject *args) { GtkViewPanel *panel; /* Panneau à manipuler */ - vmpa_t addr; /* Adresse demandée en visuel */ + PyObject *py_vmpa; /* Localisation version Python */ int ret; /* Bilan de lecture des args. */ + vmpa2t *addr; /* Adresse visée par l'opérat° */ - panel = GTK_VIEW_PANEL(pygobject_get(self)); + ret = PyArg_ParseTuple(args, "O", &py_vmpa); + if (!ret) return NULL; - ret = PyArg_ParseTuple(args, "K", &addr); - if (!ret) Py_RETURN_NONE; + ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type()); + if (!ret) return NULL; + + addr = get_internal_vmpa(py_vmpa); + if (addr == NULL) return NULL; + + panel = GTK_VIEW_PANEL(pygobject_get(self)); - //gtk_view_panel_scroll_to_address(panel, addr); + gtk_view_panel_scroll_to_address(panel, addr, SPT_RAW); Py_RETURN_NONE; } +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les panneaux de vue. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_view_panel_define_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + result = true; + result &= PyDict_AddIntMacro(obj_type, SPT_RAW); + result &= PyDict_AddIntMacro(obj_type, SPT_TOP); + result &= PyDict_AddIntMacro(obj_type, SPT_CENTER); + result &= PyDict_AddIntMacro(obj_type, SPT_BOTTOM); + + return result; + +} /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.gtkext.ViewPanel'. * +* 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_view_panel(PyObject *module) +PyTypeObject *get_python_view_panel_type(void) { - PyObject *parent_mod; /* Module Python-EditorItem */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_view_panel_methods[] = { { "scroll_to_address", (PyCFunction)py_view_panel_scroll_to_address, METH_VARARGS, - "Ensure a given address is displayed in the view panel." + "scroll_to_address($self, addr, tweak, /)\n--\n\nEnsure a given address is displayed in the view panel." }, { NULL } }; @@ -159,37 +190,70 @@ bool register_python_view_panel(PyObject *module) static PyTypeObject py_view_panel_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.gtkext.ViewPanel", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide view panel", + .tp_doc = "PyChrysalide view panel.", .tp_methods = py_view_panel_methods, .tp_getset = py_view_panel_getseters, - .tp_new = (newfunc)py_view_panel_new, - .tp_init = (initproc)pychrysalide_allow_args_for_gobjects + //.tp_new = (newfunc)py_view_panel_new, + //.tp_init = (initproc)pychrysalide_allow_args_for_gobjects }; - parent_mod = PyImport_ImportModule("gtk"); + return &py_view_panel_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gtkext.ViewPanel'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_view_panel(PyObject *module) +{ + PyTypeObject *py_view_panel_type; /* Type Python 'ViewPanel' */ + PyObject *parent_mod; /* Module Python Fixed */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_view_panel_type = get_python_view_panel_type(); + + parent_mod = PyImport_ImportModule("gi.repository.Gtk"); if (parent_mod == NULL) return false; - py_view_panel_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "Fixed"); + py_view_panel_type->tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "Fixed"); Py_DECREF(parent_mod); - if (PyType_Ready(&py_view_panel_type) < 0) + py_view_panel_type->tp_basicsize = py_view_panel_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_view_panel_type) != 0) + return false; + + if (!py_view_panel_define_constants(py_view_panel_type)) return false; - Py_INCREF(&py_view_panel_type); - ret = PyModule_AddObject(module, "ViewPanel", (PyObject *)&py_view_panel_type); + Py_INCREF(py_view_panel_type); + ret = PyModule_AddObject(module, "ViewPanel", (PyObject *)py_view_panel_type); + if (ret != 0) return false; - pygobject_register_class(module, "GtkViewPanel", GTK_TYPE_VIEW_PANEL, &py_view_panel_type, - Py_BuildValue("(O)", py_view_panel_type.tp_base)); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "ViewPanel", GTK_TYPE_VIEW_PANEL, py_view_panel_type, + Py_BuildValue("(O)", py_view_panel_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/gtkext/viewpanel.h b/plugins/pychrysa/gtkext/viewpanel.h index 175546b..7a349f8 100644 --- a/plugins/pychrysa/gtkext/viewpanel.h +++ b/plugins/pychrysa/gtkext/viewpanel.h @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_PYCHRYSA_GTKEXT_MODULE_VIEW_PANEL_H -#define _PLUGINS_PYCHRYSA_GTKEXT_MODULE_VIEW_PANEL_H +#ifndef _PLUGINS_PYCHRYSA_GTKEXT_VIEWPANEL_H +#define _PLUGINS_PYCHRYSA_GTKEXT_VIEWPANEL_H #include <Python.h> @@ -31,9 +31,12 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_view_panel_type(void); + /* Prend en charge l'objet 'pychrysalide.gtkext.ViewPanel'. */ bool register_python_view_panel(PyObject *module); -#endif /* _PLUGINS_PYCHRYSA_GTKEXT_MODULE_VIEW_PANEL_H */ +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_VIEWPANEL_H */ diff --git a/plugins/pychrysa/gui/editem.c b/plugins/pychrysa/gui/editem.c index 7a40a04..6db03ce 100644 --- a/plugins/pychrysa/gui/editem.c +++ b/plugins/pychrysa/gui/editem.c @@ -90,7 +90,7 @@ static void _update_editor_item_for_binary_python_wrapper(GEditorItem *item, GLo * des éléments d'éditeur, via py_editor_item_register(), donc son compteur * de références doit le maintenir en vie. * - * On peut donc le récupérer directement depuis l'instane GLib, sans passer + * On peut donc le récupérer directement depuis l'instance GLib, sans passer * par la procédure de pygobject, qui obligerait à connaître le type précis * de l'instance GLib manipulée. */ @@ -355,21 +355,18 @@ static PyObject *py_editor_item_register(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.gui.EditorItem'. * +* 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_editor_item(PyObject *module) +PyTypeObject *get_python_editor_item_type(void) { - PyObject *parent_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_editor_item_methods[] = { { "update_for_binary", (PyCFunction)py_editor_item_update_for_binary, @@ -387,19 +384,19 @@ bool register_python_editor_item(PyObject *module) "Called by Chrysalide on each view content change, if the item is registered." }, { - "get_current_binary", (PyCFunction)py_editor_item_get_current_binary, + "get_current_binary()", (PyCFunction)py_editor_item_get_current_binary, METH_NOARGS, - "Provide the current binary." + "get_current_binary($self, /)\n--\n\nProvide the current binary." }, { "get_current_view", (PyCFunction)py_editor_item_get_current_view, METH_NOARGS, - "Provide the current binary view." + "get_current_view($self, /)\n--\n\nProvide the current binary view." }, { "register", (PyCFunction)py_editor_item_register, METH_NOARGS, - "Register the item as editor item." + "register($self, /)\n--\n\nRegister the item as editor item." }, { NULL } }; @@ -410,32 +407,58 @@ bool register_python_editor_item(PyObject *module) static PyTypeObject py_editor_item_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.gui.EditorItem", - .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = "PyChrysalide editor item", .tp_methods = py_editor_item_methods, - .tp_getset = py_editor_item_getseters + .tp_getset = py_editor_item_getseters, }; - parent_mod = PyImport_ImportModule("gobject"); - if (parent_mod == NULL) return false; + return &py_editor_item_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gui.EditorItem'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_editor_item(PyObject *module) +{ + PyTypeObject *py_editor_item_type; /* Type Python 'LoadedBinary' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_editor_item_type = get_python_editor_item_type(); - py_editor_item_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "GObject"); - Py_DECREF(parent_mod); + py_editor_item_type->tp_base = &PyGObject_Type; + py_editor_item_type->tp_basicsize = py_editor_item_type->tp_base->tp_basicsize; - if (PyType_Ready(&py_editor_item_type) < 0) + if (PyType_Ready(py_editor_item_type) != 0) return false; - Py_INCREF(&py_editor_item_type); - ret = PyModule_AddObject(module, "EditorItem", (PyObject *)&py_editor_item_type); + Py_INCREF(py_editor_item_type); + ret = PyModule_AddObject(module, "EditorItem", (PyObject *)py_editor_item_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "EditorItem", G_TYPE_EDITOR_ITEM, py_editor_item_type, + Py_BuildValue("(O)", py_editor_item_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/gui/editem.h b/plugins/pychrysa/gui/editem.h index 197efd5..329a79e 100644 --- a/plugins/pychrysa/gui/editem.h +++ b/plugins/pychrysa/gui/editem.h @@ -31,8 +31,11 @@ +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_editor_item_type(void); + /* Prend en charge l'objet 'pychrysalide.gui.EditorItem'. */ -bool register_python_editor_item(PyObject *module); +bool register_python_editor_item(PyObject *); diff --git a/plugins/pychrysa/gui/module.c b/plugins/pychrysa/gui/module.c index 605877f..0c5403e 100644 --- a/plugins/pychrysa/gui/module.c +++ b/plugins/pychrysa/gui/module.c @@ -25,6 +25,10 @@ #include "module.h" +#include <assert.h> + + + #include "editem.h" #include "panels/module.h" @@ -44,27 +48,46 @@ bool add_gui_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_gui_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_gui_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.gui", + .m_doc = "Python module for the Chrysalide GUI", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.gui", py_gui_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_gui_module); if (module == NULL) return false; - Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.gui", module); + ret = PyState_AddModule(super, &py_chrysalide_gui_module); + if (ret != 0) goto loading_failed; - result = (ret == 0); + ret = _PyImport_FixupBuiltin(module, "pychrysalide.gui"); + if (ret != 0) goto loading_failed; + + Py_INCREF(module); + ret = PyModule_AddObject(super, "gui", module); + if (ret != 0) goto loading_failed; - if (ret != 0) /* ... */; + result = true; result &= register_python_editor_item(module); + result &= add_gui_panels_module_to_python_module(module); - return true; + loading_failed: + + assert(result); + + return result; } diff --git a/plugins/pychrysa/gui/panels/log.c b/plugins/pychrysa/gui/panels/log.c index 00f4e9e..ba68fe9 100644 --- a/plugins/pychrysa/gui/panels/log.c +++ b/plugins/pychrysa/gui/panels/log.c @@ -25,11 +25,14 @@ #include "log.h" - #include <pygobject.h> -#include "../../quirks.h" +#include <gui/panels/log.h> + + +#include "panel.h" +#include "../../helpers.h" @@ -37,7 +40,7 @@ static PyObject *py_log_panel_log_message(PyObject *, PyObject *); /* Définit les constantes pour les types de message. */ -static bool define_python_log_constants(PyObject *); +static bool define_python_log_constants(PyTypeObject *); @@ -90,7 +93,7 @@ static PyObject *py_log_panel_log_message(PyObject *self, PyObject *args) /****************************************************************************** * * -* Paramètres : dict = dictionnaire à compléter. * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * * * * Description : Définit les constantes pour les types de message. * * * @@ -100,52 +103,42 @@ static PyObject *py_log_panel_log_message(PyObject *self, PyObject *args) * * ******************************************************************************/ -static bool define_python_log_constants(PyObject *dict) +static bool define_python_log_constants(PyTypeObject *obj_type) { - int ret; /* Bilan d'un ajout */ - - ret = PyDict_SetItemString(dict, "LMT_INFO", PyInt_FromLong(LMT_INFO)); - if (ret == -1) return false; - - ret = PyDict_SetItemString(dict, "LMT_BAD_BINARY", PyInt_FromLong(LMT_BAD_BINARY)); - if (ret == -1) return false; + bool result; /* Bilan à retourner */ - ret = PyDict_SetItemString(dict, "LMT_PROCESS", PyInt_FromLong(LMT_PROCESS)); - if (ret == -1) return false; + result = true; - ret = PyDict_SetItemString(dict, "LMT_ERROR", PyInt_FromLong(LMT_ERROR)); - if (ret == -1) return false; + result &= PyDict_AddIntMacro(obj_type, LMT_INFO); + result &= PyDict_AddIntMacro(obj_type, LMT_BAD_BINARY); + result &= PyDict_AddIntMacro(obj_type, LMT_PROCESS); + result &= PyDict_AddIntMacro(obj_type, LMT_ERROR); + result &= PyDict_AddIntMacro(obj_type, LMT_WARNING); - ret = PyDict_SetItemString(dict, "LMT_WARNING", PyInt_FromLong(LMT_WARNING)); - if (ret == -1) return false; - - return true; + return result; } /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.gui.panels.LogPanel'. * +* 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_log_panel(PyObject *module) +PyTypeObject *get_python_log_panel_type(void) { - //PyObject *parent_mod; /* Module Python-EditorItem */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_log_panel_methods[] = { { "log_message", (PyCFunction)py_log_panel_log_message, METH_VARARGS | METH_STATIC, - "Display a message in the log window." + "log_message(type, msg, /)\n--\n\nDisplay a message in the log window, if any." }, { NULL } }; @@ -156,35 +149,62 @@ bool register_python_log_panel(PyObject *module) static PyTypeObject py_log_panel_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.gui.panels.LogPanel", - .tp_basicsize = sizeof(PyObject), + .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "PyChrysalide log panel", .tp_methods = py_log_panel_methods, - .tp_getset = py_log_panel_getseters, + .tp_getset = py_log_panel_getseters }; - /* - parent_mod = PyImport_ImportModule("pychrysalide.gui.panels"); - if (parent_mod == NULL) return false; - - py_log_panel_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "PanelItem"); - Py_DECREF(parent_mod); - */ - if (PyType_Ready(&py_log_panel_type) < 0) + + return &py_log_panel_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gui.panels.LogPanel'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_log_panel(PyObject *module) +{ + PyTypeObject *py_log_panel_type; /* Type Python 'LoadedBinary' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_log_panel_type = get_python_log_panel_type(); + + py_log_panel_type->tp_base = get_python_panel_item_type(); + py_log_panel_type->tp_basicsize = py_log_panel_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_log_panel_type) != 0) return false; - if (!define_python_log_constants(py_log_panel_type.tp_dict)) + if (!define_python_log_constants(py_log_panel_type)) return false; - Py_INCREF(&py_log_panel_type); - ret = PyModule_AddObject(module, "LogPanel", (PyObject *)&py_log_panel_type); + Py_INCREF(py_log_panel_type); + ret = PyModule_AddObject(module, "LogPanel", (PyObject *)py_log_panel_type); + if (ret != 0) return false; - return (ret == 0); + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "LogPanel", G_TYPE_LOG_PANEL, py_log_panel_type, + Py_BuildValue("(O)", py_log_panel_type->tp_base)); + + return true; } diff --git a/plugins/pychrysa/gui/panels/log.h b/plugins/pychrysa/gui/panels/log.h index 08b1ae2..9b67e5a 100644 --- a/plugins/pychrysa/gui/panels/log.h +++ b/plugins/pychrysa/gui/panels/log.h @@ -29,12 +29,13 @@ #include <Python.h> #include <stdbool.h> -#include <gui/panels/log.h> +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_log_panel_type(void); /* Prend en charge l'objet 'pychrysalide.gui.panels.LogPanel'. */ -bool register_python_log_panel(PyObject *module); +bool register_python_log_panel(PyObject *); diff --git a/plugins/pychrysa/gui/panels/module.c b/plugins/pychrysa/gui/panels/module.c index bd13cd9..ca8845d 100644 --- a/plugins/pychrysa/gui/panels/module.c +++ b/plugins/pychrysa/gui/panels/module.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * module.c - intégration du répertoire arch en tant que module + * module.c - intégration du répertoire panels en tant que module * * Copyright (C) 2012-2013 Cyrille Bagard * @@ -25,6 +25,9 @@ #include "module.h" +#include <assert.h> + + #include "log.h" #include "panel.h" @@ -44,27 +47,45 @@ bool add_gui_panels_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_gui_panels_methods[] = { - { NULL } + static PyModuleDef py_chrysalide_panels_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "gui.analysis.panels", + .m_doc = "Python module for Chrysalide.gui.panels", + + .m_size = -1, + }; - module = Py_InitModule("pychrysalide.gui.panels", py_gui_panels_methods); + result = false; + + module = PyModule_Create(&py_chrysalide_panels_module); if (module == NULL) return false; - Py_INCREF(module); - ret = PyModule_AddObject(super, "pychrysalide.gui.panels", module); + ret = PyState_AddModule(super, &py_chrysalide_panels_module); + if (ret != 0) goto loading_failed; + + ret = _PyImport_FixupBuiltin(module, "pychrysalide.gui.panels"); + if (ret != 0) goto loading_failed; - result = (ret == 0); + Py_INCREF(module); + ret = PyModule_AddObject(super, "panels", module); + if (ret != 0) goto loading_failed; - if (ret != 0) /* ... */; + result = true; result &= register_python_panel_item(module); result &= register_python_log_panel(module); - return true; + loading_failed: + + assert(result); + + return result; } diff --git a/plugins/pychrysa/gui/panels/module.h b/plugins/pychrysa/gui/panels/module.h index c75a475..15d46a5 100644 --- a/plugins/pychrysa/gui/panels/module.h +++ b/plugins/pychrysa/gui/panels/module.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * module.h - prototypes pour l'intégration du répertoire gui.panels en tant que module + * module.h - prototypes pour l'intégration du répertoire panels en tant que module * * Copyright (C) 2012 Cyrille Bagard * diff --git a/plugins/pychrysa/gui/panels/panel.c b/plugins/pychrysa/gui/panels/panel.c index 826982f..e713cc0 100644 --- a/plugins/pychrysa/gui/panels/panel.c +++ b/plugins/pychrysa/gui/panels/panel.c @@ -28,18 +28,24 @@ #include <pygobject.h> -#include "../../quirks.h" +#include <gui/panels/panel.h> + + +#include "../editem.h" /* Crée un nouvel objet Python de type 'PanelItem'. */ +#if 0 static PyObject *py_panel_item_new(PyTypeObject *, PyObject *, PyObject *); +#endif /* Place un panneau dans l'ensemble affiché. */ static PyObject *py_panel_item_dock(PyObject *, PyObject *); +#if 0 /****************************************************************************** * * * Paramètres : type = type de l'objet à instancier. * @@ -110,6 +116,7 @@ PyObject *_py_panel_item_from_c(GPanelItem *item, PyTypeObject *type) return pygobject_new(G_OBJECT(item)); } +#endif /****************************************************************************** @@ -138,40 +145,25 @@ static PyObject *py_panel_item_dock(PyObject *self, PyObject *args) } - - - - - - - - - - - - /****************************************************************************** * * -* Paramètres : module = module dont la définition est à compléter. * +* Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide.gui.panels.PanelItem'. * +* 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_panel_item(PyObject *module) +PyTypeObject *get_python_panel_item_type(void) { - PyObject *parent_mod; /* Module Python-EditorItem */ - int ret; /* Bilan d'un appel */ - static PyMethodDef py_panel_item_methods[] = { { "dock", (PyCFunction)py_panel_item_dock, METH_NOARGS, - "Display the panel item in the right place." + "dock($self, /)\n--\n\nDisplay the panel item in the right place." }, { NULL } }; @@ -182,34 +174,61 @@ bool register_python_panel_item(PyObject *module) static PyTypeObject py_panel_item_type = { - PyObject_HEAD_INIT(NULL) + PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.gui.panels.PanelItem", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide panel item", + .tp_doc = "PyChrysalide panel item.", .tp_methods = py_panel_item_methods, .tp_getset = py_panel_item_getseters, - .tp_new = (newfunc)py_panel_item_new, - .tp_init = (initproc)pychrysalide_allow_args_for_gobjects + //.tp_new = (newfunc)py_panel_item_new, + //.tp_init = (initproc)pychrysalide_allow_args_for_gobjects }; - parent_mod = PyImport_ImportModule("pychrysalide.gui"); - if (parent_mod == NULL) return false; + return &py_panel_item_type; - py_panel_item_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(parent_mod, "EditorItem"); - Py_DECREF(parent_mod); +} - if (PyType_Ready(&py_panel_item_type) < 0) + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gui.panels.PanelItem'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_panel_item(PyObject *module) +{ + PyTypeObject *py_panel_item_type; /* Type Python 'LoadedBinary' */ + int ret; /* Bilan d'un appel */ + PyObject *dict; /* Dictionnaire du module */ + + py_panel_item_type = get_python_panel_item_type(); + + py_panel_item_type->tp_base = get_python_editor_item_type(); + py_panel_item_type->tp_basicsize = py_panel_item_type->tp_base->tp_basicsize; + + if (PyType_Ready(py_panel_item_type) != 0) return false; - Py_INCREF(&py_panel_item_type); - ret = PyModule_AddObject(module, "PanelItem", (PyObject *)&py_panel_item_type); + Py_INCREF(py_panel_item_type); + ret = PyModule_AddObject(module, "PanelItem", (PyObject *)py_panel_item_type); + if (ret != 0) return false; + + dict = PyModule_GetDict(module); + pygobject_register_class(dict, "PanelItem", G_TYPE_PANEL_ITEM, py_panel_item_type, + Py_BuildValue("(O)", py_panel_item_type->tp_base)); - return (ret == 0); + return true; } diff --git a/plugins/pychrysa/gui/panels/panel.h b/plugins/pychrysa/gui/panels/panel.h index 4c678b1..ecbee78 100644 --- a/plugins/pychrysa/gui/panels/panel.h +++ b/plugins/pychrysa/gui/panels/panel.h @@ -29,17 +29,13 @@ #include <Python.h> #include <stdbool.h> -#include <gui/panels/panel.h> - -/* Crée un nouvel objet Python de type 'PanelItem'. */ -PyObject *_py_panel_item_from_c(GPanelItem *, PyTypeObject *); - -#define py_panel_item_from_c(item) _py_panel_item_from_c(item, NULL) +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_panel_item_type(void); /* Prend en charge l'objet 'pychrysalide.gui.panels.PanelItem'. */ -bool register_python_panel_item(PyObject *module); +bool register_python_panel_item(PyObject *); diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c index e2fc13a..d344a7f 100644 --- a/plugins/pychrysa/helpers.c +++ b/plugins/pychrysa/helpers.c @@ -27,6 +27,37 @@ /****************************************************************************** * * +* Paramètres : func = fonction Python à appeler. * +* args = arguments à associer à l'opération. * +* * +* Description : Appelle une routine Python. * +* * +* Retour : Retour obtenu ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *_run_python_method(PyObject *func, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + + result = NULL; + + if (PyCallable_Check(func)) + { + result = PyObject_CallObject(func, args); + if (result == NULL) PyErr_Print(); + } + else if (PyErr_Occurred()) PyErr_Print(); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : target = propriétaire de la routine visée. * * method = désignation de la fonction à appeler. * * args = arguments à associer à l'opération. * @@ -58,32 +89,64 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args } +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* key = désignation de la constante à intégrer. * +* value = valeur de la constante à intégrer. * +* * +* Description : Ajoute une constante au dictionnaire d'un type Python donné. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool PyDict_AddIntConstant(PyTypeObject *obj_type, const char *key, long value) +{ + bool result; /* Bilan à retourner */ + PyObject *item; /* Nouvel élément à insérer */ + int ret; /* Bilan d'un ajout */ + + item = PyLong_FromLong(value); + + ret = PyDict_SetItemString(obj_type->tp_dict, key, item); + result = (ret != -1); + + Py_DECREF(item); + + return result; + +} + /****************************************************************************** * * -* Paramètres : func = fonction Python à appeler. * -* args = arguments à associer à l'opération. * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* key = désignation de la constante à intégrer. * +* value = valeur de la constante à intégrer. * * * -* Description : Appelle une routine Python. * +* Description : Ajoute une constante au dictionnaire d'un type Python donné. * * * -* Retour : Retour obtenu ou NULL si erreur. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -PyObject *_run_python_method(PyObject *func, PyObject *args) +bool PyDict_AddStringConstant(PyTypeObject *obj_type, const char *key, const char *value) { - PyObject *result; /* Bilan à retourner */ + bool result; /* Bilan à retourner */ + PyObject *item; /* Nouvel élément à insérer */ + int ret; /* Bilan d'un ajout */ - result = NULL; + item = PyUnicode_FromString(value); - if (PyCallable_Check(func)) - { - result = PyObject_CallObject(func, args); - if (result == NULL) PyErr_Print(); - } - else if (PyErr_Occurred()) PyErr_Print(); + ret = PyDict_SetItemString(obj_type->tp_dict, key, item); + result = (ret != -1); + + Py_DECREF(item); return result; diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h index f957b9d..d47d8e7 100644 --- a/plugins/pychrysa/helpers.h +++ b/plugins/pychrysa/helpers.h @@ -26,14 +26,35 @@ #include <Python.h> +#include <stdbool.h> /* Appelle une routine Python. */ -PyObject *run_python_method(PyObject *, const char *, PyObject *); +PyObject *_run_python_method(PyObject *, PyObject *); /* Appelle une routine Python. */ -PyObject *_run_python_method(PyObject *, PyObject *); +PyObject *run_python_method(PyObject *, const char *, PyObject *); + +/* Ajoute une constante au dictionnaire d'un type Python donné. */ +bool PyDict_AddIntConstant(PyTypeObject *, const char *, long); + +/* Ajoute une constante au dictionnaire d'un type Python donné. */ +bool PyDict_AddStringConstant(PyTypeObject *, const char *, const char *); + + +#define PyDict_AddIntMacro(tp, c) PyDict_AddIntConstant(tp, #c, c) +#define PyDict_AddStringMacro(tp, c) PyDict_AddStringConstant(tp, #c, c) + + +/** + * Quelque chose est mal fait au niveau de l'abstraction GObject. + * Du coup, Py_TPFLAGS_IS_ABSTRACT n'est pas pris en compte. + * On force alors la méthode de base pour obtenir un traitement correct. + * + * Cf. http://stackoverflow.com/questions/20432335/can-python-abstract-base-classes-inherit-from-c-extensions + */ +#define APPLY_ABSTRACT_FLAG(tp) tp->tp_new = PyBaseObject_Type.tp_new diff --git a/plugins/pychrysa/linsyscalls/oidapgi.py b/plugins/pychrysa/linsyscalls/oidapgi.py deleted file mode 100755 index dd4e010..0000000 --- a/plugins/pychrysa/linsyscalls/oidapgi.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python - -import pyoida -#import oidaline -from pyoida import Noddy - - -class OpenIDAPlugin: - """A simple example class""" - - - - - -if __name__ == "__main__": - print "OpenIDA PlugIn" - - - print "Hello World\n", - - pyoida.system("ls -lh") - - test = Noddy("first", "last") - - print test.name() - - #oidaline.echo() - diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c index 00856f3..367895d 100644 --- a/plugins/pychrysa/pychrysa.c +++ b/plugins/pychrysa/pychrysa.c @@ -24,6 +24,8 @@ #include "pychrysa.h" + + #if 0 #include <dirent.h> @@ -57,32 +59,6 @@ -static PyMethodDef SpamMethods[] = { - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - - - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Précise le nom associé au greffon. * -* * -* Retour : Nom à libérer de la mémoire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char *get_plugin_name(void) -{ - return strdup("PyChrysalide"); - -} - /****************************************************************************** * * @@ -193,146 +169,8 @@ bool init_plugin(GPluginModule *plugin, GObject *ref) } -/****************************************************************************** -* * -* Paramètres : plugin = instance représentant le greffon en déchargement. * -* * -* Description : Libère le greffon permettant l'usage de Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ -void exit_plugin(GPluginModule *plugin) -{ - /* FIXME */ - //Py_Finalize(); -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon à consulter. * -* * -* Description : Indique les opérations offertes par un greffon donné. * -* * -* Retour : Action(s) offerte(s) par le greffon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PluginAction get_plugin_action(const GPluginModule *plugin) -{ - PluginAction result; /* Combinaison à retourner */ - - //result = PGA_NONE; - - return result; - -} - - - - - -#if PY_VERSION_HEX >= 0x03000000 - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Point d'entrée pour l'initialisation de Python. * -* * -* Retour : ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyMODINIT_FUNC initpychrysa/*PyInit_pychrysa*/(void) -{ - PyObject *module; - - //init_pygobject(); - //init_pygtk(); - - pychrysalide_init_quirks(); - - module = Py_InitModule("pychrysalide", SpamMethods); - - //add_analysis_roptions_to_python_module(module); - add_analysis_module_to_python_module(module); - add_arch_module_to_python_module(module); - add_debug_module_to_python_module(module); - add_format_module_to_python_module(module); - add_glibext_module_to_python_module(module); - add_gtkext_module_to_python_module(module); - add_gui_module_to_python_module(module); - - add_plugin_to_python_module(module); - - - /* - - - - static struct PyModuleDef spammodule = { - PyModuleDef_HEAD_INIT, - "pychrysalide", - "pychrysalide_doc", - -1, - SpamMethods - }; - - PyModule_Create(&spammodule); - - */ - -} - -#else - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Point d'entrée pour l'initialisation de Python. * -* * -* Retour : ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyMODINIT_FUNC initpychrysa(void) -{ - PyObject *module; - - init_pygobject(); - //init_pygtk(); - - pychrysalide_init_quirks(); - - module = Py_InitModule("pychrysalide", SpamMethods); - - //add_analysis_roptions_to_python_module(module); - add_analysis_module_to_python_module(module); - add_arch_module_to_python_module(module); - add_debug_module_to_python_module(module); - add_format_module_to_python_module(module); - add_glibext_module_to_python_module(module); - add_gtkext_module_to_python_module(module); - add_gui_module_to_python_module(module); - - add_plugin_to_python_module(module); - -} - -#endif @@ -356,8 +194,12 @@ PyMODINIT_FUNC initpychrysa(void) #include "analysis/module.h" #include "arch/module.h" +#include "common/module.h" #include "core/module.h" +#include "format/module.h" #include "glibext/module.h" +#include "gtkext/module.h" +#include "gui/module.h" @@ -537,6 +379,20 @@ static bool is_current_abi_suitable(void) * Remarques : - * * * ******************************************************************************/ +#include <gtkext/support.h> // REMME +#include <glibext/delayed.h> + +#define PYCHRYSALIDE_DOC \ + "PyChrysalide is a module containing Chrysalide's features and designed for Python users.\n" \ + "\n" \ + "The whole API is defined in a single library named 'pychrysalide.so' and can be used in two ways:\n" \ + "* either from the Chrysalide's GUI, by registering hooks or GLib signals.\n" \ + "* or from a shell command line, by setting PYTHONPATH to point to the directory containing the library.\n" \ + "\n" \ + "In both cases, it is a good start point to have a look at already existing plugins to quickly learn " \ + "how the API works.\n" \ + "\n" \ + "These plugins are located in the 'plugins/python' directory." PyMODINIT_FUNC PyInit_pychrysalide(void) { @@ -548,11 +404,11 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) { "version", py_chrysalide_version, METH_NOARGS, - "Provide the revision number of Chrysalide." + "version(/)\n--\n\nProvide the revision number of Chrysalide." }, { "mod_version", py_chrysalide_mod_version, METH_NOARGS, - "Provide the revision number of Chrysalide module for Python." + "mod_version(/)\n--\n\nProvide the revision number of Chrysalide module for Python." }, { NULL } @@ -563,7 +419,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) .m_base = PyModuleDef_HEAD_INIT, .m_name = "pychrysalide", - .m_doc = "Python module for Chrysalide", + .m_doc = PYCHRYSALIDE_DOC, .m_size = -1, @@ -576,6 +432,26 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) //init_all_processors(); //init_all_formats(); + do + { + int argc = 0; + //char *argv[] = { NULL }; + + /* Initialisation de GTK */ + g_set_prgname("Chrysalide"); + setlocale (LC_ALL, ""); + gtk_init(&argc, NULL/*&argv-*/); + + } while (0); + + add_pixmap_directory(PACKAGE_DATA_DIR); + add_pixmap_directory(PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "pixmaps"); + + init_work_queue(NULL/* !! */); + + + //////////////////////// + if (!is_current_abi_suitable()) return NULL; @@ -606,8 +482,12 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) status &= add_analysis_module_to_python_module(result); status &= add_arch_module_to_python_module(result); + status &= add_common_module_to_python_module(result); status &= add_core_module_to_python_module(result); + status &= add_format_module_to_python_module(result); status &= add_glibext_module_to_python_module(result); + status &= add_gtkext_module_to_python_module(result); + status &= add_gui_module_to_python_module(result); if (!status) { diff --git a/src/analysis/binary.c b/src/analysis/binary.c index e5b9a46..d7682cd 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -941,7 +941,7 @@ const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full) * * * Description : Fournit le format de fichier reconnu dans le contenu binaire.* * * -* Retour : Adresse du format reconnu. * +* Retour : Instance du format reconnu. * * * * Remarques : - * * * @@ -962,7 +962,7 @@ GExeFormat *g_loaded_binary_get_format(const GLoadedBinary *binary) * * * Description : Fournit le processeur de l'architecture liée au binaire. * * * -* Retour : Adresse du processeur associé. * +* Retour : Instance du processeur associé. * * * * Remarques : - * * * diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index a7c44c0..dd35eaa 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -1568,27 +1568,6 @@ size_t find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *addr } - /* - if (addr->virtual == 0x8540) - { - size_t i; - - for (i = 0; i < count; i++) - printf("[%zu] AREAS :: 0x%08x + %x\n", i, - (unsigned int)list[i].range.addr.virtual, - (unsigned int)list[i].range.length); - - - - - printf(" == CMP == 0x%08x / 0x%08x\n", - (unsigned int)addr->physical, - (unsigned int)addr->virtual); - - } - */ - - found = bsearch(addr, list, count, sizeof(mem_area), (__compar_fn_t)find_mem_area); result = (found != NULL ? found - list : count); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index b895af0..d6bf183 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -250,9 +250,6 @@ void g_arch_instruction_set_hook(GArchInstruction *instr, InstrProcessHook type, void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { - if (instr->range.addr.virtual == 0x83c2) - printf(" [%u] HAS BRANCH ? %p\n", (unsigned int)type, instr->hooks[type]); - assert(type < IPH_COUNT); if (instr->hooks[type] != NULL) @@ -671,7 +668,7 @@ bool g_arch_instruction_has_sources(const GArchInstruction *instr) * * * Description : Fournit les origines d'une instruction donnée. * * * -* Retour : Nombre de ces destinations. * +* Retour : Nombre de ces origines. * * * * Remarques : - * * * diff --git a/src/arch/processor.c b/src/arch/processor.c index 86e7845..95176e9 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -327,6 +327,9 @@ void g_arch_processor_set_disassembled_instructions(GArchProcessor *proc, GArchI { GArchInstruction *iter; /* Boucle de parcours */ + /* TODO : vider une éventuelle liste existante */ + /* TODO : incrémenter les références (cf. code Python) */ + ainstr_list_for_each(iter, list) { /* Mise à disposition de d'avantage d'espace */ diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index b10b007..d966341 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -913,7 +913,7 @@ bool mrange_contains_addr_inclusive(const mrange_t *range, const vmpa2t *addr) * Paramètres : range = zone mémoire à consulter. * * addr = localisation mémoire à déterminer. * * * -* Description : Calcule la position extérieure final d'une couverture. * +* Description : Calcule la position extérieure finale d'une couverture. * * * * Retour : - * * * diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 4611ebf..368b765 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -193,7 +193,7 @@ bool mrange_contains_addr(const mrange_t *, const vmpa2t *); /* Indique si une localisation est incluse dans une zone ou non. */ bool mrange_contains_addr_inclusive(const mrange_t *, const vmpa2t *); -/* Calcule la position extérieure final d'une couverture. */ +/* Calcule la position extérieure finale d'une couverture. */ void compute_mrange_end_addr(const mrange_t *, vmpa2t *); /* Transforme un emplacement physique en chaîne de caractères. */ diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h index aca6cef..7f427a3 100755 --- a/src/format/dex/dex.h +++ b/src/format/dex/dex.h @@ -57,6 +57,15 @@ GType g_dex_format_get_type(void); /* Prend en charge un nouveau format DEX. */ GBinFormat *g_dex_format_new(const bin_t *, off_t); +/* Redéfinition : classe issue du code source (instance) */ +typedef struct _GDexClass GDexClass; + +/* Dénombre le nombre de classes trouvées. */ +size_t g_dex_format_count_classes(const GDexFormat *); + +/* Fournit une classe du format chargée en mémoire. */ +GDexClass *g_dex_format_get_class(const GDexFormat *, size_t); + #endif /* _FORMAT_DEX_DEX_H */ diff --git a/src/format/symbol.c b/src/format/symbol.c index 898f00d..70a1d24 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -310,7 +310,13 @@ const char *g_binary_symbol_get_label(const GBinSymbol *symbol) void g_binary_symbol_set_alt_label(GBinSymbol *symbol, const char *alt) { - symbol->alt = strdup(alt); + if (symbol->alt != NULL) + free(symbol->alt); + + if (alt == NULL) + symbol->alt = NULL; + else + symbol->alt = strdup(alt); } @@ -493,7 +499,7 @@ void g_binary_symbol_attach_instruction(GBinSymbol *symbol, GArchInstruction *in * * * Description : Fournit l'éventuelle routine associée au symbole. * * * -* Retour : - * +* Retour : Instance GLib en place ou NULL si aucune. * * * * Remarques : Il n'y a pas de transfert de propriété ici ! * * * @@ -512,7 +518,7 @@ GBinRoutine *g_binary_symbol_get_routine(const GBinSymbol *symbol) * * * Description : Fournit l'éventuelle instruction associée au symbole. * * * -* Retour : - * +* Retour : Instance GLib en place ou NULL si aucune. * * * * Remarques : Il n'y a pas de transfert de propriété ici ! * * * @@ -551,7 +557,7 @@ void g_binary_symbol_set_comment(GBinSymbol *symbol, GDbComment *comment) * * * Description : Fournit l'éventuel commentaire associé au symbole. * * * -* Retour : - * +* Retour : Instance GLib en place ou NULL si aucune. * * * * Remarques : Il n'y a pas de transfert de propriété ici ! * * * diff --git a/src/format/symbol.h b/src/format/symbol.h index e0b657d..1368691 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -44,7 +44,9 @@ typedef enum _SymbolType STP_FUNCTION, /* Simple morceau de code */ STP_ENTRY_POINT, /* Morceau de code en entrée */ STP_STRING, /* Chaîne de caractères */ - STP_RO_STRING /* Chaîne de caractères */ + STP_RO_STRING, /* Chaîne de caractères */ + + STP_COUNT } SymbolType; diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index 455cc03..32a3d16 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -561,7 +561,10 @@ bool init_work_queue(GObject *ref) queue = g_object_new(G_TYPE_WORK_QUEUE, NULL); - queue->statusbar = g_object_get_data(ref, "statusbar"); + if (ref != NULL) + queue->statusbar = g_object_get_data(ref, "statusbar"); + else + queue->statusbar = NULL; if (queue != NULL) _get_work_queue(queue); diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 6da36af..3a47ee7 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -89,7 +89,9 @@ typedef enum _BufferLineFlags BLF_NONE = 0 << 0, /* Aucune */ BLF_HAS_CODE = 1 << 0, /* La ligne contient du code */ BLF_ENTRYPOINT = 1 << 1, /* Représentation d'une entrée */ - BLF_BOOKMARK = 1 << 2 /* Signet associé */ + BLF_BOOKMARK = 1 << 2, /* Signet associé */ + + BLF_ALL = ((1 << 3) - 1) } BufferLineFlags; diff --git a/src/gtkext/gtkextstatusbar.c b/src/gtkext/gtkextstatusbar.c index 5fd37fe..74c23bd 100644 --- a/src/gtkext/gtkextstatusbar.c +++ b/src/gtkext/gtkextstatusbar.c @@ -223,6 +223,8 @@ bstatus_id_t gtk_extended_status_bar_push(GtkExtStatusBar *bar, const char *mess size_t index; /* Indice du nouvel élément */ bar_update_info *info; /* Informations à mémoriser */ + if (bar == NULL) return 0; + /* Mise à jour de la pile */ g_mutex_lock(&bar->stack_access); @@ -274,6 +276,8 @@ void gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar, bstatus_id_t { bar_update_info *info; /* Informations à mémoriser */ + if (bar == NULL) return; + /* Mise à jour de la pile */ g_mutex_lock(&bar->stack_access); @@ -315,6 +319,8 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, bstatus_id_t id) size_t i; /* Boucle de parcours */ bar_update_info *info; /* Informations à mémoriser */ + if (bar == NULL) return; + /* Mise à jour de la pile */ g_mutex_lock(&bar->stack_access); @@ -402,6 +408,8 @@ static gboolean gtk_extended_status_update(bar_update_info *info) static void free_bar_update_info(bar_update_info *info) { + if (info->bar != NULL) + g_object_unref(G_OBJECT(info->bar)); free(info); @@ -425,6 +433,8 @@ static void _gtk_extended_status_bar_change_content(GtkExtStatusBar *bar) { size_t top; /* Indice de l'élément visé */ + if (bar == NULL) return; + g_mutex_lock(&bar->stack_access); if (bar->cur_msg > 0) @@ -470,6 +480,8 @@ static void _gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar) double value; /* Valeur à prendre en compte */ gchar percent[5]; /* Pourcentage en version txt. */ + if (bar == NULL) return; + g_mutex_lock(&bar->stack_access); if (bar->stack_size > 0) @@ -556,6 +568,8 @@ void fini_progessive_status(status_blob_info *info) { gtk_extended_status_bar_remove(info->bar, info->id); + if (info->bar != NULL) + g_object_unref(G_OBJECT(info->bar)); free(info); |