From e957ec4ff043f6025d6a993bb6e97fe7d57a8bd6 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 13 Dec 2018 23:55:39 +0100
Subject: Extended the Python API for code blocks.

---
 plugins/pychrysalide/analysis/block.c        | 139 ++++++++++++++++++++++++---
 plugins/pychrysalide/analysis/disass/block.c |  44 ++++++++-
 2 files changed, 171 insertions(+), 12 deletions(-)

diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index a091a6d..563b4d2 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -46,6 +46,12 @@ 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 *);
 
+/* Fournit les détails d'une source de bloc de code. */
+static PyObject *py_code_block_get_sources(PyObject *, void *);
+
+/* Fournit les détails des destinations de bloc de code. */
+static PyObject *py_code_block_get_destinations(PyObject *, void *);
+
 
 
 /* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */
@@ -54,8 +60,8 @@ static PyObject *py_code_block_get_rank(PyObject *, void *);
 /* 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 des blocs de code inclus dans une liste. */
-static PyObject *py_block_list_get_items(PyObject *, void *);
+/* Itère sur l'ensemble des blocs de code inclus dans une liste. */
+static PyObject *py_block_list_iter(PyObject *);
 
 
 
@@ -126,6 +132,110 @@ static PyObject *py_code_block_get_rank(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit les détails d'une source de bloc de code.            *
+*                                                                             *
+*  Retour      : Liens déterminés vers des bloc de code de source.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_code_block_get_sources(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GCodeBlock *block;                      /* Bloc de code à consulter    */
+    size_t count;                           /* Quantité de blocs liés      */
+    size_t i;                               /* Boucle de parcours          */
+    const block_link_t *link;               /* Informations conservées     */
+    PyObject *info;                         /* Informations à transmettre  */
+
+    block = G_CODE_BLOCK(pygobject_get(self));
+
+    g_code_block_lock_src(block);
+
+    count = g_code_block_count_sources(block);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        link = g_code_block_get_source(block, i);
+
+        info = PyTuple_New(2);
+
+        PyTuple_SetItem(info, 0, pygobject_new(G_OBJECT(link->linked)));
+        PyTuple_SetItem(info, 1, PyLong_FromUnsignedLong(link->type));
+
+        PyTuple_SetItem(result, i, info);
+
+        unref_block_link(link);
+
+    }
+
+    g_code_block_unlock_src(block);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit les détails des destinations de bloc de code.        *
+*                                                                             *
+*  Retour      : Liens déterminés vers des bloc de code de destination.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_code_block_get_destinations(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GCodeBlock *block;                      /* Bloc de code à consulter    */
+    size_t count;                           /* Quantité de blocs liés      */
+    size_t i;                               /* Boucle de parcours          */
+    const block_link_t *link;               /* Informations conservées     */
+    PyObject *info;                         /* Informations à transmettre  */
+
+    block = G_CODE_BLOCK(pygobject_get(self));
+
+    g_code_block_lock_dest(block);
+
+    count = g_code_block_count_destinations(block);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        link = g_code_block_get_destination(block, i);
+
+        info = PyTuple_New(2);
+
+        PyTuple_SetItem(info, 0, pygobject_new(G_OBJECT(link->linked)));
+        PyTuple_SetItem(info, 1, PyLong_FromUnsignedLong(link->type));
+
+        PyTuple_SetItem(result, i, info);
+
+        unref_block_link(link);
+
+    }
+
+    g_code_block_unlock_dest(block);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -151,6 +261,14 @@ PyTypeObject *get_python_code_block_type(void)
             "rank", py_code_block_get_rank, NULL,
             "Rang of the code block.", NULL
         },
+        {
+            "sources", py_code_block_get_sources, NULL,
+            "List of source blocks.", NULL
+        },
+        {
+            "destinations", py_code_block_get_destinations, NULL,
+            "List of destination blocks.", NULL
+        },
         { NULL }
     };
 
@@ -262,18 +380,17 @@ static PyObject *py_block_list_find_by_starting_addr(PyObject *self, PyObject *a
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self    = objet Python concerné par l'appel.                 *
-*                closure = non utilisé ici.                                   *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
 *                                                                             *
-*  Description : Fournit l'ensemble des blocs de code inclus dans une liste.  *
+*  Description : Itère sur l'ensemble des blocs de code inclus dans une liste.*
 *                                                                             *
-*  Retour      : Liste de blocs de code.                                      *
+*  Retour      : Liste de blocs de code capable d'itération.                  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_block_list_get_items(PyObject *self, void *closure)
+static PyObject *py_block_list_iter(PyObject *self)
 {
     PyObject *result;                       /* Trouvailles à retourner     */
     GBlockList *list;                       /* Liste de blocs manipulée    */
@@ -297,6 +414,8 @@ static PyObject *py_block_list_get_items(PyObject *self, void *closure)
 
     }
 
+    result = PySeqIter_New(result);
+
     return result;
 
 }
@@ -326,10 +445,6 @@ PyTypeObject *get_python_block_list_type(void)
     };
 
     static PyGetSetDef py_block_list_getseters[] = {
-        {
-            "items", py_block_list_get_items, NULL,
-            "All code blocks included in the list.", NULL
-        },
         { NULL }
     };
 
@@ -343,6 +458,8 @@ PyTypeObject *get_python_block_list_type(void)
 
         .tp_doc         = "PyChrysalide basic block",
 
+        .tp_iter        = py_block_list_iter,
+
         .tp_methods     = py_block_list_methods,
         .tp_getset      = py_block_list_getseters,
 
diff --git a/plugins/pychrysalide/analysis/disass/block.c b/plugins/pychrysalide/analysis/disass/block.c
index 6855368..38e65a1 100644
--- a/plugins/pychrysalide/analysis/disass/block.c
+++ b/plugins/pychrysalide/analysis/disass/block.c
@@ -40,7 +40,8 @@
 /* ------------------------ MISE EN PLACE DES BLOCS BASIQUES ------------------------ */
 
 
-
+/* Fournit les instructions limites d'un bloc basique. */
+static PyObject *py_basic_block_get_boundaries(PyObject *, void *);
 
 
 
@@ -51,6 +52,43 @@
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit les instructions limites d'un bloc basique.          *
+*                                                                             *
+*  Retour      : Première et dernière instructions du bloc.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_basic_block_get_boundaries(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GBasicBlock *block;                     /* Bloc de code à consulter    */
+    GArchInstruction *first;                /* Première instruction de bloc*/
+    GArchInstruction *last;                 /* Dernière instruction de bloc*/
+
+    block = G_BASIC_BLOCK(pygobject_get(self));
+
+    g_basic_block_get_boundaries(block, &first, &last);
+
+    result = PyTuple_New(2);
+
+    PyTuple_SetItem(result, 0, pygobject_new(G_OBJECT(first)));
+    PyTuple_SetItem(result, 1, pygobject_new(G_OBJECT(last)));
+
+    g_object_unref(G_OBJECT(first));
+    g_object_unref(G_OBJECT(last));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -68,6 +106,10 @@ PyTypeObject *get_python_basic_block_type(void)
     };
 
     static PyGetSetDef py_basic_block_getseters[] = {
+        {
+            "boundaries", py_basic_block_get_boundaries, NULL,
+            "First and last instructions of the basic block.", NULL
+        },
         { NULL }
     };
 
-- 
cgit v0.11.2-87-g4458