summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--src/analysis/decomp/reduce.c2
-rw-r--r--src/analysis/disass/macro.c456
-rw-r--r--src/arch/dalvik/register.c2
-rw-r--r--src/decomp/instr/switch.c4
5 files changed, 307 insertions, 173 deletions
diff --git a/ChangeLog b/ChangeLog
index 90a1cb1..d830550 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+13-02-05 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/analysis/decomp/reduce.c:
+ Avoid to remove variable definitions with immediate values in switch cases
+ when reducing expressions.
+
+ * src/analysis/disass/macro.c:
+ Rewrite many parts of the process which cut code into basic blocks :
+ improve it and fix it for special cases with switch cases.
+
+ * src/arch/dalvik/register.c:
+ Fix a typo, and thus a bug when comparing registers.
+
+ * src/decomp/instr/switch.c:
+ Activate some visiting functions.
+
13-02-03 Cyrille Bagard <nocbos@gmail.com>
* src/analysis/decomp/decompiler.c:
diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c
index 2d6fce3..c372f2a 100644
--- a/src/analysis/decomp/reduce.c
+++ b/src/analysis/decomp/reduce.c
@@ -332,7 +332,7 @@ static void replace_useless_variable(GDecInstruction *block, GHashTable *table)
while (g_hash_table_iter_next(&iter, (gpointer *)&var, (gpointer *)&val))
{
- replace = G_IS_IMM_EXPRESSION(val->value);
+ replace = (G_IS_IMM_EXPRESSION(val->value) && (val->used_counter > 1));
replace |= (val->used_counter == 2); /* 1 assign. + 1 usage */
if (!replace) continue;
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 993f70f..8766ed9 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -24,6 +24,7 @@
#include "macro.h"
+#include <malloc.h>
#include <string.h>
@@ -32,6 +33,40 @@
+/* ------------------------ COUVERTURE D'UNE ZONE A DECOUPER ------------------------ */
+
+
+/* Bornes d'une zone à couvrir */
+typedef struct _code_coverage
+{
+ vmpa_t start; /* Adresse de départ */
+
+ vmpa_t *ends; /* Adresses butoir de fin */
+ size_t ends_count; /* Quantité de fins possibles */
+
+} code_coverage;
+
+
+/* Met en place les délimitations d'une zone de code. */
+static code_coverage *create_code_coverage(vmpa_t, vmpa_t);
+
+/* Crée une copie d'une couverture de zone de code. */
+static code_coverage *dup_code_coverage(vmpa_t, const code_coverage *);
+
+/* Détruit des délimitations d'une zone de code. */
+static void delete_code_coverage(code_coverage *);
+
+/* Indique si une adresse est hors zone ou non. */
+static bool code_coverage_stop_here(const code_coverage *, const vmpa_t *);
+
+/* Ajoute une adresse butoir pour la zone à couvrir. */
+static void add_ending_address_code_coverage(code_coverage *, const vmpa_t *);
+
+
+
+/* ------------------------- SUIVI DES FLOTS D'INSTRUCTIONS ------------------------- */
+
+
/* Indications sur une branche */
typedef struct _branch_info
{
@@ -41,6 +76,23 @@ typedef struct _branch_info
} branch_info;
+/* Indique si une adresse est retenue comme point de passage. */
+static bool is_addr_in_branch(const branch_info *, const vmpa_t *);
+
+/* Identifie les différents points de passage d'une branche. */
+static void find_next_jumps(GArchInstruction *, vmpa_t, const code_coverage *, branch_info *);
+
+/* Retrouve le point de ralliement entre deux branches. */
+static vmpa_t compute_first_common_addr(branch_info *, branch_info *);
+
+/* Retrouve le point de ralliement entre un groupe de branches. */
+static vmpa_t compute_first_common_addr_in_group(const branch_info *, size_t);
+
+
+
+/* --------------------------- DECOUPAGE EN BLOCS DE CODE --------------------------- */
+
+
/**
* Macros pour le marquage des instructions traitées.
* Dans un soucis d'optimisation, on ne traite que les instructions
@@ -51,29 +103,159 @@ typedef struct _branch_info
#define MACRO_CLEAR_PROCESSED(_instr) g_object_set_data(G_OBJECT(_instr), "macro_done", NULL)
-/* Indique si une adresse est retenue comme point de passage. */
-static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool, size_t *);
+/* Procède à la définition de bloc regroupant des instructions. */
+static GInstrBlock *build_instruction_block(GArchInstruction *, const code_coverage *);
-/* Identifie les différents points de passage d'une branche. */
-static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *);
-/* Retrouve le point de ralliement entre deux branches. */
-static vmpa_t compute_first_common_addr(branch_info *, branch_info *);
-/* Retrouve le point de ralliement entre un groupe de branches. */
-static vmpa_t compute_first_common_addr_in_group(const branch_info *, size_t);
+/* ---------------------------------------------------------------------------------- */
+/* COUVERTURE D'UNE ZONE A DECOUPER */
+/* ---------------------------------------------------------------------------------- */
-/* Procède à la définition de bloc regroupant des instructions. */
-static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t);
+/******************************************************************************
+* *
+* Paramètres : start = adresse du début de la zone à couvrir. *
+* end = adresse de fin de la zone à couvrir (exclusive). *
+* *
+* Description : Met en place les délimitations d'une zone de code. *
+* *
+* Retour : Couverture d'une zone de code. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static code_coverage *create_code_coverage(vmpa_t start, vmpa_t end)
+{
+ code_coverage *result; /* Couverture à retourner */
+
+ result = (code_coverage *)calloc(1, sizeof(code_coverage));
+
+ result->start = start;
+
+ result->ends = (vmpa_t *)calloc(1, sizeof(vmpa_t));
+ result->ends_count = 1;
+
+ result->ends[0] = end;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : start = nouvelle adresse de début, plus profonde. *
+* src = informations de couverture à consulter. *
+* *
+* Description : Crée une copie d'une couverture de zone de code. *
+* *
+* Retour : Couverture d'une zone de code copiée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static code_coverage *dup_code_coverage(vmpa_t start, const code_coverage *src)
+{
+ code_coverage *result; /* Couverture à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = (code_coverage *)calloc(1, sizeof(code_coverage));
+
+ result->start = start;
+
+ result->ends = (vmpa_t *)calloc(src->ends_count, sizeof(vmpa_t));
+ result->ends_count = src->ends_count;
+
+ for (i = 0; i < result->ends_count; i++)
+ result->ends[i] = src->ends[i];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coverage = structure à libérer de la mémoire. *
+* *
+* Description : Détruit des délimitations d'une zone de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_code_coverage(code_coverage *coverage)
+{
+ free(coverage->ends);
+
+ free(coverage);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coverage = informations de couverture à consulter. *
+* addr = adresse à tester. *
+* *
+* Description : Indique si une adresse est hors zone ou non. *
+* *
+* Retour : true si l'adresse ne doit pas être couverte, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool code_coverage_stop_here(const code_coverage *coverage, const vmpa_t *addr)
+{
+ void *ptr; /* Résultat des recherches */
+
+ ptr = bsearch(addr, coverage->ends, coverage->ends_count,
+ sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+
+ return (ptr != NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coverage = informations de couverture à compléter. *
+* addr = adresse à ajouter. *
+* *
+* Description : Ajoute une adresse butoir pour la zone à couvrir. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void add_ending_address_code_coverage(code_coverage *coverage, const vmpa_t *addr)
+{
+ coverage->ends = (vmpa_t *)realloc(coverage->ends, ++coverage->ends_count * sizeof(vmpa_t));
+ coverage->ends[coverage->ends_count - 1] = *addr;
+
+ qsort(coverage->ends, coverage->ends_count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SUIVI DES FLOTS D'INSTRUCTIONS */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : info = informations à consulter. *
* addr = adresse à rechercher. *
-* fast = autorise une recherche rapide. *
-* pos = enregistrement de la position de la trouvaille. [OUT] *
* *
* Description : Indique si une adresse est retenue comme point de passage. *
* *
@@ -83,31 +265,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,
* *
******************************************************************************/
-static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast, size_t *pos)
+static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- void *ptr; /* Résultat des recherches */
result = false;
- if (!fast)
- for (i = 0; i < info->count && !result; i++)
- {
- result = (info->jumps[i] == *addr);
- if (result && pos != NULL)
- *pos = i;
- }
-
- else
- {
- ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
- result = (ptr != NULL);
-
- if (result && pos != NULL)
- *pos = (ptr - ((void *)info->jumps)) / sizeof(vmpa_t);
-
- }
+ for (i = 0; i < info->count && !result; i++)
+ result = (info->jumps[i] == *addr);
return result;
@@ -116,10 +282,10 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool
/******************************************************************************
* *
-* Paramètres : instrs = ensemble des instructions d'assemblage. *
-* start = adresse de début du bloc. *
-* end = adresse de fin du bloc (exclusive). *
-* count = nombre de sauts détectés. [OUT] *
+* Paramètres : instrs = ensemble des instructions d'assemblage. *
+* start = adresse de début du bloc. *
+* coverage = liste des adresses de fin butoir. *
+* count = nombre de sauts détectés. [OUT] *
* *
* Description : Identifie les différents points de passage d'une branche. *
* *
@@ -129,17 +295,17 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool
* *
******************************************************************************/
-static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info)
+static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, const code_coverage *coverage, branch_info *info)
{
GArchInstruction *iter; /* Boucle de parcours #1 */
+ vmpa_t addr; /* Adresse d'une instruction */
GArchInstruction **dests; /* Instr. visée par une autre */
InstructionLinkType *types; /* Type de lien entre lignes */
size_t dcount; /* Nombre de liens de dest. */
size_t i; /* Boucle de parcours #2 */
- vmpa_t addr; /* Adresse de la destination */
/* On évite de boucler... */
- if (is_addr_in_branch(info, &start, false, NULL))
+ if (is_addr_in_branch(info, &start))
return;
info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
@@ -148,8 +314,13 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
/* On suit le flot jusqu'à la prochaine bifurcation */
for (iter = g_arch_instruction_find_by_address(instrs, start, true);
iter != NULL;
- iter = g_arch_instruction_get_next_iter(instrs, iter, end))
+ iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX))
{
+ g_arch_instruction_get_location(iter, NULL, NULL, &addr);
+
+ if (code_coverage_stop_here(coverage, &addr))
+ break;
+
if (g_arch_instruction_is_return(iter))
{
iter = NULL;
@@ -170,7 +341,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
case ILT_JUMP_IF_TRUE:
case ILT_JUMP_IF_FALSE:
g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- find_next_jumps(instrs, addr, end, info);
+ find_next_jumps(instrs, addr, coverage, info);
break;
default:
@@ -183,10 +354,10 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
}
/* Si on termine... */
- if (iter != NULL && !is_addr_in_branch(info, &end, false, NULL))
+ if (iter != NULL && !is_addr_in_branch(info, &addr))
{
info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
- info->jumps[info->count - 1] = end;
+ info->jumps[info->count - 1] = addr;
}
}
@@ -213,11 +384,8 @@ static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)
/* Valeur conceptuellement impossible à renvoyer */
result = VMPA_MAX;
- //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
- //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
-
for (i = 0; i < a->count && result == VMPA_MAX; i++)
- if (is_addr_in_branch(b, &a->jumps[i], false, NULL))
+ if (is_addr_in_branch(b, &a->jumps[i]))
result = a->jumps[i];
return result;
@@ -248,15 +416,12 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
/* Valeur conceptuellement impossible à renvoyer */
result = VMPA_MAX;
- //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
- //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
-
for (i = 0; i < list[0].count && result == VMPA_MAX; i++)
{
keep = true;
for (j = 1; j < count && keep; j++)
- keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false, NULL);
+ keep = is_addr_in_branch(&list[j], &list[0].jumps[i]);
if (keep)
result = list[0].jumps[i];
@@ -269,56 +434,15 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
+/* ---------------------------------------------------------------------------------- */
+/* DECOUPAGE EN BLOCS DE CODE */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : list = liste d'ensembles de jalons à parcourir. *
-* count = taille de cette liste. *
-* *
-* Description : Retrouve le point de ralliement entre un groupe de branches. *
-* *
-* Retour : Adresse commune aux branches. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_t count, vmpa_t max)
-{
- vmpa_t result; /* Adresse trouvée à retourner */
- size_t found_pos; /* Plus petit tronc commun */
- size_t i; /* Boucle de parcours */
- size_t pos; /* Emplacement du cas commun */
-
- result = max;
-
- found_pos = list[cur].count;
-
- for (i = 0; i < count; i++)
- {
- if (i == cur) continue;
-
- if (is_addr_in_branch(&list[cur], &list[i].jumps[0], false, &pos))
- {
- if (pos < found_pos)
- result = list[i].jumps[0];
- }
-
- }
-
- return result;
-
-}
-
-
-
-/******************************************************************************
-* *
-* Paramètres : instrs = ensemble des instructions d'assemblage. *
-* start = adresse de début du bloc. *
-* end = adresse de fin du bloc (exclusive). *
-* stop = adresse d'arrêt en cas de saut ou VMPA_MAX. *
+* Paramètres : instrs = ensemble des instructions d'assemblage. *
+* coverage = délimitations de la zone à couvrir. *
* *
* Description : Procède à la définition de bloc regroupant des instructions. *
* *
@@ -328,7 +452,7 @@ static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_
* *
******************************************************************************/
-static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop)
+static GInstrBlock *build_instruction_block(GArchInstruction *instrs, const code_coverage *coverage)
{
GInstrBlock *result; /* Regroupement à retourner */
GInstrBlock *result_cached; /* Temporisation pour unicité */
@@ -344,13 +468,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
GInstrBlock *block; /* Nouveau bloc mis en place */
GInstrBlock *parent; /* Mémorisation pour les liens */
GInstrBlock *group; /* Regroupement de blocs */
+ size_t not_handled; /* Quantité de liens non gérés */
+ vmpa_t next_addr; /* Prochaine instruction visée */
branch_info *cases_branches; /* Branches d'un aiguillage */
size_t cases_count; /* Nombre d'aiguillages */
branch_info true_branch; /* Branche 'condition vraie' */
branch_info false_branch; /* Branche 'condition fausse' */
branch_info *excep_branches; /* Branches d'exceptions */
size_t excep_count; /* Nombre d'exceptions */
- vmpa_t next_addr; /* Prochaine instruction visée */
+ code_coverage *sub_coverage; /* Couverture pour les suivants*/
size_t j; /* Boucle de parcours #2 */
vmpa_t stop_addr; /* Adresse de fin de bloc */
@@ -386,16 +512,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
last = NULL;
memset(&main_branch, 0, sizeof(branch_info));
- find_next_jumps(instrs, start, end, &main_branch);
+ find_next_jumps(instrs, coverage->start, coverage, &main_branch);
- //printf("[+] blocking 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop);
-
- for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+ for (iter = g_arch_instruction_find_by_address(instrs, coverage->start, true);
iter != NULL;
)
{
g_arch_instruction_get_location(iter, NULL, NULL, &addr);
- if (addr == stop) break;
+
+ if (code_coverage_stop_here(coverage, &addr)) break;
/* On s'arrêter si l'instruction est déjà décompilée */
if (MACRO_IS_PROCESSED(iter)) break;
@@ -408,7 +533,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
/* On n'approfondit que les chemins qui se séparent */
if (!g_arch_instruction_has_destinations(iter))
{
- iter = g_arch_instruction_get_next_iter(instrs, iter, end);
+ iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX);
continue;
}
@@ -416,7 +541,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL);
- next_addr = 0;
+ not_handled = 0;
+ next_addr = VMPA_MAX;
cases_branches = NULL;
cases_count = 0;
memset(&true_branch, 0, sizeof(branch_info));
@@ -447,18 +573,18 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
cases_branches = (branch_info *)realloc(cases_branches,
++cases_count * sizeof(branch_info));
memset(&cases_branches[cases_count - 1], 0, sizeof(branch_info));
- find_next_jumps(instrs, addr, end, &cases_branches[cases_count - 1]);
+ find_next_jumps(instrs, addr, coverage, &cases_branches[cases_count - 1]);
break;
case ILT_JUMP_IF_TRUE:
g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- find_next_jumps(instrs, addr, end, &true_branch);
+ find_next_jumps(instrs, addr, coverage, &true_branch);
break;
case ILT_JUMP_IF_FALSE:
g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- find_next_jumps(instrs, addr, end, &false_branch);
+ find_next_jumps(instrs, addr, coverage, &false_branch);
break;
case ILT_CATCH_EXCEPTION:
@@ -468,13 +594,16 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
excep_branches = (branch_info *)realloc(excep_branches,
++excep_count * sizeof(branch_info));
memset(&excep_branches[excep_count - 1], 0, sizeof(branch_info));
- find_next_jumps(instrs, addr, end, &excep_branches[excep_count - 1]);
+ find_next_jumps(instrs, addr, coverage, &excep_branches[excep_count - 1]);
- break;
+ /**
+ * Les deux cas sont les seuls à ne pas conduire à une définition de
+ * next_addr, donc on les comptabilise sur un pied d'égalité !
+ */
+ //break;
default:
- if (next_addr == 0)
- next_addr = VMPA_MAX;
+ not_handled++;
break;
}
@@ -493,52 +622,30 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
DELAYED_BLOCK_ADDING(result, result_cached, block);
- printf(" --- cases --- start\n");
-
next_addr = compute_first_common_addr_in_group(cases_branches, cases_count);
- printf(" stop :: 0x%08llx\n", next_addr);
parent = block;
group = g_virtual_block_new();
- do
+ for (i = 0; i < cases_count; i++)
{
- size_t _i, _j;
-
- for (_i = 0; _i < cases_count; _i++)
- {
- printf(" [case %d] : ", _i);
+ sub_coverage = dup_code_coverage(cases_branches[i].jumps[0], coverage);
- for (_j = 0; _j < cases_branches[_i].count; _j++)
- printf("0x%08lx ", cases_branches[_i].jumps[_j]);
+ add_ending_address_code_coverage(sub_coverage, &next_addr);
- printf("\n");
+ for (j = 0; j < cases_count; j++)
+ if (cases_branches[j].jumps[0] != cases_branches[i].jumps[0])
+ add_ending_address_code_coverage(sub_coverage, &cases_branches[j].jumps[0]);
- }
+ block = build_instruction_block(instrs, sub_coverage);
- } while (0);
-
-
- for (j = 0; j < cases_count; j++)
- {
- printf(" ## %zu start=0x%08lx (0x%08lx)...\n", j, cases_branches[j].jumps[0],
- next_addr);
-
- //block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr);
-
- //next_addr = avoid_cases_common_part(cases_branches, j, cases_count, next_addr);
-
- block = build_instruction_block(instrs, cases_branches[j].jumps[0], end,
- avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
-
- printf(" %p (0x%08lx)\n", block,
- avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
+ delete_code_coverage(sub_coverage);
if (block != NULL)
g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
- free(cases_branches[j].jumps);
+ free(cases_branches[i].jumps);
}
@@ -550,23 +657,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
else
g_object_unref(G_OBJECT(group));
- printf(" --- cases --- end\n");
-
-
free(cases_branches);
}
- if (next_addr == VMPA_MAX)
- {
- iter = g_arch_instruction_get_next_iter(instrs, iter, end);
- continue;
- }
-
else if (true_branch.count > 0 || false_branch.count > 0)
{
next_addr = compute_first_common_addr(&true_branch, &false_branch);
- next_addr = MIN(next_addr, end);
/**
* On doit clôturer le bloc renvoyant vers les branches 'true' et 'false' ici.
@@ -582,14 +679,32 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
parent = block;
group = g_virtual_block_new();
- block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr);
+ /* Branche 'true' */
+
+ sub_coverage = dup_code_coverage(true_branch.jumps[0], coverage);
+ add_ending_address_code_coverage(sub_coverage, &next_addr);
+ add_ending_address_code_coverage(sub_coverage, &false_branch.jumps[0]);
+
+ block = build_instruction_block(instrs, sub_coverage);
if (block != NULL)
g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
- block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr);
+ delete_code_coverage(sub_coverage);
+
+ /* Branche 'false' */
+
+ sub_coverage = dup_code_coverage(false_branch.jumps[0], coverage);
+ add_ending_address_code_coverage(sub_coverage, &next_addr);
+ add_ending_address_code_coverage(sub_coverage, &true_branch.jumps[0]);
+
+ block = build_instruction_block(instrs, sub_coverage);
if (block != NULL)
g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
+ delete_code_coverage(sub_coverage);
+
+ /* Conclusion */
+
if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)
{
DELAYED_BLOCK_ADDING(result, result_cached, group);
@@ -601,8 +716,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
free(true_branch.jumps);
free(false_branch.jumps);
- if (next_addr == end) break;
-
}
/* Post-traitements de ILT_CATCH_EXCEPTION */
@@ -621,9 +734,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
for (j = 0; j < excep_count; j++)
{
stop_addr = compute_first_common_addr(&main_branch, &excep_branches[j]);
- //next_addr = MIN(next_addr, end);
- block = build_instruction_block(instrs, excep_branches[j].jumps[0], end, stop_addr);
+ sub_coverage = dup_code_coverage(excep_branches[j].jumps[0], coverage);
+ add_ending_address_code_coverage(sub_coverage, &stop_addr);
+
+ block = build_instruction_block(instrs, sub_coverage);
+
+ delete_code_coverage(sub_coverage);
if (block != NULL)
@@ -638,7 +755,11 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
}
/* Détermination du prochain point de chute */
- iter = g_arch_instruction_find_by_address(instrs, next_addr, true);
+
+ if (not_handled == dcount)
+ iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX);
+ else
+ iter = g_arch_instruction_find_by_address(instrs, next_addr, true);
}
@@ -646,10 +767,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
{
if (!MACRO_IS_PROCESSED(first))
{
- //printf("--close?--\n");
block = g_flow_block_new(instrs, first, last);
MACRO_MARK_AS_PROCESSED(first);
- //printf("--close!--\n");
DELAYED_BLOCK_ADDING(result, result_cached, block);
@@ -657,12 +776,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
}
- if ((result != NULL ? result : result_cached) == NULL)
- {
- //printf("WARNING :: null !\n");
- //exit(0);
- }
-
return (result != NULL ? result : result_cached);
}
@@ -689,6 +802,7 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,
size_t i; /* Boucle de parcours */
vmpa_t start; /* Adresse de départ */
vmpa_t end; /* Adresse de fin */
+ code_coverage *coverage; /* Couverture de zone de code */
GInstrBlock *block; /* Regroupement d'instructions */
for (i = 0; i < count; i++)
@@ -696,9 +810,13 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,
start = g_binary_routine_get_address(routines[i]);
end = start + g_binary_routine_get_size(routines[i]);
- block = build_instruction_block(list, start, end, VMPA_MAX);
+ coverage = create_code_coverage(start, end);
+
+ block = build_instruction_block(list, coverage);
g_binary_routine_set_basic_blocks(routines[i], block);
+ delete_code_coverage(coverage);
+
gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
}
diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c
index 4e91cd4..39363b1 100644
--- a/src/arch/dalvik/register.c
+++ b/src/arch/dalvik/register.c
@@ -192,7 +192,7 @@ int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b
if (a->index < b->index)
result = -1;
- else if (a->index < b->index)
+ else if (a->index > b->index)
result = 1;
else
result = 0;
diff --git a/src/decomp/instr/switch.c b/src/decomp/instr/switch.c
index 4b1662b..b475eae 100644
--- a/src/decomp/instr/switch.c
+++ b/src/decomp/instr/switch.c
@@ -179,7 +179,7 @@ static bool g_switch_instruction_visit(GSwitchInstruction *instr, dec_instr_visi
size_t i; /* Boucle de parcours */
result = true;
- return true;
+
for (i = 0; i < instr->cases_count && result; i++)
result = _g_dec_instruction_visit(instr->cases[i].instrs, G_DEC_INSTRUCTION(instr),
callback, flags, data);
@@ -213,7 +213,7 @@ static bool g_switch_instruction_replace(GSwitchInstruction *instr, GDecInstruct
size_t i; /* Boucle de parcours */
result = false;
- return false;
+
for (i = 0; i < instr->cases_count; i++)
result |= g_dec_instruction_replace(instr->cases[i].instrs, old, new);