summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/disass/area.c153
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);
}