summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/area.c57
-rw-r--r--src/analysis/disass/dragon.c2
2 files changed, 44 insertions, 15 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;