summaryrefslogtreecommitdiff
path: root/src/analysis/disass/area.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass/area.c')
-rw-r--r--src/analysis/disass/area.c361
1 files changed, 335 insertions, 26 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 48ac6ec..71e2784 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -25,6 +25,8 @@
#include <assert.h>
+#include <malloc.h>
+#include <string.h>
#include <i18n.h>
@@ -34,10 +36,14 @@
#include "../../arch/raw.h"
#include "../../common/bits.h"
#include "../../format/format.h"
+#include "../../glibext/delayed-int.h"
#include "../../gui/panels/log.h"
+/* ------------------------- TRAITEMENT DES ZONES DE DONNES ------------------------- */
+
+
/* Zone mémoire bien bornée */
typedef struct _mem_area
{
@@ -52,6 +58,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 */
bool is_exec; /* Zone exécutable ? */
@@ -83,8 +90,76 @@ static void load_data_from_mem_area(mem_area *, GProcContext *, const vmpa2t *,
static void fill_mem_area(mem_area *, mem_area *, size_t, GProcContext *, GtkStatusStack *, activity_id_t);
/* Rassemble les instructions conservées dans une zone donnée. */
-static GArchInstruction *get_instructions_from_mem_area(const mem_area *);
+static GArchInstruction **get_instructions_from_mem_area(const mem_area *, GArchInstruction **, size_t *);
+
+
+
+/* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */
+
+
+#define G_TYPE_AREA_COLLECTOR g_area_collector_get_type()
+#define G_AREA_COLLECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_AREA_COLLECTOR, GAreaCollector))
+#define G_IS_AREA_COLLECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_AREA_COLLECTOR))
+#define G_AREA_COLLECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_AREA_COLLECTOR, GAreaCollectorClass))
+#define G_IS_AREA_COLLECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_AREA_COLLECTOR))
+#define G_AREA_COLLECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_AREA_COLLECTOR, GAreaCollectorClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GAreaCollector
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ activity_id_t id; /* Groupe de progression */
+ run_task_fc run; /* Activité dans la pratique */
+
+ mem_area *areas; /* Zone de productions */
+
+ size_t begin; /* Début du parcours à mener */
+ size_t end; /* Fin de ce même parcours */
+
+ GArchInstruction **collected; /* Instructions collectées */
+ size_t count; /* Quantité de ces instructions*/
+
+} GAreaCollector;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GAreaCollectorClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+} GAreaCollectorClass;
+
+
+/* Indique le type défini pour les tâches de traitement des zones. */
+GType g_area_collector_get_type(void);
+
+/* Initialise la classe des manipulations parallèles de zones. */
+static void g_area_collector_class_init(GAreaCollectorClass *);
+
+/* Initialise des manipulations parallèles de zones. */
+static void g_area_collector_init(GAreaCollector *);
+
+/* Supprime toutes les références externes. */
+static void g_area_collector_dispose(GAreaCollector *);
+/* Procède à la libération totale de la mémoire. */
+static void g_area_collector_finalize(GAreaCollector *);
+
+/* Assure un traitement particulier concernant les zones. */
+static void g_area_collector_process(GAreaCollector *, GtkStatusStack *);
+
+/* Crée une tâche de récupération d'instructions différée. */
+static GAreaCollector *g_area_collector_new_outro(activity_id_t, mem_area *, size_t, size_t);
+
+/* Assure la récupération d'instructions en différé. */
+static void g_area_collector_do_collect(GAreaCollector *, GtkStatusStack *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RAITEMENT DES ZONES DE DONNES */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -123,6 +198,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;
}
@@ -226,7 +302,13 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
result |= force;
if (result)
+ {
+ assert(area->instructions[offset] == NULL);
+
area->instructions[offset] = instr;
+ g_atomic_pointer_add(&area->count, 1);
+
+ }
return result;
@@ -642,7 +724,9 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, GProcCon
/******************************************************************************
* *
-* Paramètres : area = aire représentant à contenu à parcourir. *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* list = liste d'instructions à compléter. *
+* count = taille de cette liste. [OUT] *
* *
* Description : Rassemble les instructions conservées dans une zone donnée. *
* *
@@ -652,17 +736,24 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, GProcCon
* *
******************************************************************************/
-static GArchInstruction *get_instructions_from_mem_area(const mem_area *area)
+static GArchInstruction **get_instructions_from_mem_area(const mem_area *area, GArchInstruction **list, size_t *count)
{
- GArchInstruction *result; /* Liste d'instr. à renvoyer */
+ GArchInstruction **result; /* Liste d'instr. à renvoyer */
phys_t len; /* Nombre d'instructions au max*/
+#ifndef NDEBUG
+ size_t check; /* Verification de débordement */
+#endif
phys_t i; /* Boucle de parcours */
GArchInstruction *instr; /* Instruction décodée */
- result = NULL;
+ result = (GArchInstruction **)realloc(list, (*count + area->count) * sizeof(GArchInstruction *));
len = get_mrange_length(&area->range);
+#ifndef NDEBUG
+ check = 0;
+#endif
+
for (i = 0; i < len; i++)
{
instr = area->instructions[i];
@@ -670,7 +761,13 @@ static GArchInstruction *get_instructions_from_mem_area(const mem_area *area)
if (instr != NULL)
{
g_object_ref(G_OBJECT(instr));
- g_arch_instruction_add_to_list(&result, instr);
+ result[(*count)++] = instr;
+
+#ifndef NDEBUG
+ check++;
+ assert(check <= area->count);
+#endif
+
}
}
@@ -1044,32 +1141,152 @@ void ensure_all_mem_areas_are_filled(mem_area *list, size_t count, GProcContext
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATIONS PARALLELES DES ZONES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de traitement des zones. */
+G_DEFINE_TYPE(GAreaCollector, g_area_collector, G_TYPE_DELAYED_WORK);
+
+
/******************************************************************************
* *
-* Paramètres : list = série d'aires représentant du contenu à parcourir. *
-* count = nombre de ces zones présentes. *
+* Paramètres : klass = classe à initialiser. *
* *
-* Description : Rassemble les instructions conservées dans des zones données.*
+* Description : Initialise la classe des manipulations parallèles de zones. *
* *
-* Retour : Liste d'instructions prêtes à emploi. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchInstruction *collect_instructions_from_mem_areas(const mem_area *list, size_t count)
+static void g_area_collector_class_init(GAreaCollectorClass *klass)
{
- GArchInstruction *result; /* Liste d'instr. à renvoyer */
- size_t i; /* Boucle de parcours */
- GArchInstruction *instr; /* Instruction(s) à insérer */
+ GObjectClass *object; /* Autre version de la classe */
+ GDelayedWorkClass *work; /* Version en classe parente */
- result = NULL;
+ object = G_OBJECT_CLASS(klass);
- for (i = 0; i < count; i++)
- {
- instr = get_instructions_from_mem_area(&list[i]);
- g_arch_instruction_merge_lists(&result, &instr);
- }
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_area_collector_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_area_collector_finalize;
+
+ work = G_DELAYED_WORK_CLASS(klass);
+
+ work->run = (run_task_fc)g_area_collector_process;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collector = instance à initialiser. *
+* *
+* Description : Initialise des manipulations parallèles de zones. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_init(GAreaCollector *collector)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collector = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_dispose(GAreaCollector *collector)
+{
+ G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collector = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_finalize(GAreaCollector *collector)
+{
+ G_OBJECT_CLASS(g_area_collector_parent_class)->finalize(G_OBJECT(collector));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collector = opérations à mener. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Assure un traitement particulier concernant les zones. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_process(GAreaCollector *collector, GtkStatusStack *status)
+{
+ collector->run(G_DELAYED_WORK(collector), status);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : id = identifiant pour signaler la progression courante. *
+* list = liste des zones en place à parcourir. *
+* begin = indice de la première zone à traiter. *
+* end = indice de la première zone à ne pas traiter. *
+* *
+* Description : Crée une tâche de récupération d'instructions différée. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GAreaCollector *g_area_collector_new_outro(activity_id_t id, mem_area *list, size_t begin, size_t end)
+{
+ GAreaCollector *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_AREA_COLLECTOR, NULL);
+
+ result->id = id;
+ result->run = (run_task_fc)g_area_collector_do_collect;
+
+ result->areas = list;
+
+ result->begin = begin;
+ result->end = end;
+
+ result->collected = NULL;
+ result->count = 0;
return result;
@@ -1078,10 +1295,10 @@ GArchInstruction *collect_instructions_from_mem_areas(const mem_area *list, size
/******************************************************************************
* *
-* Paramètres : list = série d'aires représentant du contenu à libérer. *
-* count = nombre de ces zones présentes. *
+* Paramètres : fetching = récupération à mener. *
+* status = barre de statut à tenir informée. *
* *
-* Description : Libère la mémoire occupée par des zones de données. *
+* Description : Assure la récupération d'instructions en différé. *
* *
* Retour : - *
* *
@@ -1089,13 +1306,105 @@ GArchInstruction *collect_instructions_from_mem_areas(const mem_area *list, size
* *
******************************************************************************/
-void release_mem_areas(mem_area *list, size_t count)
+static void g_area_collector_do_collect(GAreaCollector *collector, GtkStatusStack *status)
{
size_t i; /* Boucle de parcours */
- for (i = 0; i < count; i++)
- fini_mem_area(&list[i]);
+ for (i = collector->begin; i < collector->end; i++)
+ {
+ collector->collected = get_instructions_from_mem_area(&collector->areas[i],
+ collector->collected, &collector->count);
+
+ fini_mem_area(&collector->areas[i]);
+
+ gtk_status_stack_update_activity_value(status, collector->id, 1);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gid = groupe de travail impliqué. *
+* status = barre de statut à tenir informée. *
+* list = liste des zones de données à relire puis libérer. *
+* acount = taille de cette liste de zones. *
+* icount = nombre d'instructions récupérées. [OUT] *
+* *
+* Description : Rassemble les instructions conservées dans des zones données.*
+* *
+* Retour : Liste d'instructions rassemblées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction **collect_disassembled_instructions(wgroup_id_t gid, GtkStatusStack *status, mem_area *list, size_t acount, size_t *icount)
+{
+ GArchInstruction **result; /* Liste finale à retourner */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ GAreaCollector **collectors; /* Collecteurs à suivre */
+ size_t run_size; /* Volume réparti par exécution*/
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ activity_id_t id; /* Identifiant de progression */
+ guint i; /* Boucle de parcours */
+ size_t begin; /* Début de bloc de traitement */
+ size_t end; /* Fin d'un bloc de traitement */
+
+ runs_count = g_get_num_processors();
+
+ collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *));
+
+ run_size = acount / runs_count;
+
+ queue = get_work_queue();
+
+ id = gtk_status_stack_add_activity(status, _("Collecting all disassembled instructions"), acount);
+
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = acount;
+ else
+ end = begin + run_size;
+
+ collectors[i] = g_area_collector_new_outro(id, list, begin, end);
+
+ g_object_ref(G_OBJECT(collectors[i]));
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(collectors[i]), gid);
+
+ }
+
+ g_work_queue_wait_for_completion(queue, gid);
+
+ /* Récupération des instructions */
+
+ result = NULL;
+ *icount = 0;
+
+ for (i = 0; i < runs_count; i++)
+ {
+ result = (GArchInstruction **)realloc(result,
+ (*icount + collectors[i]->count) * sizeof(GArchInstruction *));
+
+ memcpy(&result[*icount], collectors[i]->collected, collectors[i]->count * sizeof(GArchInstruction *));
+ *icount += collectors[i]->count;
+
+ g_object_unref(G_OBJECT(collectors[i]));
+
+ }
+
+ /* Fin */
+
+ free(collectors);
free(list);
+ gtk_status_stack_remove_activity(status, id);
+
+ return result;
+
}