From 13be5aa2ac44f7bfc70ee25e7ba20ae2adf58ad5 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 7 May 2017 23:13:00 +0200 Subject: Made the preloading process work as intended. --- ChangeLog | 21 ++++++++++++ src/analysis/disass/area.c | 4 ++- src/analysis/disass/fetch.c | 20 +++++++---- src/analysis/disass/output.c | 55 +++++++++++++++++++----------- src/common/array.c | 58 +++++++++++++++++++++++++++++++ src/common/array.h | 3 ++ src/format/format.c | 27 ++++++++++++--- src/format/format.h | 7 ++-- src/format/preload.c | 81 ++++++++++++++++++++++---------------------- src/format/preload.h | 8 ++--- 10 files changed, 207 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index dbced06..8f374bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,26 @@ 17-05-07 Cyrille Bagard + * src/analysis/disass/area.c: + Update code. + + * src/analysis/disass/fetch.c: + * src/analysis/disass/output.c: + Make the preloading process work as intended. + + * src/common/array.c: + * src/common/array.h: + Reset a flat array when needed. + + * src/format/format.c: + * src/format/format.h: + Distinguish two steps to extend disassembly context: setup and start. + + * src/format/preload.c: + * src/format/preload.h: + Optimize memory access for instructions and comments. + +17-05-07 Cyrille Bagard + * src/arch/archbase.h: Create a macro for memory data signs. diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 130a7f0..f01b89c 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -1556,7 +1556,7 @@ static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack for (i = collector->start; i < collector->stop; i++) { - instr = _g_preload_info_get_instruction(collector->info, i); + instr = _g_preload_info_grab_instruction(collector->info, i); range = g_arch_instruction_get_range(instr); addr = get_mrange_addr(range); @@ -1651,6 +1651,8 @@ void populate_fresh_memory_areas(wgroup_id_t gid, GtkStatusStack *status, mem_ar _g_preload_info_drain_instructions(info); + assert(_g_preload_info_count_instructions(info) == 0); + g_preload_info_unlock_instructions(info); gtk_status_stack_remove_activity(status, id); diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index c5489d6..586c084 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -417,8 +417,6 @@ 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 */ @@ -432,7 +430,17 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex g_proc_context_attach_counter(template.ctx, &remaining_counter); /** - * Première phase de désassemblage : suivi des chemins tracés. + * Première phase de désassemblage : intégration des infos du format. + */ + + g_binary_format_preload_disassembling_context(format, template.ctx, status); + + populate_fresh_memory_areas(gid, status, template.areas, template.count, G_PRELOAD_INFO(ctx)); + + g_work_queue_wait_for_completion(queue, gid); + + /** + * Seconde phase : suivi des chemins tracés. */ g_work_queue_set_extra_wait_callback(queue, gid, @@ -445,12 +453,12 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex _("Disassembling following the execution flow..."), length); - g_binary_format_setup_disassembling_context(format, template.ctx, status); + g_binary_format_activate_disassembling_context(format, template.ctx, status); g_work_queue_wait_for_completion(queue, gid); /** - * Seconde phase : on comble les trous laissés. + * Troisième phase : on comble les trous laissés. */ gtk_status_stack_update_activity(status, template.id, _("Disassembling the remaining instructions...")); @@ -466,7 +474,7 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex gtk_status_stack_remove_activity(status, template.id); /** - * Troisième et dernière phase : récolte des fruits. + * Quatrième et dernière phase : récolte des fruits. */ result = collect_disassembled_instructions(gid, status, template.areas, template.count, count); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 5a74d92..421cfb6 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -24,6 +24,9 @@ #include "output.h" +#include + + #include @@ -67,6 +70,8 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, bool expect_outro; /* Fin de zone de code définie */ + size_t comment_count; /* Quantité de commentaires */ + size_t comment_index; /* Indice du commantaire actif */ GDbComment *comment; /* Commentaire à ajouter */ const vmpa2t *caddr; /* Localisation du commentaire */ @@ -137,11 +142,22 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, expect_outro = false; - comment = g_preload_info_pop_comment(info); + g_preload_info_lock_comments(info); - if (comment != NULL) + comment_count = _g_preload_info_count_comments(info); + comment_index = 0; + + if (comment_index < comment_count) + { + comment = _g_preload_info_grab_comment(info, comment_index); caddr = g_db_comment_get_address(comment); + comment_index++; + + } + + else + comment = NULL; /* if (comment != NULL) @@ -306,32 +322,29 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, { compared = cmp_vmpa(iaddr, caddr); - if (compared == 0) + if (compared >= 0) { - if (g_loaded_binary_add_to_collection(binary, G_DB_ITEM(comment))) + if (compared == 0) 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)); + 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 (comment_index < comment_count) + { + comment = _g_preload_info_grab_comment(info, comment_index); + caddr = g_db_comment_get_address(comment); - if (compared >= 0) - { - comment = g_preload_info_pop_comment(info); + comment_index++; - if (comment != NULL) - caddr = g_db_comment_get_address(comment); + } + + else + comment = NULL; } @@ -343,6 +356,10 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, } + assert(comment_index == comment_count); + + g_preload_info_unlock_comments(info); + gtk_status_stack_remove_activity(status, id); g_arch_processor_unlock(proc); diff --git a/src/common/array.c b/src/common/array.c index e4e7bb1..f520d1d 100644 --- a/src/common/array.c +++ b/src/common/array.c @@ -157,6 +157,64 @@ void unlock_flat_array(flat_array_t **array) /****************************************************************************** * * +* Paramètres : array = tableau compressé à mettre à jour. [OUT] * +* * +* Description : Réinitialise un tableau sans traitement excessif. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_flat_array(flat_array_t **array) +{ + size_t count; /* Nombre d'éléments présents */ + ext_flat_array_t *extended; /* Version de tableau étendue */ + + assert(FLAT_ARRAY_IS_LOCKED(*array)); + + count = count_flat_array_items(*array); + + switch (count) + { + case 0: + break; + + case 1: + + assert(FLAT_ARRAY_HAS_NO_INDEX(*array)); + + free(GET_LONELY_ITEM(*array)); + + *array = NULL; + + lock_flat_array(array); + + break; + + default: + + assert(!FLAT_ARRAY_HAS_NO_INDEX(*array)); + + extended = EXTENDED_ARRAY(*array); + + free(extended->items); + free(extended); + + *array = NULL; + + lock_flat_array(array); + + break; + + } + +} + + +/****************************************************************************** +* * * Paramètres : array = tableau compressé à consulter. * * * * Description : Indique la quantité d'éléments présents dans le tableau. * diff --git a/src/common/array.h b/src/common/array.h index 2dd5b9f..bdb1ae4 100644 --- a/src/common/array.h +++ b/src/common/array.h @@ -40,6 +40,9 @@ void lock_flat_array(flat_array_t **); /* Déverrouille l'accès à un tableau compressé. */ void unlock_flat_array(flat_array_t **); +/* Réinitialise un tableau sans traitement excessif. */ +void reset_flat_array(flat_array_t **); + /* Indique la quantité d'éléments présents dans le tableau. */ size_t count_flat_array_items(const flat_array_t *); diff --git a/src/format/format.c b/src/format/format.c index 11216a2..1eef759 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -250,7 +250,7 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent * ctx = contexte de désassemblage à préparer. * * status = barre de statut à tenir informée. * * * -* Description : Fournit un contexte initialisé pour un désassemblage. * +* Description : Intègre dans un contexte les informations tirées d'un format.* * * * Retour : - * * * @@ -258,12 +258,31 @@ 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, GtkStatusStack *status) +void g_binary_format_preload_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); +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* ctx = contexte de désassemblage à préparer. * +* status = barre de statut à tenir informée. * +* * +* Description : Définit les points de départ d'un contexte de désassemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_activate_disassembling_context(GBinFormat *format, GProcContext *ctx, GtkStatusStack *status) +{ + size_t i; /* Boucle de parcours */ + 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 b04f11b..e1c4e37 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -65,8 +65,11 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *); /* Enregistre une adresse comme début d'une zone de code. */ 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 *, GtkStatusStack *); +/* Intègre dans un contexte les informations tirées d'un format. */ +void g_binary_format_preload_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *); + +/* Définit les points de départ d'un contexte de désassemblage. */ +void g_binary_format_activate_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.c b/src/format/preload.c index 145dfd9..750a67c 100644 --- a/src/format/preload.c +++ b/src/format/preload.c @@ -110,6 +110,12 @@ static void g_preload_info_dispose(GPreloadInfo *info) g_preload_info_lock_instructions(info); + while (_g_preload_info_count_instructions(info) > 0) + { + instr = _g_preload_info_grab_instruction(info, 0); + g_object_unref(G_OBJECT(instr)); + } + _g_preload_info_drain_instructions(info); g_preload_info_unlock_instructions(info); @@ -118,14 +124,12 @@ static void g_preload_info_dispose(GPreloadInfo *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 *)); - + comment = _g_preload_info_grab_comment(info, 0); g_object_unref(G_OBJECT(comment)); - } + _g_preload_info_drain_comments(info); + g_preload_info_unlock_comments(info); G_OBJECT_CLASS(g_preload_info_parent_class)->dispose(G_OBJECT(info)); @@ -286,7 +290,7 @@ size_t _g_preload_info_count_instructions(const GPreloadInfo *info) * * ******************************************************************************/ -GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *info, size_t index) +GArchInstruction *_g_preload_info_grab_instruction(const GPreloadInfo *info, size_t index) { GArchInstruction *result; /* Opérande à retourner */ GArchInstruction **ptr; /* Adresse dans le tableau */ @@ -295,7 +299,14 @@ GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *info, size result = *ptr; - g_object_ref(G_OBJECT(result)); + /** + * La propriétée de l'élément est transmise à l'appelant. + * + * Ainsi, pour vider une liste via _g_preload_info_drain_instructions(), + * il suffit juste de libérer la mémoire occupée pour le stockage sans + * se préoccuper des références contenues ; le gain de temps est important + * puisqu'on évite là un parcours et des déplacements. + */ return result; @@ -354,17 +365,12 @@ GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *info) 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)); + /** + * A utiliser en conjonction avec _g_preload_info_grab_instruction() + * uniquement. + */ - } + reset_flat_array(&info->instructions); } @@ -480,7 +486,7 @@ size_t _g_preload_info_count_comments(const GPreloadInfo *info) * * ******************************************************************************/ -GDbComment *_g_preload_info_get_comment(const GPreloadInfo *info, size_t index) +GDbComment *_g_preload_info_grab_comment(const GPreloadInfo *info, size_t index) { GDbComment *result; /* Opérande à retourner */ GDbComment **ptr; /* Adresse dans le tableau */ @@ -489,7 +495,14 @@ GDbComment *_g_preload_info_get_comment(const GPreloadInfo *info, size_t index) result = *ptr; - g_object_ref(G_OBJECT(result)); + /** + * La propriétée de l'élément est transmise à l'appelant. + * + * Ainsi, pour vider une liste via _g_preload_info_drain_comments(), + * il suffit juste de libérer la mémoire occupée pour le stockage sans + * se préoccuper des références contenues ; le gain de temps est important + * puisqu'on évite là un parcours et des déplacements. + */ return result; @@ -500,35 +513,21 @@ GDbComment *_g_preload_info_get_comment(const GPreloadInfo *info, size_t index) * * * Paramètres : info = instance à manipuler. * * * -* Description : Dépile un commentaire présent dans les préchargements. * +* Description : Retire des préchargements tous les commentaires. * * * -* Retour : Commentaire retiré ou NULL si aucune. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GDbComment *g_preload_info_pop_comment(GPreloadInfo *info) +void _g_preload_info_drain_comments(GPreloadInfo *info) { - GDbComment *result; /* Instruction à retourner */ - GDbComment **ptr; /* Adresse dans le tableau */ - - g_preload_info_lock_comments(info); + /** + * A utiliser en conjonction avec _g_preload_info_grab_comment() + * uniquement. + */ - 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; + reset_flat_array(&info->comments); } diff --git a/src/format/preload.h b/src/format/preload.h index a915462..d88366a 100644 --- a/src/format/preload.h +++ b/src/format/preload.h @@ -67,7 +67,7 @@ void g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *); 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); +GArchInstruction *_g_preload_info_grab_instruction(const GPreloadInfo *, size_t); /* Dépile une instruction présente dans les préchargements. */ GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *); @@ -88,10 +88,10 @@ void g_preload_info_add_comment(GPreloadInfo *, GDbComment *); 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); +GDbComment *_g_preload_info_grab_comment(const GPreloadInfo *, size_t); -/* Dépile un commentaire présent dans les préchargements. */ -GDbComment *g_preload_info_pop_comment(GPreloadInfo *); +/* Retire des préchargements tous les commentaires. */ +void _g_preload_info_drain_comments(GPreloadInfo *); -- cgit v0.11.2-87-g4458