summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-10-15 19:18:31 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-10-15 19:18:31 (GMT)
commit83dccba3a9b6c18d6fe7b6f30794a16336803962 (patch)
tree982e6ec5d7eae20020315936cbfbd9494bc9111e
parentc9449c389834c580196527c4e1cb010a701e7a32 (diff)
Detected loops as introduced in the book "Compilers: Principles, Techniques, and Tools".
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@596 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog16
-rw-r--r--src/analysis/disass/area.c6
-rw-r--r--src/analysis/disass/loop.c595
-rw-r--r--src/arch/arm/context.c2
-rw-r--r--src/common/bits.c194
-rw-r--r--src/common/bits.h25
6 files changed, 826 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 7964745..f5894ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+15-10-15 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/analysis/disass/area.c:
+ Add more checks.
+
+ * src/analysis/disass/loop.c:
+ Detect loops as introduced in the book
+ "Compilers: Principles, Techniques, and Tools".
+
+ * src/arch/arm/context.c:
+ Add one extra check.
+
+ * src/common/bits.c:
+ * src/common/bits.h:
+ Define more features for bit fields.
+
15-10-14 Cyrille Bagard <nocbos@gmail.com>
* src/analysis/disass/area.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index b45e7fc..de2c742 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -554,6 +554,8 @@ bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
diff = compute_vmpa_diff(&prev, &pos);
+ assert(diff == 4 || diff == 2); /* FIXME */
+
init_mrange(&range, &prev, diff);
g_arch_instruction_set_range(instr, &range);
@@ -840,7 +842,7 @@ void fill_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedB
copy_vmpa(&start, get_mrange_addr(&area->range));
advance_vmpa(&start, i);
- if (area->exec && get_virt_addr(&start) % 2 == 0)
+ if (area->exec && get_virt_addr(&start) % 4/*2 - FIXME */ == 0)
{
refresh = load_code_from_mem_area(list, count, index, binary, ctx, &start, info);
@@ -1396,6 +1398,8 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, G
/* Si le symbole est construit avec une localisation partielle, on complète ! */
if (get_phy_addr(&sym_pos) == VMPA_NO_PHYSICAL || get_virt_addr(&sym_pos) == VMPA_NO_VIRTUAL)
{
+ assert(false);
+
diff = compute_vmpa_diff(&area_pos, &sym_pos);
copy_vmpa(&sym_pos, &area_pos);
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index 5f97981..d9a3f2d 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -24,6 +24,592 @@
#include "loop.h"
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "../../common/bits.h"
+
+
+
+/* Description de noeud, en référence à "Compilers: Principles, Techniques, and Tools" */
+typedef struct _dragon_node
+{
+ GArchInstruction *first; /* Arrivée d'un lien (début) */
+ GArchInstruction *last; /* Départ d'un lien (fin) */
+
+ bitfield_t *bits; /* Représentation par masque */
+
+} dragon_node;
+
+
+/* Définition des blocs d'allocation */
+#define NODE_ALLOC_SIZE 100
+
+
+/* Dénombre le nombre de noeuds présents dans une routine. */
+static dragon_node *create_dragon_nodes(const GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *, size_t *);
+
+/* Termine l'initialisation de noeuds trouvés dans une routine. */
+static void define_mask_for_nodes(dragon_node *, size_t);
+
+/* Supprime de la mémoire tous les noeuds détectés. */
+static void delete_dragon_nodes(dragon_node *, size_t);
+
+/* Recherche un noeud selon son intruction de départ. */
+static dragon_node *find_node_for_instruction(dragon_node *, size_t, bool, const GArchInstruction *);
+
+/* Détermine toute la chaîne hiérarchique de domination. */
+static void compute_all_dominators(dragon_node *, size_t);
+
+/* Matérialise les liens de retour arrière en tant que boucles. */
+static void detect_back_edges(dragon_node *, size_t);
+
+/* Suit un flot d'exécution à la recherche de boucles. */
+static void track_loops_in_code(const GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *, memfield_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = ensemble d'instructions à parcourir. *
+* coverage = zone de couverture où rechercher des instructions.*
+* range = zone de couverture de la routine analysée. *
+* start = adresse du début de l'analyse. *
+* count = taille de la liste de noeuds retournés. [OUT] *
+* *
+* Description : Dénombre le nombre de noeuds présents dans une routine. *
+* *
+* Retour : Liste de noeuds initialisés de façon incomplète. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, size_t *count)
+{
+ dragon_node *result; /* Liste à créer et renvoyer */
+ size_t allocated; /* Dimensionnement en mémoire */
+ GArchInstruction *last; /* Mémorisation du passé */
+ GArchInstruction *iter; /* Boucle de parcours */
+ const mrange_t *irange; /* Emplacement d'instruction */
+ InstructionLinkType *types; /* Type de lien entre instr. */
+ size_t scount; /* Nombre de liens de dest. */
+ size_t i; /* Boucle de parcours */
+ dragon_node *new; /* Nouvel élément à créer */
+
+ result = NULL;
+ *count = 0;
+
+ allocated = 0;
+
+ for (last = NULL, iter = g_arch_processor_find_covered_instr_by_address(proc, coverage, start);
+ iter != NULL;
+ last = iter, iter = g_arch_instruction_get_next_iter(iter /* FIXME : list*/, iter, ~0))
+ {
+ /* L'instruction sort-elle des clous ? */
+
+ irange = g_arch_instruction_get_range(iter);
+
+ if (!mrange_contains_mrange(range, irange))
+ break;
+
+ /* Analyse des sources */
+
+ if (result == NULL)
+ {
+ (*count)++;
+
+ if (*count >= allocated)
+ {
+ allocated += NODE_ALLOC_SIZE;
+ result = (dragon_node *)realloc(result, allocated * sizeof(dragon_node));
+ }
+
+ new = &result[*count - 1];
+
+ new->first = iter;
+
+ }
+ else
+ {
+ scount = g_arch_instruction_get_sources(iter, NULL, &types);
+ if (scount == 0) continue;
+
+ for (i = 0; i < scount; i++)
+ switch (types[i])
+ {
+ case ILT_EXEC_FLOW:
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+
+ if (*count > 0)
+ result[*count - 1].last = last;
+
+ (*count)++;
+ i = scount;
+
+ if (*count >= allocated)
+ {
+ allocated += NODE_ALLOC_SIZE;
+ result = (dragon_node *)realloc(result, allocated * sizeof(dragon_node));
+ }
+
+ new = &result[*count - 1];
+
+ new->first = iter;
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ }
+
+ if (*count > 0)
+ result[*count - 1].last = last;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : nodes = liste de noeuds détectés dans une routine. *
+* count = taille de cette liste de noeuds à traiter. *
+* *
+* Description : Termine l'initialisation de noeuds trouvés dans une routine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void define_mask_for_nodes(dragon_node *nodes, size_t count)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < count; i++)
+ nodes[i].bits = create_bit_field(count, i > 0);
+
+ set_in_bit_field(nodes[0].bits, 0, 1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : nodes = liste de noeuds détectés dans une routine. *
+* count = taille de cette liste de noeuds à traiter. *
+* *
+* Description : Supprime de la mémoire tous les noeuds détectés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_dragon_nodes(dragon_node *nodes, size_t count)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < count; i++)
+ delete_bit_field(nodes[i].bits);
+
+ free(nodes);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : nodes = liste de noeuds détectés dans une routine. *
+* count = taille de cette liste de noeuds à parcourir. *
+* final = précise si l'instruction visée est la première. *
+* instr = instruction à retrouver en tant que début de noeud. *
+* *
+* Description : Recherche un noeud selon son intruction de départ. *
+* *
+* Retour : Noeud trouvé ou NULL si aucune trouvaille. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static dragon_node *find_node_for_instruction(dragon_node *nodes, size_t count, bool final, const GArchInstruction *instr)
+{
+ dragon_node *result; /* Résultat des recherches */
+ const mrange_t *irange; /* Emplacement d'instruction */
+
+ int find_node_from_range(const mrange_t *range, const dragon_node *node)
+ {
+ int status; /* Bilan à retourner */
+ const mrange_t *nrange; /* Emplacement de noeud */
+
+ nrange = g_arch_instruction_get_range(final ? node->last : node->first);
+
+ status = cmp_mrange(range, nrange);
+
+ return status;
+
+ }
+
+ irange = g_arch_instruction_get_range(instr);
+
+ result = bsearch(irange, nodes, count, sizeof(dragon_node), (__compar_fn_t)find_node_from_range);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : nodes = liste de noeuds détectés dans une routine. *
+* count = taille de cette liste de noeuds à traiter. *
+* *
+* Description : Détermine toute la chaîne hiérarchique de domination. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void compute_all_dominators(dragon_node *nodes, size_t count)
+{
+ bitfield_t *inter; /* Intersection de dominations */
+ bool changed; /* Note un changement qq part */
+ size_t k; /* Boucle de parcours #1 */
+ dragon_node *node; /* Noeud à traiter */
+ dragon_node *predecessor; /* Noeud prédécesseur direct */
+ GArchInstruction **srcs; /* Instructions d'origine */
+ InstructionLinkType *types; /* Type de lien entre instr. */
+ size_t scount; /* Nombre de liens de source */
+ size_t i; /* Boucle de parcours #2 */
+
+ inter = create_bit_field(count, false);
+
+ do
+ {
+ changed = false;
+
+ for (k = 1; k < count; k++)
+ {
+ node = &nodes[k];
+
+ set_all_in_bit_field(inter);
+
+ scount = g_arch_instruction_get_sources(node->first, &srcs, &types);
+ assert(scount > 0);
+
+ for (i = 0; i < scount; i++)
+ switch (types[i])
+ {
+ case ILT_EXEC_FLOW:
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+
+ predecessor = find_node_for_instruction(nodes, count, true, srcs[i]);
+
+
+ printf(" -- finding pred @ 0x%08x -> 0x%08x :: %p\n",
+ (unsigned int)g_arch_instruction_get_range(node->first)->addr.virtual,
+ (unsigned int)g_arch_instruction_get_range(srcs[i])->addr.virtual,
+ predecessor);
+
+
+
+ if (predecessor == NULL) break;
+
+ and_bit_field(inter, predecessor->bits);
+ break;
+
+ default:
+ break;
+
+ }
+
+ set_in_bit_field(inter, k, 1);
+
+ if (!is_bit_field_equal_to(node->bits, inter))
+ {
+ copy_bit_field(node->bits, inter);
+ changed = true;
+ }
+
+ }
+
+ }
+ while (changed);
+
+ delete_bit_field(inter);
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : nodes = liste de noeuds détectés dans une routine. *
+* count = taille de cette liste de noeuds à traiter. *
+* *
+* Description : Matérialise les liens de retour arrière en tant que boucles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void detect_back_edges(dragon_node *nodes, size_t count)
+{
+ size_t k; /* Boucle de parcours #1 */
+ dragon_node *node; /* Noeud à traiter */
+ GArchInstruction **dests; /* Instr. visée par une autre */
+ InstructionLinkType *types; /* Type de lien entre lignes */
+ size_t dcount; /* Nombre de liens de dest. */
+ size_t i; /* Boucle de parcours #2 */
+ dragon_node *target; /* Noeud référencé à tester */
+ size_t id; /* Indice du bit associé */
+
+
+
+ printf("-----------------------------------------------------------------\n");
+
+ for (k = 0; k < count; k++)
+ {
+ node = &nodes[k];
+
+ printf("#[ node %zu ]# @ 0x%08x / 0x%08x - mask = 0x%08lx\n", k,
+ (unsigned int)g_arch_instruction_get_range(node->first)->addr.virtual,
+ (unsigned int)g_arch_instruction_get_range(node->last)->addr.virtual,
+ gfw(node->bits));
+
+ }
+
+ printf("\n");
+
+
+
+ for (k = 1; k < count; k++)
+ {
+ node = &nodes[k];
+
+ dcount = g_arch_instruction_get_destinations(node->last, &dests, &types, NULL);
+ if (dcount == 0) continue;
+
+ for (i = 0; i < dcount; i++)
+ switch (types[i])
+ {
+ case ILT_EXEC_FLOW:
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+
+ target = find_node_for_instruction(nodes, count, false, dests[i]);
+ if (target == NULL) break;
+
+ id = (target - nodes);
+
+ if (test_in_bit_field(node->bits, id, 1))
+ {
+
+ printf("BACKEDGE :: 0x%08lx -> 0x%08lx\n",
+ (unsigned int)g_arch_instruction_get_range(node->last)->addr.virtual,
+ (unsigned int)g_arch_instruction_get_range(dests[i])->addr.virtual);
+
+
+ /* status = */g_arch_instruction_change_link(node->last, dests[i], types[i], ILT_LOOP);
+
+
+ }
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = ensemble d'instructions à parcourir. *
+* coverage = zone de couverture où rechercher des instructions.*
+* range = zone de couverture de la routine analysée. *
+* start = adresse du début de l'analyse. *
+* flow = ensemble des jalons de l'exécution du code. *
+* *
+* Description : Suit un flot d'exécution à la recherche de boucles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void track_loops_in_code(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, memfield_t *flow)
+{
+ dragon_node *nodes; /* Liste des noeuds détectés */
+ size_t count; /* Taille de cette liste */
+
+ nodes = create_dragon_nodes(proc, coverage, range, start, &count);
+ assert(nodes != NULL);
+
+ printf("nodes count :: %d\n", (int)count);
+
+ define_mask_for_nodes(nodes, count);
+
+ compute_all_dominators(nodes, count);
+
+ detect_back_edges(nodes, count);
+
+ delete_dragon_nodes(nodes, count);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = ensemble d'instructions à relier. *
+* routines = prototypes existants à insérer. *
+* count = quantité de ces prototypes. *
+* statusbar = barre de statut avec progression à mettre à jour.*
+* id = identifiant du message affiché à l'utilisateur. *
+* *
+* Description : Détecte les boucles dans du code machine. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void detect_loops_in_code(const GArchProcessor *proc, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+{
+ size_t i; /* Boucle de parcours */
+ const mrange_t *range; /* Couverture d'une routine */
+ const vmpa2t *start; /* Adresse de départ */
+ const instr_coverage *coverage; /* Instructions couvertes */
+ memfield_t *flow; /* Flot d'exécution à suivre */
+
+ //for (i = 286; i == 286; i++)
+ for (i = 0; i < count; i++)
+ {
+
+
+ range = g_binary_routine_get_range(routines[i]);
+ start = get_mrange_addr(range);
+
+
+ printf("====== '%s' @ 0x%08x\n",
+ g_binary_routine_get_name(routines[i]),
+ start->virtual);
+
+
+ coverage = g_arch_processor_find_coverage_by_address(proc, start);
+
+ flow = NULL;//create_mem_field(range);
+ track_loops_in_code(proc, coverage, range, start, flow);
+ //delete_mem_field(flow);
+
+ gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
+
+ }
+
+
+ printf("done\n\n");
+ //exit(0);
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+#if 0
+
+
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
@@ -193,6 +779,8 @@ void detect_loops_in_code(const GArchProcessor *proc, GBinRoutine **routines, si
for (i = 0; i < count; i++)
{
+
+
range = g_binary_routine_get_range(routines[i]);
start = get_mrange_addr(range);
@@ -207,3 +795,10 @@ void detect_loops_in_code(const GArchProcessor *proc, GBinRoutine **routines, si
}
}
+
+
+
+
+
+
+#endif
diff --git a/src/arch/arm/context.c b/src/arch/arm/context.c
index 386f21a..b54de42 100644
--- a/src/arch/arm/context.c
+++ b/src/arch/arm/context.c
@@ -267,6 +267,8 @@ void _g_arm_context_define_encoding(GArmContext *ctx, virt_t addr, unsigned int
selected = find_disass_arm_area(ctx->areas, addr, 0, ctx->acount - 1);
+ assert(ctx->areas[selected].start != addr || ctx->areas[selected].marker == marker);
+
/* S'agit-il d'une redéfinition ? */
if (ctx->areas[selected].start == addr)
ctx->areas[selected].marker = marker;
diff --git a/src/common/bits.c b/src/common/bits.c
index 1bd90f4..d451100 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -37,6 +37,7 @@
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 */
@@ -46,7 +47,7 @@ struct _bitfield_t
/* Crée un champ de bits initialisé à zéro. */
-static bitfield_t *_create_bit_field(size_t, size_t);
+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 *, size_t);
@@ -64,6 +65,7 @@ static bitfield_t *_dup_bit_field(const bitfield_t *, size_t);
/******************************************************************************
* *
* 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. *
@@ -74,7 +76,7 @@ static bitfield_t *_dup_bit_field(const bitfield_t *, size_t);
* *
******************************************************************************/
-static bitfield_t *_create_bit_field(size_t length, size_t extra)
+static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
{
bitfield_t *result; /* Création à retourner */
size_t requested; /* Nombre de mots à allouer */
@@ -88,10 +90,14 @@ static bitfield_t *_create_bit_field(size_t length, size_t extra)
result = (bitfield_t *)malloc(base + extra);
result->length = length;
+ result->requested = requested;
result->tail = ((char *)result) + base;
- memset(result->bits, 0, requested * sizeof(unsigned long));
+ if (state)
+ set_all_in_bit_field(result);
+ else
+ reset_all_in_bit_field(result);
return result;
@@ -101,6 +107,7 @@ static bitfield_t *_create_bit_field(size_t length, size_t extra)
/******************************************************************************
* *
* Paramètres : length = nom de bits du champ à représenter. *
+* state = état initial de chaque des bits. *
* *
* Description : Crée un champ de bits initialisé à zéro. *
* *
@@ -110,9 +117,9 @@ static bitfield_t *_create_bit_field(size_t length, size_t extra)
* *
******************************************************************************/
-bitfield_t *create_bit_field(size_t length)
+bitfield_t *create_bit_field(size_t length, bool state)
{
- return _create_bit_field(length, 0);
+ return _create_bit_field(length, state, 0);
}
@@ -132,7 +139,7 @@ bitfield_t *create_bit_field(size_t length)
static bitfield_t *_create_bit_field_from(const bitfield_t *field, size_t extra)
{
- return _create_bit_field(field->length, extra);
+ return _create_bit_field(field->length, false, extra);
}
@@ -177,6 +184,28 @@ void delete_bit_field(bitfield_t *field)
/******************************************************************************
* *
+* Paramètres : dest = champ de bits à modifier. *
+* src = champ de bits à utiliser pour l'opération. *
+* *
+* Description : Copie un champ de bits dans un autre. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
+{
+ assert(dest->length == src->length);
+
+ memcpy(dest->bits, src->bits, dest->requested * sizeof(unsigned long));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = champ de bits à dupliquer. *
* extra = espace mémoire supplémentaire à ajouter au final. *
* *
@@ -193,7 +222,7 @@ static bitfield_t *_dup_bit_field(const bitfield_t *field, size_t extra)
bitfield_t *result; /* Copie à retourner */
size_t requested; /* Nombre de mots à allouer */
- result = _create_bit_field(field->length, extra);
+ result = _create_bit_field(field->length, false, extra);
requested = field->length / sizeof(unsigned long);
if (field->length % sizeof(unsigned long) != 0) requested++;
@@ -227,6 +256,44 @@ bitfield_t *dup_bit_field(const bitfield_t *field)
/******************************************************************************
* *
* Paramètres : field = champ de bits à modifier. *
+* *
+* Description : Bascule à 0 un champ de bits dans son intégralité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_all_in_bit_field(bitfield_t *field)
+{
+ memset(field->bits, 0u, field->requested * sizeof(unsigned long));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à modifier. *
+* *
+* Description : Bascule à 1 un champ de bits dans son intégralité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_all_in_bit_field(bitfield_t *field)
+{
+ memset(field->bits, ~0u, field->requested * sizeof(unsigned long));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à modifier. *
* first = indice du premier bit à traiter. *
* count = nombre de bits à marquer. *
* *
@@ -263,6 +330,56 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
/******************************************************************************
* *
+* Paramètres : dest = champ de bits à modifier. *
+* src = champ de bits à utiliser pour l'opération. *
+* *
+* Description : Réalise une opération ET logique entre deux champs de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void and_bit_field(bitfield_t *dest, const bitfield_t *src)
+{
+ size_t i; /* Boucle de parcours */
+
+ assert(dest->length == src->length);
+
+ for (i = 0; i < dest->requested; i++)
+ dest->bits[i] &= src->bits[i];
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = champ de bits à modifier. *
+* src = champ de bits à utiliser pour l'opération. *
+* *
+* Description : Réalise une opération OU logique entre deux champs de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void or_bit_field(bitfield_t *dest, const bitfield_t *src)
+{
+ size_t i; /* Boucle de parcours */
+
+ assert(dest->length == src->length);
+
+ for (i = 0; i < dest->requested; i++)
+ dest->bits[i] |= src->bits[i];
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = champ de bits à modifier. *
* first = indice du premier bit à traiter. *
* count = nombre de bits à marquer. *
@@ -303,6 +420,64 @@ bool test_in_bit_field(bitfield_t *field, size_t first, size_t count)
}
+/******************************************************************************
+* *
+* 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];
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* CHAMPS LIES À UNE ZONE MEMOIRE */
@@ -312,6 +487,7 @@ bool test_in_bit_field(bitfield_t *field, size_t first, size_t count)
/******************************************************************************
* *
* Paramètres : range = espace mémoire à couvrir. *
+* state = état initial de chaque des bits. *
* *
* Description : Crée un champ de bits couvrant une zone mémoire. *
* *
@@ -321,11 +497,11 @@ bool test_in_bit_field(bitfield_t *field, size_t first, size_t count)
* *
******************************************************************************/
-memfield_t *create_mem_field(const mrange_t *range)
+memfield_t *create_mem_field(const mrange_t *range, bool state)
{
bitfield_t *result; /* Création à retourner */
- result = _create_bit_field(get_mrange_length(range), sizeof(vmpa2t));
+ result = _create_bit_field(get_mrange_length(range), state, sizeof(vmpa2t));
copy_vmpa((vmpa2t *)result->tail, get_mrange_addr(range));
diff --git a/src/common/bits.h b/src/common/bits.h
index 6eeb19c..0e8ef65 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -37,7 +37,7 @@ typedef struct _bitfield_t bitfield_t;
/* Crée un champ de bits initialisé à zéro. */
-bitfield_t *create_bit_field(size_t);
+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 *);
@@ -45,15 +45,36 @@ bitfield_t *create_bit_field_from(const bitfield_t *);
/* Supprime de la mémoire un champ de bits donné. */
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 *);
+/* Bascule à 0 un champ de bits dans son intégralité. */
+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 à 1 une partie d'un champ de bits. */
void set_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 *);
+
+/* Réalise une opération OU logique entre deux champs de bits. */
+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(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 *);
/* ------------------------- CHAMPS LIES À UNE ZONE MEMOIRE ------------------------- */
@@ -64,7 +85,7 @@ 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 *);
+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 *);