summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/analysis/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/analysis/block.c')
-rw-r--r--plugins/pychrysalide/analysis/block.c292
1 files changed, 214 insertions, 78 deletions
diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index 010efd4..a091a6d 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -33,141 +33,273 @@
#include "../access.h"
#include "../helpers.h"
+#include "../arch/vmpa.h"
-//////////////////////////////////////////////////////////
-#if 0
+/* ----------------------------- BLOC DE CODE GENERIQUE ----------------------------- */
+
+
+/* Indique l'indice d'intégration du bloc dans une liste. */
+static PyObject *py_code_block_get_index(PyObject *, void *);
+
+/* Fournit le rang du bloc de code dans le flot d'exécution. */
+static PyObject *py_code_block_get_rank(PyObject *, void *);
-/* Permet la jonction entre C et Python lors des visites */
-typedef struct _py_block_vdata
-{
- PyObject *func; /* Fonction à appeler */
- PyObject *user; /* Donnée à faire suivre */
-} py_block_vdata;
+/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */
-/* Parcourt le bloc d'instructions dans un ordre donné. */
-static bool py_block_visitor_glue(GInstrBlock *, BlockVisitOrder, py_block_vdata *);
-/* Parcourt tous les blocs d'instructions dans un ordre donné. */
-static PyObject *py_instructions_block_visit(PyObject *, PyObject *);
+/* Recherche un bloc de code débutant à une adresse donnée. */
+static PyObject *py_block_list_find_by_starting_addr(PyObject *, PyObject *);
-/* Fournit l'ensemble contenant les blocs liés. */
-static PyObject *py_instructions_block_get_links_block(PyObject *, PyObject *);
+/* Fournit l'ensemble des blocs de code inclus dans une liste. */
+static PyObject *py_block_list_get_items(PyObject *, void *);
-/* Définit les constantes pour les blocs basiques. */
-static bool py_instructions_block_define_constants(PyTypeObject *);
+/* ---------------------------------------------------------------------------------- */
+/* BLOC DE CODE GENERIQUE */
+/* ---------------------------------------------------------------------------------- */
+
/******************************************************************************
* *
-* Paramètres : block = bloc d'instructions concerné par la visite. *
-* order = indication sur la position dans le parcours. *
-* data = donnée utilisateur à associer au parcours. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
* *
-* Description : Parcourt le bloc d'instructions dans un ordre donné. *
+* Description : Indique l'indice d'intégration du bloc dans une liste. *
* *
-* Retour : true si le parcours a été jusqu'à son terme, false sinon. *
+* Retour : Indice valide dans une liste. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool py_block_visitor_glue(GInstrBlock *block, BlockVisitOrder order, py_block_vdata *data)
+static PyObject *py_code_block_get_index(PyObject *self, void *closure)
{
- bool result; /* Bilan à retourner */
- PyObject *args; /* Arguments pour l'appel */
- PyObject *value; /* Retour obtenu */
+ PyObject *result; /* Trouvailles à retourner */
+ GCodeBlock *block; /* Bloc de code à consulter */
+ size_t value; /* Valeur à transmettre */
+
+ block = G_CODE_BLOCK(pygobject_get(self));
- Py_INCREF(data->user);
+ value = g_code_block_get_index(block);
- args = PyTuple_New(3);
- PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(block)));
- PyTuple_SetItem(args, 1, PyLong_FromLong(order));
- PyTuple_SetItem(args, 2, data->user);
+ result = PyLong_FromSize_t(value);
- value = _run_python_method(data->func, args);
- result = (value == Py_True);
+ return result;
- Py_XDECREF(value);
- Py_DECREF(args);
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le rang du bloc de code dans le flot d'exécution. *
+* *
+* Retour : Indice supérieur ou égal à zéro. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_code_block_get_rank(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ GCodeBlock *block; /* Bloc de code à consulter */
+ size_t value; /* Valeur à transmettre */
+
+ block = G_CODE_BLOCK(pygobject_get(self));
+
+ value = g_code_block_get_rank(block);
+
+ result = PyLong_FromSize_t(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_code_block_type(void)
+{
+ static PyMethodDef py_code_block_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_code_block_getseters[] = {
+ {
+ "index", py_code_block_get_index, NULL,
+ "Index of the code block in the parent list, if any.", NULL
+ },
+ {
+ "rank", py_code_block_get_rank, NULL,
+ "Rang of the code block.", NULL
+ },
+ { NULL }
+ };
+
+ static PyTypeObject py_code_block_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.CodeBlock",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = "PyChrysalide code block",
+
+ .tp_methods = py_code_block_methods,
+ .tp_getset = py_code_block_getseters,
+
+ };
+
+ return &py_code_block_type;
+
+}
+
/******************************************************************************
* *
-* Paramètres : self = classe représentant un binaire. *
-* args = arguments fournis à l'appel. *
+* Paramètres : - *
* *
-* Description : Parcourt tous les blocs d'instructions dans un ordre donné. *
+* Description : Prend en charge l'objet 'pychrysalide.analysis.CodeBlock'. *
* *
-* Retour : True si le parcours a été jusqu'à son terme, False sinon. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_instructions_block_visit(PyObject *self, PyObject *args)
+bool ensure_python_code_block_is_registered(void)
{
- PyObject *result; /* Conclusion à retourner */
- py_block_vdata data; /* Transition entre C et Python*/
- int ret; /* Bilan de lecture des args. */
- GInstrBlock *block; /* Point de départ des visites */
- bool status; /* Bilan du parcours */
+ PyTypeObject *type; /* Type Python 'InstrBlock' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
- ret = PyArg_ParseTuple(args, "OO", &data.func, &data.user);
- if (!ret) Py_RETURN_NONE;
+ type = get_python_code_block_type();
- if (PyCallable_Check(data.func) != 1) return NULL;
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis");
- block = G_INSTR_BLOCK(pygobject_get(self));
- status = g_instr_block_visit(block, (instr_block_visitor_cb)py_block_visitor_glue, &data);
+ dict = PyModule_GetDict(module);
- result = (status ? Py_True : Py_False);
- Py_INCREF(result);
+ if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type, &PyGObject_Type))
+ return false;
- return result;
+ }
+
+ return true;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* REGROUPEMENT EN LISTE DE BLOCS */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : self = classe représentant un binaire. *
+* Paramètres : self = classe représentant une liste de blocs de code. *
* args = arguments fournis à l'appel. *
* *
-* Description : Fournit l'ensemble contenant les blocs liés. *
+* Description : Recherche un bloc de code débutant à une adresse donnée. *
* *
-* Retour : Bloc contenant les blocs liés au bloc. *
+* Retour : Bloc de code trouvé ou None si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_instructions_block_get_links_block(PyObject *self, PyObject *args)
+static PyObject *py_block_list_find_by_starting_addr(PyObject *self, PyObject *args)
{
PyObject *result; /* Conclusion à retourner */
- GInstrBlock *block; /* Point de départ des visites */
+ vmpa2t addr; /* Emplacement ciblé */
+ int ret; /* Bilan de lecture des args. */
+ GBlockList *list; /* Liste de blocs manipulée */
+ GCodeBlock *found; /* Eventuel bloc trouvé */
- block = G_INSTR_BLOCK(pygobject_get(self));
+ ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
+ if (!ret) return NULL;
- block = g_instr_block_get_links_block(block);
+ list = G_BLOCK_LIST(pygobject_get(self));
- result = pygobject_new(G_OBJECT(block));
+ found = g_block_list_find_by_starting_addr(list, &addr);
+
+ if (found != NULL)
+ {
+ result = pygobject_new(G_OBJECT(found));
+ g_object_unref(G_OBJECT(found));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
}
-#endif
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit l'ensemble des blocs de code inclus dans une liste. *
+* *
+* Retour : Liste de blocs de code. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_block_list_get_items(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ GBlockList *list; /* Liste de blocs manipulée */
+ size_t count; /* Nombre de blocs présents */
+ size_t i; /* Boucle de parcours */
+ GCodeBlock *block; /* Bloc de code à intégrer */
+
+ list = G_BLOCK_LIST(pygobject_get(self));
+
+ count = g_block_list_count_blocks(list);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ {
+ block = g_block_list_get_block(list, i);
+
+ PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(block)));
+
+ g_object_unref(G_OBJECT(block));
+
+ }
+
+ return result;
+
+}
/******************************************************************************
@@ -182,46 +314,50 @@ static PyObject *py_instructions_block_get_links_block(PyObject *self, PyObject
* *
******************************************************************************/
-PyTypeObject *get_python_instr_block_type(void)
+PyTypeObject *get_python_block_list_type(void)
{
- static PyMethodDef py_instr_block_methods[] = {
-#if 0
+ static PyMethodDef py_block_list_methods[] = {
{
- "get_links_block", (PyCFunction)py_instructions_block_get_links_block,
+ "find_by_starting_addr", py_block_list_find_by_starting_addr,
METH_VARARGS,
- "get_links_block($self, /)\n--\n\nGet the block containing all blocks linked to the caller."
+ "find_by_starting_addr($self, addr, /)\n--\n\nFind a code block starting at a given address."
},
-#endif
{ NULL }
};
- static PyGetSetDef py_instr_block_getseters[] = {
+ static PyGetSetDef py_block_list_getseters[] = {
+ {
+ "items", py_block_list_get_items, NULL,
+ "All code blocks included in the list.", NULL
+ },
{ NULL }
};
- static PyTypeObject py_instr_block_type = {
+ static PyTypeObject py_block_list_type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.analysis.InstrBlock",
+ .tp_name = "pychrysalide.analysis.BlockList",
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = "PyChrysalide basic block",
- .tp_methods = py_instr_block_methods,
- .tp_getset = py_instr_block_getseters,
+ .tp_methods = py_block_list_methods,
+ .tp_getset = py_block_list_getseters,
};
- return &py_instr_block_type;
+ return &py_block_list_type;
}
+
+
/******************************************************************************
* *
* Paramètres : - *
* *
-* Description : Prend en charge l'objet 'pychrysalide.analysis.InstrBlock'. *
+* Description : Prend en charge l'objet 'pychrysalide.analysis.BlockList'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -229,13 +365,13 @@ PyTypeObject *get_python_instr_block_type(void)
* *
******************************************************************************/
-bool ensure_python_instr_block_is_registered(void)
+bool ensure_python_block_list_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'InstrBlock' */
+ PyTypeObject *type; /* Type Python 'BlockList' */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- type = get_python_instr_block_type();
+ type = get_python_block_list_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
@@ -243,7 +379,7 @@ bool ensure_python_instr_block_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BLOCK_LIST, type, &PyGObject_Type))
return false;
}