summaryrefslogtreecommitdiff
path: root/src/analysis/routine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/routine.c')
-rw-r--r--src/analysis/routine.c252
1 files changed, 252 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;
+
+}