From d8eb070be32504949ad55fd644d9f1a69df1e05d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 21 May 2020 22:43:30 +0200
Subject: Written a proper documentation for the binary format Python bindings.

---
 plugins/pychrysalide/analysis/constants.c |  56 ++++
 plugins/pychrysalide/analysis/constants.h |   3 +
 plugins/pychrysalide/arch/constants.c     |  56 ++++
 plugins/pychrysalide/arch/constants.h     |   3 +
 plugins/pychrysalide/format/constants.c   |  56 ++++
 plugins/pychrysalide/format/constants.h   |   3 +
 plugins/pychrysalide/format/format.c      | 435 +++++++++++++++++++++++++-----
 plugins/pychrysalide/format/module.c      |   9 +-
 src/format/format.c                       |   6 +-
 9 files changed, 559 insertions(+), 68 deletions(-)

diff --git a/plugins/pychrysalide/analysis/constants.c b/plugins/pychrysalide/analysis/constants.c
index a162ac7..9bc3e9f 100644
--- a/plugins/pychrysalide/analysis/constants.c
+++ b/plugins/pychrysalide/analysis/constants.c
@@ -98,3 +98,59 @@ bool define_analysis_content_constants(PyTypeObject *type)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en constante SourceEndian.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_source_endian(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to SourceEndian");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if (value > SRE_BIG)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for SourceEndian");
+                result = 0;
+            }
+
+            else
+                *((SourceEndian *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/constants.h b/plugins/pychrysalide/analysis/constants.h
index c4da054..2ab1f0a 100644
--- a/plugins/pychrysalide/analysis/constants.h
+++ b/plugins/pychrysalide/analysis/constants.h
@@ -33,6 +33,9 @@
 /* Définit les constantes relatives aux contenus binaires. */
 bool define_analysis_content_constants(PyTypeObject *);
 
+/* Tente de convertir en constante SourceEndian. */
+int convert_to_source_endian(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_CONSTANTS_H */
diff --git a/plugins/pychrysalide/arch/constants.c b/plugins/pychrysalide/arch/constants.c
index f738ec3..04d0917 100644
--- a/plugins/pychrysalide/arch/constants.c
+++ b/plugins/pychrysalide/arch/constants.c
@@ -192,3 +192,59 @@ bool define_proc_context_constants(PyTypeObject *type)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en constante DisassPriorityLevel.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_disass_priority_level(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to DisassPriorityLevel");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if (value > DPL_COUNT)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for DisassPriorityLevel");
+                result = 0;
+            }
+
+            else
+                *((DisassPriorityLevel *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/arch/constants.h b/plugins/pychrysalide/arch/constants.h
index f047c56..24b3908 100644
--- a/plugins/pychrysalide/arch/constants.h
+++ b/plugins/pychrysalide/arch/constants.h
@@ -40,6 +40,9 @@ bool define_arch_vmpa_constants(PyTypeObject *);
 /* Définit les constantes relatives aux contextes. */
 bool define_proc_context_constants(PyTypeObject *);
 
+/* Tente de convertir en constante DisassPriorityLevel. */
+int convert_to_disass_priority_level(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ARCH_CONSTANTS_H */
diff --git a/plugins/pychrysalide/format/constants.c b/plugins/pychrysalide/format/constants.c
index 9669b46..df40479 100644
--- a/plugins/pychrysalide/format/constants.c
+++ b/plugins/pychrysalide/format/constants.c
@@ -89,6 +89,62 @@ bool define_binary_format_constants(PyTypeObject *type)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en constante BinaryFormatError.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_binary_format_error(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to BinaryFormatError");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if ((value & (BFE_SPECIFICATION | BFE_STRUCTURE)) != 0)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for BinaryFormatError");
+                result = 0;
+            }
+
+            else
+                *((BinaryFormatError *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : type = type dont le dictionnaire est à compléter.            *
 *                                                                             *
 *  Description : Définit les constantes pour les symboles binaires.           *
diff --git a/plugins/pychrysalide/format/constants.h b/plugins/pychrysalide/format/constants.h
index bbed6ae..ffc1802 100644
--- a/plugins/pychrysalide/format/constants.h
+++ b/plugins/pychrysalide/format/constants.h
@@ -34,6 +34,9 @@
 /* Définit les constantes pour les formats binaires. */
 bool define_binary_format_constants(PyTypeObject *);
 
+/* Tente de convertir en constante BinaryFormatError. */
+int convert_to_binary_format_error(PyObject *, void *);
+
 /* Définit les constantes pour les symboles binaires. */
 bool define_binary_symbol_constants(PyTypeObject *);
 
diff --git a/plugins/pychrysalide/format/format.c b/plugins/pychrysalide/format/format.c
index 34826cf..1b34b38 100644
--- a/plugins/pychrysalide/format/format.c
+++ b/plugins/pychrysalide/format/format.c
@@ -28,7 +28,9 @@
 #include <pygobject.h>
 
 
-#include <format/format.h>
+#include <i18n.h>
+#include <format/format-int.h>
+#include <plugins/dt.h>
 
 
 #include "constants.h"
@@ -38,7 +40,27 @@
 #include "symiter.h"
 #include "../access.h"
 #include "../helpers.h"
+#include "../analysis/constants.h"
+#include "../analysis/content.h"
 #include "../arch/vmpa.h"
+#include "../arch/constants.h"
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_binary_format_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise la classe des descriptions de fichier binaire. */
+static void py_binary_format_init_gclass(GBinFormatClass *, gpointer);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_binary_format_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le boutisme employé par le format binaire analysé. */
+static SourceEndian py_binary_format_get_endianness_wrapper(const GBinFormat *);
 
 
 
@@ -78,6 +100,9 @@ static PyObject *py_binary_format_resolve_symbol(PyObject *, PyObject *);
 /* Fournit les particularités du format. */
 static PyObject *py_binary_format_get_flags(PyObject *, void *);
 
+/* Indique le boutisme employé par le format binaire analysé. */
+static PyObject *py_binary_format_get_endianness(PyObject *, void *);
+
 /* Fournit la liste de tous les symboles détectés. */
 static PyObject *py_binary_format_get_symbols(PyObject *, void *);
 
@@ -94,9 +119,182 @@ static PyObject *py_binary_format_get_errors(PyObject *, void *);
 
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                          GLUE POUR CREATION DEPUIS PYTHON                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type du nouvel objet à mettre en place.               *
+*                args = éventuelle liste d'arguments.                         *
+*                kwds = éventuel dictionnaire de valeurs mises à disposition. *
+*                                                                             *
+*  Description : Accompagne la création d'une instance dérivée en Python.     *
+*                                                                             *
+*  Retour      : Nouvel objet Python mis en place ou NULL en cas d'échec.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static PyObject *py_binary_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;                       /* Objet à retourner           */
+    PyTypeObject *base;                     /* Type de base à dériver      */
+    bool first_time;                        /* Evite les multiples passages*/
+    GType gtype;                            /* Nouveau type de processeur  */
+    bool status;                            /* Bilan d'un enregistrement   */
 
+    /* Validations diverses */
 
+    base = get_python_known_format_type();
+
+    if (type == base)
+    {
+        result = NULL;
+        PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+        goto exit;
+    }
+
+    /* Mise en place d'un type dédié */
+
+    first_time = (g_type_from_name(type->tp_name) == 0);
+
+    gtype = build_dynamic_type(G_TYPE_BIN_FORMAT, type->tp_name,
+                               (GClassInitFunc)py_binary_format_init_gclass, NULL, NULL);
+
+    if (first_time)
+    {
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+
+        if (!status)
+        {
+            result = NULL;
+            goto exit;
+        }
+
+    }
+
+    /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+    result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                unused = données non utilisées ici.                          *
+*                                                                             *
+*  Description : Initialise la classe générique des processeurs.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_binary_format_init_gclass(GBinFormatClass *class, gpointer unused)
+{
+    class->get_endian = py_binary_format_get_endianness_wrapper;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_format_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define BINARY_FORMAT_DOC                                               \
+    "The BinFormat class is the major poart of binary format support."  \
+    " It is the core class used by loading most of the binary files.\n" \
+    "\n"                                                                \
+    "One item has to be defined as class attribute in the final"        \
+    " class:\n"                                                         \
+    "* *_endianness*: a pychrysalide.analysis.BinContent.SourceEndian"  \
+    " value indicating the endianness of the format.\n"                 \
+    "\n"                                                                \
+    "Calls to the *__init__* constructor of this abstract object expect"\
+    " no particular argument.\n"
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description du format connu à consulter.            *
+*                                                                             *
+*  Description : Indique le boutisme employé par le format binaire analysé.   *
+*                                                                             *
+*  Retour      : Boutisme associé au format.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static SourceEndian py_binary_format_get_endianness_wrapper(const GBinFormat *format)
+{
+    SourceEndian result;                    /* Boutisme à retourner        */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pyret;                        /* Valeur retournée            */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = SRE_LITTLE;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(format));
+
+    if (PyObject_HasAttrString(pyobj, "_endianness"))
+    {
+        pyret = PyObject_GetAttrString(pyobj, "_endianness");
+
+        if (pyret != NULL)
+        {
+            ret = convert_to_source_endian(pyret, &result);
+
+            if (ret != 1)
+                result = SRE_LITTLE;
+
+            Py_DECREF(pyret);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -266,11 +464,22 @@ static PyObject *py_binary_format_has_flag(PyObject *self, PyObject *args)
 static PyObject *py_binary_format_register_code_point(PyObject *self, PyObject *args)
 {
     unsigned long long pt;                  /* Adresse virtuelle du point  */
-    unsigned long level;                    /* Nature du point fourni      */
+    DisassPriorityLevel level;              /* Nature du point fourni      */
     int ret;                                /* Bilan de lecture des args.  */
     GBinFormat *format;                     /* Format de binaire manipulé  */
 
-    ret = PyArg_ParseTuple(args, "Kk", &pt, &level);
+#define BINARY_FORMAT_REGISTER_CODE_POINT_METHOD PYTHON_METHOD_DEF  \
+(                                                                   \
+    register_code_point, "$self, point, level, /",                  \
+    METH_VARARGS, py_binary_format,                                 \
+    "Register a virtual address as entry point or basic point.\n"   \
+    "\n"                                                            \
+    "The point is an integer value for the virtual memory location" \
+    " of the new (entry) point. The type of this entry has to be a" \
+    " pychrysalide.arch.ProcContext.DisassPriorityLevel value."     \
+)
+
+    ret = PyArg_ParseTuple(args, "kO&", &pt, convert_to_disass_priority_level, &level);
     if (!ret) return NULL;
 
     format = G_BIN_FORMAT(pygobject_get(self));
@@ -303,6 +512,15 @@ static PyObject *py_binary_format_add_symbol(PyObject *self, PyObject *args)
     GBinFormat *format;                     /* Format de binaire manipulé  */
     bool added;                             /* Bilan de l'appel interne    */
 
+#define BINARY_FORMAT_ADD_SYMBOL_METHOD PYTHON_METHOD_DEF               \
+(                                                                       \
+    add_symbol, "$self, symbol, /",                                     \
+    METH_VARARGS, py_binary_format,                                     \
+    "Register a new symbol for the format.\n"                           \
+    "\n"                                                                \
+    "The symbol has to be a pychrysalide.format.BinSymbol instance."    \
+)
+
     ret = PyArg_ParseTuple(args, "O&", convert_to_binary_symbol, &symbol);
     if (!ret) return NULL;
 
@@ -339,6 +557,15 @@ static PyObject *py_binary_format_remove_symbol(PyObject *self, PyObject *args)
     int ret;                                /* Bilan de lecture des args.  */
     GBinFormat *format;                     /* Format de binaire manipulé  */
 
+#define BINARY_FORMAT_REMOVE_SYMBOL_METHOD PYTHON_METHOD_DEF            \
+(                                                                       \
+    remove_symbol, "$self, symbol, /",                                  \
+    METH_VARARGS, py_binary_format,                                     \
+    "Unregister a symbol from the format.\n"                            \
+    "\n"                                                                \
+    "The symbol has to be a pychrysalide.format.BinSymbol instance."    \
+)
+
     ret = PyArg_ParseTuple(args, "O&", convert_to_binary_symbol, &symbol);
     if (!ret) return NULL;
 
@@ -370,21 +597,28 @@ static PyObject *py_binary_format_remove_symbol(PyObject *self, PyObject *args)
 static PyObject *py_binary_format_find_symbol_by_label(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Valeur à retourner          */
-    PyObject *label;                        /* Etiquette à retrouver       */
+    const char *label;                      /* Etiquette à retrouver       */
     int ret;                                /* Bilan de lecture des args.  */
     GBinFormat *format;                     /* Format de binaire manipulé  */
     GBinSymbol *symbol;                     /* Enventuel symbole trouvé    */
     bool found;                             /* Bilan de la recherche       */
 
-    ret = PyArg_ParseTuple(args, "O", &label);
-    if (!ret) return NULL;
+#define BINARY_FORMAT_FIND_SYMBOL_BY_LABEL_METHOD PYTHON_METHOD_DEF     \
+(                                                                       \
+    find_symbol_by_label, "$self, label, /",                            \
+    METH_VARARGS, py_binary_format,                                     \
+    "Find the symbol with a given label, provided as a string.\n"       \
+    "\n"                                                                \
+    "The result is a pychrysalide.format.BinSymbol instance, or None"   \
+    " if no symbol was found."                                          \
+)
 
-    ret = PyUnicode_Check(label);
+    ret = PyArg_ParseTuple(args, "s", &label);
     if (!ret) return NULL;
 
     format = G_BIN_FORMAT(pygobject_get(self));
 
-    found = g_binary_format_find_symbol_by_label(format, PyUnicode_DATA(label), &symbol);
+    found = g_binary_format_find_symbol_by_label(format, label, &symbol);
 
     if (found)
     {
@@ -424,6 +658,17 @@ static PyObject *py_binary_format_find_symbol_at(PyObject *self, PyObject *args)
     GBinSymbol *symbol;                     /* Enventuel symbole trouvé    */
     bool found;                             /* Bilan de la recherche       */
 
+#define BINARY_FORMAT_FIND_SYMBOL_AT_METHOD PYTHON_METHOD_DEF       \
+(                                                                   \
+    find_symbol_at, "$self, addr, /",                               \
+    METH_VARARGS, py_binary_format,                                 \
+    "Find the symbol located at a given address, provided as a"     \
+    " pychrysalide.arch.vmpa instance.\n"                           \
+    "\n"                                                            \
+    "The result is a pychrysalide.format.BinSymbol instance, or"    \
+    " None if no symbol was found."                                 \
+)
+
     format = G_BIN_FORMAT(pygobject_get(self));
 
     conv.format = G_IS_EXE_FORMAT(format) ? G_EXE_FORMAT(format) : NULL;
@@ -471,6 +716,17 @@ static PyObject *py_binary_format_find_next_symbol_at(PyObject *self, PyObject *
     GBinSymbol *symbol;                     /* Enventuel symbole trouvé    */
     bool found;                             /* Bilan de la recherche       */
 
+#define BINARY_FORMAT_FIND_NEXT_SYMBOL_AT_METHOD PYTHON_METHOD_DEF  \
+(                                                                   \
+    find_next_symbol_at, "$self, addr, /",                          \
+    METH_VARARGS, py_binary_format,                                 \
+    "Find the symbol next to the one found at a given address,"     \
+    " provided as a pychrysalide.arch.vmpa instance.\n"             \
+    "\n"                                                            \
+    "The result is a pychrysalide.format.BinSymbol instance, or"    \
+    " None if no symbol was found."                                 \
+)
+
     format = G_BIN_FORMAT(pygobject_get(self));
 
     conv.format = G_IS_EXE_FORMAT(format) ? G_EXE_FORMAT(format) : NULL;
@@ -520,6 +776,21 @@ static PyObject *py_binary_format_resolve_symbol(PyObject *self, PyObject *args)
     phys_t diff;                            /* Décalage éventuel mesuré    */
     bool found;                             /* Bilan de la recherche       */
 
+#define BINARY_FORMAT_RESOLVE_SYMBOL_METHOD PYTHON_METHOD_DEF       \
+(                                                                   \
+    resolve_symbol, "$self, addr, strict, /",                       \
+    METH_VARARGS, py_binary_format,                                 \
+    "Search for a position inside a symbol by a given address.\n"   \
+    "\n"                                                            \
+    "The result is a couple of (pychrysalide.format.BinSymbol,"     \
+    " offset) values, or None if no symbol was found. The offset"   \
+    " is the distance between the start location of the symbol and" \
+    " the location provided as argument.\n"                         \
+    "\n"                                                            \
+    "If the search is run in strict mode, then the offset is"       \
+    " always 0 upon success."                                       \
+)
+
     format = G_BIN_FORMAT(pygobject_get(self));
 
     conv.format = G_IS_EXE_FORMAT(format) ? G_EXE_FORMAT(format) : NULL;
@@ -587,6 +858,42 @@ static PyObject *py_binary_format_get_flags(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique le boutisme employé par le format binaire analysé.   *
+*                                                                             *
+*  Retour      : Boutisme associé au format.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_format_get_endianness(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GBinFormat *format;                     /* Elément à consulter         */
+    SourceEndian endianness;                /* Boutisme du format          */
+
+#define BINARY_FORMAT_ENDIANNESS_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                               \
+    endianness, py_binary_format,                               \
+    "Endianness of the format. The return value is of type"     \
+    " pychrysalide.analysis.BinContent.SourceEndian."           \
+)
+
+    format = G_BIN_FORMAT(pygobject_get(self));
+    endianness = g_binary_format_get_endianness(format);
+
+    result = cast_with_constants_group_from_type(get_python_binary_content_type(), "SourceEndian", endianness);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self    = classe représentant un format binaire.             *
 *                closure = adresse non utilisée ici.                          *
 *                                                                             *
@@ -604,6 +911,16 @@ static PyObject *py_binary_format_get_symbols(PyObject *self, void *closure)
     PyTypeObject *iterator_type;            /* Type Python de l'itérateur  */
     PyObject *args;                         /* Liste des arguments d'appel */
 
+#define BINARY_FORMAT_SYMBOLS_ATTRIB PYTHON_GET_DEF_FULL            \
+(                                                                   \
+    symbols, py_binary_format,                                      \
+    "Iterable list of all symbols found in the binary format.\n"    \
+    "\n"                                                            \
+    "The returned iterator is a pychrysalide.format.SymIterator"    \
+    " instance and remains valid until the list from the format"    \
+    " does not change."                                             \
+)
+
     iterator_type = get_python_sym_iterator_type();
 
     args = Py_BuildValue("On", self, 0);
@@ -644,7 +961,20 @@ static PyObject *py_binary_format_add_error(PyObject *self, PyObject *args)
     int ret;                                /* Bilan de lecture des args.  */
     GBinFormat *format;                     /* Format binaire manipulé     */
 
-    ret = PyArg_ParseTuple(args, "IO&s", &type, convert_any_to_vmpa, &addr, &desc);
+#define BINARY_FORMAT_ADD_ERROR_METHOD PYTHON_METHOD_DEF            \
+(                                                                   \
+    add_error, "$self, type, addr, desc, /",                        \
+    METH_VARARGS, py_binary_format,                                 \
+    "Extend the list of detected errors linked to the format.\n"    \
+    "\n"                                                            \
+    "The type of error has to be one of the"                        \
+    " pychrysalide.format.BinFormat.BinaryFormatError flags. The"   \
+    " location of the error is a pychrysalide.arch.vmpa instance"   \
+    " and a one-line description should give some details about"    \
+    " what has failed."                                             \
+)
+
+    ret = PyArg_ParseTuple(args, "O&O&s", convert_to_binary_format_error, &type, convert_any_to_vmpa, &addr, &desc);
     if (!ret) return NULL;
 
     format = G_BIN_FORMAT(pygobject_get(self));
@@ -683,8 +1013,19 @@ static PyObject *py_binary_format_get_errors(PyObject *self, void *closure)
     BinaryFormatError type;                 /* Type d'erreur détectée      */
     vmpa2t addr;                            /* Position d'une erreur       */
     char *desc;                             /* Description d'une erreur    */
+    PyObject *py_type;                      /* Version Python du type      */
     PyObject *error;                        /* Nouvelle erreur à rajouter  */
 
+#define BINARY_FORMAT_ERRORS_ATTRIB PYTHON_GET_DEF_FULL                             \
+(                                                                                   \
+    errors, py_binary_format,                                                       \
+    "List of all detected errors which occurred while loading the binary.\n"        \
+    "\n"                                                                            \
+    "The result is a tuple of (pychrysalide.format.BinFormat.BinaryFormatError,"    \
+    " pychrysalide.arch.vmpa, string) values, providing a location and a"           \
+    " description for each error."                                                  \
+)
+
     format = G_BIN_FORMAT(pygobject_get(self));
 
     g_binary_format_lock_errors(format);
@@ -702,7 +1043,9 @@ static PyObject *py_binary_format_get_errors(PyObject *self, void *closure)
         g_binary_format_get_error(format, i, &type, &addr, &desc);
 #endif
 
-        error = Py_BuildValue("IO&s", type, build_from_internal_vmpa, &addr, desc);
+        py_type = cast_with_constants_group_from_type(get_python_binary_format_type(), "BinaryFormatError", type);
+        error = Py_BuildValue("OO&s", py_type, build_from_internal_vmpa, &addr, desc);
+        Py_DECREF(py_type);
 
         PyTuple_SetItem(result, i, error);
 
@@ -715,10 +1058,6 @@ static PyObject *py_binary_format_get_errors(PyObject *self, void *closure)
 }
 
 
-
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : -                                                            *
@@ -737,59 +1076,22 @@ PyTypeObject *get_python_binary_format_type(void)
         BINARY_FORMAT_SET_FLAG_METHOD,
         BINARY_FORMAT_UNSET_FLAG_METHOD,
         BINARY_FORMAT_HAS_FLAG_METHOD,
-        {
-            "register_code_point", py_binary_format_register_code_point,
-            METH_VARARGS,
-            "register_code_point($self, pt, entry, /)\n--\n\nRegister a virtual address as entry point or basic point."
-        },
-        {
-            "add_symbol", py_binary_format_add_symbol,
-            METH_VARARGS,
-            "add_symbol($self, symbol, /)\n--\n\nRegister a new symbol for the format."
-        },
-        {
-            "remove_symbol", py_binary_format_remove_symbol,
-            METH_VARARGS,
-            "remove_symbol($self, symbol, /)\n--\n\nUnregister a symbol from the format."
-        },
-        {
-            "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."
-        },
-        {
-            "find_next_symbol_at", py_binary_format_find_next_symbol_at,
-            METH_VARARGS,
-            "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, strict, /)\n--\n\nSearch a position inside a routine by a given address."
-        },
-        {
-            "add_error", py_binary_format_add_error,
-            METH_VARARGS,
-            "add_error($self, type, addr, desc, /)\n--\n\nExtend the list of detected disassembling errors."
-        },
+        BINARY_FORMAT_REGISTER_CODE_POINT_METHOD,
+        BINARY_FORMAT_ADD_SYMBOL_METHOD,
+        BINARY_FORMAT_REMOVE_SYMBOL_METHOD,
+        BINARY_FORMAT_FIND_SYMBOL_BY_LABEL_METHOD,
+        BINARY_FORMAT_FIND_SYMBOL_AT_METHOD,
+        BINARY_FORMAT_FIND_NEXT_SYMBOL_AT_METHOD,
+        BINARY_FORMAT_RESOLVE_SYMBOL_METHOD,
+        BINARY_FORMAT_ADD_ERROR_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_bin_format_getseters[] = {
         BINARY_FORMAT_FLAGS_ATTRIB,
-        {
-            "symbols", py_binary_format_get_symbols, NULL,
-            "Iterable list of all symbols found in the binary format.", NULL
-        },
-        {
-            "errors", py_binary_format_get_errors, NULL,
-            "List of all detected errors which occurred while loading the binary.", NULL
-        },
+        BINARY_FORMAT_ENDIANNESS_ATTRIB,
+        BINARY_FORMAT_SYMBOLS_ATTRIB,
+        BINARY_FORMAT_ERRORS_ATTRIB,
         { NULL }
     };
 
@@ -802,10 +1104,13 @@ PyTypeObject *get_python_binary_format_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
 
-        .tp_doc         = "PyChrysalide binary format",
+        .tp_doc         = BINARY_FORMAT_DOC,
 
         .tp_methods     = py_bin_format_methods,
-        .tp_getset      = py_bin_format_getseters
+        .tp_getset      = py_bin_format_getseters,
+
+        .tp_init        = py_binary_format_init,
+        .tp_new         = py_binary_format_new,
 
     };
 
@@ -838,8 +1143,6 @@ bool ensure_python_binary_format_is_registered(void)
     {
         module = get_access_to_python_module("pychrysalide.format");
 
-        APPLY_ABSTRACT_FLAG(type);
-
         dict = PyModule_GetDict(module);
 
         if (!ensure_python_known_format_is_registered())
diff --git a/plugins/pychrysalide/format/module.c b/plugins/pychrysalide/format/module.c
index 48c6822..52dc58b 100644
--- a/plugins/pychrysalide/format/module.c
+++ b/plugins/pychrysalide/format/module.c
@@ -56,12 +56,19 @@ bool add_format_module(PyObject *super)
     bool result;                            /* Bilan à retourner           */
     PyObject *module;                       /* Sous-module mis en place    */
 
+#define PYCHRYSALIDE_FORMAT_DOC                                         \
+    "This module contains the basic definitions requiered for dealing"  \
+    " with file formats.\n"                                             \
+    "\n"                                                                \
+    "Support for specific formats (such as ELF files for instance)"     \
+    " needs extra definitions in a specific module."
+
     static PyModuleDef py_chrysalide_format_module = {
 
         .m_base = PyModuleDef_HEAD_INIT,
 
         .m_name = "pychrysalide.format",
-        .m_doc = "Python module for Chrysalide.format",
+        .m_doc = PYCHRYSALIDE_FORMAT_DOC,
 
         .m_size = -1,
 
diff --git a/src/format/format.c b/src/format/format.c
index 0cebc98..045bc92 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -360,7 +360,11 @@ FormatFlag g_binary_format_get_flags(const GBinFormat *format)
 
 SourceEndian g_binary_format_get_endianness(const GBinFormat *format)
 {
-    return G_BIN_FORMAT_GET_CLASS(format)->get_endian(format);
+    SourceEndian result;                    /* Boutisme à retourner        */
+
+    result = G_BIN_FORMAT_GET_CLASS(format)->get_endian(format);
+
+    return result;
 
 }
 
-- 
cgit v0.11.2-87-g4458