summaryrefslogtreecommitdiff
path: root/src/analysis/decomp
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/decomp')
-rw-r--r--src/analysis/decomp/il.c153
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);