diff options
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/disass/dragon.c | 80 | ||||
-rw-r--r-- | src/analysis/disass/rank.c | 12 |
2 files changed, 66 insertions, 26 deletions
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c index 24c24dc..58c293e 100644 --- a/src/analysis/disass/dragon.c +++ b/src/analysis/disass/dragon.c @@ -92,7 +92,7 @@ struct _dragon_knight * Remarques : - * * * ******************************************************************************/ -#include "../../arch/instruction-int.h" + static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, size_t *count) { dragon_node *result; /* Liste à créer et renvoyer */ @@ -102,9 +102,11 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ GArchInstruction *iter; /* Boucle de parcours */ const mrange_t *irange; /* Emplacement d'instruction */ InstructionLinkType *types; /* Type de lien entre instr. */ - size_t scount; /* Nombre de liens de dest. */ + size_t scount; /* Nombre de liens de source */ + bool cut; /* Un découpage a été réalisé ?*/ size_t i; /* Boucle de parcours */ dragon_node *new; /* Nouvel élément à créer */ + size_t dcount; /* Nombre de liens de dest. */ result = NULL; *count = 0; @@ -123,7 +125,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ if (!mrange_contains_mrange(range, irange)) break; - /* Analyse des sources */ + /* Découpage en blocs */ if (need_alloc) { @@ -143,13 +145,31 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ } + /** + * Il y a plusieurs raisons à la création d'un nouveau bloc : + * + * - une instruction définit un saut vers une autre, + * et cette seconde instruction démarre donc un nouveau bloc. + * + * Pour traiter ce cas, il suffit d'analyser toutes les arrivées. + * + * - une instruction réalise un saut inconditionnel vers une autre. + * Cela se matérialise par un lien de type ILT_JUMP, ou de façon + * plus abstraite par un point de retour. + * + * Pour traiter ce cas, on s'attache à regarder les destinations. + */ else { + /* Analyse des sources */ + g_arch_instruction_rlock_src(iter); scount = g_arch_instruction_get_sources(iter, NULL, &types); - for (i = 0; i < scount; i++) + cut = false; + + for (i = 0; i < scount && !cut; i++) switch (types[i]) { case ILT_EXEC_FLOW: @@ -158,17 +178,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ case ILT_JUMP_IF_TRUE: case ILT_JUMP_IF_FALSE: - if (*count > 0) - result[*count - 1].last = last; - - - /* - printf(" %% ?jmp? %% cut @ %zu ; last = 0x%08x ; iter = 0x%08x\n", *count - 1, - (unsigned int)last->range.addr.virtual, - (unsigned int)iter->range.addr.virtual); - fflush(NULL); - */ - + result[*count - 1].last = last; (*count)++; i = scount; @@ -183,6 +193,8 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ new->first = iter; + cut = true; + break; default: @@ -194,24 +206,40 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ } + /* Analyse des destinations */ + g_arch_instruction_rlock_dest(iter); + dcount = g_arch_instruction_get_destinations(iter, NULL, &types, NULL); - if (g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) - { - if (*count > 0) - result[*count - 1].last = iter; + cut = false; + + for (i = 0; i < dcount && !cut; i++) + switch (types[i]) + { + case ILT_JUMP: - /* - printf(" %% return %% cut @ %zu ; addr = 0x%08x\n", *count - 1, - (unsigned int)iter->range.addr.virtual); - fflush(NULL); - */ + result[*count - 1].last = iter; - need_alloc = true; + cut = true; - } + need_alloc = true; + + break; + default: + break; + } + + g_arch_instruction_runlock_dest(iter); + + if (!need_alloc && g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) + { + result[*count - 1].last = iter; + + need_alloc = true; + + } } diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c index 0b9068b..7504231 100644 --- a/src/analysis/disass/rank.c +++ b/src/analysis/disass/rank.c @@ -324,6 +324,18 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block) /* La boucle de remontée n'abaisse pas les rangs */ if (types[i] == ILT_LOOP) continue; + /** + * On se doit de suivre le même cheminement que celui emprunté lors + * du parcours de create_dragon_nodes(). + * Sinon, les chemins divergent et une récursion infinie peut survenir. + */ + if (types[i] != ILT_EXEC_FLOW + && types[i] != ILT_JUMP + && types[i] != ILT_CASE_JUMP + && types[i] != ILT_JUMP_IF_TRUE + && types[i] != ILT_JUMP_IF_FALSE) + continue; + target = g_block_list_find_by_starting_instr(list, dests[i]); /** |