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.c354
1 files changed, 237 insertions, 117 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 5dab3ab..130a7f0 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -96,6 +96,8 @@ static void fill_mem_area(mem_area *, mem_area *, size_t, GProcContext *, GtkSta
/* Rassemble les instructions conservées dans une zone donnée. */
static GArchInstruction **get_instructions_from_mem_area(const mem_area *, GArchInstruction **, size_t *);
+/* Insère une instruction dans un découpage en aires. */
+static void insert_extra_instr_into_mem_areas(mem_area *, size_t, GArchInstruction *);
/* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */
@@ -123,7 +125,7 @@ typedef struct _GAreaCollector
{
struct
{
- size_t acount; /* Nombre de zones créées */
+ size_t created; /* Nombre de zones créées */
GLoadedBinary *binary; /* Binaire à associer aux zones*/
@@ -136,6 +138,17 @@ typedef struct _GAreaCollector
struct
{
+ size_t available; /* Nombre de zones créées */
+
+ GPreloadInfo *info; /* Préchargements à intégrer */
+
+ size_t start; /* Départ des intégrations */
+ size_t stop; /* Fin des intégrations */
+
+ };
+
+ struct
+ {
size_t begin; /* Début du parcours à mener */
size_t end; /* Fin de ce même parcours */
@@ -180,6 +193,12 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t, GLoadedBinary *
/* Construit une liste bornée de zones contigües. */
static void g_area_collector_do_compute(GAreaCollector *, GtkStatusStack *);
+/* Crée une tâche de calcul des zones binaires à remplir. */
+static GAreaCollector *g_area_collector_new_insert(activity_id_t, mem_area *, size_t, GPreloadInfo *, size_t, size_t);
+
+/* Insère dans les zones contigües les instructions préchargées. */
+static void g_area_collector_do_insert(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);
@@ -388,12 +407,19 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
if (old != NULL)
{
g_object_unref(G_OBJECT(old));
- area->instructions[offset + 1] = NULL;
+ area->instructions[offset + i] = NULL;
g_atomic_pointer_add(&area->count, -1);
}
}
+#ifndef NDEBUG
+
+ for (i = 0; i < len; i++)
+ assert(area->instructions[offset + i] == NULL);
+
+#endif
+
area->instructions[offset] = instr;
g_atomic_pointer_add(&area->count, 1);
@@ -593,10 +619,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc
bool done; /* Enregistrement effectué ? */
- vmpa2t sym_addr; /* Adresse de nouveau symbole */
- bool has_new_sym; /* Statut d'un dépilement */
-
- GBinSymbol *symbol; /* Symbole créé en parallèle */
+ GArchInstruction *extra; /* Instruction supplémentaire */
@@ -679,18 +702,11 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc
/* Insertion des symboles découverts en parallèle */
- for (has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr);
- has_new_sym;
- has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr))
+ for (extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx));
+ extra != NULL;
+ extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx)))
{
- has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol);
-
- if (has_new_sym)
- {
- insert_extra_symbol_into_mem_areas(list, count, symbol);
- g_object_unref(G_OBJECT(symbol));
- }
-
+ insert_extra_instr_into_mem_areas(list, count, extra);
}
/* Rupture du flot d'exécution ? */
@@ -932,11 +948,11 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a
/******************************************************************************
* *
-* Paramètres : areas = liste de zones délimitant des contenus à traiter. *
-* count = nombre de zones à disposition. *
-* symbol = élément nouveau à venir insérer dans les zones. *
+* Paramètres : areas = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* instr = nouvelle instruction à venir insérer dans les zones. *
* *
-* Description : Insère un symbole dans un découpage en aires. *
+* Description : Insère une instruction dans un découpage en aires. *
* *
* Retour : - *
* *
@@ -944,22 +960,16 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a
* *
******************************************************************************/
-void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBinSymbol *symbol)
+static void insert_extra_instr_into_mem_areas(mem_area *areas, size_t count, GArchInstruction *instr)
{
- SymbolType type; /* Type de symbole */
- GArchInstruction *instr; /* Instruction à insérer */
const mrange_t *range; /* Emplacement d'instruction */
const vmpa2t *addr; /* Départ de cet emplacement */
mem_area *area; /* Zone d'accueil désignée */
VMPA_BUFFER(loc); /* Description d'un emplacement*/
phys_t start; /* Point de départ */
-
- type = g_binary_symbol_get_target_type(symbol);
-
- if (!HAS_DATA_INSTR(type))
- return;
-
- instr = g_binary_symbol_get_instruction(symbol);
+#ifndef NDEBUG
+ bool status; /* Validation d'une insertion */
+#endif
range = g_arch_instruction_get_range(instr);
addr = get_mrange_addr(range);
@@ -972,13 +982,13 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi
{
vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
- log_variadic_message(LMT_WARNING, _("No place found for symbol located at %s."), loc);
- return;
+ log_variadic_message(LMT_WARNING, _("No place found for an instruction located at %s."), loc);
+ goto ieiima_failed;
}
/**
- * Un symbole (au sens large) ne peut avoir une adresse virtuelle que s'il
+ * Une instruction ne peut avoir une adresse virtuelle que s'il
* est compris dans une zone chargée en mémoire (en toute logique).
*/
assert(has_virt_addr(get_mrange_addr(&area->range)) == has_virt_addr(addr));
@@ -991,16 +1001,25 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi
{
vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
- log_variadic_message(LMT_WARNING, _("The symbol located at %s is too big for one place only."), loc);
- return;
+ log_variadic_message(LMT_WARNING, _("The instruction located at %s is too big for one place only."), loc);
+ goto ieiima_failed;
}
- /* Inscription d'une instruction de symbole (sans retour arrière possible :/ ) */
+ /* Inscription d'une instruction (sans retour arrière possible :/ ) */
+#ifndef NDEBUG
+ status = mark_range_in_mem_area_as_processed(area, instr, true);
+ assert(status);
+#else
mark_range_in_mem_area_as_processed(area, instr, true);
+#endif
+
+ return;
- g_object_ref(G_OBJECT(instr));
+ ieiima_failed:
+
+ g_object_unref(G_OBJECT(instr));
}
@@ -1106,6 +1125,9 @@ static void g_area_collector_dispose(GAreaCollector *collector)
if (collector->run == (run_task_fc)g_area_collector_do_compute)
g_object_unref(G_OBJECT(collector->binary));
+ else if (collector->run == (run_task_fc)g_area_collector_do_insert)
+ g_object_unref(G_OBJECT(collector->info));
+
G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector));
}
@@ -1160,6 +1182,7 @@ static void g_area_collector_process(GAreaCollector *collector, GtkStatusStack *
* *
* Paramètres : id = identifiant pour signaler la progression courante. *
* binary = binaire chargé à conserver dans les zones définies.*
+* info = préchargements effectués via le format binaire. *
* first = localisation du début de la portion à traiter. *
* last = localisation de la fin de la portion à traiter. *
* closing = indique si la tâche doit terminer l'analyse. *
@@ -1183,7 +1206,7 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t id, GLoadedBinar
result->areas = NULL;
- result->acount = 0;
+ result->created = 0;
result->binary = binary;
g_object_ref(G_OBJECT(binary));
@@ -1220,60 +1243,8 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac
GExeFormat *format; /* Format du binaire */
vmpa2t prev; /* Dernière bordure rencontrée */
bool state; /* Bilan d'une conversion */
- GBinSymbol **symbols; /* Symboles à représenter */
- size_t sym_count; /* Qté de symboles présents */
- bool has_sym_index; /* Détermine une validité */
- size_t sym_index; /* Prochain symbole non traité */
GBinPortion *portions; /* Couche première de portions */
- void populate_with_symbols(const vmpa2t *limit)
- {
- GBinSymbol *symbol; /* Symbole en cours d'analyse */
- SymbolType type; /* Nature d'un symbole */
- const mrange_t *range; /* Couverture d'un symbole */
- vmpa2t end; /* Adresse de fin du symbole */
-
- for (; sym_index < sym_count; sym_index++)
- {
- symbol = symbols[sym_index];
-
- type = g_binary_symbol_get_target_type(symbol);
-
- /**
- * On ne garde que les symboles renvoyant directement une ou
- * plusieurs instructions, c'est à dire les symboles valides
- * pour un appel à g_binary_symbol_get_instruction().
- *
- * Les instructions des autres symboles sont obtenues et mises
- * en place durant la procédure de désassemblage.
- */
-
- if (type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_CODE_LABEL)
- continue;
-
- range = g_binary_symbol_get_range(symbol);
-
- if (get_mrange_length(range) == 0)
- continue;
-
- if (cmp_vmpa(get_mrange_addr(range), limit) >= 0)
- break;
-
- compute_mrange_end_addr(range, &end);
-
- /**
- * Si un symbole est à cheval entre deux zones, tant pis pour lui !
- */
-
- if (cmp_vmpa(&end, limit) > 0)
- break;
-
- insert_extra_symbol_into_mem_areas(*list, *count, symbol);
-
- }
-
- }
-
void fill_gap(vmpa2t *old, vmpa2t *new, bool alloc, bool exec)
{
phys_t diff; /* Espace entre bordures */
@@ -1300,24 +1271,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac
init_mem_area_from_addr(area, old, diff, collector->binary);
area->is_exec = exec;
- /* Insertion des symboles existants */
-
- if (!has_sym_index)
- {
- int cmp_vmpa_with_symbol(const vmpa2t *a, const GBinSymbol **s)
- {
- return g_binary_symbol_cmp_with_vmpa(*s, a);
- }
-
- bsearch_index(old, symbols, sym_count, sizeof(GBinSymbol *),
- (__compar_fn_t)cmp_vmpa_with_symbol, &sym_index);
-
- has_sym_index = true;
-
- }
-
- populate_with_symbols(new);
-
/* Avancée du curseur */
copy_vmpa(old, new);
@@ -1423,7 +1376,7 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac
}
list = &collector->areas;
- count = &collector->acount;
+ count = &collector->created;
init_vmpa(&first, collector->first, VMPA_NO_VIRTUAL);
init_vmpa(&last, collector->last, VMPA_NO_VIRTUAL);
@@ -1437,10 +1390,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac
g_exe_format_translate_offset_into_vmpa(format, 0, &prev);
#endif
- symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
-
- has_sym_index = false;
-
portions = g_exe_format_get_portions(format);
g_binary_portion_visit(portions, (visit_portion_fc)build_area_from_portion, NULL);
@@ -1518,10 +1467,10 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB
for (i = 0; i < runs_count; i++)
{
- result = (mem_area *)realloc(result, (*count + collectors[i]->acount) * sizeof(mem_area));
+ result = (mem_area *)realloc(result, (*count + collectors[i]->created) * sizeof(mem_area));
- memcpy(&result[*count], collectors[i]->areas, collectors[i]->acount * sizeof(mem_area));
- *count += collectors[i]->acount;
+ memcpy(&result[*count], collectors[i]->areas, collectors[i]->created * sizeof(mem_area));
+ *count += collectors[i]->created;
g_object_unref(G_OBJECT(collectors[i]));
@@ -1540,6 +1489,177 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB
/******************************************************************************
* *
+* Paramètres : id = identifiant pour signaler la progression. *
+* areas = liste des zones en place à parcourir. *
+* available = nombre de zones disponibles pour les traitements.*
+* info = préchargements effectués via le format binaire. *
+* start = indice de la première instruction à insérer. *
+* stop = indice de la première instruction à ignorer. *
+* *
+* Description : Crée une tâche de calcul des zones binaires à remplir. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GAreaCollector *g_area_collector_new_insert(activity_id_t id, mem_area *areas, size_t available, GPreloadInfo *info, size_t start, size_t stop)
+{
+ 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_insert;
+
+ result->areas = areas;
+
+ result->available = available;
+
+ result->info = info;
+ g_object_ref(G_OBJECT(info));
+
+ result->start = start;
+ result->stop = stop;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : fetching = récupération à mener. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Insère dans les zones contigües les instructions préchargées.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack *status)
+{
+ mem_area *area; /* Zone d'appartenance */
+ size_t i; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction à analyser */
+ const mrange_t *range; /* Emplacement d'instruction */
+ const vmpa2t *addr; /* Localisation précise */
+#ifndef NDEBUG
+ bool inserted; /* Validation d'une insertion */
+#endif
+
+ area = NULL;
+
+ for (i = collector->start; i < collector->stop; i++)
+ {
+ instr = _g_preload_info_get_instruction(collector->info, i);
+ range = g_arch_instruction_get_range(instr);
+ addr = get_mrange_addr(range);
+
+ if (area != NULL)
+ {
+ if (!mrange_contains_addr(&area->range, addr))
+ area = NULL;
+ }
+
+ if (area == NULL)
+ area = find_memory_area_by_addr(collector->areas, collector->available, addr);
+
+ assert(area != NULL);
+
+#ifndef NDEBUG
+ inserted = mark_range_in_mem_area_as_processed(area, instr, false);
+ assert(inserted);
+#else
+ mark_range_in_mem_area_as_processed(area, instr, false);
+#endif
+
+ gtk_status_stack_update_activity_value(status, collector->id, 1);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gid = groupe de travail impliqué. *
+* status = barre de statut à tenir informée. *
+* area = nombre de zones mises en place. *
+* count = quantité de ces zones. *
+* info = préchargements effectués via le format binaire. *
+* *
+* Description : Intègre toutes les instructions préchargées dans des zones. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void populate_fresh_memory_areas(wgroup_id_t gid, GtkStatusStack *status, mem_area *areas, size_t count, GPreloadInfo *info)
+{
+ size_t icount; /* Quantité d'instructions */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ GAreaCollector **collectors; /* Collecteurs à suivre */
+ phys_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 start; /* Premier indice à traiter */
+ size_t stop; /* Premier indice à ignorer */
+
+ g_preload_info_lock_instructions(info);
+
+ icount = _g_preload_info_count_instructions(info);
+
+ runs_count = g_get_num_processors();
+
+ collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *));
+
+ run_size = icount / runs_count;
+
+ queue = get_work_queue();
+
+ id = gtk_status_stack_add_activity(status, _("Inserting all preloaded instructions"), icount);
+
+ for (i = 0; i < runs_count; i++)
+ {
+ start = i * run_size;
+
+ if ((i + 1) == runs_count)
+ stop = icount;
+ else
+ stop = start + run_size;
+
+ collectors[i] = g_area_collector_new_insert(id, areas, count, info, start, stop);
+
+ 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);
+
+ /* Fin */
+
+ free(collectors);
+
+ _g_preload_info_drain_instructions(info);
+
+ g_preload_info_unlock_instructions(info);
+
+ gtk_status_stack_remove_activity(status, id);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : id = identifiant pour signaler la progression courante. *
* list = liste des zones en place à parcourir. *
* begin = indice de la première zone à traiter. *