diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-03-24 07:38:31 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-03-24 07:38:31 (GMT) |
commit | b7347c96930027fc11b9c5038157f972d58a41bf (patch) | |
tree | 182ddabae529e89b28db93acb3404cd7424086ed /src/analysis | |
parent | 518ce6e1594ba80be4286bd3e561b0b7f73ce4b0 (diff) |
Built routine digest for tooltip hints.
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/routine.c | 252 | ||||
-rw-r--r-- | src/analysis/routine.h | 8 |
2 files changed, 260 insertions, 0 deletions
diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 8322acf..089d287 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -26,9 +26,14 @@ #include <malloc.h> #include <string.h> +#include <stdio.h> #include <stdlib.h> +#include <i18n.h> + + +#include "../arch/raw.h" #include "../common/extstr.h" @@ -1130,3 +1135,250 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang, } #endif + + + + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* binary = informations relatives au binaire chargé. * +* * +* Description : Construit un petit résumé concis de la routine. * +* * +* Retour : Chaîne de caractères à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *g_binary_routine_build_tooltip(const GBinRoutine *routine, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + 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 */ + GBufferCache *cache; /* Tampon de désassemblage */ + instr_iter_t *iter; /* Parcours local d'adresses */ + GArchInstruction *instr; /* Instruction correspondante */ + instr_link_t *dests; /* Instr. visées par une autre */ + size_t dcount; /* Nombre de liens de dest. */ + size_t i; /* Boucle de parcours */ + const mrange_t *irange; /* Emplacement d'instruction */ + size_t index; /* Indice de ligne à traiter */ + GBufferLine *line; /* Ligne présente à l'adresse */ + char *info; /* Ligne d'information créée */ + size_t blk_count; /* Nombre de blocs basiques */ + + result = NULL; + + ins_count = 0; + + call_count = 0; + call_info = NULL; + + string_count = 0; + string_info = NULL; + + proc = g_loaded_binary_get_processor(binary); + cache = g_loaded_binary_get_disassembled_cache(binary); + + /* Parcours des instructions */ + + iter = g_arch_processor_get_iter_from_address(proc, get_mrange_addr(&routine->range)); + if (iter == NULL) goto gbrbt_no_iter; + + restrict_instruction_iterator(iter, &routine->range); + + for (instr = get_instruction_iterator_current(iter); + instr != NULL; + instr = get_instruction_iterator_next(iter)) + { + ins_count ++; + + /* Appels ? */ + + g_arch_instruction_rlock_dest(instr); + dcount = g_arch_instruction_get_destinations(instr, &dests); + + for (i = 0; i < dcount; i++) + switch (dests[i].type) + { + case ILT_CALL: + + call_count++; + + if (call_count > 6) + continue; + + if (call_count == 6) + { + call_info = stradd(call_info, "\n ..."); + continue; + } + + irange = g_arch_instruction_get_range(instr); + + index = g_buffer_cache_find_index_by_addr(cache, get_mrange_addr(irange), true); + + 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(dests[i].linked)) + continue; + + if (!g_raw_instruction_is_string(G_RAW_INSTRUCTION(dests[i].linked))) + continue; + + string_count++; + + if (string_count > 6) + continue; + + if (string_count == 6) + { + string_info = stradd(string_info, "\n ..."); + continue; + } + + irange = g_arch_instruction_get_range(dests[i].linked); + + index = g_buffer_cache_find_index_by_addr(cache, get_mrange_addr(irange), true); + + 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; + + } + + g_arch_instruction_runlock_dest(instr); + + g_object_unref(G_OBJECT(instr)); + + } + + delete_instruction_iterator(iter); + + /* Construction du résumé */ + + if (ins_count > 1) + asprintf(&result, "%u %s, ", ins_count, _("instructions")); + else + asprintf(&result, "%u %s, ", ins_count, _("instruction")); + + blk_count = g_block_list_count_blocks(routine->blocks); + + if (blk_count > 1) + asprintf(&info, "%zu %s", blk_count, _("basic blocks")); + else + asprintf(&info, "%zu %s", blk_count, _("basic block")); + + result = stradd(result, info); + free(info); + + result = stradd(result, "\n"); + + if (call_count > 1) + asprintf(&info, "%u %s, ", call_count, _("calls")); + else + asprintf(&info, "%u %s, ", call_count, _("call")); + + result = stradd(result, info); + free(info); + + if (string_count > 1) + asprintf(&info, "%u %s", string_count, _("strings")); + else + asprintf(&info, "%u %s", string_count, _("string")); + + result = stradd(result, info); + free(info); + + if (call_count > 0) + { + result = stradd(result, "\n\n"); + result = stradd(result, call_count > 1 ? _("Calls:") : _("Call:")); + result = stradd(result, "\n"); + + result = stradd(result, call_info); + free(call_info); + + } + + if (string_count > 0) + { + result = stradd(result, "\n\n"); + result = stradd(result, string_count > 1 ? _("Strings:") : _("String:")); + result = stradd(result, "\n"); + + result = stradd(result, string_info); + free(string_info); + + } + + gbrbt_no_iter: + + g_object_unref(G_OBJECT(cache)); + g_object_unref(G_OBJECT(proc)); + + return result; + +} diff --git a/src/analysis/routine.h b/src/analysis/routine.h index aab0818..e880118 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -30,8 +30,10 @@ #include <sys/types.h> +#include "binary.h" #include "variable.h" #include "disass/block.h" +#include "../arch/processor.h" //#include "../arch/instruction.h" @@ -187,4 +189,10 @@ char *_g_binary_routine_to_string(const GBinRoutine *, Routine2StringOptions); + +/* Construit un petit résumé concis de la routine. */ +char *g_binary_routine_build_tooltip(const GBinRoutine *, const GLoadedBinary *); + + + #endif /* _ANALYSIS_ROUTINE_H */ |