diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-05-10 20:21:56 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-05-10 20:21:56 (GMT) |
commit | 8e76324b01e5b4979f346f0bc8c84372477a3d38 (patch) | |
tree | 3db4057e113aa9f664f5b217dd349bb1e9288009 /src | |
parent | b0c6ffacf5c6c45c047172e348c737cb85fb5b36 (diff) |
Rewritten the whole bitfield management.
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/disass/area.c | 57 | ||||
-rw-r--r-- | src/analysis/disass/dragon.c | 2 | ||||
-rw-r--r-- | src/common/bits.c | 293 | ||||
-rw-r--r-- | src/common/bits.h | 22 |
4 files changed, 139 insertions, 235 deletions
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 */ |