diff options
Diffstat (limited to 'src/analysis/disass')
-rw-r--r-- | src/analysis/disass/macro.c | 125 |
1 files changed, 96 insertions, 29 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 46dc0d3..2e5c0ee 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -277,6 +277,7 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop) { GInstrBlock *result; /* Regroupement à retourner */ + GInstrBlock *result_cached; /* Temporisation pour unicité */ branch_info main_branch; /* Flot d'exécution complet */ GArchInstruction *first; /* Première instruction */ GArchInstruction *last; /* Dernière instruction */ @@ -287,6 +288,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta size_t dcount; /* Nombre de liens de dest. */ size_t i; /* Boucle de parcours #1 */ GInstrBlock *block; /* Nouveau bloc mis en place */ + GInstrBlock *group; /* Regroupement de blocs */ branch_info *cases_branches; /* Branches d'un aiguillage */ size_t cases_count; /* Nombre d'aiguillages */ branch_info true_branch; /* Branche 'condition vraie' */ @@ -298,6 +300,32 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta vmpa_t stop_addr; /* Adresse de fin de bloc */ result = NULL; + result_cached = NULL; + + /** + * Procédure d'ajout de blocs : pour le premier, on conserve le bloc en mémoire + * et on attend. Si rien ne suit, il constitura l'unique retour. Sinon, on + * l'ajoute à partir de la sauvegarde, et le reste suit. + */ +#define DELAYED_BLOCK_ADDING(res, cache, blk) \ + do \ + { \ + if (res == NULL) \ + { \ + if (cache == NULL) \ + cache = blk; \ + else \ + { \ + res = g_virtual_block_new(); \ + g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), cache); \ + } \ + } \ + \ + if (res != NULL) \ + g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), blk); \ + \ + } \ + while (0) first = NULL; last = NULL; @@ -347,14 +375,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta case ILT_EXEC_FLOW: case ILT_JUMP: - if (result == NULL) - result = g_virtual_block_new(); block = g_flow_block_new(instrs, first, iter); MACRO_MARK_AS_PROCESSED(first); - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); first = NULL; + DELAYED_BLOCK_ADDING(result, result_cached, block); + g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); break; @@ -401,15 +428,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta /* Post-traitements de ILT_CASE_JUMP */ if (cases_count > 0) { - if (result == NULL) - result = g_virtual_block_new(); - if (first != NULL) { block = g_flow_block_new(instrs, first, iter); MACRO_MARK_AS_PROCESSED(first); - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); first = NULL; + + DELAYED_BLOCK_ADDING(result, result_cached, block); + } //printf(" --- cases --- start\n"); @@ -417,6 +443,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta next_addr = compute_first_common_addr_in_group(cases_branches, cases_count); //printf(" stop :: 0x%08llx\n", next_addr); + group = g_virtual_block_new(); + for (j = 0; j < cases_count; j++) { //printf(" ## %zu\n", j); @@ -425,12 +453,17 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta if (block != NULL) - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); free(cases_branches[j].jumps); } + if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0) + DELAYED_BLOCK_ADDING(result, result_cached, group); + else + g_object_unref(G_OBJECT(group)); + //printf(" --- cases --- end\n"); @@ -441,15 +474,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta /* Post-traitements de ILT_CATCH_EXCEPTION */ if (excep_count > 0) { - if (result == NULL) - result = g_virtual_block_new(); - if (first != NULL) { block = g_flow_block_new(instrs, first, iter); MACRO_MARK_AS_PROCESSED(first); - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); first = NULL; + + DELAYED_BLOCK_ADDING(result, result_cached, block); + } for (j = 0; j < excep_count; j++) @@ -482,28 +514,30 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta next_addr = compute_first_common_addr(&true_branch, &false_branch); next_addr = MIN(next_addr, end); - if (result == NULL) - result = g_virtual_block_new(); - if (first != NULL) { block = g_flow_block_new(instrs, first, iter); MACRO_MARK_AS_PROCESSED(first); - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); first = NULL; - } - block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr); + DELAYED_BLOCK_ADDING(result, result_cached, block); - if (block != NULL) + } - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + group = g_virtual_block_new(); - block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr); + block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr); + if (block != NULL) + g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); - if (block != NULL) + block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr); + if (block != NULL) + g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0) + DELAYED_BLOCK_ADDING(result, result_cached, group); + else + g_object_unref(G_OBJECT(group)); free(true_branch.jumps); free(false_branch.jumps); @@ -526,21 +560,51 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta MACRO_MARK_AS_PROCESSED(first); //printf("--close!--\n"); - if (result == NULL) - result = block; - else - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + DELAYED_BLOCK_ADDING(result, result_cached, block); + } } - if (result == NULL) + if ((result != NULL ? result : result_cached) == NULL) { //printf("WARNING :: null !\n"); //exit(0); } - return result; + return (result != NULL ? result : result_cached); + +} + + +static bool print_blocks(GInstrBlock *blk, BlockVisitOrder order, int *pad) +{ + int i; + vmpa_t start, end; + + if (order != BVO_OUT) + for (i = 0; i < *pad; i++) + printf(" "); + + if (G_IS_FLOW_BLOCK(blk)) + { + g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end); + printf(" - flow %p : 0x%08lx -> 0x%08lx\n", blk, start, end); + } + else + { + if (order != BVO_OUT) + { + printf(" - virtual %p\n", blk); + *pad += 1; + } + else *pad -= 1; + + } + + fflush(NULL); + + return true; } @@ -580,6 +644,9 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines, block = build_instruction_block(list, start, end, VMPA_MAX); g_binary_routine_set_basic_blocks(routines[i], block); + + //g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 }); + gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); } |