summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-05-21 20:43:30 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-05-21 20:43:30 (GMT)
commitd8eb070be32504949ad55fd644d9f1a69df1e05d (patch)
tree321a2591b67b3131baa514fdfe47ae492f665263
parent7e5b1add6fdeb74b2356acf8ccf7009f45cfa85e (diff)
Written a proper documentation for the binary format Python bindings.
-rw-r--r--plugins/pychrysalide/analysis/constants.c56
-rw-r--r--plugins/pychrysalide/analysis/constants.h3
-rw-r--r--plugins/pychrysalide/arch/constants.c56
-rw-r--r--plugins/pychrysalide/arch/constants.h3
-rw-r--r--plugins/pychrysalide/format/constants.c56
-rw-r--r--plugins/pychrysalide/format/constants.h3
-rw-r--r--plugins/pychrysalide/format/format.c435
-rw-r--r--plugins/pychrysalide/format/module.c9
-rw-r--r--src/format/format.c6
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;
}