diff options
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/disass/area.c | 637 | ||||
-rw-r--r-- | src/analysis/disass/area.h | 6 | ||||
-rw-r--r-- | src/analysis/disass/disassembler.c | 10 | ||||
-rw-r--r-- | src/analysis/disass/fetch.c | 4 | ||||
-rw-r--r-- | src/analysis/disass/fetch.h | 2 | ||||
-rw-r--r-- | src/analysis/disass/limit.c | 55 | ||||
-rw-r--r-- | src/analysis/disass/limit.h | 2 | ||||
-rw-r--r-- | src/analysis/disass/output.c | 26 | ||||
-rw-r--r-- | src/analysis/disass/routines.c | 14 | ||||
-rw-r--r-- | src/analysis/disass/routines.h | 2 |
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); |