summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-05-10 20:21:56 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-05-10 20:21:56 (GMT)
commit8e76324b01e5b4979f346f0bc8c84372477a3d38 (patch)
tree3db4057e113aa9f664f5b217dd349bb1e9288009
parentb0c6ffacf5c6c45c047172e348c737cb85fb5b36 (diff)
Rewritten the whole bitfield management.
-rw-r--r--ChangeLog36
-rw-r--r--plugins/pychrysa/arch/vmpa.c46
-rw-r--r--plugins/pychrysa/common/Makefile.am1
-rw-r--r--plugins/pychrysa/common/bits.c653
-rw-r--r--plugins/pychrysa/common/bits.h48
-rw-r--r--plugins/pychrysa/common/module.c2
-rw-r--r--plugins/pychrysa/format/symbol.c39
-rw-r--r--plugins/pychrysa/helpers.c54
-rw-r--r--plugins/pychrysa/helpers.h3
-rw-r--r--src/analysis/disass/area.c57
-rw-r--r--src/analysis/disass/dragon.c2
-rw-r--r--src/common/bits.c293
-rw-r--r--src/common/bits.h22
-rw-r--r--tests/common/bitfield.py106
-rw-r--r--tests/common/pathname.py4
15 files changed, 1058 insertions, 308 deletions
diff --git a/ChangeLog b/ChangeLog
index 123b47e..48e8334 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+17-05-10 Cyrille Bagard <nocbos@gmail.com>
+
+ * plugins/pychrysa/arch/vmpa.c:
+ Typo. Update code.
+
+ * plugins/pychrysa/common/Makefile.am:
+ Add the 'bits.[ch]' files to libpychrysacommon_la_SOURCES.
+
+ * plugins/pychrysa/common/bits.c:
+ * plugins/pychrysa/common/bits.h:
+ New entries: provide Python bindings for bitfields.
+
+ * plugins/pychrysa/common/module.c:
+ Register the new bindings.
+
+ * plugins/pychrysa/format/symbol.c:
+ Typo. Update code.
+
+ * plugins/pychrysa/helpers.c:
+ * plugins/pychrysa/helpers.h:
+ Translate C comparison status to Python rich comparison status.
+
+ * src/analysis/disass/area.c:
+ * src/analysis/disass/dragon.c:
+ Update code.
+
+ * src/common/bits.c:
+ * src/common/bits.h:
+ Rewrite the whole bitfield management.
+
+ * tests/common/bitfield.py:
+ New entry: test the new bitfield bindings.
+
+ * tests/common/pathname.py:
+ Typo.
+
17-05-08 Cyrille Bagard <nocbos@gmail.com>
* src/arch/raw.c:
diff --git a/plugins/pychrysa/arch/vmpa.c b/plugins/pychrysa/arch/vmpa.c
index 10acf35..03434d7 100644
--- a/plugins/pychrysa/arch/vmpa.c
+++ b/plugins/pychrysa/arch/vmpa.c
@@ -186,8 +186,9 @@ static PyObject *py_vmpa_to_str(PyObject *obj)
/******************************************************************************
* *
-* Paramètres : obj = objet Python à tenter de convertir. *
-* addr = structure équivalente pour Chrysalide. *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
* *
* Description : Effectue une comparaison avec un objet Python 'vmpa_t'. *
* *
@@ -199,7 +200,7 @@ static PyObject *py_vmpa_to_str(PyObject *obj)
static PyObject *py_vmpa_richcompare(PyObject *a, PyObject *b, int op)
{
- PyObject *result; /* Chaîne à retourner */
+ PyObject *result; /* Bilan à retourner */
vmpa2t *addr_a; /* Première adresse à traiter */
vmpa2t addr_b; /* Seconde adresse à traiter */
@@ -829,8 +830,9 @@ static PyObject *py_mrange_to_str(PyObject *obj)
/******************************************************************************
* *
-* Paramètres : obj = objet Python à tenter de convertir. *
-* addr = structure équivalente pour Chrysalide. *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
* *
* Description : Effectue une comparaison avec un objet Python 'mrange_t'. *
* *
@@ -842,7 +844,7 @@ static PyObject *py_mrange_to_str(PyObject *obj)
static PyObject *py_mrange_richcompare(PyObject *a, PyObject *b, int op)
{
- PyObject *result; /* Chaîne à retourner */
+ PyObject *result; /* Bilan à retourner */
mrange_t *range_a; /* Premier espace à traiter */
mrange_t *range_b; /* Second espace à traiter */
int status; /* Résultat d'une comparaison */
@@ -854,37 +856,7 @@ static PyObject *py_mrange_richcompare(PyObject *a, PyObject *b, int op)
status = cmp_mrange(range_a, range_b);
- switch (op)
- {
- case Py_LT:
- result = status < 0 ? Py_True : Py_False;
- break;
-
- case Py_LE:
- result = status <= 0 ? Py_True : Py_False;
- break;
-
- case Py_EQ:
- result = status == 0 ? Py_True : Py_False;
- break;
-
- case Py_NE:
- result = status != 0 ? Py_True : Py_False;
- break;
-
- case Py_GT:
- result = status > 0 ? Py_True : Py_False;
- break;
-
- case Py_GE:
- result = status >= 0 ? Py_True : Py_False;
- break;
-
- default:
- result = Py_NotImplemented;
- break;
-
- }
+ result = status_to_rich_cmp_state(status, op);
Py_INCREF(result);
diff --git a/plugins/pychrysa/common/Makefile.am b/plugins/pychrysa/common/Makefile.am
index 93d92ac..0637229 100644
--- a/plugins/pychrysa/common/Makefile.am
+++ b/plugins/pychrysa/common/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libpychrysacommon.la
libpychrysacommon_la_SOURCES = \
+ bits.h bits.c \
fnv1a.h fnv1a.c \
module.h module.c \
pathname.h pathname.c
diff --git a/plugins/pychrysa/common/bits.c b/plugins/pychrysa/common/bits.c
new file mode 100644
index 0000000..33f81c3
--- /dev/null
+++ b/plugins/pychrysa/common/bits.c
@@ -0,0 +1,653 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.c - équivalent Python du fichier "common/bits.c"
+ *
+ * Copyright (C) 2017 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 "bits.h"
+
+
+#include "../helpers.h"
+
+
+
+/* Encapsulation d'un champ de bits */
+typedef struct _py_bitfield_t
+{
+ PyObject_HEAD /* A laisser en premier */
+
+ bitfield_t *native; /* Champ de bits représenté */
+
+} py_bitfield_t;
+
+
+
+/* Crée un nouvel objet Python de type 'bitfield_t'. */
+static PyObject *py_bitfield_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Crée une copie d'un champ de bits classique. */
+static PyObject *py_bitfield_dup(PyObject *, PyObject *);
+
+/* Effectue une opération de type 'and' avec le type 'bitfield'. */
+static PyObject *py_bitfield_nb_and(PyObject *, PyObject *);
+
+/* Effectue une opération de type 'or' avec le type 'bitfield'. */
+static PyObject *py_bitfield_nb_or(PyObject *, PyObject *);
+
+/* Effectue une comparaison avec un objet Python 'bitfield'. */
+static PyObject *py_bitfield_richcompare(PyObject *, PyObject *, int);
+
+/* Bascule à 0 un champ de bits dans son intégralité. */
+static PyObject *py_bitfield_reset_all(PyObject *, PyObject *);
+
+/* Bascule à 1 un champ de bits dans son intégralité. */
+static PyObject *py_bitfield_set_all(PyObject *, PyObject *);
+
+/* Bascule à 0 une partie d'un champ de bits. */
+static PyObject *py_bitfield_reset(PyObject *, PyObject *);
+
+/* Bascule à 1 une partie d'un champ de bits. */
+static PyObject *py_bitfield_set(PyObject *, PyObject *);
+
+/* Détermine si un bit est à 1 dans un champ de bits. */
+static PyObject *py_bitfield_test(PyObject *, PyObject *);
+
+/* Détermine si un ensemble de bits est à 0 dans un champ. */
+static PyObject *py_bitfield_test_none(PyObject *, PyObject *);
+
+/* Détermine si un ensemble de bits est à 1 dans un champ. */
+static PyObject *py_bitfield_test_all(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'bitfield_t'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ py_bitfield_t *result; /* Instance à retourner */
+ unsigned long length; /* Taille du champ à créer */
+ int state; /* Initialisation par défaut */
+ int ret; /* Bilan de lecture des args. */
+
+ ret = PyArg_ParseTuple(args, "kp", &length, &state);
+ if (!ret) return NULL;
+
+ result = (py_bitfield_t *)type->tp_alloc(type, 0);
+
+ result->native = create_bit_field(length, state);
+
+ return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à dupliquer. *
+* args = non utilisé ici. *
+* *
+* Description : Crée une copie d'un champ de bits classique. *
+* *
+* Retour : Champ de bits mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_dup(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+ bf = (py_bitfield_t *)self;
+
+ result = build_from_internal_bitfield(bf->native);;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : o1 = premier élément concerné par l'opération. *
+* o2 = second élément concerné par l'opération. *
+* *
+* Description : Effectue une opération de type 'and' avec le type 'bitfield'.*
+* *
+* Retour : Résultat de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_nb_and(PyObject *o1, PyObject *o2)
+{
+ PyObject *result; /* Résultat à retourner */
+ int ret; /* Bilan de compatibilité */
+ py_bitfield_t *bf_1; /* Instance à manipuler #1 */
+ py_bitfield_t *bf_2; /* Instance à manipuler #2 */
+ py_bitfield_t *new; /* Nouvelle version en place */
+
+ ret = PyObject_IsInstance(o2, (PyObject *)get_python_bitfield_type());
+ if (!ret)
+ {
+ result = NULL;
+ goto pbna_done;
+ }
+
+ bf_1 = (py_bitfield_t *)o1;
+ bf_2 = (py_bitfield_t *)o2;
+
+ result = build_from_internal_bitfield(bf_1->native);
+
+ new = (py_bitfield_t *)result;
+
+ and_bit_field(new->native, bf_2->native);
+
+ pbna_done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : o1 = premier élément concerné par l'opération. *
+* o2 = second élément concerné par l'opération. *
+* *
+* Description : Effectue une opération de type 'or' avec le type 'bitfield'. *
+* *
+* Retour : Résultat de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_nb_or(PyObject *o1, PyObject *o2)
+{
+ PyObject *result; /* Résultat à retourner */
+ int ret; /* Bilan de compatibilité */
+ py_bitfield_t *bf_1; /* Instance à manipuler #1 */
+ py_bitfield_t *bf_2; /* Instance à manipuler #2 */
+ py_bitfield_t *new; /* Nouvelle version en place */
+
+ ret = PyObject_IsInstance(o2, (PyObject *)get_python_bitfield_type());
+ if (!ret)
+ {
+ result = NULL;
+ goto pbna_done;
+ }
+
+ bf_1 = (py_bitfield_t *)o1;
+ bf_2 = (py_bitfield_t *)o2;
+
+ result = build_from_internal_bitfield(bf_1->native);
+
+ new = (py_bitfield_t *)result;
+
+ or_bit_field(new->native, bf_2->native);
+
+ pbna_done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
+* *
+* Description : Effectue une comparaison avec un objet Python 'bitfield'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_richcompare(PyObject *a, PyObject *b, int op)
+{
+ PyObject *result; /* Bilan à retourner */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf_a; /* Instance à manipuler #1 */
+ py_bitfield_t *bf_b; /* Instance à manipuler #2 */
+ int status; /* Résultat d'une comparaison */
+
+ ret = PyObject_IsInstance(b, (PyObject *)get_python_bitfield_type());
+ if (!ret)
+ {
+ result = Py_NotImplemented;
+ goto cmp_done;
+ }
+
+ bf_a = (py_bitfield_t *)a;
+ bf_b = (py_bitfield_t *)b;
+
+ status = compare_bit_fields(bf_a->native, bf_b->native);
+
+ result = status_to_rich_cmp_state(status, op);
+
+ cmp_done:
+
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à modifier. *
+* args = non utilisé ici. *
+* *
+* Description : Bascule à 0 un champ de bits dans son intégralité. *
+* *
+* Retour : Rien (None). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_reset_all(PyObject *self, PyObject *args)
+{
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+ bf = (py_bitfield_t *)self;
+
+ reset_all_in_bit_field(bf->native);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à modifier. *
+* args = non utilisé ici. *
+* *
+* Description : Bascule à 1 un champ de bits dans son intégralité. *
+* *
+* Retour : Rien (None). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_set_all(PyObject *self, PyObject *args)
+{
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+ bf = (py_bitfield_t *)self;
+
+ set_all_in_bit_field(bf->native);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Bascule à 0 une partie d'un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_reset(PyObject *self, PyObject *args)
+{
+ unsigned long first; /* Indice du premier bit testé */
+ unsigned long count; /* Nombre de bits à analyser */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+ ret = PyArg_ParseTuple(args, "kk", &first, &count);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ reset_in_bit_field(bf->native, first, count);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Bascule à 1 une partie d'un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_set(PyObject *self, PyObject *args)
+{
+ unsigned long first; /* Indice du premier bit testé */
+ unsigned long count; /* Nombre de bits à analyser */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+ ret = PyArg_ParseTuple(args, "kk", &first, &count);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ set_in_bit_field(bf->native, first, count);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Détermine si un bit est à 1 dans un champ de bits. *
+* *
+* Retour : true si le bit correspondant est à l'état haut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long n; /* Indice du bit à traiter */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+ ret = PyArg_ParseTuple(args, "k", &n);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_in_bit_field(bf->native, n);
+
+ result = status ? Py_True : Py_False;
+
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Détermine si un ensemble de bits est à 0 dans un champ. *
+* *
+* Retour : True si les bits correspondants sont à l'état bas. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_none(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ unsigned long count; /* Nombre de bits à analyser */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+ ret = PyArg_ParseTuple(args, "kk", &first, &count);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_none_in_bit_field(bf->native, first, count);
+
+ result = status ? Py_True : Py_False;
+
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Détermine si un ensemble de bits est à 1 dans un champ. *
+* *
+* Retour : True si les bits correspondants sont à l'état haut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ unsigned long count; /* Nombre de bits à analyser */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+ ret = PyArg_ParseTuple(args, "kk", &first, &count);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_all_in_bit_field(bf->native, first, count);
+
+ result = status ? Py_True : Py_False;
+
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_bitfield_type(void)
+{
+ static PyNumberMethods py_bitfield_nb_proto = {
+
+ .nb_and = py_bitfield_nb_and,
+ .nb_or = py_bitfield_nb_or
+
+ };
+
+ static PyMethodDef py_bitfield_methods[] = {
+ {
+ "dup", py_bitfield_dup,
+ METH_NOARGS,
+ "dup(self, /)\n--\n\nDuplicate a bitfield."
+ },
+ {
+ "reset_all", py_bitfield_reset_all,
+ METH_NOARGS,
+ "reset_all(self, /)\n--\n\nSwitch to 0 all bits in a bitfield."
+ },
+ {
+ "set_all", py_bitfield_set_all,
+ METH_NOARGS,
+ "set_all(self, /)\n--\n\nSwitch to 1 all bits in a bitfield."
+ },
+ {
+ "reset", py_bitfield_reset,
+ METH_VARARGS,
+ "reset(self, first, count, /)\n--\n\nSwitch to 0 a part of bits in a bitfield."
+ },
+ {
+ "set", py_bitfield_set,
+ METH_VARARGS,
+ "set(self, first, count, /)\n--\n\nSwitch to 1 a part of bits in a bitfield."
+ },
+ {
+ "test", py_bitfield_test,
+ METH_VARARGS,
+ "test(self, n, /)\n--\n\nTest if a given bit is set in a bitfield."
+ },
+ {
+ "test_none", py_bitfield_test_none,
+ METH_VARARGS,
+ "test_none(self, first, count, /)\n--\n\nTest a range of bits to 0."
+ },
+ {
+ "test_all", py_bitfield_test_all,
+ METH_VARARGS,
+ "test_all(self, first, count, /)\n--\n\nTest a range of bits to 1."
+ },
+ { NULL }
+ };
+
+ static PyGetSetDef py_bitfield_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_bitfield_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.common.bitfield",
+ .tp_basicsize = sizeof(py_bitfield_t),
+
+ .tp_as_number = &py_bitfield_nb_proto,
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = "Python object for bitfield_t.",
+
+ .tp_richcompare = py_bitfield_richcompare,
+
+ .tp_methods = py_bitfield_methods,
+ .tp_getset = py_bitfield_getseters,
+ .tp_new = (newfunc)py_bitfield_new
+
+ };
+
+ return &py_bitfield_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.common.bitfield'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_bitfield(PyObject *module)
+{
+ PyTypeObject *py_bitfield_type; /* Type Python pour 'bitfield' */
+ int ret; /* Bilan d'un appel */
+
+ py_bitfield_type = get_python_bitfield_type();
+
+ if (PyType_Ready(py_bitfield_type) != 0)
+ return false;
+
+ Py_INCREF(py_bitfield_type);
+ ret = PyModule_AddObject(module, "bitfield", (PyObject *)py_bitfield_type);
+
+ return (ret == 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = structure interne à copier en objet Python. *
+* *
+* Description : Convertit une structure de type 'bitfield' en objet Python. *
+* *
+* Retour : Object Python résultant de la conversion opérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *build_from_internal_bitfield(const bitfield_t *field)
+{
+ py_bitfield_t *result; /* Instance à retourner */
+ PyTypeObject *type; /* Type à instancier */
+
+ type = get_python_bitfield_type();
+
+ result = (py_bitfield_t *)type->tp_alloc(type, 0);
+
+ result->native = dup_bit_field(field);
+
+ return (PyObject *)result;
+
+}
diff --git a/plugins/pychrysa/common/bits.h b/plugins/pychrysa/common/bits.h
new file mode 100644
index 0000000..41465ce
--- /dev/null
+++ b/plugins/pychrysa/common/bits.h
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour l'équivalent Python du fichier "common/bits.h"
+ *
+ * Copyright (C) 2017 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_PYCHRYSA_COMMON_BITS_H
+#define _PLUGINS_PYCHRYSA_COMMON_BITS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+#include <common/bits.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_bitfield_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.common.bitfield'. */
+bool register_python_bitfield(PyObject *);
+
+/* Convertit une structure de type 'bitfield' en objet Python. */
+PyObject *build_from_internal_bitfield(const bitfield_t *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSA_COMMON_BITS_H */
diff --git a/plugins/pychrysa/common/module.c b/plugins/pychrysa/common/module.c
index cc23631..cc2623a 100644
--- a/plugins/pychrysa/common/module.c
+++ b/plugins/pychrysa/common/module.c
@@ -25,6 +25,7 @@
#include "module.h"
+#include "bits.h"
#include "fnv1a.h"
#include "pathname.h"
@@ -76,6 +77,7 @@ bool add_common_module_to_python_module(PyObject *super)
result = true;
+ result &= register_python_bitfield(module);
result &= register_python_fnv1a(module);
result &= register_python_pathname(module);
diff --git a/plugins/pychrysa/format/symbol.c b/plugins/pychrysa/format/symbol.c
index 53fb9c9..75f226a 100644
--- a/plugins/pychrysa/format/symbol.c
+++ b/plugins/pychrysa/format/symbol.c
@@ -85,8 +85,9 @@ static bool py_binary_symbol_define_constants(PyTypeObject *);
/******************************************************************************
* *
-* Paramètres : obj = objet Python à tenter de convertir. *
-* addr = structure équivalente pour Chrysalide. *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
* *
* Description : Effectue une comparaison avec un objet Python 'BinSymbol'. *
* *
@@ -98,7 +99,7 @@ static bool py_binary_symbol_define_constants(PyTypeObject *);
static PyObject *py_binary_symbol_richcompare(PyObject *a, PyObject *b, int op)
{
- PyObject *result; /* Chaîne à retourner */
+ PyObject *result; /* Bilan à retourner */
int ret; /* Bilan de lecture des args. */
const GBinSymbol *sym_a; /* Premier élément à traiter */
const GBinSymbol *sym_b; /* Second élément à traiter */
@@ -116,37 +117,7 @@ static PyObject *py_binary_symbol_richcompare(PyObject *a, PyObject *b, int op)
status = g_binary_symbol_cmp(&sym_a, &sym_b);
- switch (op)
- {
- case Py_LT:
- result = status < 0 ? Py_True : Py_False;
- break;
-
- case Py_LE:
- result = status <= 0 ? Py_True : Py_False;
- break;
-
- case Py_EQ:
- result = status == 0 ? Py_True : Py_False;
- break;
-
- case Py_NE:
- result = status != 0 ? Py_True : Py_False;
- break;
-
- case Py_GT:
- result = status > 0 ? Py_True : Py_False;
- break;
-
- case Py_GE:
- result = status >= 0 ? Py_True : Py_False;
- break;
-
- default:
- result = Py_NotImplemented;
- break;
-
- }
+ result = status_to_rich_cmp_state(status, op);
cmp_done:
diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c
index 36d0d76..df1df05 100644
--- a/plugins/pychrysa/helpers.c
+++ b/plugins/pychrysa/helpers.c
@@ -31,6 +31,60 @@
/******************************************************************************
* *
+* Paramètres : status = bilan de comparaison à traduire. *
+* op = type de comparaison menée. *
+* *
+* Description : Traduit pour Python le bilan d'une comparaison riche. *
+* *
+* Retour : Objet Python à référencer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *status_to_rich_cmp_state(int status, int op)
+{
+ PyObject *result; /* Bilan àretourner */
+
+ switch (op)
+ {
+ case Py_LT:
+ result = status < 0 ? Py_True : Py_False;
+ break;
+
+ case Py_LE:
+ result = status <= 0 ? Py_True : Py_False;
+ break;
+
+ case Py_EQ:
+ result = status == 0 ? Py_True : Py_False;
+ break;
+
+ case Py_NE:
+ result = status != 0 ? Py_True : Py_False;
+ break;
+
+ case Py_GT:
+ result = status > 0 ? Py_True : Py_False;
+ break;
+
+ case Py_GE:
+ result = status >= 0 ? Py_True : Py_False;
+ break;
+
+ default:
+ result = Py_NotImplemented;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : target = propriétaire de la routine visée. *
* method = désignation de la fonction à appeler. *
* *
diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h
index 3e079b7..950c85b 100644
--- a/plugins/pychrysa/helpers.h
+++ b/plugins/pychrysa/helpers.h
@@ -31,6 +31,9 @@
+/* Traduit pour Python le bilan d'une comparaison riche. */
+PyObject *status_to_rich_cmp_state(int, int);
+
/* Indique si une routine Python existe ou non. */
bool has_python_method(PyObject *, const char *);
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index f01b89c..ed53b28 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -60,6 +60,7 @@ typedef struct _mem_area
bitfield_t *processed; /* Octets traités dans la zone */
GArchInstruction **instructions; /* Instructions en place */
size_t count; /* Quantité d'instructions */
+ GMutex mutex; /* Garantie d'atomicité */
bool is_exec; /* Zone exécutable ? */
@@ -249,6 +250,7 @@ static void init_mem_area_from_addr(mem_area *area, const vmpa2t *addr, phys_t l
area->processed = create_bit_field(len, false);
area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
area->count = 0;
+ g_mutex_init(&area->mutex);
}
@@ -284,6 +286,8 @@ static void fini_mem_area(mem_area *area)
free(area->instructions);
+ g_mutex_clear(&area->mutex);
+
}
@@ -365,6 +369,10 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
phys_t offset; /* Décallage de départ */
phys_t i; /* Boucle de parcours */
GArchInstruction *old; /* Instruction remplacée */
+ const mrange_t *old_range; /* Emplacement de l'instruction*/
+ phys_t old_len; /* Taille de cette instruction */
+
+ /* Détermination de la couverture */
start = get_mrange_addr(&area->range);
@@ -374,21 +382,23 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
offset = compute_vmpa_diff(start, addr);
- result = set_atomic_in_bit_field(area->processed, offset, len);
+ /* Début des choses sérieuses */
+
+ g_mutex_lock(&area->mutex);
- /* Si l'instruction était bien la première à s'inscrire... */
+ /* Vérification de couverture */
- result |= force;
+ result = test_none_in_bit_field(area->processed, offset, len);
- if (result)
+ if (!result)
{
- assert(area->instructions[offset] == NULL || force);
+ if (!force) goto mrimaap_exit;
/**
* Un cas de remplacement forcé intervient en ARM, lorsque qu'une
* instruction utilise une valeur immédiate placée dans le code.
*
- * Cette valeur est référencée en tant que symbole.
+ * Cette valeur doit être référencée en tant que donnée.
*
* Mais cette même valeur a pu être désassemblée en tant que code
* exécutable si le flot d'exécution s'est poursuivi jusqu'à elle.
@@ -400,33 +410,52 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
* On réinitialise donc la zone couverte par la nouvelle instruction.
*/
- for (i = 0; force && i < len; i++)
+ for (i = 0; i < len; i++)
{
old = area->instructions[offset + i];
if (old != NULL)
{
+ old_range = g_arch_instruction_get_range(old);
+ old_len = get_mrange_length(old_range);
+
+ reset_in_bit_field(area->processed, offset + i, old_len);
+
g_object_unref(G_OBJECT(old));
area->instructions[offset + i] = NULL;
+
g_atomic_pointer_add(&area->count, -1);
+
}
}
+ result = true;
+
+ }
+
+ /* Inscription de l'instruction dans les comptes */
+
#ifndef NDEBUG
- for (i = 0; i < len; i++)
- assert(area->instructions[offset + i] == NULL);
+ for (i = 0; i < len; i++)
+ assert(area->instructions[offset + i] == NULL);
#endif
- area->instructions[offset] = instr;
- g_atomic_pointer_add(&area->count, 1);
+ set_in_bit_field(area->processed, offset, len);
- /* Au passage, association du contenu */
- g_arch_instruction_set_global_content(instr, area->content);
+ area->instructions[offset] = instr;
+ g_atomic_pointer_add(&area->count, 1);
- }
+ /* Au passage, association du contenu */
+ g_arch_instruction_set_global_content(instr, area->content);
+
+ mrimaap_exit:
+
+ /* Fin des choses sérieuses */
+
+ g_mutex_unlock(&area->mutex);
return result;
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c
index 75ccc40..9064af8 100644
--- a/src/analysis/disass/dragon.c
+++ b/src/analysis/disass/dragon.c
@@ -591,7 +591,7 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
set_in_bit_field(inter, k, 1);
- if (!is_bit_field_equal_to(node->bits, inter))
+ if (compare_bit_fields(node->bits, inter) != 0)
{
copy_bit_field(node->bits, inter);
changed = true;
diff --git a/src/common/bits.c b/src/common/bits.c
index d4d5074..4d4731a 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -37,22 +37,13 @@ struct _bitfield_t
size_t length; /* Nombre de bits représentés */
size_t requested; /* Nombre de mots alloués */
- void *tail; /* Limite du tableau de bits */
-
- GMutex mutex; /* Garantie d'atomicité */
unsigned long bits[0]; /* Mémoire d'accès associée */
};
/* Crée un champ de bits initialisé à zéro. */
-static bitfield_t *_create_bit_field(size_t, bool, size_t);
-
-/* Crée une copie de champ de bits initialisé à zéro. */
-static bitfield_t *_create_bit_field_from(const bitfield_t *, bool, size_t);
-
-/* Crée une copie d'un champ de bits classique. */
-static bitfield_t *_dup_bit_field(const bitfield_t *, size_t);
+static bitfield_t *_create_bit_field(size_t);
/* Détermine si un ensemble de bits est homogène dans un champ. */
static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
@@ -62,8 +53,6 @@ static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
/******************************************************************************
* *
* Paramètres : length = nom de bits du champ à représenter. *
-* state = état initial de chaque des bits. *
-* extra = espace mémoire supplémentaire à ajouter au final. *
* *
* Description : Crée un champ de bits initialisé à zéro. *
* *
@@ -73,31 +62,22 @@ static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
* *
******************************************************************************/
-static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
+static bitfield_t *_create_bit_field(size_t length)
{
bitfield_t *result; /* Création à retourner */
size_t requested; /* Nombre de mots à allouer */
size_t base; /* Allocation de base en octets*/
- requested = length / sizeof(unsigned long);
- if (length % sizeof(unsigned long) != 0) requested++;
+ requested = length / (sizeof(unsigned long) * 8);
+ if (length % (sizeof(unsigned long) * 8) != 0) requested++;
base = sizeof(bitfield_t) + requested * sizeof(unsigned long);
- result = (bitfield_t *)malloc(base + extra);
+ result = (bitfield_t *)malloc(base);
result->length = length;
result->requested = requested;
- result->tail = ((char *)result) + base;
-
- g_mutex_init(&result->mutex);
-
- if (state)
- set_all_in_bit_field(result);
- else
- reset_all_in_bit_field(result);
-
return result;
}
@@ -105,7 +85,7 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
/******************************************************************************
* *
-* Paramètres : length = nom de bits du champ à représenter. *
+* Paramètres : length = nombre de bits du champ à représenter. *
* state = état initial de chaque des bits. *
* *
* Description : Crée un champ de bits initialisé. *
@@ -118,38 +98,25 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
bitfield_t *create_bit_field(size_t length, bool state)
{
- return _create_bit_field(length, state, 0);
-
-}
+ bitfield_t *result; /* Création à retourner */
+ result = _create_bit_field(length);
-/******************************************************************************
-* *
-* Paramètres : field = champde bits à prendre pour modèle. *
-* state = état initial de chaque des bits. *
-* extra = espace mémoire supplémentaire à ajouter au final. *
-* *
-* Description : Crée une copie de champ de bits initialisé à zéro. *
-* *
-* Retour : Champ de bits mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (state)
+ set_all_in_bit_field(result);
+ else
+ reset_all_in_bit_field(result);
-static bitfield_t *_create_bit_field_from(const bitfield_t *field, bool state, size_t extra)
-{
- return _create_bit_field(field->length, state, extra);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : field = champde bits à prendre pour modèle. *
-* state = état initial de chaque des bits. *
+* Paramètres : field = champ de bits à dupliquer. *
* *
-* Description : Crée une copie de champ de bits initialisé à zéro. *
+* Description : Crée une copie d'un champ de bits classique. *
* *
* Retour : Champ de bits mis en place. *
* *
@@ -157,9 +124,15 @@ static bitfield_t *_create_bit_field_from(const bitfield_t *field, bool state, s
* *
******************************************************************************/
-bitfield_t *create_bit_field_from(const bitfield_t *field, bool state)
+bitfield_t *dup_bit_field(const bitfield_t *field)
{
- return _create_bit_field_from(field, state, 0);
+ bitfield_t *result; /* Copie à retourner */
+
+ result = _create_bit_field(field->length);
+
+ memcpy(result->bits, field->bits, result->requested * sizeof(unsigned long));
+
+ return result;
}
@@ -178,8 +151,6 @@ bitfield_t *create_bit_field_from(const bitfield_t *field, bool state)
void delete_bit_field(bitfield_t *field)
{
- g_mutex_clear(&field->mutex);
-
free(field);
}
@@ -209,49 +180,64 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
/******************************************************************************
* *
-* Paramètres : field = champ de bits à dupliquer. *
-* extra = espace mémoire supplémentaire à ajouter au final. *
+* Paramètres : a = premier champ à analyser. *
+* b = second champ à analyser. *
* *
-* Description : Crée une copie d'un champ de bits classique. *
+* Description : Compare deux champs de bits entre eux. *
* *
-* Retour : Champ de bits mis en place. *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bitfield_t *_dup_bit_field(const bitfield_t *field, size_t extra)
+int compare_bit_fields(const bitfield_t *a, const bitfield_t *b)
{
- bitfield_t *result; /* Copie à retourner */
- size_t requested; /* Nombre de mots à allouer */
+ int result; /* Bilan à retourner */
+ unsigned long final; /* Masque de la partie finale */
+ size_t i; /* Boucle de parcours */
+ unsigned long val_a; /* Valeur d'un mot de A */
+ unsigned long val_b; /* Valeur d'un mot de B */
- result = _create_bit_field(field->length, false, extra);
+ result = 0;
- requested = field->length / sizeof(unsigned long);
- if (field->length % sizeof(unsigned long) != 0) requested++;
+ if (a->length > b->length)
+ result = 1;
- memcpy(result->bits, field->bits, requested * sizeof(unsigned long));
+ else if (a->length < b->length)
+ result = -1;
- return result;
+ if (result == 0)
+ {
+ final = a->length % sizeof(unsigned long);
-}
+ if (final == 0)
+ final = ~0lu;
+ else
+ final = (1 << final) - 1;
+ for (i = 0; i < a->requested && result == 0; i++)
+ {
+ val_a = a->bits[i];
+ val_b = b->bits[i];
-/******************************************************************************
-* *
-* Paramètres : field = champ de bits à dupliquer. *
-* *
-* Description : Crée une copie d'un champ de bits classique. *
-* *
-* Retour : Champ de bits mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if ((i + 1) == a->requested)
+ {
+ val_a &= final;
+ val_b &= final;
+ }
-bitfield_t *dup_bit_field(const bitfield_t *field)
-{
- return _dup_bit_field(field, 0);
+ if (val_a > val_b)
+ result = 1;
+
+ else if (val_a < val_b)
+ result = -1;
+
+ }
+
+ }
+
+ return result;
}
@@ -300,7 +286,7 @@ void set_all_in_bit_field(bitfield_t *field)
* first = indice du premier bit à traiter. *
* count = nombre de bits à marquer. *
* *
-* Description : Bascule à 1 une partie d'un champ de bits. *
+* Description : Bascule à 0 une partie d'un champ de bits. *
* *
* Retour : - *
* *
@@ -308,7 +294,7 @@ void set_all_in_bit_field(bitfield_t *field)
* *
******************************************************************************/
-void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
{
size_t last; /* Point d'arrêt de la boucle */
size_t i; /* Boucle de parcours */
@@ -324,7 +310,7 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
index = i / (sizeof(unsigned long) * 8);
remaining = i % (sizeof(unsigned long) * 8);
- field->bits[index] |= (1ul << remaining);
+ field->bits[index] &= ~(1ul << remaining);
}
@@ -337,79 +323,34 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
* first = indice du premier bit à traiter. *
* count = nombre de bits à marquer. *
* *
-* Description : Bascule à 1 de façon atomique une partie d'un champ de bits. *
+* Description : Bascule à 1 une partie d'un champ de bits. *
* *
-* Retour : true si la zone traitée était entièrement vierge. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
{
- bool result; /* Bilan à retourner */
- size_t start; /* Mot de départ */
- size_t end; /* Mot d'arrivée */
+ size_t last; /* Point d'arrêt de la boucle */
+ size_t i; /* Boucle de parcours */
+ size_t index; /* Cellule de tableau visée */
size_t remaining; /* Nombre de bits restants */
- unsigned long mask; /* Nouvelle valeur à insérer */
- unsigned long oldval; /* Ancienne valeur présente */
-
- start = first / (sizeof(unsigned long) * 8);
- end = (first + count - 1) / (sizeof(unsigned long) * 8);
-
- if (start == end)
- {
- remaining = first % (sizeof(unsigned long) * 8);
- assert(count > 0 && count <= (sizeof(unsigned long) * 8));
-
- if (count == 64)
- {
- assert(remaining == 0);
- mask = ~0lu;
- }
- else
- {
- mask = (1lu << count) - 1;
- mask <<= remaining;
- }
-
- /**
- * Pour une raison inconnue, l'appel suivant est parfois sans effet :
- *
- * oldval = g_atomic_pointer_or(&field->bits[start], mask);
- *
- * On bascule donc dans l'équivalent plus long à exécuter...
- */
-
- g_mutex_lock(&field->mutex);
-
- oldval = field->bits[start];
-
- field->bits[start] |= mask;
-
- g_mutex_unlock(&field->mutex);
-
- result = ((oldval & mask) == 0);
+ last = first + count;
- assert(test_all_in_bit_field(field, first, count));
+ assert(last <= field->length);
- }
- else
+ for (i = first; i < last; i++)
{
- g_mutex_lock(&field->mutex);
-
- result = test_none_in_bit_field(field, first, count);
-
- if (result)
- set_in_bit_field(field, first, count);
+ index = i / (sizeof(unsigned long) * 8);
+ remaining = i % (sizeof(unsigned long) * 8);
- g_mutex_unlock(&field->mutex);
+ field->bits[index] |= (1ul << remaining);
}
- return result;
-
}
@@ -465,7 +406,7 @@ void or_bit_field(bitfield_t *dest, const bitfield_t *src)
/******************************************************************************
* *
-* Paramètres : field = champ de bits à modifier. *
+* Paramètres : field = champ de bits à consulter. *
* n = indice du bit à traiter. *
* *
* Description : Détermine si un bit est à 1 dans un champ de bits. *
@@ -503,7 +444,7 @@ bool test_in_bit_field(const bitfield_t *field, size_t n)
* *
* Description : Détermine si un ensemble de bits est homogène dans un champ. *
* *
-* Retour : true si le bit correspondant est à l'état haut. *
+* Retour : true si les bits correspondants sont à l'état indiqué. *
* *
* Remarques : - *
* *
@@ -539,13 +480,13 @@ static bool test_state_in_bit_field(const bitfield_t *field, size_t first, size_
/******************************************************************************
* *
-* Paramètres : field = champ de bits à modifier. *
+* Paramètres : field = champ de bits à consulter. *
* first = indice du premier bit à traiter. *
-* count = nombre de bits à marquer. *
+* count = nombre de bits à analyser. *
* *
* Description : Détermine si un ensemble de bits est à 0 dans un champ. *
* *
-* Retour : true si le bit correspondant est à l'état haut. *
+* Retour : true si les bits correspondants sont à l'état bas. *
* *
* Remarques : - *
* *
@@ -564,13 +505,13 @@ bool test_none_in_bit_field(const bitfield_t *field, size_t first, size_t count)
/******************************************************************************
* *
-* Paramètres : field = champ de bits à modifier. *
+* Paramètres : field = champ de bits à consulter. *
* first = indice du premier bit à traiter. *
-* count = nombre de bits à marquer. *
+* count = nombre de bits à analyser. *
* *
* Description : Détermine si un ensemble de bits est à 1 dans un champ. *
* *
-* Retour : true si le bit correspondant est à l'état haut. *
+* Retour : true si les bits correspondants sont à l'état haut. *
* *
* Remarques : - *
* *
@@ -585,61 +526,3 @@ bool test_all_in_bit_field(const bitfield_t *field, size_t first, size_t count)
return result;
}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier champ de bits à comparer. *
-* b = second champ de bits à comparer. *
-* *
-* Description : Indique si deux champs de bits sont identiques ou non. *
-* *
-* Retour : true si les champs de bits sont égaux ou false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool is_bit_field_equal_to(const bitfield_t *a, const bitfield_t *b)
-{
- bool result; /* Résultat à retourner */
- size_t i; /* Boucle de parcours */
- size_t remaining; /* Nombre de bits restants */
-
- if (a->length != b->length)
- return false;
-
- result = true;
-
- for (i = 0; i < (a->requested - 1) && result; i++)
- result = (a->bits[i] == b->bits[i]);
-
- if (result)
- {
- remaining = a->length % sizeof(unsigned long);
-
- if (remaining == 0)
- result = (a->bits[i] == b->bits[i]);
-
- else
- {
- remaining = (1 << (remaining + 1)) - 1;
-
- result = ((a->bits[i] & remaining) == (b->bits[i] & remaining));
-
- }
-
- }
-
- return result;
-
-}
-
-
-
-
-unsigned long gfw(const bitfield_t *field)
-{
- return field->bits[0];
-
-}
diff --git a/src/common/bits.h b/src/common/bits.h
index 4a2937f..b9fc0e6 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -36,8 +36,8 @@ typedef struct _bitfield_t bitfield_t;
/* Crée un champ de bits initialisé. */
bitfield_t *create_bit_field(size_t, bool);
-/* Crée une copie de champ de bits initialisé à zéro. */
-bitfield_t *create_bit_field_from(const bitfield_t *, bool);
+/* Crée une copie d'un champ de bits classique. */
+bitfield_t *dup_bit_field(const bitfield_t *);
/* Supprime de la mémoire un champ de bits donné. */
void delete_bit_field(bitfield_t *);
@@ -45,8 +45,8 @@ void delete_bit_field(bitfield_t *);
/* Copie un champ de bits dans un autre. */
void copy_bit_field(bitfield_t *, const bitfield_t *);
-/* Crée une copie d'un champ de bits classique. */
-bitfield_t *dup_bit_field(const bitfield_t *);
+/* Compare deux champs de bits entre eux. */
+int compare_bit_fields(const bitfield_t *, const bitfield_t *);
/* Bascule à 0 un champ de bits dans son intégralité. */
void reset_all_in_bit_field(bitfield_t *);
@@ -54,12 +54,12 @@ void reset_all_in_bit_field(bitfield_t *);
/* Bascule à 1 un champ de bits dans son intégralité. */
void set_all_in_bit_field(bitfield_t *);
+/* Bascule à 0 une partie d'un champ de bits. */
+void reset_in_bit_field(bitfield_t *, size_t, size_t);
+
/* Bascule à 1 une partie d'un champ de bits. */
void set_in_bit_field(bitfield_t *, size_t, size_t);
-/* Bascule à 1 de façon atomique une partie d'un champ de bits. */
-bool set_atomic_in_bit_field(bitfield_t *, size_t, size_t);
-
/* Réalise une opération ET logique entre deux champs de bits. */
void and_bit_field(bitfield_t *, const bitfield_t *);
@@ -75,14 +75,6 @@ bool test_none_in_bit_field(const bitfield_t *, size_t, size_t);
/* Détermine si un ensemble de bits est à 1 dans un champ. */
bool test_all_in_bit_field(const bitfield_t *, size_t, size_t);
-/* Indique si deux champs de bits sont identiques ou non. */
-bool is_bit_field_equal_to(const bitfield_t *, const bitfield_t *);
-
-
-
-
-unsigned long gfw(const bitfield_t *);
-
#endif /* _COMMON_BITS_H */
diff --git a/tests/common/bitfield.py b/tests/common/bitfield.py
new file mode 100644
index 0000000..ec61291
--- /dev/null
+++ b/tests/common/bitfield.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+# Tests minimalistes pour valider la construction de chemins relatifs et absolus.
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.common import bitfield
+
+
+class TestBitfields(ChrysalideTestCase):
+ """TestCase for common.bitfield*"""
+
+ def testDuplicateBitfield(self):
+ """Check duplicated bitfield value."""
+
+ bf = bitfield(10, 0)
+
+ bf2 = bf.dup()
+
+ self.assertEqual(bf, bf2)
+
+
+ def testBitfieldValues(self):
+ """Evaluate bitfields basic values."""
+
+ bf_a = bitfield(75, 1)
+
+ bf_b = bitfield(75, 0)
+
+ self.assertNotEqual(bf_a, bf_b)
+
+ bf_a = bitfield(75, 1)
+
+ bf_b = bitfield(75, 0)
+ bf_b.set_all()
+
+ self.assertEqual(bf_a, bf_b)
+
+ bf_a = bitfield(75, 1)
+ bf_a.reset_all()
+
+ bf_b = bitfield(75, 0)
+
+ self.assertEqual(bf_a, bf_b)
+
+
+ def testBitfieldLogicalOperations(self):
+ """Perform logical operations on bitfields."""
+
+ bf_a = bitfield(75, 1)
+
+ bf_b = bitfield(75, 0)
+
+ bf_f = bf_a & bf_b
+
+ self.assertEqual(bf_f, bf_b)
+
+ bf_f = bf_a | bf_b
+
+ self.assertEqual(bf_f, bf_a)
+
+
+ def testBitfieldSwitch(self):
+ """Switch various bits in bitfields."""
+
+ bf_1 = bitfield(75, 1)
+
+ bf_0 = bitfield(75, 0)
+
+ bf_t = bitfield(75, 0)
+
+ for i in range(75):
+ bf_t.set(i, 1)
+
+ self.assertEqual(bf_t, bf_1)
+
+ for i in range(75):
+ bf_t.reset(i, 1)
+
+ self.assertEqual(bf_t, bf_0)
+
+
+ def testBitfieldBits(self):
+ """Test bits in bitfields."""
+
+ bf = bitfield(54, 1)
+
+ self.assertTrue(bf.test(0))
+
+ self.assertTrue(bf.test(53))
+
+ self.assertTrue(bf.test_all(0, 54))
+
+ self.assertFalse(bf.test_none(0, 54))
+
+ bf = bitfield(54, 0)
+
+ self.assertFalse(bf.test(0))
+
+ self.assertFalse(bf.test(53))
+
+ self.assertFalse(bf.test_all(0, 54))
+
+ self.assertTrue(bf.test_none(0, 54))
diff --git a/tests/common/pathname.py b/tests/common/pathname.py
index 5cd238c..3692434 100644
--- a/tests/common/pathname.py
+++ b/tests/common/pathname.py
@@ -9,13 +9,13 @@ from chrysacase import ChrysalideTestCase
from pychrysalide.common import pathname
-class TestRestrictedContent(ChrysalideTestCase):
+class TestPathNames(ChrysalideTestCase):
"""TestCase for common.pathname.build*"""
@classmethod
def setUpClass(cls):
- super(TestRestrictedContent, cls).setUpClass()
+ super(TestPathNames, cls).setUpClass()
cls._tests = [
{