diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-05-05 21:58:46 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-05-05 21:59:01 (GMT) |
commit | a66f854ce4e19dc0f772fc55a3899643252afa3d (patch) | |
tree | 52e46f77acc199904a73e2260117a3a5198aeb86 /src | |
parent | 07768223823d8c2b0071be8d8e6dfc5ccb891b17 (diff) |
Inserted preloaded format information from instructions instead of symbols.
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/db/items/comment.c | 2 | ||||
-rw-r--r-- | src/analysis/db/items/comment.h | 2 | ||||
-rw-r--r-- | src/analysis/disass/area.c | 354 | ||||
-rw-r--r-- | src/analysis/disass/area.h | 7 | ||||
-rw-r--r-- | src/analysis/disass/disassembler.c | 4 | ||||
-rw-r--r-- | src/analysis/disass/fetch.c | 4 | ||||
-rw-r--r-- | src/analysis/disass/output.c | 75 | ||||
-rw-r--r-- | src/analysis/disass/output.h | 3 | ||||
-rw-r--r-- | src/arch/arm/v7/fetch.c | 81 | ||||
-rw-r--r-- | src/arch/context-int.h | 7 | ||||
-rw-r--r-- | src/arch/context.c | 2 | ||||
-rw-r--r-- | src/arch/instruction.c | 10 | ||||
-rw-r--r-- | src/arch/instruction.h | 4 | ||||
-rw-r--r-- | src/common/array.c | 61 | ||||
-rw-r--r-- | src/common/array.h | 4 | ||||
-rw-r--r-- | src/format/Makefile.am | 2 | ||||
-rw-r--r-- | src/format/format.c | 6 | ||||
-rw-r--r-- | src/format/format.h | 3 | ||||
-rw-r--r-- | src/format/preload-int.h | 54 | ||||
-rw-r--r-- | src/format/preload.c | 534 | ||||
-rw-r--r-- | src/format/preload.h | 98 | ||||
-rw-r--r-- | src/plugins/pglist.h | 3 | ||||
-rw-r--r-- | src/plugins/plugin-def.h | 3 | ||||
-rw-r--r-- | src/plugins/plugin-int.h | 5 | ||||
-rw-r--r-- | src/plugins/plugin.c | 29 | ||||
-rw-r--r-- | src/plugins/plugin.h | 4 |
26 files changed, 1153 insertions, 208 deletions
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index beec629..3e1c06f 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -1095,7 +1095,7 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si * * ******************************************************************************/ -const vmpa2t *g_db_comment_get_address(GDbComment *comment) +const vmpa2t *g_db_comment_get_address(const GDbComment *comment) { return &comment->addr; diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index ee68491..9fdfa32 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -64,7 +64,7 @@ GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, bool); GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *, bool); /* Fournit l'adresse associée à un commentaire. */ -const vmpa2t *g_db_comment_get_address(GDbComment *); +const vmpa2t *g_db_comment_get_address(const GDbComment *); /* Fournit le commentaire associé à un commentaire. */ char *g_db_comment_get_text(GDbComment *); diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 5dab3ab..130a7f0 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -96,6 +96,8 @@ static void fill_mem_area(mem_area *, mem_area *, size_t, GProcContext *, GtkSta /* Rassemble les instructions conservées dans une zone donnée. */ static GArchInstruction **get_instructions_from_mem_area(const mem_area *, GArchInstruction **, size_t *); +/* Insère une instruction dans un découpage en aires. */ +static void insert_extra_instr_into_mem_areas(mem_area *, size_t, GArchInstruction *); /* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */ @@ -123,7 +125,7 @@ typedef struct _GAreaCollector { struct { - size_t acount; /* Nombre de zones créées */ + size_t created; /* Nombre de zones créées */ GLoadedBinary *binary; /* Binaire à associer aux zones*/ @@ -136,6 +138,17 @@ typedef struct _GAreaCollector struct { + size_t available; /* Nombre de zones créées */ + + GPreloadInfo *info; /* Préchargements à intégrer */ + + size_t start; /* Départ des intégrations */ + size_t stop; /* Fin des intégrations */ + + }; + + struct + { size_t begin; /* Début du parcours à mener */ size_t end; /* Fin de ce même parcours */ @@ -180,6 +193,12 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t, GLoadedBinary * /* Construit une liste bornée de zones contigües. */ static void g_area_collector_do_compute(GAreaCollector *, GtkStatusStack *); +/* Crée une tâche de calcul des zones binaires à remplir. */ +static GAreaCollector *g_area_collector_new_insert(activity_id_t, mem_area *, size_t, GPreloadInfo *, size_t, size_t); + +/* Insère dans les zones contigües les instructions préchargées. */ +static void g_area_collector_do_insert(GAreaCollector *, GtkStatusStack *); + /* Crée une tâche de récupération d'instructions différée. */ static GAreaCollector *g_area_collector_new_outro(activity_id_t, mem_area *, size_t, size_t); @@ -388,12 +407,19 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction if (old != NULL) { g_object_unref(G_OBJECT(old)); - area->instructions[offset + 1] = NULL; + area->instructions[offset + i] = NULL; g_atomic_pointer_add(&area->count, -1); } } +#ifndef NDEBUG + + for (i = 0; i < len; i++) + assert(area->instructions[offset + i] == NULL); + +#endif + area->instructions[offset] = instr; g_atomic_pointer_add(&area->count, 1); @@ -593,10 +619,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc bool done; /* Enregistrement effectué ? */ - vmpa2t sym_addr; /* Adresse de nouveau symbole */ - bool has_new_sym; /* Statut d'un dépilement */ - - GBinSymbol *symbol; /* Symbole créé en parallèle */ + GArchInstruction *extra; /* Instruction supplémentaire */ @@ -679,18 +702,11 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc /* Insertion des symboles découverts en parallèle */ - for (has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr); - has_new_sym; - has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr)) + for (extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx)); + extra != NULL; + extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx))) { - has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol); - - if (has_new_sym) - { - insert_extra_symbol_into_mem_areas(list, count, symbol); - g_object_unref(G_OBJECT(symbol)); - } - + insert_extra_instr_into_mem_areas(list, count, extra); } /* Rupture du flot d'exécution ? */ @@ -932,11 +948,11 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a /****************************************************************************** * * -* Paramètres : areas = liste de zones délimitant des contenus à traiter. * -* count = nombre de zones à disposition. * -* symbol = élément nouveau à venir insérer dans les zones. * +* Paramètres : areas = liste de zones délimitant des contenus à traiter. * +* count = nombre de zones à disposition. * +* instr = nouvelle instruction à venir insérer dans les zones. * * * -* Description : Insère un symbole dans un découpage en aires. * +* Description : Insère une instruction dans un découpage en aires. * * * * Retour : - * * * @@ -944,22 +960,16 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a * * ******************************************************************************/ -void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBinSymbol *symbol) +static void insert_extra_instr_into_mem_areas(mem_area *areas, size_t count, GArchInstruction *instr) { - SymbolType type; /* Type de symbole */ - GArchInstruction *instr; /* Instruction à insérer */ const mrange_t *range; /* Emplacement d'instruction */ const vmpa2t *addr; /* Départ de cet emplacement */ mem_area *area; /* Zone d'accueil désignée */ VMPA_BUFFER(loc); /* Description d'un emplacement*/ phys_t start; /* Point de départ */ - - type = g_binary_symbol_get_target_type(symbol); - - if (!HAS_DATA_INSTR(type)) - return; - - instr = g_binary_symbol_get_instruction(symbol); +#ifndef NDEBUG + bool status; /* Validation d'une insertion */ +#endif range = g_arch_instruction_get_range(instr); addr = get_mrange_addr(range); @@ -972,13 +982,13 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi { vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); - log_variadic_message(LMT_WARNING, _("No place found for symbol located at %s."), loc); - return; + log_variadic_message(LMT_WARNING, _("No place found for an instruction located at %s."), loc); + goto ieiima_failed; } /** - * Un symbole (au sens large) ne peut avoir une adresse virtuelle que s'il + * Une instruction ne peut avoir une adresse virtuelle que s'il * est compris dans une zone chargée en mémoire (en toute logique). */ assert(has_virt_addr(get_mrange_addr(&area->range)) == has_virt_addr(addr)); @@ -991,16 +1001,25 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi { vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); - log_variadic_message(LMT_WARNING, _("The symbol located at %s is too big for one place only."), loc); - return; + log_variadic_message(LMT_WARNING, _("The instruction located at %s is too big for one place only."), loc); + goto ieiima_failed; } - /* Inscription d'une instruction de symbole (sans retour arrière possible :/ ) */ + /* Inscription d'une instruction (sans retour arrière possible :/ ) */ +#ifndef NDEBUG + status = mark_range_in_mem_area_as_processed(area, instr, true); + assert(status); +#else mark_range_in_mem_area_as_processed(area, instr, true); +#endif + + return; - g_object_ref(G_OBJECT(instr)); + ieiima_failed: + + g_object_unref(G_OBJECT(instr)); } @@ -1106,6 +1125,9 @@ static void g_area_collector_dispose(GAreaCollector *collector) if (collector->run == (run_task_fc)g_area_collector_do_compute) g_object_unref(G_OBJECT(collector->binary)); + else if (collector->run == (run_task_fc)g_area_collector_do_insert) + g_object_unref(G_OBJECT(collector->info)); + G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector)); } @@ -1160,6 +1182,7 @@ static void g_area_collector_process(GAreaCollector *collector, GtkStatusStack * * * * Paramètres : id = identifiant pour signaler la progression courante. * * binary = binaire chargé à conserver dans les zones définies.* +* info = préchargements effectués via le format binaire. * * first = localisation du début de la portion à traiter. * * last = localisation de la fin de la portion à traiter. * * closing = indique si la tâche doit terminer l'analyse. * @@ -1183,7 +1206,7 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t id, GLoadedBinar result->areas = NULL; - result->acount = 0; + result->created = 0; result->binary = binary; g_object_ref(G_OBJECT(binary)); @@ -1220,60 +1243,8 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac GExeFormat *format; /* Format du binaire */ vmpa2t prev; /* Dernière bordure rencontrée */ bool state; /* Bilan d'une conversion */ - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ - bool has_sym_index; /* Détermine une validité */ - size_t sym_index; /* Prochain symbole non traité */ GBinPortion *portions; /* Couche première de portions */ - void populate_with_symbols(const vmpa2t *limit) - { - GBinSymbol *symbol; /* Symbole en cours d'analyse */ - SymbolType type; /* Nature d'un symbole */ - const mrange_t *range; /* Couverture d'un symbole */ - vmpa2t end; /* Adresse de fin du symbole */ - - for (; sym_index < sym_count; sym_index++) - { - symbol = symbols[sym_index]; - - type = g_binary_symbol_get_target_type(symbol); - - /** - * On ne garde que les symboles renvoyant directement une ou - * plusieurs instructions, c'est à dire les symboles valides - * pour un appel à g_binary_symbol_get_instruction(). - * - * Les instructions des autres symboles sont obtenues et mises - * en place durant la procédure de désassemblage. - */ - - if (type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_CODE_LABEL) - continue; - - range = g_binary_symbol_get_range(symbol); - - if (get_mrange_length(range) == 0) - continue; - - if (cmp_vmpa(get_mrange_addr(range), limit) >= 0) - break; - - compute_mrange_end_addr(range, &end); - - /** - * Si un symbole est à cheval entre deux zones, tant pis pour lui ! - */ - - if (cmp_vmpa(&end, limit) > 0) - break; - - insert_extra_symbol_into_mem_areas(*list, *count, symbol); - - } - - } - void fill_gap(vmpa2t *old, vmpa2t *new, bool alloc, bool exec) { phys_t diff; /* Espace entre bordures */ @@ -1300,24 +1271,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac init_mem_area_from_addr(area, old, diff, collector->binary); area->is_exec = exec; - /* Insertion des symboles existants */ - - if (!has_sym_index) - { - int cmp_vmpa_with_symbol(const vmpa2t *a, const GBinSymbol **s) - { - return g_binary_symbol_cmp_with_vmpa(*s, a); - } - - bsearch_index(old, symbols, sym_count, sizeof(GBinSymbol *), - (__compar_fn_t)cmp_vmpa_with_symbol, &sym_index); - - has_sym_index = true; - - } - - populate_with_symbols(new); - /* Avancée du curseur */ copy_vmpa(old, new); @@ -1423,7 +1376,7 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac } list = &collector->areas; - count = &collector->acount; + count = &collector->created; init_vmpa(&first, collector->first, VMPA_NO_VIRTUAL); init_vmpa(&last, collector->last, VMPA_NO_VIRTUAL); @@ -1437,10 +1390,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac g_exe_format_translate_offset_into_vmpa(format, 0, &prev); #endif - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); - - has_sym_index = false; - portions = g_exe_format_get_portions(format); g_binary_portion_visit(portions, (visit_portion_fc)build_area_from_portion, NULL); @@ -1518,10 +1467,10 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB for (i = 0; i < runs_count; i++) { - result = (mem_area *)realloc(result, (*count + collectors[i]->acount) * sizeof(mem_area)); + result = (mem_area *)realloc(result, (*count + collectors[i]->created) * sizeof(mem_area)); - memcpy(&result[*count], collectors[i]->areas, collectors[i]->acount * sizeof(mem_area)); - *count += collectors[i]->acount; + memcpy(&result[*count], collectors[i]->areas, collectors[i]->created * sizeof(mem_area)); + *count += collectors[i]->created; g_object_unref(G_OBJECT(collectors[i])); @@ -1540,6 +1489,177 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB /****************************************************************************** * * +* Paramètres : id = identifiant pour signaler la progression. * +* areas = liste des zones en place à parcourir. * +* available = nombre de zones disponibles pour les traitements.* +* info = préchargements effectués via le format binaire. * +* start = indice de la première instruction à insérer. * +* stop = indice de la première instruction à ignorer. * +* * +* Description : Crée une tâche de calcul des zones binaires à remplir. * +* * +* Retour : Tâche créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GAreaCollector *g_area_collector_new_insert(activity_id_t id, mem_area *areas, size_t available, GPreloadInfo *info, size_t start, size_t stop) +{ + GAreaCollector *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_AREA_COLLECTOR, NULL); + + result->id = id; + result->run = (run_task_fc)g_area_collector_do_insert; + + result->areas = areas; + + result->available = available; + + result->info = info; + g_object_ref(G_OBJECT(info)); + + result->start = start; + result->stop = stop; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : fetching = récupération à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Insère dans les zones contigües les instructions préchargées.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack *status) +{ + mem_area *area; /* Zone d'appartenance */ + size_t i; /* Boucle de parcours */ + GArchInstruction *instr; /* Instruction à analyser */ + const mrange_t *range; /* Emplacement d'instruction */ + const vmpa2t *addr; /* Localisation précise */ +#ifndef NDEBUG + bool inserted; /* Validation d'une insertion */ +#endif + + area = NULL; + + for (i = collector->start; i < collector->stop; i++) + { + instr = _g_preload_info_get_instruction(collector->info, i); + range = g_arch_instruction_get_range(instr); + addr = get_mrange_addr(range); + + if (area != NULL) + { + if (!mrange_contains_addr(&area->range, addr)) + area = NULL; + } + + if (area == NULL) + area = find_memory_area_by_addr(collector->areas, collector->available, addr); + + assert(area != NULL); + +#ifndef NDEBUG + inserted = mark_range_in_mem_area_as_processed(area, instr, false); + assert(inserted); +#else + mark_range_in_mem_area_as_processed(area, instr, false); +#endif + + gtk_status_stack_update_activity_value(status, collector->id, 1); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : gid = groupe de travail impliqué. * +* status = barre de statut à tenir informée. * +* area = nombre de zones mises en place. * +* count = quantité de ces zones. * +* info = préchargements effectués via le format binaire. * +* * +* Description : Intègre toutes les instructions préchargées dans des zones. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void populate_fresh_memory_areas(wgroup_id_t gid, GtkStatusStack *status, mem_area *areas, size_t count, GPreloadInfo *info) +{ + size_t icount; /* Quantité d'instructions */ + guint runs_count; /* Qté d'exécutions parallèles */ + GAreaCollector **collectors; /* Collecteurs à suivre */ + phys_t run_size; /* Volume réparti par exécution*/ + GWorkQueue *queue; /* Gestionnaire de différés */ + activity_id_t id; /* Identifiant de progression */ + guint i; /* Boucle de parcours */ + size_t start; /* Premier indice à traiter */ + size_t stop; /* Premier indice à ignorer */ + + g_preload_info_lock_instructions(info); + + icount = _g_preload_info_count_instructions(info); + + runs_count = g_get_num_processors(); + + collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *)); + + run_size = icount / runs_count; + + queue = get_work_queue(); + + id = gtk_status_stack_add_activity(status, _("Inserting all preloaded instructions"), icount); + + for (i = 0; i < runs_count; i++) + { + start = i * run_size; + + if ((i + 1) == runs_count) + stop = icount; + else + stop = start + run_size; + + collectors[i] = g_area_collector_new_insert(id, areas, count, info, start, stop); + + g_object_ref(G_OBJECT(collectors[i])); + g_work_queue_schedule_work(queue, G_DELAYED_WORK(collectors[i]), gid); + + } + + g_work_queue_wait_for_completion(queue, gid); + + /* Fin */ + + free(collectors); + + _g_preload_info_drain_instructions(info); + + g_preload_info_unlock_instructions(info); + + gtk_status_stack_remove_activity(status, id); + +} + + +/****************************************************************************** +* * * Paramètres : id = identifiant pour signaler la progression courante. * * list = liste des zones en place à parcourir. * * begin = indice de la première zone à traiter. * diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h index 173f4be..5ee71a3 100644 --- a/src/analysis/disass/area.h +++ b/src/analysis/disass/area.h @@ -27,6 +27,7 @@ #include "../binary.h" #include "../../arch/instruction.h" +#include "../../format/preload.h" #include "../../format/symbol.h" #include "../../glibext/delayed.h" #include "../../gtkext/gtkstatusstack.h" @@ -46,9 +47,6 @@ void load_code_from_mem_area(mem_area *, mem_area *, size_t, GProcContext *, con /* 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. */ -void insert_extra_symbol_into_mem_areas(mem_area *, size_t, const GBinSymbol *); - /* S'assure que l'ensemble des aires est entièrement décodé. */ void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStatusStack *, activity_id_t); @@ -59,6 +57,9 @@ void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStat /* Détermine une liste de zones contigües à traiter. */ mem_area *collect_memory_areas(wgroup_id_t, GtkStatusStack *, GLoadedBinary *, phys_t, size_t *); +/* Intègre toutes les instructions préchargées dans des zones. */ +void populate_fresh_memory_areas(wgroup_id_t, GtkStatusStack *, mem_area *, size_t, GPreloadInfo *); + /* 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 c9aa472..0ffcccd 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -409,8 +409,6 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus - - /* Première étape */ //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); @@ -576,7 +574,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus - print_disassembled_instructions(disass->cache, disass->lang, disass->binary, status); + print_disassembled_instructions(disass->cache, disass->lang, disass->binary, G_PRELOAD_INFO(ctx), status); diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 211ed31..c5489d6 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -417,6 +417,8 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex template.areas = collect_memory_areas(gid, status, binary, length, &template.count); + populate_fresh_memory_areas(gid, status, template.areas, template.count, G_PRELOAD_INFO(ctx)); + template.status = status; /* Amorce des traitements */ @@ -443,7 +445,7 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex _("Disassembling following the execution flow..."), length); - g_binary_format_setup_disassembling_context(format, template.ctx); + g_binary_format_setup_disassembling_context(format, template.ctx, status); g_work_queue_wait_for_completion(queue, gid); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index fcbc0c6..5a74d92 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -38,6 +38,7 @@ * Paramètres : cache = tampon de récueil des résultats d'impression. * * lang = langage de haut niveau préféré pour l'impression. * * binary = tampon de récueil des résultats d'impression. * +* info = informations complémentaires à intégrer. * * status = barre de statut avec progression à mettre à jour. * * * * Description : Transcrit du code désassemblé en texte humainement lisible. * @@ -48,7 +49,7 @@ * * ******************************************************************************/ -void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GLoadedBinary *binary, GtkStatusStack *status) +void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GLoadedBinary *binary, GPreloadInfo *info, GtkStatusStack *status) { GExeFormat *format; /* Format associé au binaire */ GArchProcessor *proc; /* Processeur de l'architecture*/ @@ -64,6 +65,11 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, size_t count; /* Nombre total d'instructions */ activity_id_t id; /* Identifiant de progression */ bool expect_outro; /* Fin de zone de code définie */ + + + GDbComment *comment; /* Commentaire à ajouter */ + const vmpa2t *caddr; /* Localisation du commentaire */ + size_t i; /* Boucle de parcours */ GArchInstruction *instr; /* Instruction à traiter */ const vmpa2t *iaddr; /* Adresse d'instruction */ @@ -78,7 +84,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, BufferLineFlags flags; /* Propriétés pour la ligne */ //mrange_t range; /* Couverture sans surface */ - GDbComment *comment; /* Commentaire à ajouter */ + GDbComment *_comment; /* Commentaire à ajouter */ @@ -131,6 +137,20 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, expect_outro = false; + comment = g_preload_info_pop_comment(info); + + if (comment != NULL) + caddr = g_db_comment_get_address(comment); + + + /* + if (comment != NULL) + log_variadic_message(LMT_BAD_BINARY, + _("Got comment '%s' @ 0x%08x"), + g_db_comment_get_text(comment), get_phy_addr(caddr)); + */ + + for (i = 0; i < count; i++) { instr = g_arch_processor_get_instruction(proc, i); @@ -184,7 +204,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, { log_variadic_message(LMT_BAD_BINARY, _("Unable to find a proper location for symbol '%s' @ 0x%08x"), - g_binary_symbol_get_label(symbols[sym_index]), get_virt_addr(saddr)); + g_binary_symbol_get_label(symbols[sym_index]), get_phy_addr(saddr)); _missing++; @@ -261,18 +281,61 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, g_buffer_cache_append(cache, G_LINE_GENERATOR(instr), flags); + + + ////////////////////////////////// if (compared == 0) { /* Commentaire ? */ - comment = g_binary_symbol_get_comment(symbols[sym_index]); + _comment = g_binary_symbol_get_comment(symbols[sym_index]); - if (comment != NULL) - g_db_item_apply(G_DB_ITEM(comment), binary); + if (_comment != NULL) + g_db_item_apply(G_DB_ITEM(_comment), binary); sym_index++; } + /////////////////////////////////////// + + + + /* Commentaire en bout de ligne ? */ + + if (comment != NULL) + { + compared = cmp_vmpa(iaddr, caddr); + + if (compared == 0) + { + if (g_loaded_binary_add_to_collection(binary, G_DB_ITEM(comment))) + g_db_item_apply(G_DB_ITEM(comment), binary); + + else + g_object_unref(G_OBJECT(comment)); + + } + + else if (compared > 0) + { + log_variadic_message(LMT_BAD_BINARY, + _("Unable to find a proper location for comment '%s' @ 0x%08x"), + g_db_comment_get_text(comment), get_phy_addr(caddr)); + + g_object_unref(G_OBJECT(comment)); + + } + + if (compared >= 0) + { + comment = g_preload_info_pop_comment(info); + + if (comment != NULL) + caddr = g_db_comment_get_address(comment); + + } + + } g_object_unref(G_OBJECT(instr)); diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h index 7a4cf8f..a05a3c4 100644 --- a/src/analysis/disass/output.h +++ b/src/analysis/disass/output.h @@ -27,13 +27,14 @@ #include "../binary.h" #include "../human/lang.h" +#include "../../format/preload.h" #include "../../glibext/gbuffercache.h" #include "../../gtkext/gtkstatusstack.h" /* Transcrit du code désassemblé en texte humainement lisible. */ -void print_disassembled_instructions(GBufferCache *, GCodingLanguage *, GLoadedBinary *, GtkStatusStack *); +void print_disassembled_instructions(GBufferCache *, GCodingLanguage *, GLoadedBinary *, GPreloadInfo *, GtkStatusStack *); diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c index 11864f6..788d7ab 100644 --- a/src/arch/arm/v7/fetch.c +++ b/src/arch/arm/v7/fetch.c @@ -25,7 +25,7 @@ #include <assert.h> -#include <malloc.h> +#include <stdio.h> #include <i18n.h> @@ -36,6 +36,7 @@ #include "../../raw.h" #include "../../sharing/container.h" #include "../../../format/format.h" +#include "../../../format/preload.h" @@ -361,18 +362,15 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst uint32_t offset; /* Décallage encodé en dur */ bool ret; /* Bilan d'une récupération */ off_t val_offset; /* Position de valeur à lire */ - vmpa2t sym_addr; /* Adresse de nouveau symbole */ + vmpa2t loaded_addr; /* Adresse de valeur chargée */ + mrange_t loaded_range; /* Espace de chargement */ GBinContent *content; /* Contenu binaire à relire */ uint32_t target; /* Adresse virtuelle visée */ vmpa2t pos; /* Tête de lecture de valeur */ - mrange_t sym_range; /* Espace du nouveau symbole */ VMPA_BUFFER(loc); /* Adresse au format texte */ - size_t name_len; /* Taille de nomination finale */ - char *name; /* Désignation humaine */ - GArchInstruction *sym_instr; /* Instruction de symbole */ - GBinSymbol *symbol; /* Nouveau symbole construit */ + GArchInstruction *loaded; /* Instruction de valeur */ + char *desc; /* Description d'accompagnement*/ GDbComment *comment; /* Définition de commentaire */ - bool added; /* Bilan de l'insertion */ GArchOperand *new; /* Instruction de ciblage */ /* Récupération de l'adresse visée par le chargement */ @@ -410,32 +408,24 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst return; } - /* Transformations et conservation d'une position de symbole */ + /* Transformations et conservation d'une position de chargement */ val_offset = phys_pc + offset; - if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &sym_addr)) + if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &loaded_addr)) { assert(0); g_arch_instruction_unlock_operands(instr); return; } - //init_vmpa(&sym_addr, val_offset, VMPA_NO_VIRTUAL); - init_mrange(&sym_range, &sym_addr, 4); - - - - - - - + init_mrange(&loaded_range, &loaded_addr, 4); /* Lecture de la valeur vers laquelle renvoyer */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); - copy_vmpa(&pos, &sym_addr); + copy_vmpa(&pos, &loaded_addr); ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE /* FIXME */, &target); g_object_unref(G_OBJECT(content)); @@ -446,55 +436,24 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst return; } - /* Réalise l'intégration du symbole associé */ + /* Réalise l'intégration de la valeur chargée */ - sym_instr = g_raw_instruction_new_from_value(&sym_addr, MDS_32_BITS_UNSIGNED, target); + copy_vmpa(&pos, &loaded_addr); - name_len = strlen(_("Value used @ %s")) + VMPA_MAX_LEN + 1; + loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target); - name = (char *)calloc(name_len, sizeof(char)); + g_preload_info_add_instruction(G_PRELOAD_INFO(context), loaded); vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); - snprintf(name, name_len, _("Value used @ %s"), loc); - - added = ADD_RAW_AS_SYM(G_BIN_FORMAT(format), symbol, sym_instr, comment, name); - - free(name); - - - - if (added) - g_proc_context_push_new_symbol_at(G_PROC_CONTEXT(context), &sym_addr); - - - - //g_proc_context_push_new_symbol_at(context, &sym_addr); - - - - - - - - - - - - - - - - - - - //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target, G_SHARE_CONTAINER(instr)); - + asprintf(&desc, _("Value used @ %s"), loc); - /// FIXME ?! - //if (target < 0x8000) return; + comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false); + g_db_comment_add_static_text(comment, desc); + g_db_item_set_volatile(G_DB_ITEM(comment), true); - //if (target > 0x6966c) return; + g_preload_info_add_comment(G_PRELOAD_INFO(context), comment); + /* Mise à jour de l'affichage et conclusion */ new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target); _g_arch_instruction_replace_operand(instr, op, new); diff --git a/src/arch/context-int.h b/src/arch/context-int.h index 4e188cc..3a5c7ee 100644 --- a/src/arch/context-int.h +++ b/src/arch/context-int.h @@ -31,6 +31,9 @@ #include <stdarg.h> +#include "../format/preload-int.h" + + /* Granularité des allocations */ #define DP_ALLOC_BLOCK 10 @@ -43,7 +46,7 @@ typedef void (* push_drop_point_fc) (GProcContext *, DisassPriorityLevel, virt_t /* Définition d'un contexte pour processeur (instance) */ struct _GProcContext { - GObject parent; /* A laisser en premier */ + GPreloadInfo parent; /* A laisser en premier */ virt_t *drop_points[DPL_COUNT]; /* Liste de points de départ */ size_t dp_allocated[DPL_COUNT]; /* Taille de liste allouée */ @@ -67,7 +70,7 @@ struct _GProcContext /* Définition d'un contexte pour processeur (classe) */ struct _GProcContextClass { - GObjectClass parent; /* A laisser en premier */ + GPreloadInfoClass parent; /* A laisser en premier */ push_drop_point_fc push_point; /* Inclusion de points de chute*/ diff --git a/src/arch/context.c b/src/arch/context.c index ddb74fd..c7a59da 100644 --- a/src/arch/context.c +++ b/src/arch/context.c @@ -55,7 +55,7 @@ static void _g_proc_context_push_drop_point(GProcContext *, DisassPriorityLevel, /* Indique le type définit par la GLib pour le contexte de processeur. */ -G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT); +G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_PRELOAD_INFO); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index a9bc4f2..807bbbb 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -463,7 +463,7 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchReg * * * Paramètres : instr = instruction à mettre à jour. * * * -* Description : Verrouille les accès la liste des opérandes. * +* Description : Verrouille les accès à la liste des opérandes. * * * * Retour : - * * * @@ -482,7 +482,7 @@ void g_arch_instruction_lock_operands(GArchInstruction *instr) * * * Paramètres : instr = instruction à mettre à jour. * * * -* Description : Déverrouille les accès la liste des opérandes. * +* Description : Déverrouille les accès à la liste des opérandes. * * * * Retour : - * * * @@ -546,12 +546,12 @@ size_t _g_arch_instruction_count_operands(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* index = indice de l'opérande concernée. * +* Paramètres : instr = instance à consulter. * +* index = indice de l'opérande concerné. * * * * Description : Fournit un opérande donné d'une instruction. * * * -* Retour : Opérande trouvée ou NULL si aucune. * +* Retour : Opérande trouvée. * * * * Remarques : - * * * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 55c845e..64b8dd5 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -131,10 +131,10 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister /* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ -/* Verrouille les accès la liste des opérandes. */ +/* Verrouille les accès à la liste des opérandes. */ void g_arch_instruction_lock_operands(GArchInstruction *); -/* Déverrouille les accès la liste des opérandes. */ +/* Déverrouille les accès à la liste des opérandes. */ void g_arch_instruction_unlock_operands(GArchInstruction *); /* Attache un opérande supplémentaire à une instruction. */ diff --git a/src/common/array.c b/src/common/array.c index 641a885..e4e7bb1 100644 --- a/src/common/array.c +++ b/src/common/array.c @@ -34,6 +34,9 @@ #include <string.h> +#include "sort.h" + + /** * L'expression du besoin d'une gestion optimisée des tableaux se base sur la @@ -259,6 +262,64 @@ void add_item_to_flat_array(flat_array_t **array, const void *item, size_t size) /****************************************************************************** * * +* Paramètres : array = tableau compressé à mettre à jour. [OUT] * +* item = adresse de l'élément à rajouter. * +* size = taille de ce nouvel élément. * +* compar = méthode de comparaison entre éléments. * +* * +* Description : Ajoute un élément supplémentaire à un tableau trié. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void insert_item_into_flat_array(flat_array_t **array, void *item, size_t size, __compar_fn_t compar) +{ + ext_flat_array_t *extended; /* Version de tableau étendue */ + + assert(FLAT_ARRAY_IS_LOCKED(*array)); + + if (FLAT_ARRAY_IS_EMPTY(*array)) + { + *array = malloc(size); + memcpy(*array, item, size); + + lock_flat_array(array); + + } + + else + { + if (FLAT_ARRAY_HAS_NO_INDEX(*array)) + { + extended = (ext_flat_array_t *)malloc(sizeof(ext_flat_array_t)); + + extended->items = malloc(size); + extended->count = 1; + + memcpy(extended->items, GET_LONELY_ITEM(*array), size); + + FLAT_ARRAY_SET_INDEX(extended); + + *array = (flat_array_t *)extended; + + lock_flat_array(array); + + } + + extended = EXTENDED_ARRAY(*array); + + extended->items = qinsert(extended->items, &extended->count, size, compar, item); + + } + +} + + +/****************************************************************************** +* * * Paramètres : array = tableau compressé à mettre à jour. * * index = indice de l'élément à remplacer. * * new = adresse de l'élément à rajouter. * diff --git a/src/common/array.h b/src/common/array.h index 416800d..2dd5b9f 100644 --- a/src/common/array.h +++ b/src/common/array.h @@ -25,6 +25,7 @@ #define _COMMON_ARRAY_H +#include <stdlib.h> #include <sys/types.h> @@ -45,6 +46,9 @@ size_t count_flat_array_items(const flat_array_t *); /* Ajoute un élément supplémentaire à un tableau. */ void add_item_to_flat_array(flat_array_t **, const void *, size_t); +/* Ajoute un élément supplémentaire à un tableau trié. */ +void insert_item_into_flat_array(flat_array_t **, void *, size_t, __compar_fn_t); + /* Remplace un élément d'un tableau compressé par un autre. */ void rpl_item_in_flat_array(flat_array_t *, size_t, void *, size_t); diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 3f18b88..2fef6c6 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -8,6 +8,8 @@ libformat_la_SOURCES = \ executable.h executable.c \ format-int.h \ format.h format.c \ + preload-int.h \ + preload.h preload.c \ symbol.h symbol.c libformat_la_LIBADD = \ diff --git a/src/format/format.c b/src/format/format.c index 978a3d2..11216a2 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -31,6 +31,7 @@ #include "format-int.h" +#include "preload.h" #include "dex/dex.h" #include "dwarf/dwarf.h" #include "elf/elf.h" @@ -247,6 +248,7 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent * * * Paramètres : format = description de l'exécutable à consulter. * * ctx = contexte de désassemblage à préparer. * +* status = barre de statut à tenir informée. * * * * Description : Fournit un contexte initialisé pour un désassemblage. * * * @@ -256,10 +258,12 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent * * ******************************************************************************/ -void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContext *ctx) +void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContext *ctx, GtkStatusStack *status) { size_t i; /* Boucle de parcours */ + preload_binary_format(PGA_FORMAT_PRELOAD, format, G_PRELOAD_INFO(ctx), status); + g_rw_lock_reader_lock(&format->pt_lock); for (i = 0; i < format->ep_count; i++) diff --git a/src/format/format.h b/src/format/format.h index c2ef895..b04f11b 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -34,6 +34,7 @@ #include "../analysis/content.h" #include "../analysis/routine.h" #include "../arch/context.h" +#include "../gtkext/gtkstatusstack.h" @@ -65,7 +66,7 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *); void g_binary_format_register_code_point(GBinFormat *, virt_t, bool); /* Fournit un contexte initialisé pour un désassemblage. */ -void g_binary_format_setup_disassembling_context(GBinFormat *, GProcContext *); +void g_binary_format_setup_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *); /* Ajoute un symbole à la collection du format binaire. */ bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); diff --git a/src/format/preload-int.h b/src/format/preload-int.h new file mode 100644 index 0000000..ccc59e3 --- /dev/null +++ b/src/format/preload-int.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.c - préchargement d'instructions à partir d'un format + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_PRELOAD_INT_H +#define _FORMAT_PRELOAD_INT_H + + +#include "preload.h" + + +#include "../common/array.h" + + + +/* Préchargement d'origine formatée (instance) */ +struct _GPreloadInfo +{ + GObject parent; /* A laisser en premier */ + + flat_array_t *instructions; /* Liste d'instructions */ + flat_array_t *comments; /* Liste de commentaires */ + +}; + +/* Préchargement d'origine formatée (classe) */ +struct _GPreloadInfoClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _FORMAT_PRELOAD_INT_H */ diff --git a/src/format/preload.c b/src/format/preload.c new file mode 100644 index 0000000..145dfd9 --- /dev/null +++ b/src/format/preload.c @@ -0,0 +1,534 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.c - préchargement d'instructions à partir d'un format + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "preload.h" + + +#include "preload-int.h" + + + +/* Initialise la classe des préchargements à partir d'un format. */ +static void g_preload_info_class_init(GPreloadInfoClass *); + +/* Initialise une instance de préchargement à partir de format. */ +static void g_preload_info_init(GPreloadInfo *); + +/* Supprime toutes les références externes. */ +static void g_preload_info_dispose(GPreloadInfo *); + +/* Procède à la libération totale de la mémoire. */ +static void g_preload_info_finalize(GPreloadInfo *); + + + +/* Indique le type défini pour un préchargement à partir d'un format. */ +G_DEFINE_TYPE(GPreloadInfo, g_preload_info, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des préchargements à partir d'un format.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_preload_info_class_init(GPreloadInfoClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_preload_info_dispose; + object->finalize = (GObjectFinalizeFunc)g_preload_info_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à initialiser. * +* * +* Description : Initialise une instance de préchargement à partir de format. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_preload_info_init(GPreloadInfo *info) +{ + info->instructions = NULL; + + info->comments = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_preload_info_dispose(GPreloadInfo *info) +{ + GArchInstruction *instr; /* Instruction à libérer */ + GDbComment *comment; /* Commentaire à libérer */ + + g_preload_info_lock_instructions(info); + + _g_preload_info_drain_instructions(info); + + g_preload_info_unlock_instructions(info); + + g_preload_info_lock_comments(info); + + while (_g_preload_info_count_comments(info) > 0) + { + comment = _g_preload_info_get_comment(info, 0); + + rem_item_from_flat_array(&info->comments, 0, sizeof(GDbComment *)); + + g_object_unref(G_OBJECT(comment)); + + } + + g_preload_info_unlock_comments(info); + + G_OBJECT_CLASS(g_preload_info_parent_class)->dispose(G_OBJECT(info)); + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_preload_info_finalize(GPreloadInfo *info) +{ + G_OBJECT_CLASS(g_preload_info_parent_class)->finalize(G_OBJECT(info)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une nouvelle collecte d'informations préchargées. * +* * +* Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPreloadInfo *g_preload_info_new(void) +{ + GPreloadInfo *result; /* Nouveau preloade à renvoyer */ + + result = g_object_new(G_TYPE_PRELOAD_INFO, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = préchargements à mettre à jour. * +* * +* Description : Verrouille les accès à la liste des instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_lock_instructions(GPreloadInfo *info) +{ + lock_flat_array(&info->instructions); + +} + + +/****************************************************************************** +* * +* Paramètres : info = préchargements à mettre à jour. * +* * +* Description : Déverrouille les accès à la liste des instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_unlock_instructions(GPreloadInfo *info) +{ + unlock_flat_array(&info->instructions); + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à mettre à jour. * +* instr = instruction à venir associer. * +* * +* Description : Ajoute une instruction supplémentaire aux préchargements. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr) +{ + int cmp_instr_by_addr(const GArchInstruction **a, const GArchInstruction **b) + { + const mrange_t *range_a; /* Emplacement pour l'instr. A */ + const mrange_t *range_b; /* Emplacement pour l'instr. B */ + + range_a = g_arch_instruction_get_range(*a); + range_b = g_arch_instruction_get_range(*b); + + return cmp_vmpa(get_mrange_addr(range_a), get_mrange_addr(range_b)); + + } + + g_preload_info_lock_instructions(info); + + insert_item_into_flat_array(&info->instructions, &instr, sizeof(GArchInstruction *), + (__compar_fn_t)cmp_instr_by_addr); + + g_preload_info_unlock_instructions(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à consulter. * +* * +* Description : Indique la quantité d'instructions préchargées disponibles. * +* * +* Retour : Nombre d'instructions attachées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t _g_preload_info_count_instructions(const GPreloadInfo *info) +{ + size_t result; /* Décompte à retourner */ + + result = count_flat_array_items(info->instructions); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à consulter. * +* index = indice de l'instruction concernée. * +* * +* Description : Fournit une instruction préchargée donnée. * +* * +* Retour : Instruction trouvée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *info, size_t index) +{ + GArchInstruction *result; /* Opérande à retourner */ + GArchInstruction **ptr; /* Adresse dans le tableau */ + + ptr = get_flat_array_item(info->instructions, index, sizeof(GArchInstruction *)); + + result = *ptr; + + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à manipuler. * +* * +* Description : Dépile une instruction présente dans les préchargements. * +* * +* Retour : Instruction retirée ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *info) +{ + GArchInstruction *result; /* Instruction à retourner */ + GArchInstruction **ptr; /* Adresse dans le tableau */ + + g_preload_info_lock_instructions(info); + + if (_g_preload_info_count_instructions(info) == 0) + result = NULL; + + else + { + ptr = get_flat_array_item(info->instructions, 0, sizeof(GArchInstruction *)); + result = *ptr; + + rem_item_from_flat_array(&info->instructions, 0, sizeof(GArchInstruction *)); + + } + + g_preload_info_unlock_instructions(info); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à manipuler. * +* * +* Description : Retire des préchargements toutes les instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void _g_preload_info_drain_instructions(GPreloadInfo *info) +{ + GArchInstruction *instr; /* Instruction à libérer */ + + while (_g_preload_info_count_instructions(info) > 0) + { + instr = _g_preload_info_get_instruction(info, 0); + + rem_item_from_flat_array(&info->instructions, 0, sizeof(GArchInstruction *)); + + g_object_unref(G_OBJECT(instr)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : info = préchargements à mettre à jour. * +* * +* Description : Verrouille les accès à la liste des commentaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_lock_comments(GPreloadInfo *info) +{ + lock_flat_array(&info->comments); + +} + + +/****************************************************************************** +* * +* Paramètres : info = préchargements à mettre à jour. * +* * +* Description : Déverrouille les accès à la liste des commentaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_unlock_comments(GPreloadInfo *info) +{ + unlock_flat_array(&info->comments); + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à mettre à jour. * +* comment = commentaire à venir associer. * +* * +* Description : Ajoute un commentaire supplémentaire aux préchargements. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) +{ + int cmp_comment_by_addr(const GDbComment * const *a, const GDbComment * const *b) + { + const vmpa2t *addr_a; /* Position du commentaire A */ + const vmpa2t *addr_b; /* Position du commentaire B */ + + addr_a = g_db_comment_get_address(*a); + addr_b = g_db_comment_get_address(*b); + + return cmp_vmpa(addr_a, addr_b); + + } + + g_preload_info_lock_comments(info); + + insert_item_into_flat_array(&info->comments, &comment, sizeof(GDbComment *), + (__compar_fn_t)cmp_comment_by_addr); + + g_preload_info_unlock_comments(info); + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à consulter. * +* * +* Description : Indique la quantité de commentaires préchargés disponibles. * +* * +* Retour : Nombre de commentaires attachés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t _g_preload_info_count_comments(const GPreloadInfo *info) +{ + size_t result; /* Décompte à retourner */ + + result = count_flat_array_items(info->comments); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à consulter. * +* index = indice de l'instruction concernée. * +* * +* Description : Fournit un commentaire préchargé donné. * +* * +* Retour : Commentaire trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *_g_preload_info_get_comment(const GPreloadInfo *info, size_t index) +{ + GDbComment *result; /* Opérande à retourner */ + GDbComment **ptr; /* Adresse dans le tableau */ + + ptr = get_flat_array_item(info->comments, index, sizeof(GDbComment *)); + + result = *ptr; + + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = instance à manipuler. * +* * +* Description : Dépile un commentaire présent dans les préchargements. * +* * +* Retour : Commentaire retiré ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *g_preload_info_pop_comment(GPreloadInfo *info) +{ + GDbComment *result; /* Instruction à retourner */ + GDbComment **ptr; /* Adresse dans le tableau */ + + g_preload_info_lock_comments(info); + + if (_g_preload_info_count_comments(info) == 0) + result = NULL; + + else + { + ptr = get_flat_array_item(info->comments, 0, sizeof(GDbComment *)); + result = *ptr; + + rem_item_from_flat_array(&info->comments, 0, sizeof(GDbComment *)); + + } + + g_preload_info_unlock_comments(info); + + return result; + +} diff --git a/src/format/preload.h b/src/format/preload.h new file mode 100644 index 0000000..a915462 --- /dev/null +++ b/src/format/preload.h @@ -0,0 +1,98 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.h - prototypes pour le préchargement d'instructions à partir d'un format + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_PRELOAD_H +#define _FORMAT_PRELOAD_H + + +#include <glib-object.h> + + +#include "../analysis/db/items/comment.h" +#include "../arch/instruction.h" + + + +#define G_TYPE_PRELOAD_INFO g_preload_info_get_type() +#define G_PRELOAD_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PRELOAD_INFO, GPreloadInfo)) +#define G_IS_PRELOAD_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PRELOAD_INFO)) +#define G_PRELOAD_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PRELOAD_INFO, GPreloadInfoClass)) +#define G_IS_PRELOAD_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PRELOAD_INFO)) +#define G_PRELOAD_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PRELOAD_INFO, GPreloadInfoClass)) + + +/* Préchargement d'origine formatée (instance) */ +typedef struct _GPreloadInfo GPreloadInfo; + +/* Préchargement d'origine formatée (classe) */ +typedef struct _GPreloadInfoClass GPreloadInfoClass; + + +/* Indique le type défini pour un préchargement à partir d'un format. */ +GType g_preload_info_get_type(void); + +/* Crée une nouvelle collecte d'informations préchargées. */ +GPreloadInfo *g_preload_info_new(void); + +/* Verrouille les accès à la liste des instructions. */ +void g_preload_info_lock_instructions(GPreloadInfo *); + +/* Déverrouille les accès à la liste des instructions. */ +void g_preload_info_unlock_instructions(GPreloadInfo *); + +/* Ajoute une instruction supplémentaire aux préchargements. */ +void g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *); + +/* Indique la quantité d'instructions préchargées disponibles. */ +size_t _g_preload_info_count_instructions(const GPreloadInfo *); + +/* Fournit une instruction préchargée donnée. */ +GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *, size_t); + +/* Dépile une instruction présente dans les préchargements. */ +GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *); + +/* Retire des préchargements toutes les instructions. */ +void _g_preload_info_drain_instructions(GPreloadInfo *); + +/* Verrouille les accès à la liste des commentaires. */ +void g_preload_info_lock_comments(GPreloadInfo *); + +/* Déverrouille les accès à la liste des commentaires. */ +void g_preload_info_unlock_comments(GPreloadInfo *); + +/* Ajoute un commentaire supplémentaire aux préchargements. */ +void g_preload_info_add_comment(GPreloadInfo *, GDbComment *); + +/* Indique la quantité de commentaires préchargés disponibles. */ +size_t _g_preload_info_count_comments(const GPreloadInfo *); + +/* Fournit un commentaire préchargé donné. */ +GDbComment *_g_preload_info_get_comment(const GPreloadInfo *, size_t); + +/* Dépile un commentaire présent dans les préchargements. */ +GDbComment *g_preload_info_pop_comment(GPreloadInfo *); + + + +#endif /* _FORMAT_PRELOAD_H */ diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 53556b3..e085102 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -68,7 +68,8 @@ const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); #define handle_binary_format(a, f, s) \ process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s) - +#define preload_binary_format(a, f, i, s) \ + process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s) /* DPS_DISASSEMBLY */ diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index b0523e1..7344a06 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -122,6 +122,9 @@ typedef enum _PluginAction /* Accompagnement du chargement (fin) */ PGA_FORMAT_LOADER_LAST = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(1), + /* Accompagnement du chargement (fin) */ + PGA_FORMAT_PRELOAD = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(2), + /** * DPC_BINARY_PROCESSING | DPS_DISASSEMBLY */ diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 6f02369..7ccd2a6 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -51,6 +51,9 @@ typedef void (* pg_process_disassembly_fc) (const GPluginModule *, PluginAction, /* Procède à une opération liée au format de fichier uniquement. */ typedef bool (* pg_handle_format) (const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *); +/* Procède à un préchargement de format de fichier. */ +typedef bool (* pg_preload_format) (const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *); + @@ -109,7 +112,7 @@ struct _GPluginModule //pg_format_is_matching is_matching; /* Recherche de correspondance */ pg_handle_format handle_format; /* Manipulation du format */ - + pg_preload_format preload_format; /* Préchargement d'un format */ }; diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 7a5c680..0c287d6 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -279,6 +279,12 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) goto bad_plugin; break; + case PGA_FORMAT_PRELOAD: + if (!load_plugin_symbol(result->module, + "preload_binary_format", &result->preload_format)) + goto bad_plugin; + break; + default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), @@ -509,6 +515,29 @@ bool g_plugin_module_handle_binary_format(const GPluginModule *plugin, PluginAct * * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * +* format = format de binaire à manipuler pendant l'opération. * +* info = informations à constituer en avance de phase. * +* status = barre de statut à tenir informée. * +* * +* Description : Procède à un préchargement de format de fichier. * +* * +* Retour : Bilan de l'exécution du traitement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status) +{ + return plugin->preload_format(plugin, action, format, info, status); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * * binary = binaire dont le contenu est en cours de traitement. * * * * Description : Exécute une action pendant un désassemblage de binaire. * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index e09189d..bc52c93 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -32,6 +32,7 @@ #include "plugin-def.h" #include "../analysis/binary.h" #include "../format/format.h" +#include "../format/preload.h" #include "../gtkext/gtkstatusstack.h" @@ -66,6 +67,9 @@ const plugin_interface *g_plugin_module_get_interface(const GPluginModule *); /* Procède à une opération liée au format de fichier uniquement. */ bool g_plugin_module_handle_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *); +/* Procède à un préchargement de format de fichier. */ +bool g_plugin_module_preload_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *); + /* Exécute une action pendant un désassemblage de binaire. */ void g_plugin_module_process_disassembly_event(const GPluginModule *, PluginAction, GLoadedBinary *); |