From 3467b0cdb09976faccc6dbef09315cc38dbe6fb5 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 5 Feb 2013 23:01:48 +0000 Subject: Rewritten many parts of the process which cut code into basic blocks. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@338 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 16 ++ src/analysis/decomp/reduce.c | 2 +- src/analysis/disass/macro.c | 456 +++++++++++++++++++++++++++---------------- src/arch/dalvik/register.c | 2 +- src/decomp/instr/switch.c | 4 +- 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 + + * 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 * 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 #include @@ -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); -- cgit v0.11.2-87-g4458