From dda68634391bea512a7861468fcf45f8292300bb Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 30 Mar 2017 19:20:58 +0200
Subject: Discriminated between tests for set and unset ranges of bits.

---
 ChangeLog                  |  13 +++
 src/analysis/disass/area.c |  54 ++++++++---
 src/analysis/disass/loop.c |   2 +-
 src/common/bits.c          | 234 ++++++++++++++-------------------------------
 src/common/bits.h          |  42 ++------
 src/gtkext/graph/cluster.c |   2 +-
 6 files changed, 138 insertions(+), 209 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4f92fe8..c1fd565 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+17-03-30  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	* src/analysis/disass/loop.c:
+	Update code.
+
+	* src/common/bits.c:
+	* src/common/bits.h:
+	Discriminate between tests for set and unset ranges of bits.
+
+	* src/gtkext/graph/cluster.c:
+	Update code.
+
 17-03-29  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/readelf/section.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 5478fe3..5dab3ab 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -72,8 +72,11 @@ static void init_mem_area_from_addr(mem_area *, const vmpa2t *, phys_t, const GL
 /* Libère d'une aire de données les ressources allouées. */
 static void fini_mem_area(mem_area *);
 
-/* Indique si une zone donnée est intégralement vierge ou non. */
-static bool is_range_blank_in_mem_area(mem_area *, phys_t, phys_t);
+/* Indique si une zone donnée est intégralement vierge. */
+static bool is_range_empty_in_mem_area(mem_area *, phys_t, phys_t);
+
+/* Indique si une zone donnée est intégralement occupée. */
+static bool is_range_busy_in_mem_area(mem_area *, phys_t, phys_t);
 
 /* Marque une série d'octets comme ayant été traités. */
 static bool mark_range_in_mem_area_as_processed(mem_area *, GArchInstruction *, bool);
@@ -271,6 +274,33 @@ static void fini_mem_area(mem_area *area)
 *                start = début de la zone à manipuler.                        *
 *                len   = taille de cette même aire de données.                *
 *                                                                             *
+*  Description : Indique si une zone donnée est intégralement vierge.         *
+*                                                                             *
+*  Retour      : true si l'aire visée n'a jamais été traitée, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_range_empty_in_mem_area(mem_area *area, phys_t start, phys_t len)
+{
+    bool result;                            /* Résultat à renvoyer         */
+
+    assert((start + len) <= get_mrange_length(&area->range));
+
+    result = test_none_in_bit_field(area->processed, start, len);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area  = aire représentant à contenu à parcourir.             *
+*                start = début de la zone à manipuler.                        *
+*                len   = taille de cette même aire de données.                *
+*                                                                             *
 *  Description : Indique si une zone donnée est intégralement vierge ou non.  *
 *                                                                             *
 *  Retour      : true si l'aire visée n'a jamais été traitée, false sinon.    *
@@ -279,13 +309,13 @@ static void fini_mem_area(mem_area *area)
 *                                                                             *
 ******************************************************************************/
 
-static bool is_range_blank_in_mem_area(mem_area *area, phys_t start, phys_t len)
+static bool is_range_busy_in_mem_area(mem_area *area, phys_t start, phys_t len)
 {
     bool result;                            /* Résultat à renvoyer         */
 
     assert((start + len) <= get_mrange_length(&area->range));
 
-    result = !test_in_bit_field(area->processed, start, len);
+    result = test_all_in_bit_field(area->processed, start, len);
 
     return result;
 
@@ -425,7 +455,7 @@ static GArchInstruction *load_raw_instruction_from_mem_area(mem_area *area, phys
 
     if (get_virt_addr(pos) % sz == 0
         && (offset + sz) <= get_mrange_length(&area->range)
-        && is_range_blank_in_mem_area(area, offset, sz))
+        && is_range_empty_in_mem_area(area, offset, sz))
     {
         *size = sz;
 
@@ -593,7 +623,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc
          * inutile.
          */
 
-        if (!is_range_blank_in_mem_area(area, i, 1))
+        if (is_range_busy_in_mem_area(area, i, 1))
             break;
 
         /* Décodage d'une nouvelle instruction */
@@ -636,7 +666,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc
 
         gtk_status_stack_update_activity_value(status, id, diff);
 
-        assert(!is_range_blank_in_mem_area(area, i, diff));
+        assert(is_range_busy_in_mem_area(area, i, diff));
 
         /* Enregistrement d'un éventuel début de routine */
 
@@ -712,7 +742,7 @@ static void load_data_from_mem_area(mem_area *area, GProcContext *ctx, const vmp
     {
         /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
 
-        if (!is_range_blank_in_mem_area(area, i, 1))
+        if (is_range_busy_in_mem_area(area, i, 1))
             break;
 
         /* Décodage d'une nouvelle instruction, sur mesure puis minimale */
@@ -745,7 +775,7 @@ static void load_data_from_mem_area(mem_area *area, GProcContext *ctx, const vmp
 
         gtk_status_stack_update_activity_value(status, id, diff);
 
-        assert(!is_range_blank_in_mem_area(area, i, diff));
+        assert(is_range_busy_in_mem_area(area, i, diff));
 
         /* On laisse une chance au code pour se reprendre... */
 
@@ -786,7 +816,7 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, GProcCon
 
     for (i = 0; i < len; i++)
     {
-        if (is_range_blank_in_mem_area(area, i, 1))
+        if (is_range_empty_in_mem_area(area, i, 1))
         {
             copy_vmpa(&start, addr);
             advance_vmpa(&start, i);
@@ -794,12 +824,12 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, GProcCon
             if (area->is_exec && get_virt_addr(&start) % area->packing_size == 0)
                 load_code_from_mem_area(area, list, count, ctx, &start, false, status, id);
 
-            if (is_range_blank_in_mem_area(area, i, 1))
+            if (is_range_empty_in_mem_area(area, i, 1))
                 load_data_from_mem_area(area, ctx, &start, status, id);
 
         }
 
-        assert(!is_range_blank_in_mem_area(area, i, 1));
+        assert(is_range_busy_in_mem_area(area, i, 1));
 
     }
 
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index a0dba66..d8ca355 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -80,7 +80,7 @@ static void detect_back_edges(dragon_node *nodes, size_t count)
 
                     id = get_dragon_node_index(nodes, target);
 
-                    if (test_in_bit_field(dominators, id, 1))
+                    if (test_in_bit_field(dominators, id))
                     {
 
                         /*
diff --git a/src/common/bits.c b/src/common/bits.c
index d941e54..d4d5074 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -31,9 +31,6 @@
 
 
 
-/* ----------------------------- CHAMPS DE BITS SIMPLES ----------------------------- */
-
-
 /* Champ de bits simple */
 struct _bitfield_t
 {
@@ -57,12 +54,10 @@ 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);
 
+/* 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);
 
 
-/* ---------------------------------------------------------------------------------- */
-/*                               CHAMPS DE BITS SIMPLES                               */
-/* ---------------------------------------------------------------------------------- */
-
 
 /******************************************************************************
 *                                                                             *
@@ -397,14 +392,14 @@ bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
 
         result = ((oldval & mask) == 0);
 
-        assert(test_in_bit_field(field, first, count));
+        assert(test_all_in_bit_field(field, first, count));
 
     }
     else
     {
         g_mutex_lock(&field->mutex);
 
-        result = !test_in_bit_field(field, first, count);
+        result = test_none_in_bit_field(field, first, count);
 
         if (result)
             set_in_bit_field(field, first, count);
@@ -471,8 +466,7 @@ void or_bit_field(bitfield_t *dest, const bitfield_t *src)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : field = champ de bits à modifier.                            *
-*                first = indice du premier bit à traiter.                     *
-*                count = nombre de bits à marquer.                            *
+*                n     = indice du bit à traiter.                             *
 *                                                                             *
 *  Description : Détermine si un bit est à 1 dans un champ de bits.           *
 *                                                                             *
@@ -482,28 +476,18 @@ void or_bit_field(bitfield_t *dest, const bitfield_t *src)
 *                                                                             *
 ******************************************************************************/
 
-bool test_in_bit_field(const bitfield_t *field, size_t first, size_t count)
+bool test_in_bit_field(const bitfield_t *field, size_t n)
 {
     bool result;                            /* Valeur retrouvée à renvoyer */
-    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     */
 
-    last = first + count;
-
-    assert(last <= field->length);
-
-    result = true;
-
-    for (i = first; i < last && result; i++)
-    {
-        index = i / (sizeof(unsigned long) * 8);
-        remaining = i % (sizeof(unsigned long) * 8);
+    assert(n < field->length);
 
-        result = field->bits[index] & (1ul << remaining);
+    index = n / (sizeof(unsigned long) * 8);
+    remaining = n % (sizeof(unsigned long) * 8);
 
-    }
+    result = field->bits[index] & (1ul << remaining);
 
     return result;
 
@@ -512,220 +496,150 @@ bool test_in_bit_field(const bitfield_t *field, size_t first, size_t count)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : a = premier champ de bits à comparer.                        *
-*                b = second champ de bits à comparer.                         *
+*  Paramètres  : field = champ de bits à modifier.                            *
+*                first = indice du premier bit à traiter.                     *
+*                count = nombre de bits à marquer.                            *
+*                state = état global à retrouver idéalement.                  *
 *                                                                             *
-*  Description : Indique si deux champs de bits sont identiques ou non.       *
+*  Description : Détermine si un ensemble de bits est homogène dans un champ. *
 *                                                                             *
-*  Retour      : true si les champs de bits sont égaux ou false sinon.        *
+*  Retour      : true si le bit correspondant est à l'état haut.              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool is_bit_field_equal_to(const bitfield_t *a, const bitfield_t *b)
+static bool test_state_in_bit_field(const bitfield_t *field, size_t first, size_t count, bool state)
 {
-    bool result;                            /* Résultat à retourner        */
+    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     */
+    bool current;                           /* Etat d'un bit donné         */
 
-    if (a->length != b->length)
-        return false;
-
-    result = true;
+    assert(count > 0);
 
-    for (i = 0; i < (a->requested - 1) && result; i++)
-        result = (a->bits[i] == b->bits[i]);
+    last = first + count;
 
-    if (result)
+    for (i = first; i < last; i++)
     {
-        remaining = a->length % sizeof(unsigned long);
-
-        if (remaining == 0)
-            result = (a->bits[i] == b->bits[i]);
-
-        else
-        {
-            remaining = (1 << (remaining + 1)) - 1;
+        index = i / (sizeof(unsigned long) * 8);
+        remaining = i % (sizeof(unsigned long) * 8);
 
-            result = ((a->bits[i] & remaining) == (b->bits[i] & remaining));
+        current = field->bits[index] & (1ul << remaining);
 
-        }
+        if (current != state) break;
 
     }
 
-    return result;
-
-}
-
-
-
-
-unsigned long gfw(const bitfield_t *field)
-{
-    return field->bits[0];
+    return (i == last);
 
 }
 
-#if 0
-
-/* ---------------------------------------------------------------------------------- */
-/*                           CHAMPS LIES À UNE ZONE MEMOIRE                           */
-/* ---------------------------------------------------------------------------------- */
-
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : range = espace mémoire à couvrir.                            *
-*                state = état initial de chaque des bits.                     *
+*  Paramètres  : field = champ de bits à modifier.                            *
+*                first = indice du premier bit à traiter.                     *
+*                count = nombre de bits à marquer.                            *
 *                                                                             *
-*  Description : Crée un champ de bits couvrant une zone mémoire.             *
+*  Description : Détermine si un ensemble de bits est à 0 dans un champ.      *
 *                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
+*  Retour      : true si le bit correspondant est à l'état haut.              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-memfield_t *create_mem_field(const mrange_t *range, bool state)
+bool test_none_in_bit_field(const bitfield_t *field, size_t first, size_t count)
 {
-    bitfield_t *result;                     /* Création à retourner        */
-
-    result = _create_bit_field(get_mrange_length(range), state, sizeof(vmpa2t));
+    bool result;                            /* Valeur retrouvée à renvoyer */
 
-    copy_vmpa((vmpa2t *)result->tail, get_mrange_addr(range));
+    result = test_state_in_bit_field(field, first, count, false);
 
-    return (memfield_t *)result;
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : range = espace mémoire à couvrir.                            *
+*  Paramètres  : field = champ de bits à modifier.                            *
+*                first = indice du premier bit à traiter.                     *
+*                count = nombre de bits à marquer.                            *
 *                                                                             *
-*  Description : Crée une copie de champ de bits couvrant une zone mémoire.   *
+*  Description : Détermine si un ensemble de bits est à 1 dans un champ.      *
 *                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
+*  Retour      : true si le bit correspondant est à l'état haut.              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-memfield_t *create_mem_field_from(const memfield_t *field)
+bool test_all_in_bit_field(const bitfield_t *field, size_t first, size_t count)
 {
-    bitfield_t *result;                     /* Création à retourner        */
-
-    result = _create_bit_field_from((bitfield_t *)field, false, sizeof(vmpa2t));
-
-    copy_vmpa((vmpa2t *)result->tail, (vmpa2t *)field->tail);
-
-    return (memfield_t *)result;
-
-}
-
+    bool result;                            /* Valeur retrouvée à renvoyer */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : field = champ de bits à effacer.                             *
-*                                                                             *
-*  Description : Supprime de la mémoire un champ de bits donné.               *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    result = test_state_in_bit_field(field, first, count, true);
 
-void delete_mem_field(memfield_t *field)
-{
-    delete_bit_field((bitfield_t *)field);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champ de bits à dupliquer.                           *
+*  Paramètres  : a = premier champ de bits à comparer.                        *
+*                b = second champ de bits à comparer.                         *
 *                                                                             *
-*  Description : Crée une copie d'un champ de bits couvrant une zone mémoire. *
+*  Description : Indique si deux champs de bits sont identiques ou non.       *
 *                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
+*  Retour      : true si les champs de bits sont égaux ou false sinon.        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-memfield_t *dup_mem_field(const memfield_t *field)
+bool is_bit_field_equal_to(const bitfield_t *a, const bitfield_t *b)
 {
-    bitfield_t *result;                     /* Création à retourner        */
-
-    result = _dup_bit_field((bitfield_t *)field, sizeof(vmpa2t));
+    bool result;                            /* Résultat à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+    size_t remaining;                       /* Nombre de bits restants     */
 
-    copy_vmpa((vmpa2t *)result->tail, (vmpa2t *)field->tail);
+    if (a->length != b->length)
+        return false;
 
-    return (memfield_t *)result;
+    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);
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : field = champ de bits à modifier.                            *
-*                addr  = emplacement en mémoire à traiter.                    *
-*                                                                             *
-*  Description : Bascule à 1 un bit d'un champ de bits.                       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+        if (remaining == 0)
+            result = (a->bits[i] == b->bits[i]);
 
-void set_in_mem_field(memfield_t *field, const vmpa2t *addr)
-{
-    vmpa2t *start;                          /* Adresse de début            */
-    phys_t offset;                          /* Décallage de départ         */
+        else
+        {
+            remaining = (1 << (remaining + 1)) - 1;
 
-    start = (vmpa2t *)field->tail;
+            result = ((a->bits[i] & remaining) == (b->bits[i] & remaining));
 
-    assert(cmp_vmpa(start, addr) <= 0);
+        }
 
-    offset = compute_vmpa_diff(start, addr);
+    }
 
-    set_in_bit_field((bitfield_t *)field, offset, 1);
+    return result;
 
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : field = champ de bits à modifier.                            *
-*                addr  = emplacement en mémoire à tester.                     *
-*                                                                             *
-*  Description : Détermine si un bit est à 1 dans un champ de bits.           *
-*                                                                             *
-*  Retour      : true si le bit correspondant est à l'état haut.              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool test_in_mem_field(memfield_t *field, const vmpa2t *addr)
-{
-    bool result;                            /* Valeur retrouvée à renvoyer */
-    vmpa2t *start;                          /* Adresse de début            */
-    phys_t offset;                          /* Décallage de départ         */
-
-    start = (vmpa2t *)field->tail;
-
-    assert(cmp_vmpa(start, addr) <= 0);
 
-    offset = compute_vmpa_diff(start, addr);
 
-    result = test_in_bit_field((bitfield_t *)field, offset, 1);
-
-    return result;
+unsigned long gfw(const bitfield_t *field)
+{
+    return field->bits[0];
 
 }
-#endif
diff --git a/src/common/bits.h b/src/common/bits.h
index 1396789..4a2937f 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -29,9 +29,6 @@
 
 
 
-/* ----------------------------- CHAMPS DE BITS SIMPLES ----------------------------- */
-
-
 /* Champ de bits simple */
 typedef struct _bitfield_t bitfield_t;
 
@@ -70,7 +67,13 @@ void and_bit_field(bitfield_t *, const bitfield_t *);
 void or_bit_field(bitfield_t *, const bitfield_t *);
 
 /* Détermine si un bit est à 1 dans un champ de bits. */
-bool test_in_bit_field(const bitfield_t *, size_t, size_t);
+bool test_in_bit_field(const bitfield_t *, size_t);
+
+/* Détermine si un ensemble de bits est à 0 dans un champ. */
+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 *);
@@ -80,37 +83,6 @@ bool is_bit_field_equal_to(const bitfield_t *, const bitfield_t *);
 
 unsigned long gfw(const bitfield_t *);
 
-#if 0
-/* ------------------------- CHAMPS LIES À UNE ZONE MEMOIRE ------------------------- */
-
-
-/* Champ de bits couvrant une mémoire */
-typedef struct _bitfield_t memfield_t;
-
-
-/* Crée un champ de bits couvrant une zone mémoire. */
-memfield_t *create_mem_field(const mrange_t *, bool);
-
-/* Crée une copie de champ de bits couvrant une zone mémoire. */
-memfield_t *create_mem_field_from(const memfield_t *);
-
-/* Supprime de la mémoire un champ de bits donné. */
-void delete_mem_field(memfield_t *);
-
-/* Crée une copie d'un champ de bits couvrant une zone mémoire. */
-memfield_t *dup_mem_field(const memfield_t *);
-
-/* Bascule à 1 un bit d'un champ de bits. */
-void set_in_mem_field(memfield_t *, const vmpa2t *);
-
-/* Détermine si un bit est à 1 dans un champ de bits. */
-bool test_in_mem_field(memfield_t *, const vmpa2t *);
-
-
-
-#define set_atomic_in_mem_field(f, range) false
-
-#endif
 
 
 #endif  /* _COMMON_BITS_H */
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index c1ed8ce..9aee82c 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -1631,7 +1631,7 @@ static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockLi
             block = pending->list[i];
             dominators = g_basic_block_get_domination(block);
 
-            if (test_in_bit_field(dominators, index, 1))
+            if (test_in_bit_field(dominators, index))
             {
                 /* Dépilement */
 
-- 
cgit v0.11.2-87-g4458