From dda68634391bea512a7861468fcf45f8292300bb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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 + + * 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 * 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