summaryrefslogtreecommitdiff
path: root/plugins/pychrysa/format/format.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-07-17 16:36:21 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-07-17 16:36:21 (GMT)
commit24d3836fcf8d443eb654b981f65478cd9923b8f1 (patch)
tree7672a28b864127e8958c3c6cce751dcf646d2fbe /plugins/pychrysa/format/format.c
parenta61f089babe336b012da31a494b0f7470b6e1a9a (diff)
Updated the Python bindings.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@552 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'plugins/pychrysa/format/format.c')
-rw-r--r--plugins/pychrysa/format/format.c505
1 files changed, 434 insertions, 71 deletions
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;
}