diff options
Diffstat (limited to 'src/analysis/decomp')
-rw-r--r-- | src/analysis/decomp/il.c | 153 |
1 files changed, 148 insertions, 5 deletions
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c index f3c2265..6333216 100644 --- a/src/analysis/decomp/il.c +++ b/src/analysis/decomp/il.c @@ -34,6 +34,9 @@ /* --------------------- GESTION DES CONTEXTES DE DECOMPILATION --------------------- */ +/* Détermine les registres utilisés avant leur initialisation. */ +static bool track_used_registers(GFlowBlock *, BlockFollowPosition, GRAccessList **); + @@ -61,9 +64,144 @@ static GDecInstruction *decompiled_basic_block(GInstrBlock *, GDecContext *); /* ---------------------------------------------------------------------------------- */ +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions visité. * +* pos = indication sur la position du parcours. * +* needed = suivi de l'usage des registres entre les blocs. * +* * +* Description : Détermine les registres utilisés avant leur initialisation. * +* * +* Retour : true pour mener un parcours complet. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRAccessList **needed) +{ + GRAccessList *old; /* Ancienne liste remplacée */ + const GRAccessList *accesses; /* Accès divers aux registres */ + size_t count; /* Taille d'un parcours */ + GRAccessList *awaited; /* Satisfactions des besoins */ + reg_access *access; /* Accès à un registre */ + size_t i; /* Boucle de parcours */ + reg_access *found; /* Besoin trouvé ou non */ + + switch (pos) + { + case BFP_ENTER: + g_object_set_data(G_OBJECT(block), "needed_regs", *needed); + break; + + case BFP_FOLLOW: + *needed = g_raccess_list_new(); + break; + + case BFP_BACK: + + old = *needed; + *needed = G_RACCESS_LIST(g_object_get_data(G_OBJECT(block), "needed_regs")); + + g_raccess_list_merge(*needed, old); + g_object_unref(G_OBJECT(old)); + break; + case BFP_EXIT: + g_object_set_data(G_OBJECT(block), "needed_regs", NULL); + + accesses = g_flow_block_list_regs_accesses(block); + count = g_raccess_list_count(accesses); + + awaited = g_flow_block_list_awaited_regs(block); + + for (i = 0; i < count; i++) + { + access = g_raccess_list_get(accesses, i); + + /* Enregistrement des contributions possibles */ + + found = g_raccess_list_find(*needed, access->reg); + + if (found != NULL) + { + /** + * Si un autre bloc avait déjà un besoin, on ne prend note + * qu'une seule fois ! + */ + if (g_raccess_list_find(awaited, access->reg) == NULL) + g_raccess_list_add(awaited, access); + + g_raccess_list_delete(*needed, found); + + } + + /* Ajoute les besoins du bloc */ + if (access->first_access == RAT_READ) + g_raccess_list_add(*needed, access); + + } + + /* + do + { + vmpa_t start, end; + + g_flow_block_get_boundary_addresses(block, &start, &end); + + printf(" -> flow (%d) : 0x%08x - 0x%08x | needed = %zu - provided = %zu\n", + pos, start, end, + g_raccess_list_count(*needed), g_raccess_list_count(awaited)); + + } + while (0); + */ + + break; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble des instructions d'assemblage à traiter. * +* start = adresse de départ de la routine visée. * +* * +* Description : Procède à la décompilation d'une routinée déterminée. * +* * +* Retour : Instructions créées ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDecContext *init_decomp_context(const GInstrBlock *list, vmpa_t start) +{ + GDecContext *result; /* Contexte pour la décompil. */ + GInstrBlock *first; /* Bloc de départ du flot */ + GRAccessList *needed; /* Registres inter-blocs */ + + result = NULL; + + first = g_instr_block_find_by_addr(list, start, true); + + needed = g_raccess_list_new(); + + g_flow_block_follow(G_FLOW_BLOCK(first), list, BFP_ENTER | BFP_EXIT | BFP_EXIT, + (flow_block_follow_cb)track_used_registers, &needed); + + g_object_unref(G_OBJECT(needed)); + + + return result; + +} @@ -165,14 +303,15 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon { next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE); - printf("@ 0x%08llx : true : %p\n", max, next); + //printf("@ 0x%08llx : true : %p\n", max, next); true_dinstr = NULL; if (next != NULL) { g_arch_instruction_get_location(next, NULL, NULL, &next_addr); - next_block = g_instr_block_find_by_addr(g_instr_block_get_links_block(block), next_addr); + next_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); + next_block = g_instr_block_find_by_addr(next_parent, next_addr, false); if (next_block != NULL) true_dinstr = decompiled_basic_block(next_block, ctx); @@ -181,26 +320,28 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE); - printf("@ 0x%08llx : false : %p\n", max, next); + //printf("@ 0x%08llx : false : %p\n", max, next); false_dinstr = NULL; if (next != NULL) { g_arch_instruction_get_location(next, NULL, NULL, &next_addr); - next_block = g_instr_block_find_by_addr(g_instr_block_get_links_block(block), next_addr); + next_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); + next_block = g_instr_block_find_by_addr(next_parent, next_addr, false); if (next_block != NULL) false_dinstr = decompiled_basic_block(next_block, ctx); } + /* printf(" -> ite : %p + %p\n", true_dinstr, false_dinstr); printf(" -> ite : %s + %s\n", true_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(true_dinstr)) : "none", false_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(false_dinstr)) : "none"); - + */ g_ite_instruction_set_branches(G_ITE_INSTRUCTION(decomp), true_dinstr, false_dinstr); @@ -327,6 +468,8 @@ GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeForma blocks = g_binary_routine_get_basic_blocks(routine); + init_decomp_context(blocks, g_binary_routine_get_address(routine)); + result = decompiled_basic_block(blocks, context); g_object_unref(context); |