diff options
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/blocks/flow.c | 2 | ||||
-rw-r--r-- | src/analysis/decomp/il.c | 51 | ||||
-rw-r--r-- | src/analysis/disass/macro.c | 14 |
3 files changed, 58 insertions, 9 deletions
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c index 49b9c6b..4df729c 100644 --- a/src/analysis/blocks/flow.c +++ b/src/analysis/blocks/flow.c @@ -510,7 +510,7 @@ bool g_flow_block_follow(GFlowBlock *block, const GInstrBlock *list, BlockFollow if (mask & BFP_ENTER) result = callback(block, BFP_ENTER, data); - dcount = g_arch_instruction_get_destinations(block->last, &dests, &types); + dcount = g_arch_instruction_get_destinations(block->last, &dests, &types, NULL); for (i = 0; i < dcount && result; i++) switch (types[i]) diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c index 64f6398..f241e46 100644 --- a/src/analysis/decomp/il.c +++ b/src/analysis/decomp/il.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * il.h - mise en place d'un langage intermédiaire * - * Copyright (C) 2012 Cyrille Bagard + * Copyright (C) 2012-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -27,7 +27,9 @@ #include "../blocks/flow.h" #include "../blocks/virtual.h" #include "../../decomp/expr/block.h" +#include "../../decomp/expr/immediate.h" #include "../../decomp/instr/ite.h" +#include "../../decomp/instr/switch.h" @@ -328,7 +330,7 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon GArchInstruction *first; /* Première instruction du lot */ GArchInstruction *last; /* Dernière instruction du lot */ vmpa_t max; /* Adresse de fin du bloc */ - GArchInstruction *iter; /* Boucle de parcours */ + GArchInstruction *iter; /* Boucle de parcours #1 */ GDecInstruction *decomp; /* Dernier résultat de décomp. */ GInstrBlock *sub_parent; /* Groupe des sous-branches */ GHashTable *sub_shared; /* Allocations communes */ @@ -338,6 +340,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon GArchInstruction *next; /* Instruction de branchement */ vmpa_t next_addr; /* Adresse de cette instruct° */ GInstrBlock *next_block; /* Sous-bloc basique direct */ + GArchInstruction **dests; /* Instr. visée par une autre */ + link_extra_info *info; /* Compléments pour les liens */ + size_t dcount; /* Nombre de liens de dest. */ + size_t i; /* Boucle de parcours #2 */ + GDecInstruction *case_dinstr; /* Décompilation 'case' */ + GDecExpression *case_value; /* Valeur d'aiguillage */ instrs = g_flow_block_get_all_instructions_list(block); g_flow_block_get_boundary(block, &first, &last); @@ -406,6 +414,45 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon } + /* switch ... case ... */ + else if (G_IS_SWITCH_INSTRUCTION(decomp)) + { + sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); + sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, + (GEqualFunc)g_arch_register_equal, + g_object_unref, g_object_unref); + + dcount = g_arch_instruction_get_destinations(last, &dests, NULL, &info); + + for (i = 0; i < dcount; i++) + { + g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); + next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false); + + if (next_block != NULL) + { + sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); + case_dinstr = decompiled_basic_block(next_block, sub_ctx); + g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); + g_object_unref(G_OBJECT(sub_ctx)); + + if (info[i].imm != NULL) + { + case_value = G_DEC_EXPRESSION(g_imm_expression_new(info[i].imm)); + g_switch_instruction_add_case(G_SWITCH_INSTRUCTION(decomp), + case_value, case_dinstr, next_addr); + } + else g_switch_instruction_set_default_case(G_SWITCH_INSTRUCTION(decomp), + case_dinstr); + + } + + } + + g_hash_table_unref(sub_shared); + + } + /* Renvoi des instructions mises en place */ return g_dec_context_get_decomp_instrs(ctx); diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 0fef9a0..14dad95 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -150,7 +150,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, if (!g_arch_instruction_has_destinations(iter)) continue; - dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); for (i = 0; i < dcount; i++) switch (types[i]) @@ -360,7 +360,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta /* Adaptations en fonction du type de bifurcation */ - dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); next_addr = 0; cases_branches = NULL; @@ -439,20 +439,22 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta DELAYED_BLOCK_ADDING(result, result_cached, block); - //printf(" --- cases --- start\n"); + printf(" --- cases --- start\n"); next_addr = compute_first_common_addr_in_group(cases_branches, cases_count); - //printf(" stop :: 0x%08llx\n", next_addr); + printf(" stop :: 0x%08llx\n", next_addr); parent = block; group = g_virtual_block_new(); for (j = 0; j < cases_count; j++) { - //printf(" ## %zu\n", j); + printf(" ## %zu...", j); block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr); + printf(" %p\n", block); + if (block != NULL) g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); @@ -469,7 +471,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta else g_object_unref(G_OBJECT(group)); - //printf(" --- cases --- end\n"); + printf(" --- cases --- end\n"); free(cases_branches); |