From 9f9041e11efa71cb043425cd5e89daea0247e76c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 29 Dec 2016 11:30:28 +0100 Subject: Cut binary data into several areas using all the available CPUs and less memory. --- ChangeLog | 54 +++ plugins/mobicore/mclf.c | 42 +-- plugins/ropgadgets/finder.c | 31 +- src/analysis/disass/area.c | 637 +++++++++++++++++++++------------ src/analysis/disass/area.h | 6 +- src/analysis/disass/disassembler.c | 10 +- src/analysis/disass/fetch.c | 4 +- src/analysis/disass/fetch.h | 2 +- src/analysis/disass/limit.c | 55 +-- src/analysis/disass/limit.h | 2 +- src/analysis/disass/output.c | 26 +- src/analysis/disass/routines.c | 14 +- src/analysis/disass/routines.h | 2 +- src/format/dex/class.c | 9 +- src/format/dex/class.h | 2 +- src/format/dex/dex.c | 16 +- src/format/dex/method.c | 18 +- src/format/dex/method.h | 2 +- src/format/elf/elf.c | 155 ++------ src/format/executable-int.h | 8 +- src/format/executable.c | 167 +++++---- src/format/executable.h | 6 +- src/format/format.c | 1 - src/format/symbol.c | 31 ++ src/format/symbol.h | 3 + src/glibext/gbinportion.c | 708 +++++++++++-------------------------- src/glibext/gbinportion.h | 67 ++-- src/gtkext/gtkbinarystrip.c | 42 +-- src/gtkext/gtkstatusstack.c | 10 +- src/gui/panels/strings.c | 9 +- 30 files changed, 1009 insertions(+), 1130 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91bc161..2ace970 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,57 @@ +16-12-29 Cyrille Bagard + + * plugins/mobicore/mclf.c: + Register portions using the new way. + + * plugins/ropgadgets/finder.c: + Collect all executable ranges using the new visitor. + + * src/analysis/disass/area.c: + * src/analysis/disass/area.h: + Cut binary data into several areas using all the available CPUs and less + memory. + + * src/analysis/disass/disassembler.c: + * src/analysis/disass/fetch.c: + * src/analysis/disass/fetch.h: + Update code. + + * src/analysis/disass/limit.c: + * src/analysis/disass/limit.h: + Save memory by relying on portions only. + + * src/analysis/disass/output.c: + * src/analysis/disass/routines.c: + * src/analysis/disass/routines.h: + Update code. + + * src/format/dex/class.c: + * src/format/dex/class.h: + * src/format/dex/dex.c: + * src/format/dex/method.c: + * src/format/dex/method.h: + * src/format/elf/elf.c: + * src/format/executable-int.h: + * src/format/executable.c: + * src/format/executable.h: + Register portions using the new way. + + * src/format/format.c: + Typo. + + * src/format/symbol.c: + * src/format/symbol.h: + Provide an extra method to compare symbols. + + * src/glibext/gbinportion.c: + * src/glibext/gbinportion.h: + Remove all layer definitions and introduce trees of binary portions. + + * src/gtkext/gtkbinarystrip.c: + * src/gtkext/gtkstatusstack.c: + * src/gui/panels/strings.c: + Update code. + 16-12-23 Cyrille Bagard * src/gui/panels/welcome.c: diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c index edb6a4a..3cab4a6 100644 --- a/plugins/mobicore/mclf.c +++ b/plugins/mobicore/mclf.c @@ -54,7 +54,7 @@ static void g_mclf_format_finalize(GMCLFFormat *); static const char *g_mclf_format_get_target_machine(const GMCLFFormat *); /* Etend la définition des portions au sein d'un binaire. */ -static void g_mclf_format_refine_portions(const GMCLFFormat *, GPortionLayer *); +static void g_mclf_format_refine_portions(GMCLFFormat *); @@ -262,7 +262,6 @@ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -272,59 +271,54 @@ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *format) * * ******************************************************************************/ -static void g_mclf_format_refine_portions(const GMCLFFormat *format, GPortionLayer *main) +static void g_mclf_format_refine_portions(GMCLFFormat *format) { - GPortionLayer *layer; /* Couche à mettre en place */ + GExeFormat *exe_format; /* Autre version du format */ + vmpa2t addr; /* Emplacement dans le binaire */ GBinPortion *new; /* Nouvelle portion définie */ char desc[MAX_PORTION_DESC]; /* Description d'une portion */ phys_t length; /* Taille de portion globale */ - vmpa2t addr; /* Emplacement dans le binaire */ - - layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); - g_portion_layer_attach_sub(main, layer); + exe_format = G_EXE_FORMAT(format); /* Segment de code */ - new = g_binary_portion_new(BPC_CODE); + init_vmpa(&addr, 0, format->header.v1.text.start); + + new = g_binary_portion_new(BPC_CODE, &addr, format->header.v1.text.len); sprintf(desc, "%s \"%s\"", _("Segment"), "text"); g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, 0, format->header.v1.text.start); - g_binary_portion_set_values(new, &addr, format->header.v1.text.len); - g_binary_portion_set_rights(new, PAC_WRITE | PAC_EXEC); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); /* Segment de données */ - new = g_binary_portion_new(BPC_DATA); + init_vmpa(&addr, format->header.v1.text.len, format->header.v1.data.start); + + new = g_binary_portion_new(BPC_DATA, &addr, format->header.v1.data.len); sprintf(desc, "%s \"%s\"", _("Segment"), "data"); g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, format->header.v1.text.len, format->header.v1.data.start); - g_binary_portion_set_values(new, &addr, format->header.v1.data.len); - g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); /* Signature finale */ - new = g_binary_portion_new(BPC_DATA); + length = g_binary_content_compute_size(G_BIN_FORMAT(format)->content); + init_vmpa(&addr, length - 521, VMPA_NO_VIRTUAL); /* FIXME */ + + new = g_binary_portion_new(BPC_DATA, &addr, 521); sprintf(desc, "%s \"%s\"", _("Segment"), "sig"); g_binary_portion_set_desc(new, desc); - length = g_binary_content_compute_size(G_BIN_FORMAT(format)->content); - init_vmpa(&addr, length - 521, VMPA_NO_VIRTUAL); /* FIXME */ - g_binary_portion_set_values(new, &addr, 521); - g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); } diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c index 6a2283c..98871b5 100644 --- a/plugins/ropgadgets/finder.c +++ b/plugins/ropgadgets/finder.c @@ -323,6 +323,7 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd found_rop_list *result; /* Liste de listes à renvoyer */ const char *target; /* Sous-traitance requise */ search_domain domain; /* Outils pour la recherche */ + GBinPortion *portions; /* Couche première de portions */ GProcContext **contexts; /* Contextes pour recherches */ char **names; /* Désignations humaines liées */ size_t i; /* Boucle de parcours */ @@ -337,7 +338,35 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd target = g_exe_format_get_target_machine(format); domain.proc = get_arch_processor_for_type(target); - domain.exe_ranges = g_exe_format_get_x_ranges(format, &domain.exe_count); + bool collect_x_ranges(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused) + { + const mrange_t *range; + + if (visit == BPV_SHOW) + { + if (g_binary_portion_get_rights(portion) & PAC_EXEC) + { + range = g_binary_portion_get_range(portion); + + domain.exe_ranges = (mrange_t *)realloc(domain.exe_ranges, ++domain.exe_count * sizeof(mrange_t)); + copy_mrange(&domain.exe_ranges[domain.exe_count - 1], range); + + } + + } + + return true; + + } + + domain.exe_ranges = NULL; + domain.exe_count = 0; + + portions = g_exe_format_get_portions(format); + + g_binary_portion_visit(portions, (visit_portion_fc)collect_x_ranges, NULL); + + g_object_unref(G_OBJECT(portions)); /* Récupération des différents contextes */ 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); diff --git a/src/format/dex/class.c b/src/format/dex/class.c index 26907ed..c1ff62a 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -401,9 +401,8 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t /****************************************************************************** * * -* Paramètres : class = informations chargées à consulter. * +* Paramètres : class = informations chargées à consulter. * * format = format permettant d'obtenir une adresse complète. * -* layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * * * @@ -413,15 +412,15 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t * * ******************************************************************************/ -void g_dex_class_include_as_portion(const GDexClass *class, const GDexFormat *format, GPortionLayer *layer) +void g_dex_class_include_as_portion(const GDexClass *class, GExeFormat *format) { size_t i; /* Boucle de parcours */ for (i = 0; i < class->dmethods_count; i++) - g_dex_method_include_as_portion(class->direct_methods[i], format, layer); + g_dex_method_include_as_portion(class->direct_methods[i], format); for (i = 0; i < class->vmethods_count; i++) - g_dex_method_include_as_portion(class->virtual_methods[i], format, layer); + g_dex_method_include_as_portion(class->virtual_methods[i], format); } diff --git a/src/format/dex/class.h b/src/format/dex/class.h index 46529c3..ec2fa24 100644 --- a/src/format/dex/class.h +++ b/src/format/dex/class.h @@ -69,7 +69,7 @@ size_t g_dex_class_count_methods(const GDexClass *, bool); GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t); /* Intègre la méthode en tant que portion de code. */ -void g_dex_class_include_as_portion(const GDexClass *, const GDexFormat *, GPortionLayer *); +void g_dex_class_include_as_portion(const GDexClass *, GExeFormat *); /* Retrouve si possible la méthode associée à une adresse. */ GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t); diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index c550375..df920b2 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -58,7 +58,7 @@ static void g_dex_format_finalize(GDexFormat *); static const char *g_dex_format_get_target_machine(const GDexFormat *); /* Etend la définition des portions au sein d'un binaire. */ -static void g_dex_format_refine_portions(const GDexFormat *, GPortionLayer *); +static void g_dex_format_refine_portions(GDexFormat *); /* Fournit l'emplacement d'une section donnée. */ static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_t *); @@ -247,12 +247,14 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus { GDexFormat *result; /* Structure à retourner */ GBinFormat *base; /* Version basique du format */ + GExeFormat *exe_format; /* Autre version du format */ vmpa2t pos; /* Position de tête de lecture */ wgroup_id_t gid; /* Identifiant pour les tâches */ result = g_object_new(G_TYPE_DEX_FORMAT, NULL); base = G_BIN_FORMAT(result); + exe_format = G_EXE_FORMAT(result); g_binary_format_set_content(base, content); @@ -277,7 +279,7 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus if (!load_all_dex_classes(result, gid, status)) goto gdfn_error; - if (!g_binary_format_complete_loading(base, status)) + if (!g_executable_format_complete_loading(exe_format, status)) goto gdfn_error; return base; @@ -322,20 +324,18 @@ static const char *g_dex_format_get_target_machine(const GDexFormat *format) * * ******************************************************************************/ -static void g_dex_format_refine_portions(const GDexFormat *format, GPortionLayer *main) +static void g_dex_format_refine_portions(GDexFormat *format) { - GPortionLayer *layer; /* Couche à mettre en place */ + GExeFormat *exe_format; /* Autre version du format */ size_t max; /* Nombre d'itérations prévues */ size_t i; /* Boucle de parcours */ - layer = g_portion_layer_new(NO_LENGTH_YET, _("Code")); - - g_portion_layer_attach_sub(main, layer); + exe_format = G_EXE_FORMAT(format); max = g_dex_format_count_classes(format); for (i = 0; i < max; i++) - g_dex_class_include_as_portion(format->classes[i], format, layer); + g_dex_class_include_as_portion(format->classes[i], exe_format); } diff --git a/src/format/dex/method.c b/src/format/dex/method.c index 1223eb9..8659a73 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -338,7 +338,6 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) * * * Paramètres : method = représentation interne du format DEX à consulter. * * format = format permettant d'obtenir une adresse complète. * -* layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * * * @@ -348,11 +347,10 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) * * ******************************************************************************/ -void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat *format, GPortionLayer *layer) +void g_dex_method_include_as_portion(const GDexMethod *method, GExeFormat *format) { vmpa2t addr; /* Emplacement dans le binaire */ GBinPortion *new; /* Nouvelle portion définie */ - char *desc; /* Description d'une portion */ /* Si la taille est nulle, on ne fait rien */ if (method->info.access_flags & ACC_NATIVE) @@ -361,22 +359,16 @@ void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat if (!method->has_body) return; - if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr)) + if (!g_exe_format_translate_offset_into_vmpa(format, method->offset, &addr)) return; - new = g_binary_portion_new(BPC_CODE); + new = g_binary_portion_new(BPC_CODE, &addr, method->body.insns_size * sizeof(uint16_t)); - asprintf(&desc, _("Dalvik code")); - - g_binary_portion_set_desc(new, desc); - - free(desc); - - g_binary_portion_set_values(new, &addr, method->body.insns_size * sizeof(uint16_t)); + g_binary_portion_set_desc(new, _("Dalvik code")); g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(format, new); } diff --git a/src/format/dex/method.h b/src/format/dex/method.h index 41ddb4c..8836abb 100644 --- a/src/format/dex/method.h +++ b/src/format/dex/method.h @@ -82,7 +82,7 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *); GBinRoutine *g_dex_method_get_routine(const GDexMethod *); /* Intègre la méthode en tant que portion de code. */ -void g_dex_method_include_as_portion(const GDexMethod *, const GDexFormat *, GPortionLayer *); +void g_dex_method_include_as_portion(const GDexMethod *, GExeFormat *); /* Indique la position de la méthode au sein du binaire. */ bool g_dex_method_get_offset(const GDexMethod *method, phys_t *); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 2dd41e1..a51fe33 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -69,7 +69,7 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *); static const char *g_elf_format_get_target_machine(const GElfFormat *); /* Etend la définition des portions au sein d'un binaire. */ -static void g_elf_format_refine_portions(const GElfFormat *, GPortionLayer *); +static void g_elf_format_refine_portions(GElfFormat *); /* Fournit l'emplacement correspondant à une position physique. */ static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, vmpa2t *); @@ -244,10 +244,12 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus { GElfFormat *result; /* Structure à retourner */ GBinFormat *base; /* Version basique du format */ + GExeFormat *exe_format; /* Autre version du format */ result = g_object_new(G_TYPE_ELF_FORMAT, NULL); base = G_BIN_FORMAT(result); + exe_format = G_EXE_FORMAT(result); g_binary_format_set_content(base, content); @@ -305,7 +307,7 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus } - if (!g_binary_format_complete_loading(base, status)) + if (!g_executable_format_complete_loading(exe_format, status)) goto gefn_error; return base; @@ -383,7 +385,6 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -393,14 +394,13 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) * * ******************************************************************************/ -static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer *main) +static void g_elf_format_refine_portions(GElfFormat *format) { - GPortionLayer *layer; /* Couche à mettre en place */ + GExeFormat *exe_format; /* Autre version du format */ uint16_t max; /* Décompte d'éléments traités */ - elf_phdr *sorted_phdrs; /* Liste de segments triée */ uint16_t i; /* Boucle de parcours */ off_t offset; /* Début de part de programme */ - elf_phdr *phdr; /* En-tête de programme ELF */ + elf_phdr phdr; /* En-tête de programme ELF */ uint32_t p_flags; /* Droits associés à une partie*/ const char *background; /* Fond signigicatif */ GBinPortion *new; /* Nouvelle portion définie */ @@ -409,11 +409,12 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer PortionAccessRights rights; /* Droits d'une portion */ elf_shdr strings; /* Section des descriptions */ bool has_strings; /* Section trouvée ? */ - elf_shdr *sorted_shdrs; /* Liste de sections triée */ - elf_shdr *section; /* En-tête de section ELF */ + elf_shdr shdr; /* En-tête de section ELF */ uint64_t sh_flags; /* Droits associés à une partie*/ const char *name; /* Nom trouvé ou NULL */ + exe_format = G_EXE_FORMAT(format); + /** * La copie des différents en-têtes cherche à reproduire l'inclusion native * du format : @@ -429,83 +430,35 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer * Côté segments basiques. */ - layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); - - g_portion_layer_attach_sub(main, layer); - - /* Constitution d'une liste de travail */ - max = ELF_HDR(format, format->header, e_phnum); - sorted_phdrs = (elf_phdr *)calloc(max, sizeof(elf_phdr)); - for (i = 0; i < max; i++) { offset = ELF_HDR(format, format->header, e_phoff) + ELF_HDR(format, format->header, e_phentsize) * i; - if (!read_elf_program_header(format, offset, &sorted_phdrs[i])) - { - if (format->is_32b) - sorted_phdrs[i].phdr32.p_type = PT_NULL; - else - sorted_phdrs[i].phdr64.p_type = PT_NULL; - } - - } - - /* Tri de cette liste */ - - int sort_phdr(elf_phdr *a, elf_phdr *b) - { - uint64_t filesz_a; /* Taille de l'en-tête 'a' */ - uint64_t filesz_b; /* Taille de l'en-tête 'b' */ - int status; /* Bilan d'une comparaison */ - - filesz_a = ELF_PHDR(format, *a, p_filesz); - filesz_b = ELF_PHDR(format, *b, p_filesz); - - if (filesz_a < filesz_b) - status = 1; - - else if (filesz_a > filesz_b) - status = -1; - - else - status = 0; - - return status; - - } - - qsort(sorted_phdrs, max, sizeof(elf_phdr), (__compar_fn_t)sort_phdr); - - /* Inclusion de ces en-têtes */ - - for (i = 0; i < max; i++) - { - phdr = &sorted_phdrs[i]; + if (!read_elf_program_header(format, offset, &phdr)) + continue; - if (ELF_PHDR(format, *phdr, p_type) == PT_NULL) + if (ELF_PHDR(format, phdr, p_type) == PT_NULL) continue; - p_flags = ELF_PHDR(format, *phdr, p_flags); + p_flags = ELF_PHDR(format, phdr, p_flags); if (p_flags & PF_X) background = BPC_CODE; else if (p_flags & PF_W) background = BPC_DATA; else background = BPC_DATA_RO; - new = g_binary_portion_new(background); + init_vmpa(&addr, ELF_PHDR(format, phdr, p_offset), ELF_PHDR(format, phdr, p_vaddr)); + + new = g_binary_portion_new(background, &addr, ELF_PHDR(format, phdr, p_filesz)); snprintf(desc, MAX_PORTION_DESC, "%s \"%s\"", _("Segment"), - get_elf_program_type_desc(ELF_PHDR(format, *phdr, p_type))); + get_elf_program_type_desc(ELF_PHDR(format, phdr, p_type))); g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, ELF_PHDR(format, *phdr, p_offset), ELF_PHDR(format, *phdr, p_vaddr)); - g_binary_portion_set_values(new, &addr, ELF_PHDR(format, *phdr, p_filesz)); - rights = PAC_NONE; if (p_flags & PF_R) rights |= PAC_READ; if (p_flags & PF_W) rights |= PAC_WRITE; @@ -513,12 +466,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_rights(new, rights); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); } - free(sorted_phdrs); - /** * Inclusion des sections, si possible... */ @@ -527,64 +478,17 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer ELF_HDR(format, format->header, e_shstrndx), &strings); - layer = g_portion_layer_new(NO_LENGTH_YET, _("Section")); - - g_portion_layer_attach_sub(main, layer); - - /* Constitution d'une liste de travail */ - max = ELF_HDR(format, format->header, e_shnum); - sorted_shdrs = (elf_shdr *)calloc(max, sizeof(elf_shdr)); - - for (i = 0; i < max; i++) - { - if (!find_elf_section_by_index(format, i, &sorted_shdrs[i])) - { - if (format->is_32b) - sorted_shdrs[i].shdr32.sh_offset = 0; - else - sorted_shdrs[i].shdr64.sh_offset = 0; - } - - } - - /* Tri de cette liste */ - - int sort_shdr(elf_shdr *a, elf_shdr *b) - { - uint64_t size_a; /* Taille de l'en-tête 'a' */ - uint64_t size_b; /* Taille de l'en-tête 'b' */ - int status; /* Bilan d'une comparaison */ - - size_a = ELF_SHDR(format, *a, sh_size); - size_b = ELF_SHDR(format, *b, sh_size); - - if (size_a < size_b) - status = 1; - - else if (size_a > size_b) - status = -1; - - else - status = 0; - - return status; - - } - - qsort(sorted_shdrs, max, sizeof(elf_shdr), (__compar_fn_t)sort_shdr); - - /* Inclusion de ces en-têtes */ - for (i = 0; i < max; i++) { - section = &sorted_shdrs[i]; + if (!find_elf_section_by_index(format, i, &shdr)) + continue; - if (ELF_SHDR(format, *section, sh_offset) == 0) + if (ELF_SHDR(format, shdr, sh_offset) == 0) continue; - sh_flags = ELF_SHDR(format, *section, sh_flags); + sh_flags = ELF_SHDR(format, shdr, sh_flags); if ((sh_flags & SHF_ALLOC) == 0) continue; @@ -593,11 +497,13 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer else if (sh_flags & SHF_WRITE) background = BPC_DATA; else background = BPC_DATA_RO; - new = g_binary_portion_new(background); + init_vmpa(&addr, ELF_SHDR(format, shdr, sh_offset), ELF_SHDR(format, shdr, sh_addr)); + + new = g_binary_portion_new(background, &addr, ELF_SHDR(format, shdr, sh_size)); if (has_strings) name = extract_name_from_elf_string_section(format, &strings, - ELF_SHDR(format, *section, sh_name)); + ELF_SHDR(format, shdr, sh_name)); else name = NULL; if (name != NULL) @@ -607,9 +513,6 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, ELF_SHDR(format, *section, sh_offset), ELF_SHDR(format, *section, sh_addr)); - g_binary_portion_set_values(new, &addr, ELF_SHDR(format, *section, sh_size)); - rights = PAC_NONE; if (sh_flags & SHF_ALLOC) rights |= PAC_READ; if (sh_flags & SHF_WRITE) rights |= PAC_WRITE; @@ -617,12 +520,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_rights(new, rights); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); } - free(sorted_shdrs); - } diff --git a/src/format/executable-int.h b/src/format/executable-int.h index a4d4b35..88527a5 100644 --- a/src/format/executable-int.h +++ b/src/format/executable-int.h @@ -36,7 +36,7 @@ typedef const char * (* get_target_machine_fc) (const GExeFormat *); /* Etend la définition des portions au sein d'un binaire. */ -typedef void (* refine_portions_fc) (const GExeFormat *, GPortionLayer *); +typedef void (* refine_portions_fc) (GExeFormat *); /* Fournit l'emplacement correspondant à une position physique. */ typedef bool (* translate_phys_fc) (const GExeFormat *, phys_t, vmpa2t *); @@ -57,7 +57,8 @@ struct _GExeFormat GDbgFormat **debugs; /* Informations de débogage */ size_t debugs_count; /* Nombre de ces informations */ - GPortionLayer *layers; /* Couches de morceaux binaires*/ + GBinPortion *portions; /* Couches de morceaux binaires*/ + GMutex mutex; /* Accès à l'arborescence */ }; @@ -77,6 +78,9 @@ struct _GExeFormatClass }; +/* Effectue les ultimes opérations de chargement d'un binaire. */ +bool g_executable_format_complete_loading(GExeFormat *, GtkStatusStack *); + /* Fournit l'emplacement correspondant à une position physique. */ bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *, phys_t, vmpa2t *); diff --git a/src/format/executable.c b/src/format/executable.c index c1ff940..3e902cf 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -24,6 +24,7 @@ #include "executable.h" +#include #include #include @@ -39,6 +40,12 @@ static void g_executable_format_class_init(GExeFormatClass *); /* Initialise une instance de format d'exécutable générique. */ static void g_executable_format_init(GExeFormat *); +/* Supprime toutes les références externes. */ +static void g_executable_format_dispose(GExeFormat *); + +/* Procède à la libération totale de la mémoire. */ +static void g_executable_format_finalize(GExeFormat *); + /* Indique le type défini pour un format d'exécutable générique. */ @@ -59,6 +66,12 @@ G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT); static void g_executable_format_class_init(GExeFormatClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_executable_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_executable_format_finalize; } @@ -77,11 +90,57 @@ static void g_executable_format_class_init(GExeFormatClass *klass) static void g_executable_format_init(GExeFormat *format) { + g_mutex_init(&format->mutex); } +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_executable_format_dispose(GExeFormat *format) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < format->debugs_count; i++) + g_object_unref(G_OBJECT(format->debugs[i])); + + if (format->portions != NULL) + g_object_unref(G_OBJECT(format->portions)); + + g_mutex_clear(&format->mutex); + G_OBJECT_CLASS(g_executable_format_parent_class)->dispose(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_executable_format_finalize(GExeFormat *format) +{ + G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format)); + +} /****************************************************************************** @@ -184,109 +243,95 @@ const char *g_exe_format_get_target_machine(const GExeFormat *format) /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * +* Paramètres : format = instance à traiter. * +* status = barre de statut à tenir informée. * * * -* Description : Fournit la première couche des portions composent le binaire.* +* Description : Effectue les ultimes opérations de chargement d'un binaire. * * * -* Retour : Couche brute des différentes portions. * +* Retour : Bilan de l'opération. * * * -* Remarques : Le compteur de références de l'instance renvoyée doit être * -* décrémenté après usage. * +* Remarques : - * * * ******************************************************************************/ -GPortionLayer *g_exe_format_get_main_layer(GExeFormat *format) +bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *status) { - GBinPortion *portion; /* Portion brute globale */ + bool result; /* Bilan à faire remonter */ + GBinFormat *base; /* Version basique du format */ vmpa2t addr; /* Emplacement vide de sens */ phys_t length; /* Taille de portion globale */ - GPortionLayer *layer; /* Couche à mettre en place */ - - if (format->layers == NULL) - { - /* Création d'une portion globale */ - - portion = g_binary_portion_new(BPC_RAW); - init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); - length = g_binary_content_compute_size(G_BIN_FORMAT(format)->content); + base = G_BIN_FORMAT(format); - g_binary_portion_set_values(portion, &addr, length); + result = g_binary_format_complete_loading(base, status); - /* Création d'une couche de base brute */ - - layer = g_portion_layer_new(length, NULL); - - g_portion_layer_include(layer, portion); + if (result) + { + result = g_exe_format_translate_offset_into_vmpa(format, 0, &addr); + assert(result); - /* Remplissage */ + length = g_binary_content_compute_size(base->content); - G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format, layer); + format->portions = g_binary_portion_new(BPC_RAW, &addr, length); - format->layers = layer; + G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format); } - g_object_ref(G_OBJECT(format->layers)); - - return format->layers; + return result; } /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * -* count = quantité de zones listées. [OUT] * +* Paramètres : format = description de l'exécutable à modifier. * +* portion = portion à inclure dans les définitions du format. * * * -* Description : Fournit les espaces mémoires des portions exécutables. * +* Description : Procède à l'enregistrement d'une portion dans un format. * * * -* Retour : Liste de zones binaires exécutables à libérer après usage. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count) +void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion) { - mrange_t *result; /* Liste à retourner */ - - typedef struct _x_ranges - { - mrange_t *list; - size_t length; + g_mutex_lock(&format->mutex); - } x_ranges; + g_binary_portion_include(format->portions, portion); - x_ranges tmp; /* Sauvegarde de la liste */ - GPortionLayer *layer; /* Couche première de portions */ + g_mutex_unlock(&format->mutex); - bool visit_for_x(GBinPortion *portion, x_ranges *ranges) - { - const mrange_t *range; - - if (g_binary_portion_get_rights(portion) & PAC_EXEC) - { - range = g_binary_portion_get_range(portion); +} - ranges->list = (mrange_t *)realloc(ranges->list, ++ranges->length * sizeof(mrange_t)); - copy_mrange(&ranges->list[ranges->length - 1], range); - } +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* * +* Description : Fournit la première couche des portions composent le binaire.* +* * +* Retour : Arborescence des différentes portions binaires. * +* * +* Remarques : Le compteur de références de l'instance renvoyée doit être * +* décrémenté après usage. * +* * +******************************************************************************/ - return true; +GBinPortion *g_exe_format_get_portions(GExeFormat *format) +{ + GBinPortion *result; /* Instance à retourner */ - } + g_mutex_lock(&format->mutex); - tmp.list = NULL; - tmp.length = 0; + result = format->portions; - layer = g_exe_format_get_main_layer(format); - g_portion_layer_visit(format->layers, (visit_portion_fc)visit_for_x, &tmp); - g_object_unref(G_OBJECT(layer)); + if (result != NULL) + g_object_ref(G_OBJECT(result)); - result = tmp.list; - *count = tmp.length; + g_mutex_unlock(&format->mutex); return result; diff --git a/src/format/executable.h b/src/format/executable.h index ad89948..6384851 100644 --- a/src/format/executable.h +++ b/src/format/executable.h @@ -52,7 +52,6 @@ typedef struct _GExeFormatClass GExeFormatClass; /* Indique le type défini pour un format d'exécutable générique. */ GType g_executable_format_get_type(void); - /* Rajoute des informations de débogage à un exécutable. */ void g_exe_format_add_debug_info(GExeFormat *, GDbgFormat *); @@ -65,8 +64,11 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t); /* Indique le type d'architecture visée par le format. */ const char *g_exe_format_get_target_machine(const GExeFormat *); +/* Procède à l'enregistrement d'une portion dans un format. */ +void g_exe_format_include_portion(GExeFormat *, GBinPortion *); + /* Fournit la première couche des portions composent le binaire. */ -GPortionLayer *g_exe_format_get_main_layer(GExeFormat *); +GBinPortion *g_exe_format_get_portions(GExeFormat *); /* Fournit les espaces mémoires des portions exécutables. */ mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count); diff --git a/src/format/format.c b/src/format/format.c index bf4a0e1..516f882 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -137,7 +137,6 @@ bool g_binary_format_complete_loading(GBinFormat *format, GtkStatusStack *status * * * Paramètres : format = description de l'exécutable à consulter. * * content = contenu binaire à parcourir. * -* length = taille du contenu fourni. * * * * Description : Définit le contenu binaire à analyser. * * * diff --git a/src/format/symbol.c b/src/format/symbol.c index 48f3dbb..97ff114 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -226,6 +226,37 @@ int g_binary_symbol_cmp(const GBinSymbol **a, const GBinSymbol **b) /****************************************************************************** * * +* Paramètres : symbol = symbole à analyser. * +* addr = localisation à venir comparer à celle du symbole. * +* * +* Description : Compare un symbole et une localisation. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut). * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_binary_symbol_cmp_with_vmpa(const GBinSymbol *symbol, const vmpa2t *addr) +{ + int result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement du symbole */ + + range = g_binary_symbol_get_range(symbol); + + if (range == NULL) + result = 1; + + else + result = cmp_mrange_with_vmpa(range, addr); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit le type du symbole. * diff --git a/src/format/symbol.h b/src/format/symbol.h index 8432d8d..78741cb 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -80,6 +80,9 @@ GBinSymbol *g_binary_symbol_new(SymbolType); /* Compare deux symboles d'exécutable selon leurs propriétés. */ int g_binary_symbol_cmp(const GBinSymbol **, const GBinSymbol **); +/* Compare un symbole et une localisation. */ +int g_binary_symbol_cmp_with_vmpa(const GBinSymbol *, const vmpa2t *); + /* Fournit le type du symbole. */ SymbolType g_binary_symbol_get_target_type(const GBinSymbol *); diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 8fc7805..4137763 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -34,6 +34,7 @@ #include "../common/extstr.h" +#include "../common/sort.h" @@ -45,8 +46,6 @@ struct _GBinPortion { GObject parent; /* A laisser en premier */ - const unsigned int *level; /* Profondeur de la portion */ - char *code; /* Code de la couleur de fond */ char *desc; /* Désignation humaine */ @@ -55,6 +54,9 @@ struct _GBinPortion PortionAccessRights rights; /* Droits d'accès */ + GBinPortion **subs; /* Portions incluses */ + size_t count; /* Quantité d'inclusions */ + }; /* Portion de données binaires quelconques (classe) */ @@ -77,58 +79,16 @@ static void g_binary_portion_dispose(GBinPortion *); /* Procède à la libération totale de la mémoire. */ static void g_binary_portion_finalize(GBinPortion *); -/* Définit le niveau de profondeur pour une branche de portions. */ -static void g_binary_portion_set_level(GBinPortion *, const unsigned int *); - /* Détermine l'aire d'une sous-portion. */ static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); -/* Détermine si une portion contient une adresse donnée. */ -static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); - - - -/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ - - -/* Couche de portions binaires quelconques (instance) */ -struct _GPortionLayer -{ - GObject parent; /* A laisser en premier */ - - phys_t length; /* Taille de portion globale */ - const char *name; /* Désignation de la couche */ - - unsigned int level; /* Profondeur de la portion */ - - GPortionLayer *sub_layer; /* Eventuelle couche inférieure*/ - - GBinPortion **portions; /* Portions incluses */ - size_t count; /* Quantité d'inclusions */ - -}; - -/* Couche de portions binaires quelconques (classe) */ -struct _GPortionLayerClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des couches de portions binaires. */ -static void g_portion_layer_class_init(GPortionLayerClass *); -/* Initialise une instance de couche de portions binaires. */ -static void g_portion_layer_init(GPortionLayer *); -/* Supprime toutes les références externes. */ -static void g_portion_layer_dispose(GPortionLayer *); - -/* Procède à la libération totale de la mémoire. */ -static void g_portion_layer_finalize(GPortionLayer *); +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ +/* Détermine si une portion contient une adresse donnée. */ +static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); @@ -180,7 +140,6 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) static void g_binary_portion_init(GBinPortion *portion) { - portion->level = NULL; } @@ -231,6 +190,8 @@ static void g_binary_portion_finalize(GBinPortion *portion) /****************************************************************************** * * * Paramètres : code = désignation humaine de la couleur de fond. * +* addr = emplacement de la section à conserver. * +* size = taille de la section à conserver. * * * * Description : Crée une description de partie de code vierge. * * * @@ -240,7 +201,7 @@ static void g_binary_portion_finalize(GBinPortion *portion) * * ******************************************************************************/ -GBinPortion *g_binary_portion_new(const char *code) +GBinPortion *g_binary_portion_new(const char *code, const vmpa2t *addr, phys_t size) { GBinPortion *result; /* Structure à retourner */ @@ -248,27 +209,9 @@ GBinPortion *g_binary_portion_new(const char *code) result->code = strdup(code); - return result; - -} + init_mrange(&result->range, addr, size); - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* level = niveau de profondeur à associer. * -* * -* Description : Définit le niveau de profondeur pour une branche de portions.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_set_level(GBinPortion *portion, const unsigned int *level) -{ - portion->level = level; + return result; } @@ -291,31 +234,12 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) int result; /* Bilan à retourner */ const vmpa2t *addr_a; /* Adresse de la portion 'a' */ const vmpa2t *addr_b; /* Adresse de la portion 'b' */ - const unsigned int *level_a; /* Niveau de la portion 'a' */ - const unsigned int *level_b; /* Niveau de la portion 'b' */ addr_a = get_mrange_addr(&(*a)->range); addr_b = get_mrange_addr(&(*b)->range); result = cmp_vmpa(addr_a, addr_b); - if (result == 0) - { - level_a = (*a)->level; - level_b = (*b)->level; - - if (level_a != NULL && level_b != NULL) - { - if (*level_a < *level_b) - result = -1; - - else if (*level_a > *level_b) - result = 1; - - } - - } - return result; } @@ -365,27 +289,6 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion) /****************************************************************************** * * * Paramètres : portion = description de partie à mettre à jour. * -* addr = emplacement de la section à conserver. * -* size = taille de la section à conserver. * -* * -* Description : Définit les valeurs utiles d'une partie de code binaire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, phys_t size) -{ - init_mrange(&portion->range, addr, size); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * * * * Description : Fournit l'emplacement d'une partie de code binaire. * * * @@ -443,76 +346,6 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) /****************************************************************************** * * -* Paramètres : portion = portion mère à consulter. * -* full = taille totale de la couche parente. * -* area = étendue de représentation de la portion mère. * -* sub_area = étendue de représentation de la portion fille. * -* * -* Description : Détermine l'aire d'une sous-portion. * -* * -* Retour : true si la sous-surface a été calculée correctement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) -{ - phys_t length; /* Taille de la portion */ - phys_t start; /* Position de départ */ - - length = get_mrange_length(&portion->range); - - /* On saute les portions comme le segment GNU_STACK... */ - if (length == 0) return false; - - start = get_phy_addr(get_mrange_addr(&portion->range)); - - sub_area->y = area->y; - sub_area->height = area->height; - - sub_area->x = area->x + (start * area->width) / full; - sub_area->width = (length * area->width) / full; - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = portion mère à consulter. * -* addr = adresse du point de recherche. * -* * -* Description : Détermine si une portion contient une adresse donnée. * -* * -* Retour : true ou false selon le résultat. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - - result = false; - - /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ - if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) - goto not_found; - - result = mrange_contains_addr(&portion->range, addr); - - not_found: - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : portion = description de partie à consulter. * * buffer = espace où placer ledit contenu. * * msize = taille idéale des positions et adresses; * @@ -686,52 +519,50 @@ void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) /****************************************************************************** * * -* Paramètres : portion = description de partie à consulter. * -* cr = contexte graphique pour le dessin. * -* area = étendue mise à disposition. * +* Paramètres : portion = portion mère à consulter. * +* full = taille totale de la couche parente. * +* area = étendue de représentation de la portion mère. * +* sub_area = étendue de représentation de la portion fille. * * * -* Description : Représente la portion sur une bande dédiée. * +* Description : Détermine l'aire d'une sous-portion. * * * -* Retour : - * +* Retour : true si la sous-surface a été calculée correctement. * * * * Remarques : - * * * ******************************************************************************/ -void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) { - //cairo_set_line_width(cr, 1.0); + phys_t length; /* Taille de la portion */ + phys_t start; /* Position de départ */ - cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + length = get_mrange_length(&portion->range); - gtk_style_context_save(context); + /* On saute les portions comme le segment GNU_STACK... */ + if (length == 0) return false; - gtk_style_context_add_class(context, portion->code); + start = get_phy_addr(get_mrange_addr(&portion->range)); - gtk_render_background(context, cr, area->x, area->y, area->width, area->height); + sub_area->y = area->y; + sub_area->height = area->height; - gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); + sub_area->x = area->x + (start * area->width) / full; + sub_area->width = (length * area->width) / full; - gtk_style_context_restore(context); + return true; } - -/* ---------------------------------------------------------------------------------- */ -/* COUCHES DE PORTIONS BINAIRES */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini par la GLib pour les couches de portions binaires. */ -G_DEFINE_TYPE(GPortionLayer, g_portion_layer, G_TYPE_OBJECT); - - /****************************************************************************** * * -* Paramètres : klass = classe à initialiser. * +* Paramètres : portion = description de partie à consulter. * +* context = contexte graphique associé à la procédure. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * * * -* Description : Initialise la classe des couches de portions binaires. * +* Description : Représente la portion sur une bande dédiée. * * * * Retour : - * * * @@ -739,70 +570,51 @@ G_DEFINE_TYPE(GPortionLayer, g_portion_layer, G_TYPE_OBJECT); * * ******************************************************************************/ -static void g_portion_layer_class_init(GPortionLayerClass *klass) +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) { - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à montrer */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ - object->dispose = (GObjectFinalizeFunc/* ! */)g_portion_layer_dispose; - object->finalize = (GObjectFinalizeFunc)g_portion_layer_finalize; + /* Dessin de la portion courante */ + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); -} + gtk_style_context_save(context); + gtk_style_context_add_class(context, portion->code); -/****************************************************************************** -* * -* Paramètres : layer = instance à initialiser. * -* * -* Description : Initialise une instance de couche de portions binaires. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + gtk_render_background(context, cr, area->x, area->y, area->width, area->height); -static void g_portion_layer_init(GPortionLayer *layer) -{ - layer->level = 0; + gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); -} + gtk_style_context_restore(context); + /* Dessin des portions contenues */ -/****************************************************************************** -* * -* Paramètres : layer = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + full = get_mrange_length(&portion->range); -static void g_portion_layer_dispose(GPortionLayer *layer) -{ - size_t i; /* Boucle de parcours */ + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; - if (layer->sub_layer != NULL) - g_object_unref(G_OBJECT(layer->sub_layer)); + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; - for (i = 0; i < layer->count; i++) - g_object_unref(G_OBJECT(layer->portions[i])); + g_binary_portion_draw(sub, context, cr, &sub_area); - G_OBJECT_CLASS(g_portion_layer_parent_class)->dispose(G_OBJECT(layer)); + } } /****************************************************************************** * * -* Paramètres : layer = instance d'objet GLib à traiter. * +* Paramètres : portion = portion principale à compléter. * +* sub = portion à inclure dans la définition courante. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Procède à l'inclusion d'une portion dans une autre. * * * * Retour : - * * * @@ -810,204 +622,161 @@ static void g_portion_layer_dispose(GPortionLayer *layer) * * ******************************************************************************/ -static void g_portion_layer_finalize(GPortionLayer *layer) +void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) { - if (layer->portions != NULL) - free(layer->portions); - - G_OBJECT_CLASS(g_portion_layer_parent_class)->finalize(G_OBJECT(layer)); - -} - - -/****************************************************************************** -* * -* Paramètres : length = -* name = désignation pouvant servir de suffixe aux portions. * -* * -* Description : Crée une nouvelle couche de portions binaires. * -* * -* Retour : Instance mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GPortionLayer *g_portion_layer_new(phys_t length, const char *name) -{ - GPortionLayer *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_BIN_PORTION, NULL); - - result->length = length; - result->name = name; - - return result; - -} + bool found; /* Zone d'accueil trouvée ? */ + size_t best; /* Meilleur point d'insertion */ + const mrange_t *prange; /* Emplacement de portion #1 */ + const mrange_t *srange; /* Emplacement de portion #2 */ + GBinPortion tmp; /* Sauvegarde temporaire */ + found = bsearch_index(sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_compare, &best); -/****************************************************************************** -* * -* Paramètres : layer = couche rassemblant des portions à modifier. * -* Paramètres : sub = couche inférieure à rattacher à la couche courante. * -* * -* Description : Attache une couche à une autre en tant que couche inférieure.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + if (!found) + portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_compare, &sub); -void g_portion_layer_attach_sub(GPortionLayer *layer, GPortionLayer *sub) -{ - void set_layers_length(GPortionLayer *parent, GPortionLayer *child) + else { - if (child->length == NO_LENGTH_YET) + /** + * On prend ici en compte le genre de situations suivantes : + * + * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8 + * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4 + * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1 + * + * Pendant le désassemblage, la procédure n'aime pas trop les intersections + * de zones mémoire. + */ + + prange = g_binary_portion_get_range(portion->subs[best]); + srange = g_binary_portion_get_range(sub); + + if (mrange_contains_mrange(prange, srange)) + g_binary_portion_include(portion->subs[best], sub); + + else { - assert(parent->length != NO_LENGTH_YET); + assert(mrange_contains_mrange(srange, prange)); - child->length = parent->length; + memcpy(&tmp, portion->subs[best], sizeof(GBinPortion)); + memcpy(portion->subs[best], sub, sizeof(GBinPortion)); + memcpy(sub, &tmp, sizeof(GBinPortion)); - if (child->sub_layer != NULL) - set_layers_length(child, child->sub_layer); + g_binary_portion_include(portion->subs[best], sub); } } - void set_layers_depth(GPortionLayer *parent, GPortionLayer *child) - { - child->level = parent->level + 1; - - if (child->sub_layer != NULL) - set_layers_length(child, child->sub_layer); - - } - - set_layers_length(layer, sub); - - set_layers_depth(layer, sub); - - layer->sub_layer = sub; - } /****************************************************************************** * * -* Paramètres : layer = couche rassemblant les portions d'un même niveau. * -* portion = portion à inclure dans la définition courante. * +* Paramètres : portion = première couche amorçant la visite. * +* visitor = fonction à appeler à chaque étape de la descente. * +* data = adresse pointant vers des données de l'utilisateur.* * * -* Description : Procède à l'inclusion d'une portion dans une couche. * +* Description : Parcourt un ensemble de portions binaires. * * * -* Retour : - * +* Retour : true si la visite a été jusqu'à son terme, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_portion_layer_include(GPortionLayer *layer, GBinPortion *portion) +bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) { - GPortionLayer *sub; /* Sous couche indispensable */ - bool conflict; /* Conflit dû aux débordements */ - const mrange_t *range; /* Emplacement de la portion */ - size_t i; /* Boucle de parcours */ - const mrange_t *other; /* Emplacements déjà occupés */ - - /** - * On prend ici en compte le genre de situations suivantes : - * - * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8 - * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4 - * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1 - * - * Pendant le désassemblage, la procédure n'aime pas trop les intersections - * de zones mémoire. - */ + bool result; /* Etat à retourner */ - conflict = false; + bool visit_portion(GBinPortion *p, GBinPortion *pp) + { + bool ret; /* Etat à retourner */ + size_t i; /* Boucle de parcours */ - range = g_binary_portion_get_range(portion); + if (p->count == 0) + ret = visitor(p, pp, BPV_SHOW, data); - for (i = 0; i < layer->count && !conflict; i++) - { - other = g_binary_portion_get_range(layer->portions[i]); + else + { + ret = visitor(p, pp, BPV_ENTER, data); - conflict = mrange_intersects_mrange(range, other); + for (i = 0; i < p->count && ret; i++) + ret = visit_portion(p->subs[i], p); - } + if (ret) + ret = visitor(p, pp, BPV_EXIT, data); - /* La portion recouvre-t-elle une portion déjà existante ? */ - if (conflict) - { - if (layer->sub_layer == NULL) - { - sub = g_portion_layer_new(layer->length, layer->name); - g_portion_layer_attach_sub(layer, sub); } - g_portion_layer_include(layer->sub_layer, portion); + return ret; } - /* Sinon on l'intègre dans la couche courante */ - else - { - layer->portions = (GBinPortion **)realloc(layer->portions, - ++layer->count * sizeof(GBinPortion *)); + result = visit_portion(portion, NULL); - layer->portions[layer->count - 1] = portion; + return result; - g_binary_portion_set_level(portion, &layer->level); +} - qsort(layer->portions, layer->count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); - } -} +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS D'ENSEMBLES DE PORTIONS */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : layer = couche première à parcourir intégralement. * -* count = nombre de portions trouvées et renvoyées. [OUT] * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* x = abscisse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * * * -* Description : Fournit une liste triée de portions d'un binaire. * +* Description : Recherche la portion présente à un point donné. * * * -* Retour : Liste de définitions de zones à libérer après usage. * +* Retour : Portion trouvée à l'endroit indiqué. * * * * Remarques : - * * * ******************************************************************************/ -GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, size_t *count) +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) { - GBinPortion **result; /* Liste construite à renvoyer */ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à traiter */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ - GBinPortion **do_collect(const GPortionLayer *l, GBinPortion **lst, size_t *c) - { - size_t start; /* Indice de départ des ajouts */ - size_t i; /* Boucle de parcours */ + result = NULL; - start = *c; - *c += l->count; + full = get_mrange_length(&portion->range); - lst = (GBinPortion **)realloc(lst, *c * sizeof(GBinPortion *)); + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; - for (i = 0; i < l->count; i++) - lst[start + i] = l->portions[i]; + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; - return lst; + if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) + { + result = g_binary_portion_find_at_pos(sub, x, &sub_area); - } + if (result != NULL) + *area = sub_area; - *count = 0; + } - result = do_collect(layer, NULL, count); + } - qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } return result; @@ -1016,44 +785,30 @@ GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, s /****************************************************************************** * * -* Paramètres : layer = couche de portions à parcourir pour les recherches. * -* x = abscisse du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * +* Paramètres : portion = portion mère à consulter. * +* addr = adresse du point de recherche. * * * -* Description : Recherche la portion présente à un point donné. * +* Description : Détermine si une portion contient une adresse donnée. * * * -* Retour : Portion trouvée à l'endroit indiqué. * +* Retour : true ou false selon le résultat. * * * * Remarques : - * * * ******************************************************************************/ -GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gint x, GdkRectangle *area) +static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr) { - GBinPortion *result; /* Portion à retourner */ - size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à traiter */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - if (layer->sub_layer != NULL) - result = g_portion_layer_find_portion_at_pos(layer->sub_layer, x, area); - else - result = NULL; + bool result; /* Bilan à retourner */ - for (i = 0; i < layer->count && result == NULL; i++) - { - sub = layer->portions[i]; + result = false; - if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) - continue; + /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ + if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) + goto not_found; - if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) - { - result = sub; - *area = sub_area; - } + result = mrange_contains_addr(&portion->range, addr); - } + not_found: return result; @@ -1062,9 +817,9 @@ GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gin /****************************************************************************** * * -* Paramètres : layer = couche de portions à parcourir pour les recherches. * -* addr = adresse du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* addr = adresse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * * * * Description : Recherche la portion présente à une adresse donnée. * * * @@ -1074,31 +829,39 @@ GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gin * * ******************************************************************************/ -GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, const vmpa2t *addr, GdkRectangle *area) +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) { GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ size_t i; /* Boucle de parcours #1 */ GBinPortion *sub; /* Portion incluse à traiter */ GdkRectangle sub_area; /* Etendue d'une sous-portion */ - if (layer->sub_layer != NULL) - result = g_portion_layer_find_portion_at_addr(layer->sub_layer, addr, area); - else - result = NULL; + result = NULL; + + full = get_mrange_length(&portion->range); - for (i = 0; i < layer->count && result == NULL; i++) + for (i = 0; i < portion->count && result == NULL; i++) { - sub = layer->portions[i]; + sub = portion->subs[i]; if (!g_portion_layer_contains_addr(sub, addr)) continue; - if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) continue; - result = sub; - *area = sub_area; + result = g_binary_portion_find_at_addr(sub, addr, &sub_area); + + if (result != NULL) + *area = sub_area; + + } + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); } return result; @@ -1108,10 +871,10 @@ GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, co /****************************************************************************** * * -* Paramètres : layer = couche de portions à parcourir pour les recherches. * -* x = abscisse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* addr = adresse correspondante. [OUT] * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* x = abscisse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* addr = adresse correspondante. [OUT] * * * * Description : Fournit la position correspondant à une adresse donnée. * * * @@ -1121,20 +884,22 @@ GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, co * * ******************************************************************************/ -bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRectangle *area, vmpa2t *addr) +bool get_binary_portion_addr_from_pos(GBinPortion *root, gint x, const GdkRectangle *area, vmpa2t *addr) { GdkRectangle owner_area; /* Aire de contenance */ GBinPortion *owner; /* Conteneur propriétaire */ owner_area = *area; - owner = g_portion_layer_find_portion_at_pos(layer, x, &owner_area); + owner = g_binary_portion_find_at_pos(root, x, &owner_area); if (owner == NULL) return false; copy_vmpa(addr, get_mrange_addr(&owner->range)); advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); + g_object_unref(G_OBJECT(owner)); + return true; } @@ -1142,10 +907,10 @@ bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRe /****************************************************************************** * * -* Paramètres : layer = couche de portions à parcourir pour les recherches. * -* addr = adresse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* x = position correspondante. [OUT] * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* addr = adresse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* x = position correspondante. [OUT] * * * * Description : Fournit l'adresse correspondant à une position donnée. * * * @@ -1155,7 +920,7 @@ bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRe * * ******************************************************************************/ -bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr, const GdkRectangle *area, gint *x) +bool get_binary_portion_pos_from_addr(GBinPortion *root, const vmpa2t *addr, const GdkRectangle *area, gint *x) { GdkRectangle owner_area; /* Aire de contenance */ GBinPortion *owner; /* Conteneur propriétaire */ @@ -1163,46 +928,16 @@ bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr, owner_area = *area; - owner = g_portion_layer_find_portion_at_addr(layer, addr, &owner_area); + owner = g_binary_portion_find_at_addr(root, addr, &owner_area); if (owner == NULL) return false; diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range)); *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); - return true; - -} - + g_object_unref(G_OBJECT(owner)); -/****************************************************************************** -* * -* Paramètres : layer = première couche amorçant la visite. * -* visitor = fonction à appeler à chaque étape de la descente. * -* data = adresse pointant vers des données de l'utilisateur.* -* * -* Description : Parcours un ensemble de portions binaires. * -* * -* Retour : true si la visite a été jusqu'à son terme, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_portion_layer_visit(const GPortionLayer *layer, visit_portion_fc visitor, void *data) -{ - bool result; /* Etat à retourner */ - size_t i; /* Boucle de parcours */ - - if (layer->sub_layer != NULL) - result = g_portion_layer_visit(layer->sub_layer, visitor, data); - else - result = true; - - for (i = 0; i < layer->count && result; i++) - result = visitor(layer->portions[i], data); - - return result; + return true; } @@ -1223,52 +958,17 @@ bool g_portion_layer_visit(const GPortionLayer *layer, visit_portion_fc visitor, * * ******************************************************************************/ -gboolean g_portion_layer_query_tooltip(const GPortionLayer *layer, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) { GBinPortion *selected; /* Portion à décrire ici */ - selected = g_portion_layer_find_portion_at_pos(layer, x, (GdkRectangle []) { *area }); + selected = g_binary_portion_find_at_pos(root, x, (GdkRectangle []) { *area }); if (selected == NULL) return FALSE; g_binary_portion_query_tooltip(selected, tooltip); - return TRUE; - -} - + g_object_unref(G_OBJECT(selected)); -/****************************************************************************** -* * -* Paramètres : layer = couche de portions à consulter. * -* cr = contexte graphique pour le dessin. * -* area = étendue mise à disposition. * -* * -* Description : Représente une couche de portions sur une bande dédiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_portion_layer_draw(const GPortionLayer *layer, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) -{ - size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à montrer */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - for (i = 0; i < layer->count; i++) - { - sub = layer->portions[i]; - - if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) - continue; - - g_binary_portion_draw(sub, context, cr, &sub_area); - - } - - if (layer->sub_layer != NULL) - g_portion_layer_draw(layer->sub_layer, context, cr, area); + return TRUE; } diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index b91af05..2aa5e1a 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -80,7 +80,7 @@ typedef enum _PortionAccessRights GType g_binary_portion_get_type(void); /* Crée une description de partie de code vierge. */ -GBinPortion *g_binary_portion_new(const char *); +GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t); /* Etablit la comparaison ascendante entre deux portions. */ int g_binary_portion_compare(const GBinPortion **, const GBinPortion **); @@ -91,9 +91,6 @@ void g_binary_portion_set_desc(GBinPortion *, const char *); /* Fournit la description attribuée à une partie de code. */ const char *g_binary_portion_get_desc(const GBinPortion *); -/* Définit les valeurs utiles d'une partie de code. */ -void g_binary_portion_set_values(GBinPortion *, const vmpa2t *, phys_t); - /* Fournit l'emplacement d'une partie de code binaire. */ const mrange_t *g_binary_portion_get_range(const GBinPortion *); @@ -112,68 +109,44 @@ void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); /* Représente la portion sur une bande dédiée. */ void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +/* Procède à l'inclusion d'une portion dans une autre. */ +void g_binary_portion_include(GBinPortion *, GBinPortion *); +/* Sens des visites */ +typedef enum _BinaryPortionVisit +{ + BPV_ENTER, /* Arrivée sur une branche */ + BPV_SHOW, /* Visite d'une feuille */ + BPV_EXIT /* Départ d'une branche */ -/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ - - -#define G_TYPE_PORTION_LAYER (g_portion_layer_get_type()) -#define G_PORTION_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PORTION_LAYER, GPortionLayer)) -#define G_IS_PORTION_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PORTION_LAYER)) -#define G_PORTION_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PORTION_LAYER, GPortionLayerClass)) -#define G_IS_PORTION_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PORTION_LAYER)) -#define G_PORTION_LAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PORTION_LAYER, GPortionLayerClass)) - - -/* Couche de portions binaires quelconques (instance) */ -typedef struct _GPortionLayer GPortionLayer; - -/* Couche de portions binaires quelconques (classe) */ -typedef struct _GPortionLayerClass GPortionLayerClass; - +} BinaryPortionVisit; -/* Taille à définir lors d'un rattachement */ -#define NO_LENGTH_YET VMPA_NO_PHYSICAL +/* Fonction appelée à chaque visite de portion.*/ +typedef bool (* visit_portion_fc) (GBinPortion *, GBinPortion *, BinaryPortionVisit, void *); -/* Indique le type défini par la GLib pour les couches de portions binaires. */ -GType g_portion_layer_get_type(void); +/* Parcourt un ensemble de portions binaires. */ +bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); -/* Crée une nouvelle couche de portions binaires. */ -GPortionLayer *g_portion_layer_new(phys_t, const char *); -/* Attache une couche à une autre en tant que couche inférieure. */ -void g_portion_layer_attach_sub(GPortionLayer *, GPortionLayer *); -/* Procède à l'inclusion d'une portion dans une couche. */ -void g_portion_layer_include(GPortionLayer *, GBinPortion *); +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ -/* Fournit une liste triée de portions d'un binaire. */ -GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *, size_t *); /* Recherche la portion présente à un point donné. */ -GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *, gint, GdkRectangle *); +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); /* Recherche la portion présente à une adresse donnée. */ -GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *, const vmpa2t *, GdkRectangle *); +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); /* Fournit la position correspondant à une adresse donnée. */ -bool g_portion_layer_get_addr_from_pos(GPortionLayer *, gint, const GdkRectangle *, vmpa2t *); +bool get_binary_portion_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); /* Fournit l'adresse correspondant à une position donnée. */ -bool g_portion_layer_get_pos_from_addr(GPortionLayer *, const vmpa2t *, const GdkRectangle *, gint *); - -/* Fonction appelée à chaque visite de portion.*/ -typedef bool (* visit_portion_fc) (GBinPortion *, void *); - -/* Parcours un ensemble de portions binaires. */ -bool g_portion_layer_visit(const GPortionLayer *, visit_portion_fc, void *); +bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); /* Prépare une astuce concernant une portion pour son affichage. */ -gboolean g_portion_layer_query_tooltip(const GPortionLayer *, gint, gint, const GdkRectangle *, GtkTooltip *); - -/* Représente une couche de portions sur une bande dédiée. */ -void g_portion_layer_draw(const GPortionLayer *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); diff --git a/src/gtkext/gtkbinarystrip.c b/src/gtkext/gtkbinarystrip.c index fff6a78..d1638ed 100644 --- a/src/gtkext/gtkbinarystrip.c +++ b/src/gtkext/gtkbinarystrip.c @@ -211,7 +211,7 @@ static void gtk_binary_strip_size_allocate(GtkWidget *widget, GtkAllocation *all { GtkBinaryStrip *strip; /* Autre version du composant */ GExeFormat *format; /* Format du binaire */ - GPortionLayer *layer; /* Couche première de portions */ + GBinPortion *portions; /* Couche première de portions */ GdkRectangle area; /* Surface du composant */ GTK_WIDGET_CLASS(gtk_binary_strip_parent_class)->size_allocate(widget, allocation); @@ -222,17 +222,17 @@ static void gtk_binary_strip_size_allocate(GtkWidget *widget, GtkAllocation *all return; format = g_loaded_binary_get_format(strip->binary); - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); area.x = 0; area.y = 0; area.width = allocation->width; area.height = allocation->height; - if (!g_portion_layer_get_pos_from_addr(layer, &strip->cursor_addr, &area, &strip->cursor_pos)) + if (!get_binary_portion_pos_from_addr(portions, &strip->cursor_addr, &area, &strip->cursor_pos)) strip->cursor_pos = 0; - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); } @@ -257,7 +257,7 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto gint height; /* Hauteur du composant */ GtkBinaryStrip *strip; /* Autre version du composant */ GExeFormat *format; /* Format du binaire */ - GPortionLayer *layer; /* Couche première de portions */ + GBinPortion *portions; /* Couche première de portions */ GdkRectangle area; /* Surface du composant */ vmpa2t addr; /* Adresse à sélectionner */ @@ -272,14 +272,14 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto strip = GTK_BINARY_STRIP(widget); format = g_loaded_binary_get_format(strip->binary); - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); area.x = 0; area.y = 0; area.width = width; area.height = height; - if (g_portion_layer_get_addr_from_pos(layer, event->x, &area, &addr)) + if (get_binary_portion_addr_from_pos(portions, event->x, &area, &addr)) { copy_vmpa(&strip->cursor_addr, &addr); strip->cursor_pos = event->x; @@ -290,7 +290,7 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto } - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); return FALSE; @@ -314,10 +314,10 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) { GtkBinaryStrip *strip; /* Autre vision du composant */ + GtkStyleContext *context; /* Contexte du thème actuel */ GExeFormat *format; /* Format du binaire */ - GPortionLayer *layer; /* Couche première de portions */ + GBinPortion *portions; /* Portions de binaire */ GdkRectangle full; /* Taille totale de la surface */ - GtkStyleContext *context; /* Contexte du thème actuel */ GdkRGBA *color; /* Couleur du curseur */ strip = GTK_BINARY_STRIP(widget); @@ -325,21 +325,21 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) if (strip->binary == NULL) return FALSE; + context = gtk_widget_get_style_context(widget); + /* Dessin des portions de binaire */ format = g_loaded_binary_get_format(strip->binary); - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); full.x = 0; full.y = 1; full.width = gtk_widget_get_allocated_width(widget); full.height = gtk_widget_get_allocated_height(widget) - 1; - context = gtk_widget_get_style_context(widget); - - g_portion_layer_draw(layer, context, cr, &full); + g_binary_portion_draw(portions, context, cr, &full); - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); /* Dessin de la position */ @@ -348,8 +348,8 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) { cairo_set_line_width(cr, 1); - gtk_style_context_get(gtk_widget_get_style_context(widget), GTK_STATE_FLAG_NORMAL, - GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color, NULL); + gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, + GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color, NULL); cairo_set_source_rgb(cr, color->red, color->green, color->blue); @@ -395,7 +395,7 @@ static gboolean gtk_binary_strip_query_tooltip(GtkWidget *widget, gint x, gint y gboolean result; /* Bilan à retourner */ GtkBinaryStrip *strip; /* Autre version du composant */ GExeFormat *format; /* Format du binaire */ - GPortionLayer *layer; /* Couches binaires à consulter*/ + GBinPortion *portions; /* Couches binaires à consulter*/ GdkRectangle area; /* Surface du composant */ if (keyboard) return FALSE; @@ -405,16 +405,16 @@ static gboolean gtk_binary_strip_query_tooltip(GtkWidget *widget, gint x, gint y if (strip->binary != NULL) { format = g_loaded_binary_get_format(strip->binary); - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); area.x = 0; area.y = 0; area.width = gtk_widget_get_allocated_width(widget); area.height = gtk_widget_get_allocated_height(widget); - result = g_portion_layer_query_tooltip(layer, x, y, &area, tooltip); + result = query_tooltip_for_binary_portion(portions, x, y, &area, tooltip); - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); } diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index b5dc0e1..dba5145 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -527,7 +527,7 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL GExeFormat *format; /* Format de binaire à traiter */ const mrange_t *range; /* Emplacement d'instruction */ const vmpa2t *addr; /* Localisation de départ */ - GPortionLayer *layer; /* Couche première de portions */ + GBinPortion *portions; /* Couche première de portions */ GBinPortion *portion; /* Zone mémoire d'appartenance */ const char *text; /* Texte au contenu à copier */ GBinSymbol *symbol; /* Symbole présent à l'adresse */ @@ -556,9 +556,9 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL /* Zone d'appartenance */ - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); - portion = g_portion_layer_find_portion_at_addr(layer, addr, (GdkRectangle []) { }); + portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { }); text = g_binary_portion_get_desc(portion); @@ -567,7 +567,9 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL else info->segment = strdup(_("Binary")); - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portion)); + + g_object_unref(G_OBJECT(portions)); /* Adresses de base */ diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index b8631b6..38a17a2 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -465,7 +465,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin GArchProcessor *proc; /* Architecture du binaire */ MemoryDataSize msize; /* Taille par défaut */ GExeFormat *format; /* Format de travail */ - GPortionLayer *layer; /* Couche première de portions */ + GBinPortion *portions; /* Couche première de portions */ GBinContent *content; /* Contenu binaire en mémoire */ size_t count; /* Nombre des chaînes */ GBinSymbol **symbols; /* Liste des chaînes trouvées */ @@ -505,7 +505,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin g_object_unref(G_OBJECT(proc)); format = g_loaded_binary_get_format(binary); - layer = g_exe_format_get_main_layer(format); + portions = g_exe_format_get_portions(format); content = g_binary_format_get_content(G_BIN_FORMAT(format)); symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count); @@ -520,8 +520,9 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin vmpa2_phys_to_string(addr, msize, phys, NULL); vmpa2_virt_to_string(addr, msize, virt, NULL); - portion = g_portion_layer_find_portion_at_addr(layer, addr, (GdkRectangle []) { }); + portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { }); area = g_binary_portion_get_desc(portion); + g_object_unref(G_OBJECT(portion)); label = g_binary_symbol_get_label(symbols[i]); @@ -562,7 +563,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin } g_object_unref(G_OBJECT(content)); - g_object_unref(G_OBJECT(layer)); + g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); } -- cgit v0.11.2-87-g4458