diff options
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/disass/area.c | 153 |
1 files changed, 142 insertions, 11 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index f4088e4..352069c 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -80,7 +80,10 @@ static bool is_range_empty_in_mem_area(mem_area *, phys_t, phys_t); 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); +static bool mark_range_in_mem_area_as_processed(mem_area *, GArchInstruction *, bool, bool); + +/* Marque une série d'octets comme ayant été traités. */ +static void mark_range_in_mem_area_as_overlapping(mem_area *, phys_t); /* Crée une instruction issue d'un désassemblage brut. */ static GArchInstruction *load_raw_instruction_from_mem_area(mem_area *, phys_t, vmpa2t *, phys_t *); @@ -347,9 +350,10 @@ static bool is_range_busy_in_mem_area(mem_area *area, phys_t start, phys_t len) /****************************************************************************** * * -* Paramètres : area = aire représentant à contenu à parcourir. * -* instr = instruction à mémoriser pour la suite. * -* force = impose l'enregistrement de l'instruction. * +* Paramètres : area = aire représentant à contenu à parcourir. * +* instr = instruction à mémoriser pour la suite. * +* force = impose l'enregistrement de l'instruction. * +* overlap = indique si l'instruction peut déborder de la zone. * * * * Description : Marque une série d'octets comme ayant été traités. * * * @@ -359,7 +363,7 @@ static bool is_range_busy_in_mem_area(mem_area *area, phys_t start, phys_t len) * * ******************************************************************************/ -static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction *instr, bool force) +static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction *instr, bool force, bool overlap) { bool result; /* Bilan d'action à renvoyer */ const vmpa2t *start; /* Adresse de départ de la zone*/ @@ -382,6 +386,36 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction offset = compute_vmpa_diff(start, addr); + /** + * On vérifie que l'instruction tient toute entière dans la zone courante. + * + * C'est normalement forcément le cas, puisque les accès aux données lues + * pour la mise en place d'une instruction sont restreintes à la zone couverte. + * + * Cependant ce n'est pas forcément le cas lors de l'injection des + * instructions préchargées. En effet, une chaîne de caractères peut être + * découpée sur plusieurs zones : il arrive par exemple que le segment BSS + * englobe une partie de la section des chaînes. Cette section est donc coupée + * en deux portions, ce qui conduit à la création de deux zones distinctes. + * + * Dans ce cas, on inscrit ici l'instruction résultante, et charge à + * l'appelant de marquer la zone suivante comme déjà partiellement traitée. + * + * Cette situation est représentée par le test 'overlapping_areas.py'. + */ + + if ((offset + len) > get_mrange_length(&area->range)) + { + if (overlap) + len = get_mrange_length(&area->range) - offset; + +#ifndef NDEBUG + else + assert(false); +#endif + + } + /* Début des choses sérieuses */ g_mutex_lock(&area->mutex); @@ -461,6 +495,59 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction /****************************************************************************** * * +* Paramètres : area = aire représentant à contenu à parcourir. * +* count = nombre d'octets à considérer comme traités. * +* * +* Description : Marque une série d'octets comme ayant été traités. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mark_range_in_mem_area_as_overlapping(mem_area *area, phys_t count) +{ + bool status; /* Présence d'instructions ? */ + 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 */ + + assert(count <= get_mrange_length(&area->range)); + + g_mutex_lock(&area->mutex); + + status = test_none_in_bit_field(area->processed, 0, count); + + if (!status) + for (i = 0; i < count; i++) + { + old = area->instructions[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, i, old_len); + + g_object_unref(G_OBJECT(old)); + area->instructions[i] = NULL; + + g_atomic_pointer_add(&area->count, -1); + + } + + } + + g_mutex_unlock(&area->mutex); + +} + + +/****************************************************************************** +* * * Paramètres : area = aire représentant à contenu à parcourir. * * offset = point de départ au sein de l'aire en question. * * pos = tête de lecture dans l'espace global. * @@ -705,7 +792,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc /* Progression dans les traitements */ - done = mark_range_in_mem_area_as_processed(area, instr, false); + done = mark_range_in_mem_area_as_processed(area, instr, false, false); if (!done) { @@ -807,7 +894,7 @@ static void load_data_from_mem_area(mem_area *area, GProcContext *ctx, const vmp /* Progression dans les traitements */ - done = mark_range_in_mem_area_as_processed(area, instr, false); + done = mark_range_in_mem_area_as_processed(area, instr, false, false); if (!done) { @@ -1035,10 +1122,10 @@ static void insert_extra_instr_into_mem_areas(mem_area *areas, size_t count, GAr /* Inscription d'une instruction (sans retour arrière possible :/ ) */ #ifndef NDEBUG - status = mark_range_in_mem_area_as_processed(area, instr, true); + status = mark_range_in_mem_area_as_processed(area, instr, true, false); assert(status); #else - mark_range_in_mem_area_as_processed(area, instr, true); + mark_range_in_mem_area_as_processed(area, instr, true, false); #endif return; @@ -1577,6 +1664,11 @@ static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack #ifndef NDEBUG bool inserted; /* Validation d'une insertion */ #endif + vmpa2t iend; /* Position finale nominale */ + vmpa2t pos; /* Tête de lecture */ + phys_t remaining; /* Zone supplémentaire couverte*/ + phys_t available; /* Zone disponible */ + phys_t mark_len; /* Zone à marquer comme traitée*/ area = NULL; @@ -1598,12 +1690,51 @@ static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack assert(area != NULL); #ifndef NDEBUG - inserted = mark_range_in_mem_area_as_processed(area, instr, false); + inserted = mark_range_in_mem_area_as_processed(area, instr, false, true); assert(inserted); #else - mark_range_in_mem_area_as_processed(area, instr, false); + mark_range_in_mem_area_as_processed(area, instr, false, true); #endif + /** + * Si l'instruction n'a pas pu être accueillie dans son intégralité, on + * ne rassemble pas les zones pour autant. + * + * On pourrait imaginer sauver la situation pour les segments débordant + * sur une section, mais le problème resterait posé pour des zones + * définies par l'utilisateur au sein d'une section. + * + * On note donc la place occupée par le débordement éventuel ici. + */ + + compute_mrange_end_addr(g_arch_instruction_get_range(instr), &iend); + compute_mrange_end_addr(&area->range, &pos); + + if (cmp_vmpa(&iend, &pos) > 0) + { + remaining = compute_vmpa_diff(&pos, &iend); + + while (remaining > 0) + { + area = find_memory_area_by_addr(collector->areas, collector->available, &pos); + assert(area != NULL); + + available = get_mrange_length(&area->range); + + if (remaining > available) + mark_len = available; + else + mark_len = remaining; + + mark_range_in_mem_area_as_overlapping(area, mark_len); + + advance_vmpa(&pos, mark_len); + remaining -= mark_len; + + } + + } + gtk_status_stack_update_activity_value(status, collector->id, 1); } |