summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-12-07 20:33:21 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-12-07 20:33:21 (GMT)
commitc0af4cc392a246b05d41b7b7c05bbcd8b0cfb39e (patch)
tree0d645c71c40fc4b625271d0ab1ef8e7ebab04075
parenta13d12c758184449bf3305785ef33273802a761c (diff)
Relied on GObject introspection and dynamic gtypes to inherit in Python.
-rw-r--r--plugins/pychrysalide/Makefile.am1
-rw-r--r--plugins/pychrysalide/analysis/content.c45
-rw-r--r--plugins/pychrysalide/analysis/content.h3
-rw-r--r--plugins/pychrysalide/arch/Makefile.am1
-rw-r--r--plugins/pychrysalide/arch/context.c163
-rw-r--r--plugins/pychrysalide/arch/context.h45
-rw-r--r--plugins/pychrysalide/arch/instruction.c45
-rw-r--r--plugins/pychrysalide/arch/instruction.h3
-rw-r--r--plugins/pychrysalide/arch/module.c2
-rw-r--r--plugins/pychrysalide/arch/processor.c359
-rw-r--r--plugins/pychrysalide/dt.c462
-rw-r--r--plugins/pychrysalide/dt.h47
-rw-r--r--plugins/pychrysalide/format/executable.c46
-rw-r--r--plugins/pychrysalide/format/executable.h3
-rw-r--r--plugins/pychrysalide/helpers.c29
-rw-r--r--plugins/pychrysalide/pychrysa.c3
-rw-r--r--src/arch/processor.c49
-rw-r--r--src/arch/processor.h6
-rw-r--r--tests/arch/processor.py52
19 files changed, 1334 insertions, 30 deletions
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index cfd5f81..0483b2a 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -6,6 +6,7 @@ libdir = $(pluginslibdir)
pychrysalide_la_SOURCES = \
access.h access.c \
+ dt.h dt.c \
helpers.h helpers.c \
plugin.h plugin.c \
pychrysa.h pychrysa.c \
diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c
index f590f82..26e7654 100644
--- a/plugins/pychrysalide/analysis/content.c
+++ b/plugins/pychrysalide/analysis/content.c
@@ -583,3 +583,48 @@ bool ensure_python_binary_content_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* 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 contenu binaire. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_binary_content(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_binary_content_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 binary content");
+ break;
+
+ case 1:
+ *((GBinContent **)dst) = G_BIN_CONTENT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/content.h b/plugins/pychrysalide/analysis/content.h
index b433828..61b82b3 100644
--- a/plugins/pychrysalide/analysis/content.h
+++ b/plugins/pychrysalide/analysis/content.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_binary_content_type(void);
/* Prend en charge l'objet 'pychrysalide.analysis.BinContent'. */
bool ensure_python_binary_content_is_registered(void);
+/* Tente de convertir en contenu binaire. */
+int convert_to_binary_content(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_CONTENT_H */
diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am
index 6210ed3..0145db2 100644
--- a/plugins/pychrysalide/arch/Makefile.am
+++ b/plugins/pychrysalide/arch/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libpychrysaarch.la
libpychrysaarch_la_SOURCES = \
+ context.h context.c \
feeder.h feeder.c \
immediate.h immediate.c \
instriter.h instriter.c \
diff --git a/plugins/pychrysalide/arch/context.c b/plugins/pychrysalide/arch/context.c
new file mode 100644
index 0000000..4428075
--- /dev/null
+++ b/plugins/pychrysalide/arch/context.c
@@ -0,0 +1,163 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - équivalent Python du fichier "arch/context.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "context.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <arch/context.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_proc_context_type(void)
+{
+ static PyMethodDef py_proc_context_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_proc_context_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_proc_context_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.arch.ProcContext",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = "PyChrysalide disassembly context.",
+
+ .tp_methods = py_proc_context_methods,
+ .tp_getset = py_proc_context_getseters,
+
+ };
+
+ return &py_proc_context_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.arch.ArchContext'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_proc_context_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ArchContext' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_proc_context_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ APPLY_ABSTRACT_FLAG(type);
+
+ module = get_access_to_python_module("pychrysalide.arch");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PROC_CONTEXT, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 contexte de désassemblage. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_proc_context(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_proc_context_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 disassembly context");
+ break;
+
+ case 1:
+ *((GProcContext **)dst) = G_PROC_CONTEXT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/arch/context.h b/plugins/pychrysalide/arch/context.h
new file mode 100644
index 0000000..eb5f0c1
--- /dev/null
+++ b/plugins/pychrysalide/arch/context.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour l'équivalent Python du fichier "arch/context.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_CONTEXT_H
+#define _PLUGINS_PYCHRYSALIDE_ARCH_CONTEXT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_proc_context_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.arch.ProcContext'. */
+bool ensure_python_proc_context_is_registered(void);
+
+/* Tente de convertir en contexte de désassemblage. */
+int convert_to_proc_context(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_CONTEXT_H */
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 4202625..6399d63 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -568,3 +568,48 @@ bool ensure_python_arch_instruction_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* 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 instruction d'architecture. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_arch_instruction(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_arch_instruction_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 arch instruction");
+ break;
+
+ case 1:
+ *((GArchInstruction **)dst) = G_ARCH_INSTRUCTION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/arch/instruction.h b/plugins/pychrysalide/arch/instruction.h
index 5433222..fea329f 100644
--- a/plugins/pychrysalide/arch/instruction.h
+++ b/plugins/pychrysalide/arch/instruction.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_arch_instruction_type(void);
/* Prend en charge l'objet 'pychrysalide.arch.ArchInstruction'. */
bool ensure_python_arch_instruction_is_registered(void);
+/* Tente de convertir en instruction d'architecture. */
+int convert_to_arch_instruction(PyObject *, void *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_INSTRUCTION_H */
diff --git a/plugins/pychrysalide/arch/module.c b/plugins/pychrysalide/arch/module.c
index 8bd6df6..db514ef 100644
--- a/plugins/pychrysalide/arch/module.c
+++ b/plugins/pychrysalide/arch/module.c
@@ -32,6 +32,7 @@
#include <common/endianness.h>
+#include "context.h"
#include "feeder.h"
#include "immediate.h"
#include "instriter.h"
@@ -163,6 +164,7 @@ bool populate_arch_module(void)
result = true;
+ if (result) result = ensure_python_proc_context_is_registered();
if (result) result = ensure_python_proxy_feeder_is_registered();
if (result) result = ensure_python_imm_operand_is_registered();
if (result) result = ensure_python_instr_iterator_is_registered();
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 7ff374b..2ecf6b8 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -30,19 +30,35 @@
#include <i18n.h>
+#include <arch/processor-int.h>
+#include "context.h"
#include "instriter.h"
#include "instruction.h"
#include "vmpa.h"
#include "../access.h"
+#include "../dt.h"
#include "../helpers.h"
+#include "../analysis/content.h"
+#include "../format/executable.h"
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_arch_processor_new(PyTypeObject *, PyObject *, PyObject *);
+/* Initialise la classe des descriptions de fichier binaire. */
+static void py_arch_processor_init_gclass(GArchProcessorClass *, gpointer);
+
+/* Fournit un contexte propre au processeur d'une architecture. */
+static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *);
+
+/* Désassemble une instruction dans un flux de données. */
+static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProcessor *, GProcContext *, const GBinContent *, vmpa2t *, GExeFormat *);
@@ -61,6 +77,11 @@ static PyObject *py_arch_processor_get_instruction_min_size(PyObject *, void *);
/* Indique si l'architecture possède un espace virtuel ou non. */
static PyObject *py_arch_processor_has_virtual_space(PyObject *, void *);
+/* Fournit un contexte propre au processeur d'une architecture. */
+static PyObject *py_arch_processor_get_context(PyObject *, PyObject *);
+
+/* Désassemble une instruction dans un flux de données. */
+static PyObject *py_arch_processor_disassemble(PyObject *, PyObject *);
@@ -89,6 +110,7 @@ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *);
+/* ---------------------------- DEFINITION DE PROCESSEUR ---------------------------- */
/* Définit les constantes pour les types d'erreurs. */
@@ -96,7 +118,239 @@ static bool define_python_arch_processor_constants(PyTypeObject *);
+/* ---------------------------------------------------------------------------------- */
+/* 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_arch_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Objet à retourner */
+ bool abstract; /* Validation du type parent */
+ GType gtype; /* Nouveau type de processeur */
+ PyObject *sys_mod_dict; /* Dictionnaire des modules */
+ PyObject *modname; /* Nom du module du type */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire dudit module */
+
+ /* Validations diverses */
+
+ abstract = (type == get_python_arch_processor_type());
+
+ if (abstract)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+ goto exit;
+ }
+
+ /* Mise en place d'un type dédié */
+
+ gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name,
+ (GClassInitFunc)py_arch_processor_init_gclass);
+
+ /* Enregistrement du nouveau GType dans Python */
+
+ sys_mod_dict = PyImport_GetModuleDict();
+
+ modname = PyDict_GetItemString(type->tp_dict, "__module__");
+
+ module = PyObject_GetItem(sys_mod_dict, modname);
+
+ dict = PyModule_GetDict(module);
+
+ if (!_register_class_for_pygobject(dict, gtype, type,
+ &PyGObject_Type, get_python_arch_processor_type(), NULL))
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ Py_DECREF(module);
+ Py_DECREF(modname);
+
+ /* On créé, 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 des descriptions de fichier binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_arch_processor_init_gclass(GArchProcessorClass *class, gpointer unused)
+{
+ class->get_ctx = py_arch_processor_get_context_wrapper;
+
+ class->disassemble = py_arch_processor_disassemble_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = architecture visée par la procédure. *
+* *
+* Description : Fournit un contexte propre au processeur d'une architecture. *
+* *
+* Retour : Nouveau contexte mis à disposition. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GProcContext *py_arch_processor_get_context_wrapper(const GArchProcessor *proc)
+{
+ GProcContext *result; /* Instance à retourner */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyctx; /* Contexte en objet Python */
+ int ret; /* Bilan d'une conversion */
+ GArchProcessorClass *class; /* Classe de l'objet courant */
+ GArchProcessorClass *parent; /* Classe parente */
+
+ pyobj = pygobject_new(G_OBJECT(proc));
+
+ if (has_python_method(pyobj, "_get_context"))
+ {
+ pyctx = run_python_method(pyobj, "_get_context", NULL);
+
+ if (pyctx == NULL)
+ result = NULL;
+
+ else
+ {
+ ret = convert_to_proc_context(pyctx, &result);
+
+ if (ret == 1)
+ g_object_ref(G_OBJECT(result));
+ else
+ {
+ PyErr_Clear();
+ result = NULL;
+ }
+ Py_DECREF(pyctx);
+
+ }
+
+ }
+
+ else
+ {
+ class = G_ARCH_PROCESSOR_GET_CLASS(proc);
+ parent = g_type_class_peek_parent(class);
+
+ result = parent->get_ctx(proc);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = architecture visée par la procédure. *
+* ctx = contexte lié à l'exécution du processeur. *
+* content = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* format = format du fichier contenant le code. *
+* *
+* Description : Désassemble une instruction dans un flux de données. *
+* *
+* Retour : Instruction mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, vmpa2t *pos, GExeFormat *format)
+{
+ GArchInstruction *result; /* Instance à retourner */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pypos; /* Position en objet Python */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyins; /* Instruction en objet Python */
+ int ret; /* Bilan d'une conversion */
+
+ pyobj = pygobject_new(G_OBJECT(proc));
+
+ if (has_python_method(pyobj, "_disassemble"))
+ {
+ pypos = build_from_internal_vmpa(pos);
+ Py_INCREF(pypos);
+
+ args = PyTuple_New(4);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+ PyTuple_SetItem(args, 2, pypos);
+ PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(format)));
+
+ pyins = run_python_method(pyobj, "_disassemble", args);
+
+ Py_DECREF(args);
+
+ if (pyins == NULL)
+ result = NULL;
+
+ else
+ {
+ ret = convert_to_arch_instruction(pyins, &result);
+
+ if (ret == 1)
+ g_object_ref(G_OBJECT(result));
+ else
+ {
+ PyErr_Clear();
+ result = NULL;
+ }
+
+ Py_DECREF(pyins);
+
+ copy_vmpa(pos, get_internal_vmpa(pypos));
+
+ }
+
+ Py_DECREF(pypos);
+
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
@@ -229,7 +483,100 @@ static PyObject *py_arch_processor_has_virtual_space(PyObject *self, void *closu
}
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Fournit un contexte propre au processeur d'une architecture. *
+* *
+* Retour : Nouveau contexte mis à disposition. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static PyObject *py_arch_processor_get_context(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ GArchProcessor *proc; /* Processeur manipulé */
+ GProcContext *ctx; /* Nouveau contexte en place */
+
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+
+ ctx = g_arch_processor_get_context(proc);
+
+ if (ctx != NULL)
+ {
+ result = pygobject_new(G_OBJECT(ctx));
+ g_object_unref(G_OBJECT(ctx));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Désassemble une instruction dans un flux de données. *
+* *
+* Retour : Instruction mise en place ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_processor_disassemble(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ GProcContext *ctx; /* Contexte de désassemblage */
+ GBinContent *content; /* Contenu binaire à parcourir */
+ PyObject *pypos; /* Position en objet Python */
+ GExeFormat *format; /* Format de fichier associé */
+ int ret; /* Bilan de lecture des args. */
+ vmpa2t pos; /* Position d'analyse courante */
+ GArchProcessor *proc; /* Processeur manipulé */
+ GArchInstruction *instr; /* Instruction mise en place */
+
+ ret = PyArg_ParseTuple(args, "O&O&OO&",
+ convert_to_proc_context, &ctx,
+ convert_to_binary_content, &content,
+ &pypos,
+ convert_to_executable_format, &format);
+ if (!ret) return NULL;
+
+ ret = convert_any_to_vmpa(pypos, &pos);
+ if (ret != 1) return NULL;
+
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+
+ instr = g_arch_processor_disassemble(proc, ctx, content, &pos, format);
+
+ copy_vmpa(get_internal_vmpa(pypos), &pos);
+
+ if (instr != NULL)
+ {
+ result = pygobject_new(G_OBJECT(instr));
+ g_object_unref(G_OBJECT(instr));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
@@ -527,6 +874,16 @@ PyTypeObject *get_python_arch_processor_type(void)
{
static PyMethodDef py_arch_processor_methods[] = {
{
+ "get_context", py_arch_processor_get_context,
+ METH_NOARGS,
+ "get_context($self, /)\n--\n\nProvide a new disassembly context."
+ },
+ {
+ "disassemble", py_arch_processor_disassemble,
+ METH_VARARGS,
+ "disassemble($self, context, content, pos, format, /)\n--\n\nDisassemble a portion of binary content into one instruction."
+ },
+ {
"add_error", py_arch_processor_add_error,
METH_VARARGS,
"add_error($self, type, addr, desc, /)\n--\n\nExtend the list of detected disassembling errors."
@@ -581,6 +938,8 @@ PyTypeObject *get_python_arch_processor_type(void)
.tp_methods = py_arch_processor_methods,
.tp_getset = py_arch_processor_getseters,
+ .tp_new = py_arch_processor_new,
+
};
return &py_arch_processor_type;
diff --git a/plugins/pychrysalide/dt.c b/plugins/pychrysalide/dt.c
new file mode 100644
index 0000000..edfc032
--- /dev/null
+++ b/plugins/pychrysalide/dt.c
@@ -0,0 +1,462 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.c - possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dt.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
+
+
+#define G_TYPE_DYNAMIC_TYPES g_dynamic_types_get_type()
+#define G_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
+#define G_IS_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+
+
+/* Mémorisation des caractéristiques de type */
+typedef struct _type_dyn_info_t
+{
+ GType type; /* Identifiant unique obtenu */
+ GClassInitFunc init; /* Définition des méthodes */
+
+} type_dyn_info_t;
+
+/* Description de fichier binaire (instance) */
+typedef struct _GDynamicTypes
+{
+ GObject parent; /* A laisser en premier */
+
+ type_dyn_info_t **info; /* Liste d'informations utiles */
+ size_t count; /* Taille de cette liste */
+
+} GDynamicTypes;
+
+/* Description de fichier binaire (classe) */
+typedef struct _GDynamicTypesClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+} GDynamicTypesClass;
+
+
+/* Indique le type défini pour une gestion de types dynamique. */
+static GType g_dynamic_types_get_type(void);
+
+/* Initialise la classe de gestion de types dynamique. */
+static void g_dynamic_types_class_init(GDynamicTypesClass *);
+
+/* Initialise une gestion de types dynamique. */
+static void g_dynamic_types_init(GDynamicTypes *);
+
+/* Procède à l'initialisation de l'interface de typage nouveau. */
+static void g_dynamic_types_interface_init(GTypePluginClass *);
+
+/* Supprime toutes les références externes. */
+static void g_dynamic_types_dispose(GDynamicTypes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dynamic_types_finalize(GDynamicTypes *);
+
+/* Crée un nouveau gestionnaire de nouveaux types. */
+static GDynamicTypes *g_dynamic_types_new(void);
+
+/* Marque une augmentation des utilisations. */
+static void g_dynamic_types_use(GDynamicTypes *);
+
+/* Marque une diminution des utilisations. */
+static void g_dynamic_types_unuse(GDynamicTypes *);
+
+/* Complète la définition d'un type dynamiquement. */
+static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
+
+/* Retrouve les informations concernant un type dynamique. */
+static type_dyn_info_t *g_dynamic_types_find(GDynamicTypes *, GType);
+
+/* Fournit un identifiant GLib pour un nouveau type Python. */
+static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc);
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Encadrement des nouveaux types Python dérivés */
+static GDynamicTypes *_python_dtypes = NULL;
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MODULE DE GESTION DES NOUVEAUX */
+/* ---------------------------------------------------------------------------------- */
+
+/* Indique le type défini pour une gestion de types dynamique. */
+G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe de gestion de types dynamique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : types = instance à initialiser. *
+* *
+* Description : Initialise une gestion de types dynamique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_init(GDynamicTypes *types)
+{
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de typage nouveau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_interface_init(GTypePluginClass *iface)
+{
+ iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
+ iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
+ iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : types = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_dispose(GDynamicTypes *types)
+{
+ G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : types = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_finalize(GDynamicTypes *types)
+{
+ G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau gestionnaire de nouveaux types. *
+* *
+* Retour : Instance mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GDynamicTypes *g_dynamic_types_new(void)
+{
+ GDynamicTypes *result; /* Adresse à retourner */
+
+ result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : types = gestionnaire de types courant. *
+* *
+* Description : Marque une augmentation des utilisations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_use(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : types = gestionnaire de types courant. *
+* *
+* Description : Marque une diminution des utilisations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_unuse(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : types = gestionnaire de types courant. *
+* type = nouveau type GLib à traiter. *
+* info = information concernant ce type à constituer. [OUT] *
+* table = table de valeur à éventuellement initialiser. [OUT] *
+* *
+* Description : Complète la définition d'un type dynamiquement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
+{
+ type_dyn_info_t *nfo; /* Source d'inspiration */
+ GType parent; /* Type parent du type */
+ GTypeQuery query; /* Informations complémentaires*/
+
+ /* Consultation */
+
+ nfo = g_dynamic_types_find(types, type);
+ assert(nfo != NULL);
+
+ parent = g_type_parent(type);
+ g_type_query(parent, &query);
+
+ /* Définition */
+
+ info->class_size = query.class_size;
+ info->class_init = nfo->init;
+
+ info->instance_size = query.instance_size;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = type GLib parent. *
+* type = identifiant du type GLib à considérer. *
+* *
+* Description : Retrouve les informations concernant un type dynamique. *
+* *
+* Retour : Structure contenant les informations associées au type. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static type_dyn_info_t *g_dynamic_types_find(GDynamicTypes *types, GType target)
+{
+
+ return types->info[0];
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = type GLib parent. *
+* name = désignation du nouveau type. *
+* init = procédure d'initialisation de la classe associée. *
+* *
+* Description : Fournit un identifiant GLib pour un nouveau type Python. *
+* *
+* Retour : identifiant d'un nouveau type valide, ou 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init)
+{
+ GType result; /* Identifiant à retourner */
+ type_dyn_info_t *new; /* Mémorisation de paramètres */
+
+ /* Création d'un nouveau type adapté */
+
+ result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
+
+ if (result == 0)
+ goto exit;
+
+ new = malloc(sizeof(type_dyn_info_t));
+
+ new->type = result;
+ new->init = init;
+
+ /* Inscription définitive */
+
+ types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
+
+ types->info[types->count - 1] = new;
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ACCOMPAGNEMENTS DES NOUVEAUX TYPES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Lance le support de dérivations de types dans Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_dynamic_python_types(void)
+{
+ bool result; /* Bilan à retourner */
+
+ _python_dtypes = g_dynamic_types_new();
+
+ result = (_python_dtypes != NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Arrête le support de dérivations de types dans Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void exit_dynamic_python_types(void)
+{
+ g_object_unref(G_OBJECT(_python_dtypes));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = type GLib parent. *
+* name = désignation du nouveau type. *
+* init = procédure d'initialisation de la classe associée. *
+* *
+* Retour : Identifiant d'un nouveau type valide, ou 0. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init)
+{
+ GType result; /* Identifiant à retourner */
+
+ result = g_type_from_name(name);
+
+ if (result == 0)
+ result = g_dynamic_types_register_type(_python_dtypes, parent, name, init);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/dt.h b/plugins/pychrysalide/dt.h
new file mode 100644
index 0000000..b0f16db
--- /dev/null
+++ b/plugins/pychrysalide/dt.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_DT_H
+#define _PLUGINS_PYCHRYSALIDE_DT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Lance le support de dérivations de types dans Python. */
+bool init_dynamic_python_types(void);
+
+/* Arrête le support de dérivations de types dans Python. */
+void exit_dynamic_python_types(void);
+
+/* Fournit un identifiant GLib pour un nouveau type Python. */
+GType built_dynamic_type(GType, const char *, GClassInitFunc);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index 0346ecb..cc0dd33 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -25,6 +25,7 @@
#include "executable.h"
+#include <assert.h>
#include <pygobject.h>
@@ -236,6 +237,51 @@ bool ensure_python_executable_format_is_registered(void)
}
+/******************************************************************************
+* *
+* 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 format exécutable. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_executable_format(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_executable_format_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 executable format");
+ break;
+
+ case 1:
+ *((GExeFormat **)dst) = G_EXE_FORMAT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* TRADUCTION D'EMPLACEMENT */
diff --git a/plugins/pychrysalide/format/executable.h b/plugins/pychrysalide/format/executable.h
index d2308e0..f94058d 100644
--- a/plugins/pychrysalide/format/executable.h
+++ b/plugins/pychrysalide/format/executable.h
@@ -43,6 +43,9 @@ PyTypeObject *get_python_executable_format_type(void);
/* Prend en charge l'objet 'pychrysalide.format.ExeFormat'. */
bool ensure_python_executable_format_is_registered(void);
+/* Tente de convertir en format exécutable. */
+int convert_to_executable_format(PyObject *, void *);
+
/* ---------------------------- TRADUCTION D'EMPLACEMENT ---------------------------- */
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 4ada405..51c2f31 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -112,12 +112,18 @@ bool has_python_method(PyObject *module, const char *method)
bool result; /* Bilan à retourner */
PyObject *func; /* Fonction visée */
- func = PyObject_GetAttrString(module, method);
- if (func == NULL) return false;
+ result = (PyObject_HasAttrString(module, method) == 1);
- result = PyCallable_Check(func);
+ if (result)
+ {
+ func = PyObject_GetAttrString(module, method);
+ assert(func != NULL);
- Py_DECREF(func);
+ result = PyCallable_Check(func);
+
+ Py_DECREF(func);
+
+ }
return result;
@@ -503,20 +509,15 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
va_end(ap);
-
+ /**
+ * les renseignements suivants ne semblent pas nécessaires...
+ */
/*
-#0 0x000055555565aad4 in insertdict (mp=0x7fffe7c2c8a8, key='GenConfig', hash=262970853803706525, value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:801
-#1 0x000055555565bf62 in PyDict_SetItem (op={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key='GenConfig', value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:1227
-#2 0x00005555556610b0 in PyDict_SetItemString (v={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key=0x7ffff69cd0bd "GenConfig", item=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:2870
-#3 0x00007ffff69b3d12 in _register_class_for_pygobject (dict={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, gtype=93824998785328, type=0x7ffff6bd9ce0 <py_generic_config_type>, base=0x7fffe80e72a0 <PyGObject_Type>) at helpers.c:320
+ type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
+ type->tp_dictoffset = offsetof(PyGObject, inst_dict);
*/
-
-
- //type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
- //type->tp_dictoffset = offsetof(PyGObject, inst_dict);
-
pygobject_register_class(dict, NULL, gtype, type, static_bases);
if (PyErr_Occurred() == NULL)
diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c
index 50d2f92..785481b 100644
--- a/plugins/pychrysalide/pychrysa.c
+++ b/plugins/pychrysalide/pychrysa.c
@@ -44,6 +44,7 @@
#include "access.h"
+#include "dt.h"
#include "helpers.h"
#include "plugin.h"
#include "struct.h"
@@ -362,6 +363,8 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
/* Mise en place des fonctionnalités offertes */
+ init_dynamic_python_types();
+
result = PyModule_Create(&py_chrysalide_module);
register_access_to_python_module(py_chrysalide_module.m_name, result);
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 4450208..4d7bacc 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -69,6 +69,8 @@ static void g_arch_processor_dispose(GArchProcessor *);
/* Procède à la libération totale de la mémoire. */
static void g_arch_processor_finalize(GArchProcessor *);
+/* Fournit un contexte générique pour l'exécution du processeur. */
+static GProcContext *_g_arch_processor_get_context(const GArchProcessor *);
@@ -125,6 +127,8 @@ static void g_arch_processor_class_init(GArchProcessorClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_processor_dispose;
object->finalize = (GObjectFinalizeFunc)g_arch_processor_finalize;
+ klass->get_ctx = _g_arch_processor_get_context;
+
g_signal_new("changed",
G_TYPE_ARCH_PROCESSOR,
G_SIGNAL_RUN_LAST,
@@ -225,28 +229,21 @@ static void g_arch_processor_finalize(GArchProcessor *proc)
/******************************************************************************
* *
-* Paramètres : proc = architecture visée par la procédure. *
+* Paramètres : proc = architecture, spectatrice ici. *
* *
-* Description : Fournit un contexte propre au processeur d'une architecture. *
+* Description : Fournit un contexte générique pour l'exécution du processeur.*
* *
-* Retour : Nouveau contexte mis à disposition. *
+* Retour : Contexte mis en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GProcContext *g_arch_processor_get_context(const GArchProcessor *proc)
+static GProcContext *_g_arch_processor_get_context(const GArchProcessor *proc)
{
- GProcContext *result; /* Contexte à retourner */
- GArchProcessorClass *class; /* Classe de l'instance active */
+ GProcContext *result; /* Instance à retourner */
- class = G_ARCH_PROCESSOR_GET_CLASS(proc);
-
- if (class->get_ctx != NULL)
- result = class->get_ctx(proc);
-
- else
- result = NULL;
+ result = g_object_new(G_TYPE_PROC_CONTEXT, NULL);
return result;
@@ -331,6 +328,32 @@ bool g_arch_processor_has_virtual_space(const GArchProcessor *proc)
/******************************************************************************
* *
+* Paramètres : proc = architecture visée par la procédure. *
+* *
+* Description : Fournit un contexte propre au processeur d'une architecture. *
+* *
+* Retour : Nouveau contexte mis à disposition. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GProcContext *g_arch_processor_get_context(const GArchProcessor *proc)
+{
+ GProcContext *result; /* Contexte à retourner */
+ GArchProcessorClass *class; /* Classe de l'instance active */
+
+ class = G_ARCH_PROCESSOR_GET_CLASS(proc);
+
+ result = class->get_ctx(proc);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : proc = architecture visée par la procédure. *
* ctx = contexte lié à l'exécution du processeur. *
* content = flux de données à analyser. *
diff --git a/src/arch/processor.h b/src/arch/processor.h
index 24d9287..26eddb1 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -55,9 +55,6 @@ typedef struct _GArchProcessorClass GArchProcessorClass;
/* Indique le type défini pour un processeur d'architecture. */
GType g_arch_processor_get_type(void);
-/* Fournit un contexte propre au processeur d'une architecture. */
-GProcContext *g_arch_processor_get_context(const GArchProcessor *);
-
/* Fournit le boustime du processeur d'une architecture. */
SourceEndian g_arch_processor_get_endianness(const GArchProcessor *);
@@ -70,6 +67,9 @@ MemoryDataSize g_arch_processor_get_instruction_min_size(const GArchProcessor *)
/* Indique si l'architecture possède un espace virtuel ou non. */
bool g_arch_processor_has_virtual_space(const GArchProcessor *);
+/* Fournit un contexte propre au processeur d'une architecture. */
+GProcContext *g_arch_processor_get_context(const GArchProcessor *);
+
/* Désassemble une instruction dans un flux de données. */
GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcContext *, const GBinContent *, vmpa2t *, GExeFormat *);
diff --git a/tests/arch/processor.py b/tests/arch/processor.py
new file mode 100644
index 0000000..5ad6490
--- /dev/null
+++ b/tests/arch/processor.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+import pychrysalide
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.arch import ArchProcessor
+from pychrysalide.arch import ProcContext
+from pychrysalide.arch import vmpa
+from pychrysalide.format import FlatFormat
+
+
+
+class TestProcessor(ChrysalideTestCase):
+ """TestCase for arch.ArchProcessor."""
+
+
+
+ def testGI(self):
+ """Validate the GObject introspection."""
+
+ with self.assertRaises(RuntimeError):
+ np = ArchProcessor()
+
+
+ class NewContext(ProcContext):
+ pass
+
+ class NewProc(ArchProcessor):
+
+ def _get_context(self):
+ return NewContext()
+
+ def _disassemble(self, ctx, content, pos, format):
+ return None
+
+
+ np = NewProc()
+
+ data = b'\x01\x02\x03\x04'
+ cnt = MemoryContent(data)
+ fmt = FlatFormat(cnt)
+
+ ctx = np.get_context()
+ self.assertTrue(type(ctx) == NewContext)
+
+ pos = vmpa(0)
+
+ ins = np.disassemble(ctx, cnt, pos, fmt)
+
+ self.assertIsNone(ins)