diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2019-02-15 22:58:40 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2019-02-15 22:58:40 (GMT) |
commit | 16242be5838a77690946cbb2f30b2e89f2df0b94 (patch) | |
tree | d3c2b2725f41f2a0d45ae7f32e2ab9cb1886b230 /src/analysis/disass | |
parent | 5ed40f0afbd58fbfdf05be7b2a10ab8d0819759f (diff) |
Displayed tooltips for graph view edges.
Diffstat (limited to 'src/analysis/disass')
-rw-r--r-- | src/analysis/disass/block.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c index 9fce202..3077dc2 100644 --- a/src/analysis/disass/block.c +++ b/src/analysis/disass/block.c @@ -28,7 +28,13 @@ #include <malloc.h> +#include <i18n.h> + + #include "../block-int.h" +#include "../../arch/raw.h" +#include "../../common/extstr.h" +#include "../../core/params.h" #include "../../glibext/gbinarycursor.h" @@ -84,6 +90,9 @@ static block_link_t *g_basic_block_get_destinations(const GBasicBlock *, const G /* Fournit la représentation graphique d'un bloc de code. */ static GBufferView *g_basic_block_build_view(const GBasicBlock *, segcnt_list *); +/* Construit un ensemble d'indications pour bloc. */ +static char *g_basic_block_build_tooltip(const GBasicBlock *); + /* ---------------------------------------------------------------------------------- */ @@ -124,6 +133,7 @@ static void g_basic_block_class_init(GBasicBlockClass *class) block->get_src = (block_get_links_fc)g_basic_block_get_sources; block->get_dest = (block_get_links_fc)g_basic_block_get_destinations; block->build = (block_build_view_fc)g_basic_block_build_view; + block->build_tooltip = (block_build_tooltip_fc)g_basic_block_build_tooltip; } @@ -499,6 +509,345 @@ static GBufferView *g_basic_block_build_view(const GBasicBlock *block, segcnt_li /****************************************************************************** * * +* Paramètres : block = bloc de code à consulter. * +* * +* Description : Construit un ensemble d'indications pour bloc. * +* * +* Retour : Informations à présenter sous forme de bulle d'aide. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_basic_block_build_tooltip(const GBasicBlock *block) +{ + char *result; /* Description à retourner */ + const mrange_t *brange[2]; /* Emplacements d'instruction */ + phys_t diff; /* Espacement entre adresses */ + mrange_t range; /* Couverture du bloc */ + char *name; /* Désignation de l'entête */ + GBinFormat *format; /* Format associé au binaire */ + GBinSymbol *symbol; /* Symbole lié au bloc */ + char *label; /* Etiquette à insérer */ + GBufferCache *cache; /* Tampon d'impression colorée */ + GBufferLine *line; /* Ligne au contenu coloré */ + VMPA_BUFFER(loc); /* Indication de position */ + GGenConfig *config; /* Configuration à consulter */ + unsigned int max_calls; /* Quantité d'appels à afficher*/ + unsigned int max_strings; /* Nbre de chaînes à afficher */ + unsigned int ins_count; /* Quantité d'instructions */ + unsigned int call_count; /* Quantité d'appels */ + char *call_info; /* Détails des appels */ + unsigned int string_count; /* Quantité de chaînes */ + char *string_info; /* Détails des chaînes */ + GArchProcessor *proc; /* Architecture utilisée */ + instr_iter_t *iter; /* Parcours local d'adresses */ + GArchInstruction *instr; /* Instruction correspondante */ + size_t dcount; /* Nombre de liens de dest. */ + size_t i; /* Boucle de parcours */ + const instr_link_t *dest; /* Instr. visée par une autre */ + const mrange_t *irange; /* Emplacement d'instruction */ + GLineCursor *cursor; /* Emplacement dans un tampon */ + size_t index; /* Indice de ligne à traiter */ + char *info; /* Ligne d'information créée */ + + /* Définition de la couverture du bloc */ + + brange[0] = g_arch_instruction_get_range(block->first); + brange[1] = g_arch_instruction_get_range(block->last); + + diff = compute_vmpa_diff(get_mrange_addr(brange[0]), get_mrange_addr(brange[1])); + + init_mrange(&range, get_mrange_addr(brange[0]), diff + get_mrange_length(brange[1])); + + /* Recherche d'un symbole de départ */ + + name = NULL; + + format = G_BIN_FORMAT(g_loaded_binary_get_format(block->binary)); + + if (g_binary_format_find_symbol_at(format, get_mrange_addr(brange[0]), &symbol)) + { + label = g_binary_symbol_get_label(symbol); + + if (label != NULL) + { + cache = g_buffer_cache_new(NULL); + g_buffer_cache_append(cache, G_LINE_GENERATOR(symbol), BLF_NONE); + + line = g_buffer_cache_find_line_by_index(cache, 0); + name = g_buffer_line_get_text(line, BLC_ASSEMBLY_LABEL, BLC_COUNT, true); + g_object_unref(G_OBJECT(line)); + + g_object_unref(G_OBJECT(cache)); + + /* Suppression de la fin de l'étiquette... */ + name = strrpl(name, ":", ""); + + } + + else + name = NULL; + + free(label); + + g_object_unref(G_OBJECT(symbol)); + + } + + if (name == NULL) + { + proc = g_loaded_binary_get_processor(block->binary); + + if (g_arch_processor_has_virtual_space(proc) && has_virt_addr(get_mrange_addr(&range))) + vmpa2_virt_to_string(get_mrange_addr(&range), MDS_UNDEFINED, loc, NULL); + else + vmpa2_phys_to_string(get_mrange_addr(&range), MDS_UNDEFINED, loc, NULL); + + name = strdup(loc); + + g_object_unref(G_OBJECT(proc)); + + } + + result = name; + + /* Lecture des paramètres de configuration */ + + config = get_main_configuration(); + + if (!g_generic_config_get_value(config, MPK_TOOLTIP_MAX_CALLS, &max_calls)) + max_calls = 0; + + max_calls++; + + if (!g_generic_config_get_value(config, MPK_TOOLTIP_MAX_STRINGS, &max_strings)) + max_strings = 0; + + max_strings++; + + /* Parcours des instructions */ + + ins_count = 0; + + call_count = 0; + call_info = NULL; + + string_count = 0; + string_info = NULL; + + proc = g_loaded_binary_get_processor(block->binary); + cache = g_loaded_binary_get_disassembled_cache(block->binary); + + iter = g_arch_processor_get_iter_from_address(proc, get_mrange_addr(&range)); + if (iter == NULL) goto no_iter; + + restrict_instruction_iterator(iter, &range); + + for (instr = get_instruction_iterator_current(iter); + instr != NULL; + instr = get_instruction_iterator_next(iter)) + { + ins_count ++; + + /* Appels ou références ? */ + + g_arch_instruction_lock_dest(instr); + dcount = g_arch_instruction_count_destinations(instr); + + for (i = 0; i < dcount; i++) + { + dest = g_arch_instruction_get_destination(instr, i); + + switch (dest->type) + { + case ILT_CALL: + + call_count++; + + if (call_count > max_calls) + goto next_dest; + + if (call_count == max_calls) + { + call_info = stradd(call_info, "\n ..."); + goto next_dest; + } + + irange = g_arch_instruction_get_range(instr); + + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(irange)); + + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); + + g_object_unref(G_OBJECT(cursor)); + + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); + + line = g_buffer_cache_find_line_by_index(cache, index); + + if (line != NULL) + { + info = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); + g_object_unref(G_OBJECT(line)); + } + + else + info = NULL; + + if (call_info != NULL) + call_info = stradd(call_info, "\n"); + + if (info != NULL) + { + call_info = stradd(call_info, " - "); + call_info = stradd(call_info, info); + free(info); + } + + else + call_info = stradd(call_info, " - ???"); + + break; + + case ILT_REF: + + if (!G_IS_RAW_INSTRUCTION(dest->linked)) + goto next_dest; + + if (!g_raw_instruction_is_string(G_RAW_INSTRUCTION(dest->linked))) + goto next_dest; + + string_count++; + + if (string_count > max_strings) + goto next_dest; + + if (string_count == max_strings) + { + string_info = stradd(string_info, "\n ..."); + goto next_dest; + } + + irange = g_arch_instruction_get_range(dest->linked); + + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(irange)); + + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); + + g_object_unref(G_OBJECT(cursor)); + + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); + + line = g_buffer_cache_find_line_by_index(cache, index); + + if (line != NULL) + { + info = g_buffer_line_get_text(line, BLC_ASSEMBLY, BLC_COUNT, true); + g_object_unref(G_OBJECT(line)); + } + + else + info = NULL; + + if (string_info != NULL) + string_info = stradd(string_info, "\n"); + + if (info != NULL) + { + string_info = stradd(string_info, " - "); + string_info = stradd(string_info, info); + free(info); + } + + else + string_info = stradd(string_info, " - ???"); + + break; + + default: + break; + + } + + next_dest: + + unref_instr_link(dest); + + } + + g_arch_instruction_unlock_dest(instr); + + g_object_unref(G_OBJECT(instr)); + + } + + delete_instruction_iterator(iter); + + no_iter: + + g_object_unref(G_OBJECT(cache)); + g_object_unref(G_OBJECT(proc)); + + /* Construction du résumé */ + + result = stradd(result, "\n"); + + if (ins_count > 1) + asprintf(&info, " - %u %s", ins_count, _("instructions")); + else + asprintf(&info, " - %u %s", ins_count, _("instruction")); + + result = stradd(result, info); + free(info); + + result = stradd(result, "\n"); + + if (call_count > 1) + asprintf(&info, " - %u %s", call_count, _("calls:")); + else if (call_count == 1) + asprintf(&info, " - 1 %s", _("call:")); + else + asprintf(&info, " - 0 %s", _("call")); + + if (call_count > 0) + { + info = stradd(info, "\n"); + info = stradd(info, call_info); + free(call_info); + } + + info = stradd(info, "\n"); + + result = stradd(result, info); + free(info); + + if (string_count > 1) + asprintf(&info, " - %u %s", string_count, _("strings:")); + else if (string_count == 1) + asprintf(&info, " - 1 %s", _("string:")); + else + asprintf(&info, " - 0 %s", _("string")); + + if (string_count > 0) + { + info = stradd(info, "\n"); + info = stradd(info, call_info); + free(call_info); + } + + result = stradd(result, info); + free(info); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : block = bloc d'instructions à consulter. * * first = instruction de départ du bloc. [OUT] * * last = dernière instruction du bloc. [OUT] * |