summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/format/known.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/format/known.c')
-rw-r--r--plugins/pychrysalide/format/known.c338
1 files changed, 94 insertions, 244 deletions
diff --git a/plugins/pychrysalide/format/known.c b/plugins/pychrysalide/format/known.c
index 3167ba2..856c087 100644
--- a/plugins/pychrysalide/format/known.c
+++ b/plugins/pychrysalide/format/known.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* known.c - équivalent Python du fichier "format/known.c"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -30,7 +30,6 @@
#include <i18n.h>
#include <format/known-int.h>
-#include <plugins/dt.h>
#include "../access.h"
@@ -42,11 +41,10 @@
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_known_format_new(PyTypeObject *, PyObject *, PyObject *);
-
/* Initialise la classe des descriptions de fichier binaire. */
-static void py_known_format_init_gclass(GKnownFormatClass *, gpointer);
+static int py_known_format_init_gclass(GKnownFormatClass *, PyTypeObject *);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(known_format, G_TYPE_KNOWN_FORMAT);
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_known_format_init(PyObject *, PyObject *, PyObject *);
@@ -58,10 +56,7 @@ static char *py_known_format_get_key_wrapper(const GKnownFormat *);
static char *py_known_format_get_description_wrapper(const GKnownFormat *);
/* Assure l'interprétation d'un format en différé. */
-static bool py_known_format_analyze_wrapper(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
-
-/* Réalise un traitement post-désassemblage. */
-static void py_known_format_complete_analysis_wrapper(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
+static bool py_known_format_analyze_wrapper(GKnownFormat *);
@@ -71,9 +66,6 @@ static void py_known_format_complete_analysis_wrapper(GKnownFormat *, wgroup_id_
/* Assure l'interprétation d'un format en différé. */
static PyObject *py_known_format_analyze(PyObject *, PyObject *);
-/* Réalise un traitement post-désassemblage. */
-static PyObject *py_known_format_complete_analysis(PyObject *, PyObject *);
-
/* Indique la désignation interne du format. */
static PyObject *py_known_format_get_key(PyObject *, void *);
@@ -92,87 +84,25 @@ static PyObject *py_known_format_get_content(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* args = éventuelle liste d'arguments. *
-* kwds = éventuel dictionnaire de valeurs mises à disposition. *
+* Paramètres : gclass = classe GLib à initialiser. *
+* pyclass = classe Python à initialiser. *
* *
-* Description : Accompagne la création d'une instance dérivée en Python. *
+* Description : Initialise la classe des formats connus. *
* *
-* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
+* Retour : 0 pour indiquer un succès de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_known_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_known_format_init_gclass(GKnownFormatClass *gclass, PyTypeObject *pyclass)
{
- 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_KNOWN_FORMAT, type->tp_name,
- (GClassInitFunc)py_known_format_init_gclass, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type);
-
- if (!status)
- {
- result = NULL;
- goto exit;
- }
+ PY_CLASS_SET_WRAPPER(gclass->get_key, py_known_format_get_key_wrapper);
+ PY_CLASS_SET_WRAPPER(gclass->get_desc, py_known_format_get_description_wrapper);
- }
-
- /* 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 : - *
-* *
-******************************************************************************/
+ PY_CLASS_SET_WRAPPER(gclass->analyze, py_known_format_analyze_wrapper);
-static void py_known_format_init_gclass(GKnownFormatClass *class, gpointer unused)
-{
- class->get_key = py_known_format_get_key_wrapper;
- class->get_desc = py_known_format_get_description_wrapper;
-
- class->analyze = py_known_format_analyze_wrapper;
- class->complete = py_known_format_complete_analysis_wrapper;
+ return 0;
}
@@ -201,18 +131,11 @@ static int py_known_format_init(PyObject *self, PyObject *args, PyObject *kwds)
"KnownFormat is a small class providing basic features for" \
" recognized formats.\n" \
"\n" \
- "One item has to be defined as class attribute in the final" \
- " class:\n" \
- "* *_key*: a string providing a small name used to identify the" \
- " format.\n" \
- "\n" \
"The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.format.KnownFormat._get_key();\n" \
"* pychrysalide.format.KnownFormat._get_description();\n" \
"* pychrysalide.format.KnownFormat._analyze().\n" \
"\n" \
- "The following method may also be defined for new classes too:\n" \
- "* pychrysalide.format.KnownFormat._complete_analysis().\n" \
- "\n" \
"Calls to the *__init__* constructor of this abstract object expect"\
" only one argument: a binary content, provided as a" \
" pychrysalide.analysis.BinContent instance."
@@ -231,7 +154,8 @@ static int py_known_format_init(PyObject *self, PyObject *args, PyObject *kwds)
format = G_KNOWN_FORMAT(pygobject_get(self));
- g_known_format_set_content(format, content);
+ if (!g_known_format_create(format, content))
+ return -1;
return 0;
@@ -255,27 +179,39 @@ static char *py_known_format_get_key_wrapper(const GKnownFormat *format)
char *result; /* Désignation à renvoyer */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyObject *pykey; /* Clef en objet Python */
+ PyObject *pyret; /* Valeur retournée */
int ret; /* Bilan d'une conversion */
+#define KNOWN_FORMAT_GET_KEY_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_key, "$self", \
+ METH_NOARGS, \
+ "Abstract method used to define the internal name" \
+ " of the known format.\n" \
+ "\n" \
+ "The return value has to be a (tiny) string." \
+)
+
result = NULL;
gstate = PyGILState_Ensure();
pyobj = pygobject_new(G_OBJECT(format));
- if (PyObject_HasAttrString(pyobj, "_key"))
+ if (has_python_method(pyobj, "_get_key"))
{
- pykey = PyObject_GetAttrString(pyobj, "_key");
+ pyret = run_python_method(pyobj, "_get_key", NULL);
- if (pykey != NULL)
+ if (pyret != NULL)
{
- ret = PyUnicode_Check(pykey);
+ ret = PyUnicode_Check(pyret);
if (ret)
- result = strdup(PyUnicode_AsUTF8(pykey));
+ result = strdup(PyUnicode_AsUTF8(pyret));
+ else
+ PyErr_SetString(PyExc_ValueError, _("unexpected value type for known format key"));
- Py_DECREF(pykey);
+ Py_DECREF(pyret);
}
@@ -335,6 +271,8 @@ static char *py_known_format_get_description_wrapper(const GKnownFormat *format)
if (ret)
result = strdup(PyUnicode_AsUTF8(pyret));
+ else
+ PyErr_SetString(PyExc_ValueError, _("unexpected value type for known format description"));
Py_DECREF(pyret);
@@ -354,8 +292,6 @@ static char *py_known_format_get_description_wrapper(const GKnownFormat *format)
/******************************************************************************
* *
* Paramètres : format = format chargé dont l'analyse est lancée. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
* *
* Description : Assure l'interprétation d'un format en différé. *
* *
@@ -365,12 +301,11 @@ static char *py_known_format_get_description_wrapper(const GKnownFormat *format)
* *
******************************************************************************/
-static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static bool py_known_format_analyze_wrapper(GKnownFormat *format)
{
bool result; /* Bilan à retourner */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Bilan d'exécution */
#define KNOWN_FORMAT_ANALYZE_WRAPPER PYTHON_WRAPPER_DEF \
@@ -380,12 +315,8 @@ static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gi
"Abstract method used to start the analysis of the known" \
" format and return its status.\n" \
"\n" \
- "The identifier refers to the working queue used to process" \
- " the analysis. A reference to the main status bar may also be" \
- " provided, as a pychrysalide.gtkext.StatusStack instance if" \
- " running in graphical mode or None otherwise.\n" \
- "\n" \
- "The expected result of the call is a boolean." \
+ "The expected result of the call is a boolean value: *True* in" \
+ " case of success, *False* in case of failure." \
)
result = false;
@@ -396,16 +327,10 @@ static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gi
if (has_python_method(pyobj, "_analyze"))
{
- args = PyTuple_New(2);
-
- PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(gid));
- PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(status)));
-
- pyret = run_python_method(pyobj, "_analyze", args);
+ pyret = run_python_method(pyobj, "_analyze", NULL);
result = (pyret == Py_True);
- Py_DECREF(args);
Py_XDECREF(pyret);
}
@@ -419,64 +344,6 @@ static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gi
}
-/******************************************************************************
-* *
-* Paramètres : format = format chargé dont l'analyse est lancée. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Réalise un traitement post-désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void py_known_format_complete_analysis_wrapper(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
-{
- PyGILState_STATE gstate; /* Sauvegarde d'environnement */
- PyObject *pyobj; /* Objet Python concerné */
- PyObject *args; /* Arguments pour l'appel */
- PyObject *pyret; /* Bilan d'exécution */
-
-#define KNOWN_FORMAT_COMPLETE_ANALYSIS_WRAPPER PYTHON_VOID_WRAPPER_DEF \
-( \
- _complete_analysis, "$self, gid, status, /", \
- METH_VARARGS, \
- "Abstract method used to complete an analysis of a known format.\n" \
- "\n" \
- "The identifier refers to the working queue used to process the" \
- " analysis. A reference to the main status bar may also be" \
- " provided, as a pychrysalide.gtkext.StatusStack instance if" \
- " running in graphical mode or None otherwise.\n" \
-)
-
- gstate = PyGILState_Ensure();
-
- pyobj = pygobject_new(G_OBJECT(format));
-
- if (has_python_method(pyobj, "_complete_analysis"))
- {
- args = PyTuple_New(2);
-
- PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(gid));
- PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(status)));
-
- pyret = run_python_method(pyobj, "_complete_analysis", args);
-
- Py_DECREF(args);
- Py_XDECREF(pyret);
-
- }
-
- Py_DECREF(pyobj);
-
- PyGILState_Release(gstate);
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DU FORMAT CONNU */
@@ -499,33 +366,24 @@ static void py_known_format_complete_analysis_wrapper(GKnownFormat *format, wgro
static PyObject *py_known_format_analyze(PyObject *self, PyObject *args)
{
PyObject *result; /* Bilan à retourner */
- int ret; /* Bilan de lecture des args. */
GKnownFormat *format; /* Format connu manipulé */
bool status; /* Bilan de l'opération */
#define KNOWN_FORMAT_ANALYZE_METHOD PYTHON_METHOD_DEF \
( \
- analyze, "$self, gid, status, /", \
- METH_VARARGS, py_known_format, \
+ analyze, "$self", \
+ METH_NOARGS, py_known_format, \
"Start the analysis of the known format and return its status." \
"\n" \
"Once this analysis is done, a few early symbols and the" \
" mapped sections are expected to be defined, if any.\n" \
"\n" \
- "The identifier refers to the working queue used to process" \
- " the analysis. A reference to the main status bar may also be" \
- " provided, as a pychrysalide.gtkext.StatusStack instance if" \
- " running in graphical mode or None otherwise.\n" \
- "\n" \
"The return value is a boolean status of the operation." \
)
- ret = PyArg_ParseTuple(args, "");//|KO!", &gid, &status);
- if (!ret) return NULL;
-
format = G_KNOWN_FORMAT(pygobject_get(self));
- status = g_known_format_analyze(format, 0, NULL);
+ status = g_known_format_analyze(format);
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -537,57 +395,6 @@ static PyObject *py_known_format_analyze(PyObject *self, PyObject *args)
/******************************************************************************
* *
-* Paramètres : self = objet représentant un format connu. *
-* args = arguments fournis pour l'opération. *
-* *
-* Description : Réalise un traitement post-désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_known_format_complete_analysis(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- int ret; /* Bilan de lecture des args. */
- GKnownFormat *format; /* Format connu manipulé */
-
-#define KNOWN_FORMAT_COMPLETE_ANALYSIS_METHOD PYTHON_METHOD_DEF \
-( \
- complete_analysis, "$self, gid, status, /", \
- METH_VARARGS, py_known_format, \
- "Complete an analysis of a known format.\n" \
- "\n" \
- "This process is usually done once the disassembling process" \
- " is completed.\n" \
- "\n" \
- "The identifier refers to the working queue used to process" \
- " the analysis. A reference to the main status bar may also be" \
- " provided, as a pychrysalide.gtkext.StatusStack instance if" \
- " running in graphical mode or None otherwise.\n" \
- "\n" \
- "The return value is a boolean status of the operation." \
-)
-
- ret = PyArg_ParseTuple(args, "");//|KO!", &gid, &status);
- if (!ret) return NULL;
-
- format = G_KNOWN_FORMAT(pygobject_get(self));
-
- g_known_format_complete_analysis(format, 0, NULL);
-
- result = Py_None;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
@@ -615,9 +422,30 @@ static PyObject *py_known_format_get_key(PyObject *self, void *closure)
key = g_known_format_get_key(format);
- result = PyUnicode_FromString(key);
+ if (key != NULL)
+ {
+ result = PyUnicode_FromString(key);
+ free(key);
+ }
+ else
+ {
+ result = NULL;
- free(key);
+ /**
+ * Si l'absence de retour vient d'une instance implémentée en Python,
+ * une exception peut (et doit dans ce cas) avoir été définie dans la
+ * fonction py_known_format_get_key_wrapper().
+ *
+ * Aucun traitement supplémntaire n'est alors nécessaire.
+ *
+ * Une action est cependant nécessaire pour assurer un traitement
+ * des extensions purement natives offrant une mauvaise implémentation.
+ */
+
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(PyExc_ValueError, _("unexpected NULL value for known format key"));
+
+ }
return result;
@@ -653,9 +481,30 @@ static PyObject *py_known_format_get_description(PyObject *self, void *closure)
desc = g_known_format_get_description(format);
- result = PyUnicode_FromString(desc);
+ if (desc != NULL)
+ {
+ result = PyUnicode_FromString(desc);
+ free(desc);
+ }
+ else
+ {
+ result = NULL;
- free(desc);
+ /**
+ * Si l'absence de retour vient d'une instance implémentée en Python,
+ * une exception peut (et doit dans ce cas) avoir été définie dans la
+ * fonction py_known_format_get_description_wrapper().
+ *
+ * Aucun traitement supplémntaire n'est alors nécessaire.
+ *
+ * Une action est cependant nécessaire pour assurer un traitement
+ * des extensions purement natives offrant une mauvaise implémentation.
+ */
+
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(PyExc_ValueError, _("unexpected NULL value for known format description"));
+
+ }
return result;
@@ -724,11 +573,10 @@ static PyObject *py_known_format_get_content(PyObject *self, void *closure)
PyTypeObject *get_python_known_format_type(void)
{
static PyMethodDef py_known_format_methods[] = {
+ KNOWN_FORMAT_GET_KEY_WRAPPER,
KNOWN_FORMAT_GET_DESCRIPTION_WRAPPER,
KNOWN_FORMAT_ANALYZE_WRAPPER,
- KNOWN_FORMAT_COMPLETE_ANALYSIS_WRAPPER,
KNOWN_FORMAT_ANALYZE_METHOD,
- KNOWN_FORMAT_COMPLETE_ANALYSIS_METHOD,
{ NULL }
};
@@ -789,6 +637,8 @@ bool ensure_python_known_format_is_registered(void)
dict = PyModule_GetDict(module);
+ pyg_register_class_init(G_TYPE_KNOWN_FORMAT, (PyGClassInitFunc)py_known_format_init_gclass);
+
if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_FORMAT, type))
return false;