From d7f78fe9a75d96b6f3d441335dcf50a5c026d8ea Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 13 Jul 2017 00:47:38 +0200 Subject: Taken into account that raw immediate values can be used more than once. --- ChangeLog | 17 +++++ src/analysis/db/items/comment.c | 2 +- src/arch/arm/v7/fetch.c | 38 ++++++++++-- src/common/array.c | 66 ++++++++++++++++++++ src/common/array.h | 3 + src/format/preload.c | 134 ++++++++++++++++++++++++++++++++++++++-- src/format/preload.h | 12 ++++ src/glibext/gbuffercache.c | 31 ++++++++-- 8 files changed, 285 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6562f78..9064308 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +17-07-13 Cyrille Bagard + + * src/analysis/db/items/comment.c: + Collect the text from all portions, not the first one. + + * src/arch/arm/v7/fetch.c: + Take into account that raw immediate values can be used more than once. + + * src/common/array.c: + * src/common/array.h: + * src/format/preload.c: + * src/format/preload.h: + Extend code. + + * src/glibext/gbuffercache.c: + Handle comments with more than one line. + 17-07-12 Cyrille Bagard * src/analysis/disass/dragon.c: diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 9368291..cad2d64 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -1129,7 +1129,7 @@ char *g_db_comment_get_text(GDbComment *comment) for (i = 0; i < count; i++) { - string = get_flat_array_item(comment->text, 0, sizeof(rle_string)); + string = get_flat_array_item(comment->text, i, sizeof(rle_string)); assert(!is_rle_string_empty(string)); diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c index 929c877..42788af 100644 --- a/src/arch/arm/v7/fetch.c +++ b/src/arch/arm/v7/fetch.c @@ -367,6 +367,7 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst uint32_t target; /* Adresse virtuelle visée */ vmpa2t pos; /* Tête de lecture de valeur */ VMPA_BUFFER(loc); /* Adresse au format texte */ + GPreloadInfo *info; /* Informations préchargées */ GArchInstruction *loaded; /* Instruction de valeur */ char *desc; /* Description d'accompagnement*/ GDbComment *comment; /* Définition de commentaire */ @@ -439,18 +440,43 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst copy_vmpa(&pos, &loaded_addr); - loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target); + info = G_PRELOAD_INFO(context); - g_preload_info_add_instruction(G_PRELOAD_INFO(context), loaded); + g_preload_info_lock_instructions(info); + + if (!_g_preload_info_has_instruction_at(info, &loaded_addr)) + { + loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target); + _g_preload_info_add_instruction(info, loaded); + } + + g_preload_info_unlock_instructions(info); vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); asprintf(&desc, _("Value used @ %s"), loc); - 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); + g_preload_info_lock_comments(info); + + comment = _g_preload_info_find_comment_at(info, &loaded_addr); + + if (comment != NULL) + { + g_db_comment_add_static_text(comment, "\n"); + g_db_comment_add_dynamic_text(comment, desc); + } + + else + { + comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false); + g_db_item_set_volatile(G_DB_ITEM(comment), true); + + g_db_comment_add_dynamic_text(comment, desc); + + _g_preload_info_add_comment(info, comment); + + } - g_preload_info_add_comment(G_PRELOAD_INFO(context), comment); + g_preload_info_unlock_comments(info); /* Mise à jour de l'affichage et conclusion */ diff --git a/src/common/array.c b/src/common/array.c index dcb9344..36c30a1 100644 --- a/src/common/array.c +++ b/src/common/array.c @@ -632,3 +632,69 @@ void *get_flat_array_item(flat_array_t *array, size_t index, size_t size) return result; } + + +/****************************************************************************** +* * +* Paramètres : array = tableau compressé à consulter. * +* size = taille de ce nouvel élément. * +* compar = méthode de comparaison entre éléments. * +* key = élément de comparaison fourni. * +* * +* Description : Recherche un élément dans un tableau trié. * +* * +* Retour : Eventuel élément trouvé ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +void *find_item_in_flat_array(flat_array_t *array, size_t size, __compar_fn_t compar, const void *key) +{ + void *result; /* Trouvaille à retourner */ + size_t count; /* Nombre d'éléments présents */ + void *item; /* Elément isolé présent */ + ext_flat_array_t *extended; /* Version de tableau étendue */ + size_t index; /* Indice de l'élément trouvé */ + + assert(FLAT_ARRAY_IS_LOCKED(array)); + + count = count_flat_array_items(array); + + switch (count) + { + case 0: + result = NULL; + break; + + case 1: + + assert(FLAT_ARRAY_HAS_NO_INDEX(array)); + + item = GET_LONELY_ITEM(array); + + if (compar(key, item) == 0) + result = item; + else + result = NULL; + + break; + + default: + + assert(!FLAT_ARRAY_HAS_NO_INDEX(array)); + + extended = EXTENDED_ARRAY(array); + + if (bsearch_index(key, extended->items, extended->count, size, compar, &index)) + result = (void *)(((char *)extended->items) + index * size); + else + result = NULL; + + break; + + } + + return result; + +} diff --git a/src/common/array.h b/src/common/array.h index 546de1a..5ddc9ba 100644 --- a/src/common/array.h +++ b/src/common/array.h @@ -67,6 +67,9 @@ void rem_item_from_flat_array(flat_array_t **, size_t, size_t); /* Fournit un élément présent dans un tableau compressé. */ void *get_flat_array_item(flat_array_t *, size_t, size_t); +/* Recherche un élément dans un tableau trié. */ +void *find_item_in_flat_array(flat_array_t *, size_t, __compar_fn_t, const void *); + #endif /* _COMMON_ARRAY_H */ diff --git a/src/format/preload.c b/src/format/preload.c index 2eec92e..7f7a435 100644 --- a/src/format/preload.c +++ b/src/format/preload.c @@ -261,6 +261,30 @@ void g_preload_info_unlock_instructions(GPreloadInfo *info) void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr) { + g_preload_info_lock_instructions(info); + + _g_preload_info_add_instruction(info, instr); + + g_preload_info_unlock_instructions(info); + +} + + +/****************************************************************************** +* * +* 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 */ @@ -273,12 +297,46 @@ void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr) } - 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 à mettre à jour. * +* addr = localisation du commentaire recherché. * +* * +* Description : Détermine si une instruction est présente à un point donné. * +* * +* Retour : true si une instruction existe à l'emplacement indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _g_preload_info_has_instruction_at(GPreloadInfo *info, const vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + GArchInstruction **ptr; /* Adresse dans le tableau */ + + int cmp_instr_by_addr(const vmpa2t *key, const GArchInstruction **i) + { + const mrange_t *range; /* Emplacement pour l'instr. */ + + range = g_arch_instruction_get_range(*i); + + return cmp_vmpa(key, get_mrange_addr(range)); + + } + + ptr = find_item_in_flat_array(info->instructions, sizeof(GArchInstruction *), + (__compar_fn_t)cmp_instr_by_addr, addr); + + result = (ptr != NULL); + + return result; } @@ -457,6 +515,30 @@ void g_preload_info_unlock_comments(GPreloadInfo *info) void g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) { + g_preload_info_lock_comments(info); + + _g_preload_info_add_comment(info, comment); + + g_preload_info_unlock_comments(info); + +} + + +/****************************************************************************** +* * +* 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 */ @@ -469,12 +551,52 @@ void g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) } - 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 à mettre à consulter. * +* addr = localisation du commentaire recherché. * +* * +* Description : Recherche un commentaire dans des préchargements. * +* * +* Retour : Eventuel commenaire retrouvé ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *_g_preload_info_find_comment_at(GPreloadInfo *info, const vmpa2t *addr) +{ + GDbComment *result; /* Trouvaille à retourner */ + GDbComment **ptr; /* Adresse dans le tableau */ + + int cmp_comment_by_addr(const vmpa2t *key, const GDbComment * const *comment) + { + const vmpa2t *caddr; /* Position du commentaire */ + + caddr = g_db_comment_get_address(*comment); + + return cmp_vmpa(key, caddr); + + } + + ptr = find_item_in_flat_array(info->comments, sizeof(GDbComment *), + (__compar_fn_t)cmp_comment_by_addr, addr); + + if (ptr != NULL) + { + result = *ptr; + g_object_ref(G_OBJECT(result)); + } + else + result = NULL; + + return result; } diff --git a/src/format/preload.h b/src/format/preload.h index 59c81b7..1e28222 100644 --- a/src/format/preload.h +++ b/src/format/preload.h @@ -66,6 +66,12 @@ void g_preload_info_unlock_instructions(GPreloadInfo *); /* Ajoute une instruction supplémentaire aux préchargements. */ void g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *); +/* Ajoute une instruction supplémentaire aux préchargements. */ +void _g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *); + +/* Détermine si une instruction est présente à un point donné. */ +bool _g_preload_info_has_instruction_at(GPreloadInfo *, const vmpa2t *); + /* Indique la quantité d'instructions préchargées disponibles. */ size_t _g_preload_info_count_instructions(const GPreloadInfo *); @@ -87,6 +93,12 @@ void g_preload_info_unlock_comments(GPreloadInfo *); /* Ajoute un commentaire supplémentaire aux préchargements. */ void g_preload_info_add_comment(GPreloadInfo *, GDbComment *); +/* Ajoute un commentaire supplémentaire aux préchargements. */ +void _g_preload_info_add_comment(GPreloadInfo *, GDbComment *); + +/* Recherche un commentaire dans des préchargements. */ +GDbComment *_g_preload_info_find_comment_at(GPreloadInfo *, const vmpa2t *); + /* Indique la quantité de commentaires préchargés disponibles. */ size_t _g_preload_info_count_comments(const GPreloadInfo *); diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c index fd7c987..f7dc49f 100644 --- a/src/glibext/gbuffercache.c +++ b/src/glibext/gbuffercache.c @@ -903,10 +903,15 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); } } -#ifndef NDEBUG - else - assert(needed == 1); -#endif + + else if (needed > 1) + { + if ((cache->used + needed - 1) >= cache->count) + { + cache->count += needed - 1 + LINE_ALLOC_BULK; + cache->lines = (cache_info *)realloc(cache->lines, cache->count * sizeof(cache_info)); + } + } /* Insertion du générateur */ @@ -934,7 +939,23 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator g_width_tracker_update(cache->tracker, index); - g_signal_emit_by_name(cache, "size-changed", true, index, 1); + if (needed > 1) + { + /* On déborde sur les lignes suivantes, donc on crée de l'espace ! */ + + memmove(&cache->lines[index + 1], + &cache->lines[index + 1 + needed - 1], (cache->used - index - 1) * sizeof(cache_info)); + + for (i = 1; i < needed; i++) + init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE); + + cache->used += needed - 1; + + g_width_tracker_update_added(cache->tracker, index + 1, needed - 1); + + } + + g_signal_emit_by_name(cache, "size-changed", true, index, needed - 1); } -- cgit v0.11.2-87-g4458