From d8eb070be32504949ad55fd644d9f1a69df1e05d Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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 -#include +#include +#include +#include #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