summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/area.c637
-rw-r--r--src/analysis/disass/area.h6
-rw-r--r--src/analysis/disass/disassembler.c10
-rw-r--r--src/analysis/disass/fetch.c4
-rw-r--r--src/analysis/disass/fetch.h2
-rw-r--r--src/analysis/disass/limit.c55
-rw-r--r--src/analysis/disass/limit.h2
-rw-r--r--src/analysis/disass/output.c26
-rw-r--r--src/analysis/disass/routines.c14
-rw-r--r--src/analysis/disass/routines.h2
10 files changed, 454 insertions, 304 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 71e2784..2bc7a53 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -35,6 +35,7 @@
#include "../../analysis/contents/restricted.h"
#include "../../arch/raw.h"
#include "../../common/bits.h"
+#include "../../common/sort.h"
#include "../../format/format.h"
#include "../../glibext/delayed-int.h"
#include "../../gui/panels/log.h"
@@ -115,11 +116,32 @@ typedef struct _GAreaCollector
mem_area *areas; /* Zone de productions */
- size_t begin; /* Début du parcours à mener */
- size_t end; /* Fin de ce même parcours */
+ union
+ {
+ struct
+ {
+ size_t acount; /* Nombre de zones créées */
+
+ GLoadedBinary *binary; /* Binaire à associer aux zones*/
- GArchInstruction **collected; /* Instructions collectées */
- size_t count; /* Quantité de ces instructions*/
+ phys_t first; /* Début de traitement */
+ phys_t last; /* Fin de traitement */
+
+ bool closing; /* Tâche clôturant le parcours */
+
+ };
+
+ struct
+ {
+ size_t begin; /* Début du parcours à mener */
+ size_t end; /* Fin de ce même parcours */
+
+ GArchInstruction **collected; /* Instructions collectées */
+ size_t ccount; /* Quantité de ces instructions*/
+
+ };
+
+ };
} GAreaCollector;
@@ -149,6 +171,12 @@ 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 calcul des zones binaires à désassembler. */
+static GAreaCollector *g_area_collector_new_intro(activity_id_t, GLoadedBinary *, phys_t, phys_t, bool);
+
+/* Construit une liste bornée de zones contigües. */
+static void g_area_collector_do_compute(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);
@@ -779,230 +807,6 @@ static GArchInstruction **get_instructions_from_mem_area(const mem_area *area, G
/******************************************************************************
* *
-* Paramètres : binary = binaire analysé contenant quantités d'infos. *
-* bin_length = quantité d'octets à traiter au total. *
-* count = nombre de zones mises en place. [OUT] *
-* *
-* Description : Détermine une liste de zones contigües à traiter. *
-* *
-* Retour : Liste de zones mémoire à libérer après usage. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-mem_area *compute_memory_areas(const GLoadedBinary *binary, phys_t bin_length, size_t *count)
-{
- mem_area *result; /* Liste à renvoyer */
- GExeFormat *format; /* Format de fichier associé */
- mrange_t *exe_ranges; /* Liste de zones exécutables */
- size_t exe_count; /* Nombre de ces zones */
- GBinSymbol **symbols; /* Symboles à représenter */
- size_t sym_count; /* Qté de symboles présents */
- vmpa2t last; /* Dernière bordure rencontrée */
- bool status; /* Bilan d'une conversion */
- size_t i; /* Boucle de parcours #1 */
- const vmpa2t *border; /* Nouvelle bordure rencontrée */
- mem_area *area; /* Zone avec valeurs à éditer */
- vmpa2t tmp; /* Stockage temporaire */
- GPortionLayer *layer; /* Couche première de portions */
- GBinPortion **portions; /* Morceaux d'encadrement */
- size_t portions_count; /* Taille de cette liste */
- const vmpa2t *portion_start; /* Point de départ de portion */
- const vmpa2t *portion_next; /* Départ de portion suivante */
- size_t j; /* Boucle de parcours #2 */
- SymbolType type; /* Nature d'un symbole */
- const mrange_t *range; /* Couverture d'un symbole */
- phys_t length; /* Taille de ce même symbole */
- phys_t new_length; /* Nouvelle taille déterminée */
-
- result = NULL;
- *count = 0;
-
- /**
- * Le parcours n'est valide que si les zones exécutables sont triées !
- */
-
- format = g_loaded_binary_get_format(binary);
-
- exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
-
- symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
-
- /* Première étape : on comble les trous ! */
-
- status = g_exe_format_translate_offset_into_vmpa(format, 0, &last);
- assert(status);
-
- for (i = 0; i < exe_count; i++)
- {
- border = get_mrange_addr(&exe_ranges[i]);
-
- /* Zone tampon à constituer */
-
- if (cmp_vmpa(&last, border) < 0)
- {
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- area = &result[*count - 1];
-
- init_mem_area_from_addr(area, &last, compute_vmpa_diff(&last, border), binary);
- area->is_exec = false;
-
- }
-
- /* Insertion d'une zone exécutable déjà définie */
-
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- area = &result[*count - 1];
-
- init_mem_area_from_addr(area, get_mrange_addr(&exe_ranges[i]),
- get_mrange_length(&exe_ranges[i]), binary);
- area->is_exec = true;
-
- /* Avancée du curseur */
-
- compute_mrange_end_addr(&exe_ranges[i], &last);
-
- }
-
- /* Extension finale complémentaire ? */
-
- area = &result[*count - 1];
-
- copy_vmpa(&tmp, get_mrange_addr(&area->range));
- advance_vmpa(&tmp, get_mrange_length(&area->range));
-
- if (get_phy_addr(&tmp) < bin_length)
- {
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- area = &result[*count - 1];
-
- init_mem_area_from_addr(area, &tmp, bin_length - get_phy_addr(&tmp), binary);
- area->is_exec = false;
-
- }
-
- /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */
-
- layer = g_exe_format_get_main_layer(format);
-
- portions = g_portion_layer_collect_all_portions(layer, &portions_count);
-
- for (i = 1; i < portions_count; i++)
- {
- portion_start = get_mrange_addr(g_binary_portion_get_range(portions[i]));
-
- /**
- * Si plusieurs portions débutent au même endroit, il ne sert
- * à rien de découper plusieurs fois.
- */
- if ((i + 1) < portions_count)
- {
- portion_next = get_mrange_addr(g_binary_portion_get_range(portions[i + 1]));
-
- if (cmp_vmpa(portion_start, portion_next) == 0)
- continue;
-
- }
-
- for (j = 0; j < *count; j++)
- {
- area = &result[j];
-
- if (!mrange_contains_addr(&area->range, portion_start))
- continue;
-
- /* Si le déccoupage actuel ne correspond pas au besoin des portions... */
- if (cmp_vmpa(get_mrange_addr(&area->range), portion_start) != 0)
- {
- fini_mem_area(&result[j]);
-
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- memmove(&result[j + 2], &result[j + 1], (*count - j - 2) * sizeof(mem_area));
-
- status = result[j].is_exec;
-
- /* Première moitié */
-
- area = &result[j];
-
- copy_vmpa(&tmp, get_mrange_addr(&area->range));
- length = get_mrange_length(&area->range);
-
- new_length = compute_vmpa_diff(&tmp, portion_start);
-
- init_mem_area_from_addr(area, &tmp, new_length, binary);
- area->is_exec = status;
-
- /* Seconde moitié */
-
- length -= get_mrange_length(&area->range);
-
- area = &result[j + 1];
-
- init_mem_area_from_addr(area, portion_start, length, binary);
- area->is_exec = status;
-
- }
-
- j = *count;
-
- }
-
- }
-
- if (portions != NULL)
- free(portions);
-
- g_object_unref(G_OBJECT(layer));
-
- /* Troisième étape : on insère les symboles existants */
-
- for (i = 0; i < sym_count; i++)
- {
- type = g_binary_symbol_get_target_type(symbols[i]);
-
- /**
- * 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(symbols[i]);
-
- length = get_mrange_length(range);
-
- if (length == 0)
- continue;
-
- insert_extra_symbol_into_mem_areas(result, *count, symbols[i]);
-
- }
-
- /* Nettoyage final */
-
- if (exe_ranges != NULL)
- free(exe_ranges);
-
- g_object_unref(G_OBJECT(format));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : list = listes de zones utable à consulter. *
* count = nombre de zones mises en place. *
* addr = adresse à retrouver dans les aires présentes. *
@@ -1212,6 +1016,9 @@ static void g_area_collector_init(GAreaCollector *collector)
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));
+
G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector));
}
@@ -1258,6 +1065,366 @@ 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.*
+* 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. *
+* *
+* Description : Crée une tâche de calcul des zones binaires à désassembler. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GAreaCollector *g_area_collector_new_intro(activity_id_t id, GLoadedBinary *binary, phys_t first, phys_t last, bool closing)
+{
+ 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_compute;
+
+ result->areas = NULL;
+
+ result->acount = 0;
+
+ result->binary = binary;
+ g_object_ref(G_OBJECT(binary));
+
+ result->first = first;
+ result->last = last;
+
+ result->closing = closing;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : fetching = récupération à mener. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Construit une liste bornée de zones contigües. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStack *status)
+{
+ mem_area **list; /* Liste de zones à constituer */
+ size_t *count; /* Nombre d'éléments intégrés */
+ vmpa2t first; /* Point de départ */
+ vmpa2t last; /* Point d'arrivée */
+ 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 exec)
+ {
+ phys_t diff; /* Espace entre bordures */
+ mem_area *area; /* Zone avec valeurs à éditer */
+
+ diff = compute_vmpa_diff(old, new);
+
+ /**
+ * S'il existe un écart entre la dernière bordure ajoutée et
+ * l'extréminité de la portion courante, on le comble !
+ */
+
+ if (diff > 0)
+ {
+ /* Zone tampon à constituer */
+
+ *list = (mem_area *)realloc(*list, ++(*count) * sizeof(mem_area));
+
+ area = &(*list)[*count - 1];
+
+ 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);
+
+ gtk_status_stack_update_activity_value(status, collector->id, diff);
+
+ }
+
+ }
+
+ bool build_area_from_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused)
+ {
+ const mrange_t *range; /* Espace de portion à traiter */
+ vmpa2t border; /* Nouvelle bordure rencontrée */
+ bool on_track; /* Le tronçon courant est bon ?*/
+ PortionAccessRights rights; /* Droits d'accès à analyser */
+
+ range = g_binary_portion_get_range(portion);
+
+ if (visit == BPV_ENTER)
+ {
+ copy_vmpa(&border, get_mrange_addr(range));
+
+ on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0;
+
+ if (on_track)
+ {
+ rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE);
+ fill_gap(&prev, &border, rights & PAC_EXEC);
+ }
+ else
+ copy_vmpa(&prev, &border);
+
+ }
+
+ else if (visit == BPV_SHOW)
+ {
+ copy_vmpa(&border, get_mrange_addr(range));
+
+ on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0;
+
+ if (on_track)
+ {
+ rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE);
+ fill_gap(&prev, &border, rights & PAC_EXEC);
+
+ compute_mrange_end_addr(range, &border);
+
+ rights = g_binary_portion_get_rights(portion);
+ fill_gap(&prev, &border, rights & PAC_EXEC);
+
+ }
+ else
+ compute_mrange_end_addr(range, &prev);
+
+ }
+
+ else if (visit == BPV_EXIT)
+ {
+ compute_mrange_end_addr(range, &border);
+
+ if (collector->closing)
+ on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) <= 0;
+ else
+ on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0;
+
+ if (on_track)
+ {
+ rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE);
+ fill_gap(&prev, &border, rights & PAC_EXEC);
+ }
+ else
+ copy_vmpa(&prev, &border);
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ return (cmp_vmpa(&prev, &last) < 0);
+
+ }
+
+ list = &collector->areas;
+ count = &collector->acount;
+
+ init_vmpa(&first, collector->first, VMPA_NO_VIRTUAL);
+ init_vmpa(&last, collector->last, VMPA_NO_VIRTUAL);
+
+ format = g_loaded_binary_get_format(collector->binary);
+
+#ifndef NDEBUG
+ state = g_exe_format_translate_offset_into_vmpa(format, 0, &prev);
+ assert(state);
+#else
+ 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);
+
+ g_object_unref(G_OBJECT(portions));
+
+ g_object_unref(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gid = groupe de travail impliqué. *
+* status = barre de statut à tenir informée. *
+* binary = binaire analysé contenant quantités d'infos. *
+* length = quantité d'octets à traiter au total. *
+* count = nombre de zones mises en place. [OUT] *
+* *
+* Description : Détermine une liste de zones contigües à traiter. *
+* *
+* Retour : Liste de zones mémoire à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedBinary *binary, phys_t length, size_t *count)
+{
+ mem_area *result; /* Liste finale à retourner */
+ 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 */
+ phys_t first; /* Début de zone de traitement */
+ bool closing; /* Détection de fin en amont */
+ phys_t last; /* Fin de zone de traitement */
+
+ runs_count = g_get_num_processors();
+
+ collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *));
+
+ run_size = length / runs_count;
+
+ queue = get_work_queue();
+
+ id = gtk_status_stack_add_activity(status, _("Computing memory areas to disassemble"), length);
+
+ for (i = 0; i < runs_count; i++)
+ {
+ first = i * run_size;
+
+ closing = ((i + 1) == runs_count);
+
+ if (closing)
+ last = length;
+ else
+ last = first + run_size;
+
+ collectors[i] = g_area_collector_new_intro(id, binary, first, last, closing);
+
+ 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 aires */
+
+ result = NULL;
+ *count = 0;
+
+ for (i = 0; i < runs_count; i++)
+ {
+ result = (mem_area *)realloc(result, (*count + collectors[i]->acount) * sizeof(mem_area));
+
+ memcpy(&result[*count], collectors[i]->areas, collectors[i]->acount * sizeof(mem_area));
+ *count += collectors[i]->acount;
+
+ g_object_unref(G_OBJECT(collectors[i]));
+
+ }
+
+ /* Fin */
+
+ free(collectors);
+
+ gtk_status_stack_remove_activity(status, id);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : id = identifiant pour signaler la progression courante. *
* list = liste des zones en place à parcourir. *
* begin = indice de la première zone à traiter. *
@@ -1286,7 +1453,7 @@ static GAreaCollector *g_area_collector_new_outro(activity_id_t id, mem_area *li
result->end = end;
result->collected = NULL;
- result->count = 0;
+ result->ccount = 0;
return result;
@@ -1313,7 +1480,7 @@ static void g_area_collector_do_collect(GAreaCollector *collector, GtkStatusStac
for (i = collector->begin; i < collector->end; i++)
{
collector->collected = get_instructions_from_mem_area(&collector->areas[i],
- collector->collected, &collector->count);
+ collector->collected, &collector->ccount);
fini_mem_area(&collector->areas[i]);
@@ -1326,8 +1493,8 @@ static void g_area_collector_do_collect(GAreaCollector *collector, GtkStatusStac
/******************************************************************************
* *
-* Paramètres : gid = groupe de travail impliqué. *
-* status = barre de statut à tenir informée. *
+* 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] *
@@ -1388,10 +1555,10 @@ GArchInstruction **collect_disassembled_instructions(wgroup_id_t gid, GtkStatusS
for (i = 0; i < runs_count; i++)
{
result = (GArchInstruction **)realloc(result,
- (*icount + collectors[i]->count) * sizeof(GArchInstruction *));
+ (*icount + collectors[i]->ccount) * sizeof(GArchInstruction *));
- memcpy(&result[*icount], collectors[i]->collected, collectors[i]->count * sizeof(GArchInstruction *));
- *icount += collectors[i]->count;
+ memcpy(&result[*icount], collectors[i]->collected, collectors[i]->ccount * sizeof(GArchInstruction *));
+ *icount += collectors[i]->ccount;
g_object_unref(G_OBJECT(collectors[i]));
diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h
index 725b9a8..d5f910b 100644
--- a/src/analysis/disass/area.h
+++ b/src/analysis/disass/area.h
@@ -43,9 +43,6 @@ typedef struct _mem_area mem_area;
void load_code_from_mem_area(mem_area *, mem_area *, size_t, GProcContext *, const vmpa2t *, bool, GtkStatusStack *, activity_id_t);
/* Détermine une liste de zones contigües à traiter. */
-mem_area *compute_memory_areas(const GLoadedBinary *, phys_t, size_t *);
-
-/* Détermine une liste de zones contigües à traiter. */
mem_area *find_memory_area_by_addr(mem_area *, size_t, const vmpa2t *);
/* Insère un symbole dans un découpage en aires. */
@@ -58,6 +55,9 @@ void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStat
/* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */
+/* Détermine une liste de zones contigües à traiter. */
+mem_area *collect_memory_areas(wgroup_id_t, GtkStatusStack *, GLoadedBinary *, phys_t, size_t *);
+
/* Rassemble les instructions conservées dans des zones données. */
GArchInstruction **collect_disassembled_instructions(wgroup_id_t, GtkStatusStack *, mem_area *, size_t, size_t *);
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 172ee1c..5326c36 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -312,8 +312,7 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co
static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format)
{
- mrange_t *exe_ranges; /* Liste de zones exécutables */
- size_t exe_count; /* Nombre de ces zones */
+ GBinPortion *portions; /* Couche première de portions */
GBinRoutine **routines; /* Liste des routines trouvées */
size_t routines_count; /* Nombre de ces routines */
guint runs_count; /* Qté d'exécutions parallèles */
@@ -325,7 +324,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
size_t end; /* Fin d'un bloc de traitement */
GRoutinesStudy *study; /* Tâche d'étude à programmer */
- exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
+ portions = g_exe_format_get_portions(format);
routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count);
@@ -346,7 +345,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
else
end = begin + run_size;
- study = g_routines_study_new(proc, exe_ranges, exe_count, routines, routines_count,
+ study = g_routines_study_new(proc, portions, routines, routines_count,
begin, end, id, fallback);
g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid);
@@ -357,8 +356,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
gtk_status_stack_remove_activity(status, id);
- if (exe_ranges != NULL)
- free(exe_ranges);
+ g_object_unref(G_OBJECT(portions));
}
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 784e103..ee0916b 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -392,7 +392,7 @@ static bool check_if_extra_wait_is_needed(GWorkQueue *queue, wgroup_id_t id, GPr
* *
******************************************************************************/
-GArchInstruction **disassemble_binary_content(const GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status, size_t *count)
+GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status, size_t *count)
{
GArchInstruction **result; /* Instruction désassemblées */
GDelayedFetching template; /* Patron des tâches à venir */
@@ -415,7 +415,7 @@ GArchInstruction **disassemble_binary_content(const GLoadedBinary *binary, GProc
length = g_binary_content_compute_size(content);
g_object_unref(G_OBJECT(content));
- template.areas = compute_memory_areas(binary, length, &template.count);
+ template.areas = collect_memory_areas(gid, status, binary, length, &template.count);
template.status = status;
diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h
index bf2b52f..b36a999 100644
--- a/src/analysis/disass/fetch.h
+++ b/src/analysis/disass/fetch.h
@@ -32,7 +32,7 @@
/* Procède au désassemblage basique d'un contenu binaire. */
-GArchInstruction **disassemble_binary_content(const GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *, size_t *);
+GArchInstruction **disassemble_binary_content(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *, size_t *);
diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c
index 28a8264..18d089a 100644
--- a/src/analysis/disass/limit.c
+++ b/src/analysis/disass/limit.c
@@ -25,48 +25,12 @@
-/* Recherche la zone correspond à une adresse donnée. */
-static const mrange_t *find_x_range_for_addr(const mrange_t *, size_t, const vmpa2t *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : ranges = liste de zones offrant une exécution et disponibles.*
-* count = taille de cette liste. *
-* *
-* Description : Recherche la zone correspond à une adresse donnée. *
-* *
-* Retour : Zone trouvée ou NULL si aucune ne correspond. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t count, const vmpa2t *addr)
-{
- const mrange_t *result; /* Zone à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < count && result == NULL; i++)
- if (mrange_contains_addr(&ranges[i], addr))
- result = &ranges[i];
-
- return result;
-
-}
-
-
/******************************************************************************
* *
-* Paramètres : proc = ensemble d'instructions désassemblées. *
-* routines = prototypes existants à insérer. *
-* count = quantité de ces prototypes. *
-* begin = point de départ du parcours de liste. *
-* end = point d'arrivée exclu du parcours. *
-* id = identifiant du message affiché à l'utilisateur. *
+* Paramètres : routine = routine dont les frontières sont à fixer. *
+* prev = routine précédente dans les traitements. *
+* proc = ensemble d'instructions désassemblées. *
+* portions = ensemble de couches binaires bornées. *
* *
* Description : S'assure qu'une routine est bien bornée. *
* *
@@ -76,12 +40,13 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun
* *
******************************************************************************/
-void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count)
+void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcessor *proc, GBinPortion *portions)
{
const mrange_t *range; /* Emplacement courant */
vmpa2t addr; /* Adresse à conserver */
GArchInstruction *start; /* Première instruction */
phys_t diff; /* Taille définie par déduction*/
+ GBinPortion *portion; /* Conteneur avec limites */
mrange_t new; /* Nouvel emplacement taillé */
range = g_binary_routine_get_range(routine);
@@ -114,12 +79,16 @@ void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcess
/* Sinon on va jusqu'à la fin de la zone ! */
else
{
- range = find_x_range_for_addr(exe_ranges, exe_count, &addr);
- if (range == NULL) goto crl_skip;
+ portion = g_binary_portion_find_at_addr(portions, &addr, (GdkRectangle []) { });
+ if (portion == NULL) goto crl_skip;
+
+ range = g_binary_portion_get_range(portion);
diff = compute_vmpa_diff(&addr, get_mrange_addr(range));
diff = get_mrange_length(range) - diff;
+ g_object_unref(G_OBJECT(portion));
+
}
init_mrange(&new, &addr, diff);
diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h
index 7aba8a6..ed53325 100644
--- a/src/analysis/disass/limit.h
+++ b/src/analysis/disass/limit.h
@@ -32,7 +32,7 @@
/* S'assure qu'une routine est bien bornée. */
-void compute_routine_limit(GBinRoutine *, GBinRoutine *, GArchProcessor *, mrange_t *, size_t);
+void compute_routine_limit(GBinRoutine *, GBinRoutine *, GArchProcessor *, GBinPortion *);
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index 0d85870..fe4d705 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -59,7 +59,7 @@
void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GArchProcessor *proc, GtkStatusStack *status)
{
- GPortionLayer *layer; /* Couche première de portions */
+ GBinPortion *root; /* Couche première de portions */
GBinPortion **portions; /* Morceaux d'encadrement */
size_t portions_count; /* Taille de cette liste */
size_t portion_index; /* Prochaine portion à traiter */
@@ -99,12 +99,29 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
+ bool collect_all_portions(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused)
+ {
+ if (visit == BPV_ENTER || visit == BPV_SHOW)
+ {
+ portions = (GBinPortion **)realloc(portions, ++portions_count * sizeof(GBinPortion *));
+ portions[portions_count - 1] = portion;
+ }
+
+ return true;
+
+ }
- layer = g_exe_format_get_main_layer(format);
+ portions = NULL;
+ portions_count = 0;
- portions = g_portion_layer_collect_all_portions(layer, &portions_count);
portion_index = 0;
+ root = g_exe_format_get_portions(format);
+
+ g_binary_portion_visit(root, (visit_portion_fc)collect_all_portions, NULL);
+
+ g_object_unref(G_OBJECT(root));
+
symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
sym_index = 0;
@@ -339,9 +356,6 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA
if (portions != NULL)
free(portions);
- g_object_unref(G_OBJECT(layer));
-
-
fprintf(stderr, "MISSING :: %u symbols\n", _missing);
diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c
index a9414fc..6fd9279 100644
--- a/src/analysis/disass/routines.c
+++ b/src/analysis/disass/routines.c
@@ -40,8 +40,7 @@ struct _GRoutinesStudy
GArchProcessor *proc; /* Processeurs avec ses instr. */
- mrange_t *exe_ranges; /* Liste de zones exécutables */
- size_t exe_count; /* Nombre de ces zones */
+ GBinPortion *portions; /* Couches de binaire bornées */
GBinRoutine **routines; /* Liste de routines à traiter */
size_t count; /* Taille de cette liste */
@@ -147,6 +146,8 @@ static void g_routines_study_init(GRoutinesStudy *study)
static void g_routines_study_dispose(GRoutinesStudy *study)
{
+ g_object_unref(G_OBJECT(study->portions));
+
G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study));
}
@@ -174,6 +175,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study)
/******************************************************************************
* *
* Paramètres : proc = ensemble d'instructions désassemblées. *
+* portions = ensemble de couches binaires bornées. *
* routines = prototypes existants à insérer. *
* count = quantité de ces prototypes. *
* begin = point de départ du parcours de liste. *
@@ -189,7 +191,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study)
* *
******************************************************************************/
-GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback)
+GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinPortion *portions, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback)
{
GRoutinesStudy *result; /* Tâche à retourner */
@@ -197,8 +199,8 @@ GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, mrange_t *exe_ranges,
result->proc = proc;
- result->exe_ranges = exe_ranges;
- result->exe_count = exe_count;
+ result->portions = portions;
+ g_object_ref(G_OBJECT(portions));
result->routines = routines;
result->count = count;
@@ -267,7 +269,7 @@ void g_routines_study_compute_limits(GRoutinesStudy *study, size_t index)
else
next = NULL;
- compute_routine_limit(routine, next, study->proc, study->exe_ranges, study->exe_count);
+ compute_routine_limit(routine, next, study->proc, study->portions);
}
diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h
index 72df309..b89f69a 100644
--- a/src/analysis/disass/routines.h
+++ b/src/analysis/disass/routines.h
@@ -52,7 +52,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, size_t);
/* Crée une tâche d'étude de routines différée. */
-GRoutinesStudy *g_routines_study_new(GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb);
+GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinPortion *, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb);
/* Détermine si besoin est les bornes des routines. */
void g_routines_study_compute_limits(GRoutinesStudy *, size_t);