diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/pychrysa/arch/instruction.c | 215 | ||||
-rw-r--r-- | plugins/pychrysa/glibext/Makefile.am | 1 | ||||
-rw-r--r-- | plugins/pychrysa/glibext/linegen.c | 404 | ||||
-rw-r--r-- | plugins/pychrysa/glibext/linegen.h | 42 | ||||
-rw-r--r-- | plugins/pychrysa/glibext/module.c | 2 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/Makefile.am | 1 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/blockdisplay.c | 15 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/bufferdisplay.c | 15 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/displaypanel.c | 35 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/dockable.c | 102 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/dockable.h | 42 | ||||
-rw-r--r-- | plugins/pychrysa/gtkext/module.c | 2 | ||||
-rw-r--r-- | plugins/pychrysa/gui/panels/panel.c | 4 | ||||
-rw-r--r-- | plugins/pychrysa/helpers.c | 35 | ||||
-rw-r--r-- | plugins/pychrysa/helpers.h | 5 | ||||
-rw-r--r-- | plugins/pychrysa/pychrysa.c | 86 |
16 files changed, 775 insertions, 231 deletions
diff --git a/plugins/pychrysa/arch/instruction.c b/plugins/pychrysa/arch/instruction.c index 0efca5a..61d1987 100644 --- a/plugins/pychrysa/arch/instruction.c +++ b/plugins/pychrysa/arch/instruction.c @@ -34,6 +34,7 @@ #include "vmpa.h" #include "../helpers.h" +#include "../glibext/linegen.h" @@ -440,6 +441,7 @@ bool register_python_arch_instruction(PyObject *module) { PyTypeObject *py_arch_instruction_type; /* Type Python 'ArchInstruc...'*/ PyObject *dict; /* Dictionnaire du module */ + PyTypeObject *py_line_generator_type; /* Type Python 'LineGenerator' */ py_arch_instruction_type = get_python_arch_instruction_type(); @@ -447,217 +449,12 @@ bool register_python_arch_instruction(PyObject *module) dict = PyModule_GetDict(module); - if (!register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_type, &PyGObject_Type)) - return false; - - return true; - -} - - - - - - - -#if 0 - - -#include <pygobject.h> -#include <stdbool.h> -#include <string.h> - - -#include <arch/instruction.h> - - -#include "../quirks.h" - - - -/* --------------------- INSTRUCTIONS D'ARCHITECTURES EN PYTHON --------------------- */ - - -/* Crée un nouvel objet Python de type 'ArchInstruction'. */ -static PyObject *py_arch_instruction_new(PyTypeObject *, PyObject *, PyObject *); - -/* Prépare un parcours d'instructions. */ -static PyObject *py_arch_instruction_get_iter(PyObject *); - -/* Fournit la valeur associée à une propriété donnée. */ -static PyObject *py_arch_instruction_get_location(PyObject *, char *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static PyObject *py_arch_instruction_get_keyword(PyObject *, void *); - - - -/* ---------------------------------------------------------------------------------- */ -/* INSTRUCTIONS D'ARCHITECTURES EN PYTHON */ -/* ---------------------------------------------------------------------------------- */ - + py_line_generator_type = get_python_line_generator_type(); -/****************************************************************************** -* * -* 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 'ArchInstruction'. * -* * -* Retour : Instance Python mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_instruction_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Py_RETURN_NONE; - -} - - -/****************************************************************************** -* * -* Paramètres : self = instance manipulée à traiter. * -* * -* Description : Prépare un parcours d'instructions. * -* * -* Retour : Point de départ d'un parcours. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_instruction_get_iter(PyObject *self) -{ - return py_arch_instruction_iterator_create(self); - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une instruction. * -* name = nom de la propriété à lire. * -* * -* Description : Fournit la valeur associée à une propriété donnée. * -* * -* Retour : Valeur associée à la propriété consultée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_instruction_get_location(PyObject *self, char *name) -{ - PyObject *result; /* Trouvailles à retourner */ - GArchInstruction *instr; /* Version native */ - off_t offset; /* Position dans le fichier */ - off_t length; /* Taille de l'instruction */ - vmpa_t address; /* Position en mémoire */ - - instr = G_ARCH_INSTRUCTION(pygobject_get(self)); - g_arch_instruction_get_location(instr, &offset, &length, &address); - - if (strcmp(name, "offset") == 0) - result = PyLong_FromLong(offset); - - else if (strcmp(name, "length") == 0) - result = PyLong_FromLong(length); - - else if (strcmp(name, "address") == 0) - result = PyLong_FromLongLong(address); - - else - result = NULL; - - return result; - -} - - - -/****************************************************************************** -* * -* 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) -{ - PyObject *pygobj_mod; /* Module Python-GObject */ - int ret; /* Bilan d'un appel */ - - static PyMethodDef py_arch_instruction_methods[] = { - { NULL } - }; - - static PyGetSetDef py_arch_instruction_getseters[] = { - { - "offset", (getter)py_arch_instruction_get_location, (setter)NULL, - "Provide the location of the instruction in the binary file.", "offset" - }, - { - "length", (getter)py_arch_instruction_get_location, (setter)NULL, - "Provide the length of the instruction.", "length" - }, - { - "address", (getter)py_arch_instruction_get_location, (setter)NULL, - "Provide the location of the instruction in memory.", "address" - }, - { - "keyword", (getter)py_arch_instruction_get_keyword, (setter)NULL, - "Give le name of the assembly instruction.", NULL - }, - { NULL } - }; - - static PyTypeObject py_arch_instruction_type = { - - PyObject_HEAD_INIT(NULL) - - .tp_name = "pychrysalide.arch.ArchInstruction", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "PyChrysalide architecture instruction", - - .tp_methods = py_arch_instruction_methods, - .tp_getset = py_arch_instruction_getseters, - .tp_new = (newfunc)py_arch_instruction_new, - - .tp_iter = (getiterfunc)py_arch_instruction_get_iter - - }; - - pygobj_mod = PyImport_ImportModule("gobject"); - if (pygobj_mod == NULL) return false; - - py_arch_instruction_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject"); - Py_DECREF(pygobj_mod); - - if (PyType_Ready(&py_arch_instruction_type) < 0) + if (!_register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_type, + &PyGObject_Type, py_line_generator_type, NULL)) return false; - Py_INCREF(&py_arch_instruction_type); - ret = PyModule_AddObject(module, "ArchInstruction", (PyObject *)&py_arch_instruction_type); - - register_class_for_pygobject(module, "GArchInstruction", G_TYPE_ARCH_INSTRUCTION, - &py_arch_instruction_type, - Py_BuildValue("(O)", py_arch_instruction_type.tp_base)); - - return (ret == 0); + return true; } - - -#endif diff --git a/plugins/pychrysa/glibext/Makefile.am b/plugins/pychrysa/glibext/Makefile.am index b53f4b0..d1b2569 100644 --- a/plugins/pychrysa/glibext/Makefile.am +++ b/plugins/pychrysa/glibext/Makefile.am @@ -5,6 +5,7 @@ libpychrysaglibext_la_SOURCES = \ buffercache.h buffercache.c \ bufferline.h bufferline.c \ configuration.h configuration.c \ + linegen.h linegen.c \ module.h module.c diff --git a/plugins/pychrysa/glibext/linegen.c b/plugins/pychrysa/glibext/linegen.c new file mode 100644 index 0000000..b6aad6b --- /dev/null +++ b/plugins/pychrysa/glibext/linegen.c @@ -0,0 +1,404 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.c - équivalent Python du fichier "glibext/linegen.h" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "linegen.h" + + +#include <pygobject.h> + + +#include <common/cpp.h> +#include <glibext/linegen.h> + + +#include "../helpers.h" +#include "../analysis/content.h" +#include "../arch/vmpa.h" +#include "../glibext/bufferline.h" + + + +/* Indique le nombre de ligne prêtes à être générées. */ +static PyObject *py_line_generator_count_lines(PyObject *, PyObject *); + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static PyObject *py_line_generator_compute_addr(PyObject *, PyObject *); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static PyObject *py_line_generator_contains_addr(PyObject *, PyObject *); + +/* Renseigne sur les propriétés liées à un générateur. */ +static PyObject *py_line_generator_get_flags(PyObject *, PyObject *); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static PyObject *py_line_generator_print(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_line_generator_count_lines(PyObject *self, PyObject *args) +{ + PyObject *result; /* Décompte à retourner */ + GLineGenerator *generator; /* Version native */ + size_t count; /* Nombre de lignes présentes */ + + generator = G_LINE_GENERATOR(pygobject_get(self)); + + count = g_line_generator_count_lines(generator); + + result = Py_BuildValue("k", count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_line_generator_compute_addr(PyObject *self, PyObject *args) +{ + PyObject *result; /* Localisation à retourner */ + GLineGenerator *generator; /* Version native */ + gint x; /* Position géographique */ + size_t index; /* Indice dans le tampon */ + size_t repeat; /* Utilisations successives */ + int ret; /* Bilan de lecture des args. */ + vmpa2t addr; /* Adresse visée par l'opérat° */ + + generator = G_LINE_GENERATOR(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "ikk", &x, &index, &repeat); + if (!ret) return NULL; + + g_line_generator_compute_addr(generator, x, &addr, index, repeat); + + result = build_from_internal_vmpa(&addr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_line_generator_contains_addr(PyObject *self, PyObject *args) +{ + GLineGenerator *generator; /* Version native */ + PyObject *py_vmpa; /* Localisation version Python */ + size_t index; /* Indice dans le tampon */ + size_t repeat; /* Utilisations successives */ + int ret; /* Bilan de lecture des args. */ + vmpa2t *addr; /* Adresse visée par l'opérat° */ + + generator = G_LINE_GENERATOR(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "O!kk", get_python_vmpa_type(), &py_vmpa, &index, &repeat); + if (!ret) return NULL; + + addr = get_internal_vmpa(py_vmpa); + if (addr == NULL) return NULL; + + g_line_generator_contains_addr(generator, addr, index, repeat); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_line_generator_get_flags(PyObject *self, PyObject *args) +{ + PyObject *result; /* Propriétés à retourner */ + GLineGenerator *generator; /* Version native */ + size_t index; /* Indice dans le tampon */ + size_t repeat; /* Utilisations successives */ + int ret; /* Bilan de lecture des args. */ + BufferLineFlags flags; /* Propriétés courantes */ + + generator = G_LINE_GENERATOR(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "kk", &index, &repeat); + if (!ret) return NULL; + + flags = g_line_generator_get_flags(generator, index, repeat); + + result = Py_BuildValue("I", flags); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_line_generator_print(PyObject *self, PyObject *args) +{ + GLineGenerator *generator; /* Version native */ + PyObject *py_line; /* Ligne version Python */ + size_t index; /* Indice dans le tampon */ + size_t repeat; /* Utilisations successives */ + PyObject *py_content; /* Contenu version Python */ + int ret; /* Bilan de lecture des args. */ + GBufferLine *line; /* Ligne de rendu à compléter */ + GBinContent *content; /* Contenu binaire associé */ + + generator = G_LINE_GENERATOR(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "O!kkO!", get_python_buffer_line_type(), &py_line, &index, + &repeat, get_python_binary_content_type(), &py_content); + if (!ret) return NULL; + + line = G_BUFFER_LINE(pygobject_get(py_line)); + + content = G_BIN_CONTENT(pygobject_get(py_content)); + + g_line_generator_print(generator, line, index, repeat, content); + + Py_RETURN_NONE; + +} + + + + + + + + + + + + + +#if 0 + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void python_line_generator_interface_init(GLineGeneratorIface *iface, PyTypeObject *type) +{ + GLineGeneratorIface *parent; /* Défintion parente */ + size_t i; /* Boucle de parcours */ + PyObject *method; /* Méthode à associer */ + + static const char *meth_names[] = { + "count_lines", + "compute_addr", + "contains_addr", + "get_flags", + "print" + }; + + parent = g_type_interface_peek_parent(iface); + + for (i = 0; i < ARRAY_SIZE(meth_names); i++) + { + method = NULL; + + if (type != NULL) + method = PyObject_GetAttrString((PyObject *)type, meth_names[i]); + + if (method != NULL && PyObject_TypeCheck(method, &PyCFunction_Type) == 0) + /*iface->iface_method = _wrap_TestInterface__proxy_do_iface_method*/; + + else + { + PyErr_Clear(); + + if (parent != NULL) + /*iface->iface_method = parent->iface_method*/; + + } + + Py_XDECREF(method); + + } + +} + + +#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_line_generator_type(void) +{ + static PyMethodDef py_line_generator_methods[] = { + { + "count_lines", py_line_generator_count_lines, + METH_NOARGS, + "count_lines($self, /)\n--\n\nCount the number of lines which can be displayed." + }, + { + "compute_addr", py_line_generator_compute_addr, + METH_VARARGS, + "compute_addr($self, x, index, repeat, /)\n--\n\nReturn the position at a given location." + }, + { + "contains_addr", py_line_generator_contains_addr, + METH_VARARGS, + "contains_addr($self, addr, index, repeat, /)\n--\n\nTell if the generator contains an address." + }, + { + "get_flags", py_line_generator_get_flags, + METH_VARARGS, + "get_flags($self, index, repeat, /)\n--\n\nGet the flags of a position from the generator." + }, + { + "print", py_line_generator_print, + METH_VARARGS, + "print($self, line, index, repeat, content, /)\n--\n\nProduce output into a line from content." + }, + { NULL } + }; + + static PyGetSetDef py_line_generator_getseters[] = { + { NULL } + }; + + static PyTypeObject py_line_generator_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.LineGenerator", + //.tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide line content generator", + + .tp_methods = py_line_generator_methods, + .tp_getset = py_line_generator_getseters, + + }; + + return &py_line_generator_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_line_generator(PyObject *module) +{ + PyTypeObject *py_line_generator_type; /* Type Python 'LineGenerator' */ + PyObject *dict; /* Dictionnaire du module */ + + py_line_generator_type = get_python_line_generator_type(); + + dict = PyModule_GetDict(module); + pyg_register_interface(dict, "LineGenerator", G_TYPE_LINE_GENERATOR, py_line_generator_type); + + return true; + +} diff --git a/plugins/pychrysa/glibext/linegen.h b/plugins/pychrysa/glibext/linegen.h new file mode 100644 index 0000000..8669bb7 --- /dev/null +++ b/plugins/pychrysa/glibext/linegen.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * linegen.h - prototypes pour l'équivalent Python du fichier "glibext/linegen.h" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSA_GLIBEXT_LINEGEN_H +#define _PLUGINS_PYCHRYSA_GLIBEXT_LINEGEN_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_line_generator_type(void); + +/* Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'. */ +bool register_python_line_generator(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSA_GLIBEXT_LINEGEN_H */ diff --git a/plugins/pychrysa/glibext/module.c b/plugins/pychrysa/glibext/module.c index eb5c892..f62b17b 100644 --- a/plugins/pychrysa/glibext/module.c +++ b/plugins/pychrysa/glibext/module.c @@ -31,6 +31,7 @@ #include "buffercache.h" #include "bufferline.h" #include "configuration.h" +#include "linegen.h" @@ -85,6 +86,7 @@ bool add_glibext_module_to_python_module(PyObject *super) result &= register_python_config_param(module); result &= register_python_config_param_iterator(module); result &= register_python_generic_config(module); + result &= register_python_line_generator(module); agmtpm_exit: diff --git a/plugins/pychrysa/gtkext/Makefile.am b/plugins/pychrysa/gtkext/Makefile.am index fee2032..4a36e63 100644 --- a/plugins/pychrysa/gtkext/Makefile.am +++ b/plugins/pychrysa/gtkext/Makefile.am @@ -5,6 +5,7 @@ libpychrysagtkext_la_SOURCES = \ blockdisplay.h blockdisplay.c \ bufferdisplay.h bufferdisplay.c \ displaypanel.h displaypanel.c \ + dockable.h dockable.c \ module.h module.c diff --git a/plugins/pychrysa/gtkext/blockdisplay.c b/plugins/pychrysa/gtkext/blockdisplay.c index 06f14d8..a329daf 100644 --- a/plugins/pychrysa/gtkext/blockdisplay.c +++ b/plugins/pychrysa/gtkext/blockdisplay.c @@ -25,6 +25,7 @@ #include "blockdisplay.h" +#include <string.h> #include <pygobject.h> @@ -65,7 +66,7 @@ PyTypeObject *get_python_block_display_type(void) .tp_name = "pychrysalide.gtkext.BlockDisplay", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE, .tp_doc = "PyChrysalide block display.", @@ -74,7 +75,17 @@ PyTypeObject *get_python_block_display_type(void) }; - return &py_block_display_type; + static PyTypeObject *result = NULL; + + if (result == NULL) + { + result = calloc(1, sizeof(PyTypeObject)); + + memcpy(result, &py_block_display_type, sizeof(PyTypeObject)); + + } + + return result; } diff --git a/plugins/pychrysa/gtkext/bufferdisplay.c b/plugins/pychrysa/gtkext/bufferdisplay.c index 7cc82ff..a6e5327 100644 --- a/plugins/pychrysa/gtkext/bufferdisplay.c +++ b/plugins/pychrysa/gtkext/bufferdisplay.c @@ -25,6 +25,7 @@ #include "bufferdisplay.h" +#include <string.h> #include <pygobject.h> @@ -65,7 +66,7 @@ PyTypeObject *get_python_buffer_display_type(void) .tp_name = "pychrysalide.gtkext.BufferDisplay", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE, .tp_doc = "PyChrysalide buffer display.", @@ -74,7 +75,17 @@ PyTypeObject *get_python_buffer_display_type(void) }; - return &py_buffer_display_type; + static PyTypeObject *result = NULL; + + if (result == NULL) + { + result = calloc(1, sizeof(PyTypeObject)); + + memcpy(result, &py_buffer_display_type, sizeof(PyTypeObject)); + + } + + return result; } diff --git a/plugins/pychrysa/gtkext/displaypanel.c b/plugins/pychrysa/gtkext/displaypanel.c index d085f4f..e857475 100644 --- a/plugins/pychrysa/gtkext/displaypanel.c +++ b/plugins/pychrysa/gtkext/displaypanel.c @@ -25,6 +25,7 @@ #include "displaypanel.h" +#include <string.h> #include <pygobject.h> @@ -196,7 +197,7 @@ PyTypeObject *get_python_display_panel_type(void) .tp_name = "pychrysalide.gtkext.DisplayPanel", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, .tp_doc = "PyChrysalide view panel.", @@ -207,7 +208,17 @@ PyTypeObject *get_python_display_panel_type(void) }; - return &py_display_panel_type; + static PyTypeObject *result = NULL; + + if (result == NULL) + { + result = calloc(1, sizeof(PyTypeObject)); + + memcpy(result, &py_display_panel_type, sizeof(PyTypeObject)); + + } + + return result; } @@ -226,27 +237,37 @@ PyTypeObject *get_python_display_panel_type(void) bool register_python_display_panel(PyObject *module) { + bool result; /* Bilan à retourner */ PyTypeObject *py_display_panel_type; /* Type Python 'DisplayPanel' */ PyObject *parent_mod; /* Module Python Fixed */ PyObject *fixed; /* Module "GtkFixed" */ PyObject *dict; /* Dictionnaire du module */ + result = false; + py_display_panel_type = get_python_display_panel_type(); parent_mod = PyImport_ImportModule("gi.repository.Gtk"); if (parent_mod == NULL) return false; fixed = PyObject_GetAttrString(parent_mod, "Fixed"); + Py_DECREF(parent_mod); dict = PyModule_GetDict(module); - if (!register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL, py_display_panel_type, (PyTypeObject *)fixed)) - return false; + result = register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL, + py_display_panel_type, (PyTypeObject *)fixed); + + Py_DECREF(fixed); - if (!py_display_panel_define_constants(py_display_panel_type)) - return false; + if (!result) + goto rpdp_exit; - return true; + result = py_display_panel_define_constants(py_display_panel_type); + + rpdp_exit: + + return result; } diff --git a/plugins/pychrysa/gtkext/dockable.c b/plugins/pychrysa/gtkext/dockable.c new file mode 100644 index 0000000..9c66159 --- /dev/null +++ b/plugins/pychrysa/gtkext/dockable.c @@ -0,0 +1,102 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * dockable.c - équivalent Python du fichier "gtkext/gtkdockable.c" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "dockable.h" + + +#include <pygobject.h> + + +#include <gtkext/gtkdockable.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_gtk_dockable_type(void) +{ + static PyMethodDef py_gtk_dockable_methods[] = { + { NULL } + }; + + static PyGetSetDef py_gtk_dockable_getseters[] = { + { NULL } + }; + + static PyTypeObject py_gtk_dockable_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.gtkext.GtkDockable", + //.tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide interface for Gtk dockable widgets", + + .tp_methods = py_gtk_dockable_methods, + .tp_getset = py_gtk_dockable_getseters, + + }; + + return &py_gtk_dockable_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.gtkext.GtkDockable'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_gtk_dockable(PyObject *module) +{ + PyTypeObject *py_gtk_dockable_type; /* Type Python 'LineGenerator' */ + PyObject *dict; /* Dictionnaire du module */ + + py_gtk_dockable_type = get_python_gtk_dockable_type(); + + dict = PyModule_GetDict(module); + pyg_register_interface(dict, "LineGenerator", GTK_TYPE_DOCKABLE, py_gtk_dockable_type); + + return true; + +} diff --git a/plugins/pychrysa/gtkext/dockable.h b/plugins/pychrysa/gtkext/dockable.h new file mode 100644 index 0000000..1709966 --- /dev/null +++ b/plugins/pychrysa/gtkext/dockable.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * dockable.h - prototypes pour l'équivalent Python du fichier "gtkext/gtkdockable.h" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 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_DOCKABLE_H +#define _PLUGINS_PYCHRYSA_GTKEXT_DOCKABLE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_gtk_dockable_type(void); + +/* Prend en charge l'objet 'pychrysalide.gtkext.GtkDockable'. */ +bool register_python_gtk_dockable(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSA_GTKEXT_DOCKABLE_H */ diff --git a/plugins/pychrysa/gtkext/module.c b/plugins/pychrysa/gtkext/module.c index 00720bb..8b2cc5e 100644 --- a/plugins/pychrysa/gtkext/module.c +++ b/plugins/pychrysa/gtkext/module.c @@ -31,6 +31,7 @@ #include "blockdisplay.h" #include "bufferdisplay.h" #include "displaypanel.h" +#include "dockable.h" @@ -83,6 +84,7 @@ bool add_gtkext_module_to_python_module(PyObject *super) result &= register_python_display_panel(module); result &= register_python_buffer_display(module); result &= register_python_block_display(module); + result &= register_python_gtk_dockable(module); agmtpm_exit: diff --git a/plugins/pychrysa/gui/panels/panel.c b/plugins/pychrysa/gui/panels/panel.c index 26637e0..9ca271f 100644 --- a/plugins/pychrysa/gui/panels/panel.c +++ b/plugins/pychrysa/gui/panels/panel.c @@ -36,6 +36,7 @@ #include "../editem.h" #include "../../helpers.h" #include "../../quirks.h" +#include "../../gtkext/dockable.h" @@ -232,7 +233,8 @@ bool register_python_panel_item(PyObject *module) dict = PyModule_GetDict(module); - if (!register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, py_panel_item_type, get_python_editor_item_type())) + if (!_register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, py_panel_item_type, + get_python_editor_item_type(), get_python_gtk_dockable_type(), NULL)) return false; if (!py_panel_item_define_constants(py_panel_item_type)) diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c index df1df05..a0a828f 100644 --- a/plugins/pychrysa/helpers.c +++ b/plugins/pychrysa/helpers.c @@ -26,6 +26,7 @@ #include <assert.h> #include <pygobject.h> +#include <stdarg.h> @@ -256,8 +257,13 @@ bool PyDict_AddStringConstant(PyTypeObject *obj_type, const char *key, const cha * * ******************************************************************************/ -bool register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base) +bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base, ...) { + Py_ssize_t size; /* Taille de liste actuelle */ + PyObject *static_bases; /* Base(s) de l'objet */ + va_list ap; /* Parcours des arguments */ + PyTypeObject *static_base; /* Base à rajouter à la liste */ + /** * pygobject_register_class() définit type->tp_base à partir des arguments fournis, * puis fait appel à PyType_Ready(). @@ -285,7 +291,32 @@ bool register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *typ type->tp_basicsize = base->tp_basicsize; } - pygobject_register_class(dict, NULL, gtype, type, Py_BuildValue("(O)", base)); + size = 1; + static_bases = PyTuple_New(size); + + Py_INCREF(base); + PyTuple_SetItem(static_bases, 0, (PyObject *)base); + + va_start(ap, base); + + while (1) + { + static_base = va_arg(ap, PyTypeObject *); + + if (static_base == NULL) break; + + _PyTuple_Resize(&static_bases, ++size); + + Py_INCREF(static_base); + PyTuple_SetItem(static_bases, size - 1, (PyObject *)static_base); + + } + + va_end(ap); + + pygobject_register_class(dict, NULL, gtype, type, static_bases); + + assert(PyErr_Occurred() == NULL); return true; diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h index 950c85b..9fb83d0 100644 --- a/plugins/pychrysa/helpers.h +++ b/plugins/pychrysa/helpers.h @@ -65,7 +65,10 @@ bool PyDict_AddStringConstant(PyTypeObject *, const char *, const char *); /* Enregistre correctement une surcouche de conversion GObject. */ -bool register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *); +bool _register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *, ...); + +#define register_class_for_pygobject(dict, gtype, type, base) \ + _register_class_for_pygobject(dict, gtype, type, base, NULL) /** diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c index 45e32b4..f09c234 100644 --- a/plugins/pychrysa/pychrysa.c +++ b/plugins/pychrysa/pychrysa.c @@ -40,6 +40,7 @@ #include <plugins/plugin-int.h> +#include "helpers.h" #include "plugin.h" #include "quirks.h" #include "analysis/module.h" @@ -72,6 +73,9 @@ static PyObject *py_chrysalide_get_global_gobject(PyObject *, PyObject *); /* Détermine si l'interpréteur lancé est celui pris en compte. */ static bool is_current_abi_suitable(void); +/* Définit la version attendue de GTK à charger dans Python. */ +static bool set_version_for_gtk_namespace(const char *); + /* Charge autant de greffons composés en Python que possible. */ static bool load_python_plugins(GPluginModule *plugin, GObject *); @@ -251,6 +255,55 @@ static bool is_current_abi_suitable(void) /****************************************************************************** * * +* Paramètres : version = idenfiant de la version de GTK à stipuler. * +* * +* Description : Définit la version attendue de GTK à charger dans Python. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool set_version_for_gtk_namespace(const char *version) +{ + bool result; /* Bilan à retourner */ + PyObject *gi_mod; /* Module Python-GObject */ + PyObject *args; /* Arguments à fournir */ + + result = false; + + /** + * On cherche ici à éviter le message suivant si on charge 'gi.repository.Gtk' directement : + * + * + * PyGIWarning: Gtk was imported without specifying a version first. \ + * Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded. + * + */ + + gi_mod = PyImport_ImportModule("gi"); + + if (gi_mod != NULL) + { + args = Py_BuildValue("ss", "Gtk", "3.0"); + + run_python_method(gi_mod, "require_version", args); + + result = (PyErr_Occurred() == NULL); + + Py_DECREF(args); + Py_DECREF(gi_mod); + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Point d'entrée pour l'initialisation de Python. * @@ -362,6 +415,9 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) return NULL; } + if (!set_version_for_gtk_namespace("3.0")) + return NULL; + if (!load_all_basic_components()) { PyErr_SetString(PyExc_SystemError, "unable to load all basic components."); @@ -386,15 +442,16 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) result = PyModule_Create(&py_chrysalide_module); - status = register_python_plugin_module(result); + /* Interface 'LineGenerator' en premier... */ + status = add_glibext_module_to_python_module(result); + status &= register_python_plugin_module(result); 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_debug_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); @@ -439,9 +496,9 @@ static bool load_python_plugins(GPluginModule *plugin, GObject *ref) save = NULL; /* gcc... */ - for (path = strtok_r(paths, ";", &save); + for (path = strtok_r(paths, ":", &save); path != NULL; - path = strtok_r(NULL, ";", &save)) + path = strtok_r(NULL, ":", &save)) { dir = opendir(path); if (dir == NULL) @@ -514,6 +571,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) { bool result; /* Bilan à retourner */ DIR *dir; /* Répertoire à parcourir */ + int ret; /* Bilan de préparatifs */ define_internal_ref(ref); @@ -524,15 +582,27 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) if (dir != NULL) { closedir(dir); - add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";"); + add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ":"); } else add_to_env_var("PYTHONPATH", PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" \ - G_DIR_SEPARATOR_S "python", ";"); + G_DIR_SEPARATOR_S "python", ":"); + + g_plugin_module_log_variadic_message(plugin, LMT_INFO, + _("PYTHONPATH environment variable set to '%s'"), + getenv("PYTHONPATH")); /* Chargement du module pour Python */ - PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide); + ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide); + + if (ret == -1) + { + g_plugin_module_log_variadic_message(plugin, LMT_ERROR, + _("Can not extend the existing table of Python built-in modules.")); + result = false; + goto cpi_done; + } Py_Initialize(); @@ -540,6 +610,8 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) result = load_python_plugins(plugin, ref); + cpi_done: + return result; } |