From 526985383c4e601775b4f04b273566b8ab930a58 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 23 Feb 2020 23:51:40 +0100
Subject: Defined a working way to build routines from Python.

---
 plugins/pychrysalide/analysis/routine.c | 126 +++++++++++++++++++++++++-------
 src/analysis/disass/routines.c          |   2 +
 src/analysis/routine.c                  |   2 +
 3 files changed, 105 insertions(+), 25 deletions(-)

diff --git a/plugins/pychrysalide/analysis/routine.c b/plugins/pychrysalide/analysis/routine.c
index 0c0ef89..dee07f7 100644
--- a/plugins/pychrysalide/analysis/routine.c
+++ b/plugins/pychrysalide/analysis/routine.c
@@ -50,6 +50,9 @@ static PyObject *py_binary_routine_to_str(PyObject *);
 /* Crée un nouvel objet Python de type 'BinRoutine'. */
 static PyObject *py_binary_routine_new(PyTypeObject *, PyObject *, PyObject *);
 
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_binary_routine_init(PyObject *, PyObject *, PyObject *);
+
 /* Fournit le groupe d'appartenance d'une routine donnée. */
 static PyObject *py_binary_routine_get_namespace(PyObject *, void *);
 
@@ -143,6 +146,49 @@ static PyObject *py_binary_routine_new(PyTypeObject *type, PyObject *args, PyObj
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_binary_routine_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+
+    /**
+     * Si cette fonction n'est pas définie, l'initialisation de l'instance
+     * se réalise via py_binary_symbol_init(), et l'interface attend là
+     * des arguments...
+     */
+
+#define BINARY_ROUTINE_DOC                                                      \
+    "BinRoutine is an object for a function in a binary.\n"                     \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    BinRoutine()"                                                          \
+    "\n"                                                                        \
+    "As routines can be built from demangling, with no information other than"  \
+    " a name at first glance, the usual process is to create a routine object"  \
+    " and to define its core properties (namely a location range and a symbol"  \
+    " type) after this operation."
+
+    result = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
@@ -160,6 +206,13 @@ static PyObject *py_binary_routine_get_namespace(PyObject *self, void *closure)
     GBinRoutine *routine;                   /* Elément à consulter         */
     GDataType *ns;                          /* Espace de noms              */
 
+#define BINARY_ROUTINE_NAMESPACE_ATTRIB PYTHON_GETSET_DEF_FULL      \
+(                                                                   \
+    namespace, py_binary_routine,                                   \
+    "Namespace of the routine, provided as a"                       \
+    " pychrysalide.analysis.DataType instance, or None if any."     \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
     ns = g_binary_routine_get_namespace(routine);
 
@@ -258,6 +311,12 @@ static PyObject *py_binary_routine_get_name(PyObject *self, void *closure)
     GBinRoutine *routine;                   /* Elément à consulter         */
     const char *name;                       /* Désignation courante        */
 
+#define BINARY_ROUTINE_NAME_ATTRIB PYTHON_GETSET_DEF_FULL       \
+(                                                               \
+    name, py_binary_routine,                                    \
+    "String for the raw name of the routine or None if any."    \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
     name = g_binary_routine_get_name(routine);
 
@@ -330,6 +389,17 @@ static PyObject *py_binary_routine_get_typed_name(PyObject *self, void *closure)
     GBinRoutine *routine;                   /* Elément à consulter         */
     GDataType *name;                        /* Type de nom                 */
 
+#define BINARY_ROUTINE_TYPED_NAME_ATTRIB PYTHON_GETSET_DEF_FULL         \
+(                                                                       \
+    typed_name, py_binary_routine,                                      \
+    "Typed name of the routine, provided as a"                          \
+    " pychrysalide.analysis.DataType instance, or None if any.\n"       \
+    "\n"                                                                \
+    "When a routine is built from a demangling operation, its final"    \
+    " name carries some type information. This kind of information can" \
+    " be retrived thanks to this attribute."                            \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
     name = g_binary_routine_get_typed_name(routine);
 
@@ -413,6 +483,13 @@ static PyObject *py_binary_routine_get_return_type(PyObject *self, void *closure
     GBinRoutine *routine;                   /* Elément à consulter         */
     GDataType *ret;                         /* Type de retour              */
 
+#define BINARY_ROUTINE_RETURN_TYPE_ATTRIB PYTHON_GETSET_DEF_FULL    \
+(                                                                   \
+    return_type, py_binary_routine,                                 \
+    "Return of the routine, provided as a"                          \
+    " pychrysalide.analysis.DataType instance, or None if any."     \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
     ret = g_binary_routine_get_return_type(routine);
 
@@ -498,6 +575,13 @@ static PyObject *py_binary_routine_get_args(PyObject *self, void *closure)
     size_t i;                               /* Boucle de parcours          */
     GBinVariable *arg;                      /* Argument à transcrire       */
 
+#define BINARY_ROUTINE_ARGS_ATTRIB PYTHON_GET_DEF_FULL      \
+(                                                           \
+    args, py_binary_routine,                                \
+    "Arguments for the routine, provided as a tuple of"     \
+    " pychrysalide.analysis.BinVariable instances."         \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
 
     count = g_binary_routine_get_args_count(routine);
@@ -538,6 +622,14 @@ static PyObject *py_binary_routine_get_basic_blocks(PyObject *self, void *closur
     GBinRoutine *routine;                   /* Version native              */
     GBlockList *blocks;                     /* Blocs basiques de routine   */
 
+#define BINARY_ROUTINE_BASIC_BLOCKS_ATTRIB PYTHON_GETSET_DEF_FULL           \
+(                                                                           \
+    basic_blocks, py_binary_routine,                                        \
+    "Basic blocks for the routine.\n"                                       \
+    "\n"                                                                    \
+    "This list is managed by a pychrysalide.analysis.BlockList instance."   \
+)
+
     routine = G_BIN_ROUTINE(pygobject_get(self));
     blocks = g_binary_routine_get_basic_blocks(routine);
 
@@ -602,30 +694,12 @@ PyTypeObject *get_python_binary_routine_type(void)
     };
 
     static PyGetSetDef py_binary_routine_getseters[] = {
-        {
-            "namespace", py_binary_routine_get_namespace, py_binary_routine_set_namespace,
-            "Namespace for the routine, None if any.", NULL
-        },
-        {
-            "name", py_binary_routine_get_name, py_binary_routine_set_name,
-            "Name of the current routine.", NULL
-        },
-        {
-            "typed_name", py_binary_routine_get_typed_name, py_binary_routine_set_typed_name,
-            "Name of the current routine provided by a type.", NULL
-        },
-        {
-            "ret", py_binary_routine_get_return_type, py_binary_routine_set_return_type,
-            "Return type of the routine, None if any.", NULL
-        },
-        {
-            "args", py_binary_routine_get_args, NULL,
-            "Arguments for the routine.", NULL
-        },
-        {
-            "basic_blocks", py_binary_routine_get_basic_blocks, py_binary_routine_set_basic_blocks,
-            "Basic blocks of the binary routine.", NULL
-        },
+        BINARY_ROUTINE_NAMESPACE_ATTRIB,
+        BINARY_ROUTINE_NAME_ATTRIB,
+        BINARY_ROUTINE_TYPED_NAME_ATTRIB,
+        BINARY_ROUTINE_RETURN_TYPE_ATTRIB,
+        BINARY_ROUTINE_ARGS_ATTRIB,
+        BINARY_ROUTINE_BASIC_BLOCKS_ATTRIB,
         { NULL }
     };
 
@@ -639,10 +713,12 @@ PyTypeObject *get_python_binary_routine_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide binary routine",
+        .tp_doc         = BINARY_ROUTINE_DOC,
 
         .tp_methods     = py_binary_routine_methods,
         .tp_getset      = py_binary_routine_getseters,
+
+        .tp_init        = py_binary_routine_init,
         .tp_new         = py_binary_routine_new
 
     };
diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c
index 5fc1dcd..be68d68 100644
--- a/src/analysis/disass/routines.c
+++ b/src/analysis/disass/routines.c
@@ -405,6 +405,8 @@ void g_routines_study_handle_blocks(GRoutinesStudy *study, GBinRoutine *routine,
 
     rank_routine_blocks(routine);
 
+    g_object_unref(G_OBJECT(blocks));
+
     /* Nettoyage final */
 
     end_dragon_knight(knight);
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index 02bd167..8c38ff1 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -792,6 +792,8 @@ void g_binary_routine_set_basic_blocks(GBinRoutine *routine, GBlockList *blocks)
 {
     g_clear_object(&routine->blocks);
 
+    g_object_ref(G_OBJECT(blocks));
+
     routine->blocks = blocks;
 
 }
-- 
cgit v0.11.2-87-g4458