diff options
36 files changed, 1144 insertions, 94 deletions
@@ -1,3 +1,64 @@ +12-11-28 Cyrille Bagard <nocbos@gmail.com> + + * src/analysis/decomp/decompiler.c: + Start the decompilation process here. + + * src/analysis/decomp/il.c: + * src/analysis/decomp/il.h: + New entries: follow the excution flow to decompile instructions. + + * src/analysis/decomp/Makefile.am: + Add the il.[ch] and reduce.[ch] files to libanalysisdecomp_la_SOURCES. + + * src/analysis/decomp/reduce.c: + * src/analysis/decomp/reduce.h: + New entries: to be completed. + + * src/analysis/routine.c: + Update code. + + * src/arch/archbase.c: + * src/arch/archbase.h: + Compare addresses. + + * src/arch/dalvik/context.c: + Break the generator of free variables. + + * src/arch/dalvik/decomp/if.c: + * src/arch/dalvik/decomp/invoke.c: + * src/arch/dalvik/decomp/move.c: + * src/arch/dalvik/decomp/translate.h: + * src/arch/dalvik/instruction.c: + Support more instructions during the decompilation process. + + * src/decomp/expr/access.c: + * src/decomp/expr/arithm.c: + * src/decomp/expr/array.c: + * src/decomp/expr/assign.c: + * src/decomp/expr/block.c: + * src/decomp/expr/call.c: + * src/decomp/expr/cond.c: + * src/decomp/expr/immediate.c: + * src/decomp/expr/pseudo.c: + * src/decomp/expr/return.c: + * src/decomp/expr/text.c: + Update code. + + * src/decomp/instr/ite.c: + * src/decomp/instr/ite.h: + Define the two code blocks (then/else) relative to the instruction. + + * src/decomp/instruction.c: + * src/decomp/instruction.h: + * src/decomp/instruction-int.h: + Begin to implement a visitor pattern. Update the code for rendering. + + * src/decomp/lang/java.c: + * src/decomp/output.c: + * src/decomp/output.h: + * src/decomp/output-int.h: + Start and finish code block. + 12-11-25 Cyrille Bagard <nocbos@gmail.com> * src/gui/panels/panel.c: diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am index 7b797bd..27388d6 100755 --- a/src/analysis/decomp/Makefile.am +++ b/src/analysis/decomp/Makefile.am @@ -2,7 +2,9 @@ noinst_LTLIBRARIES = libanalysisdecomp.la libanalysisdecomp_la_SOURCES = \ - decompiler.h decompiler.c + decompiler.h decompiler.c \ + il.h il.c \ + reduce.h reduce.c libanalysisdecomp_la_LDFLAGS = diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index 8e574c0..91a9163 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * decompiler.c - encadrement des phases de décompilation * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * @@ -32,7 +32,9 @@ #include <i18n.h> +#include "il.h" #include "../../decomp/output.h" +#include "../../decomp/expr/block.h" #include "../../decomp/lang/java.h" /* FIXME : remme ! */ #include "../../format/format.h" @@ -138,7 +140,11 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c size_t i; GDecContext *context; /* Contexte pour la décompil. */ - GDecInstruction *instr; + GDecInstruction *dinstrs; + + GArchInstruction *instrs; /* Instructions natives */ + + vmpa_t max; /* Première adresse à écarter */ format = g_loaded_binary_get_format(binary); proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); @@ -152,7 +158,28 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c { context = g_arch_processor_get_decomp_context(proc); - instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); + g_object_set_data(G_OBJECT(context), "format", format); + g_object_set_data(G_OBJECT(context), "routine", routines[i]); + g_dec_context_set_max_address(context, max); + + instrs = g_binary_routine_get_instructions(routines[i]); + + max = g_binary_routine_get_address(routines[i]) + + g_binary_routine_get_size(routines[i]); + + printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i])); + + dinstrs = build_decompiled_block(instrs, + g_binary_routine_get_address(routines[i]), + max, VMPA_MAX, context); + + //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); + + + + g_binary_routine_set_decomp_instructions(routines[i], dinstrs); + + if (context != NULL) g_object_unref(context); diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c new file mode 100644 index 0000000..d9b9588 --- /dev/null +++ b/src/analysis/decomp/il.c @@ -0,0 +1,382 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * il.h - mise en place d'un langage intermédiaire + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "il.h" + + +#include <malloc.h> +#include <stdlib.h> +#include <string.h> + + +#include "../../decomp/expr/block.h" +#include "../../decomp/instr/ite.h" + + + +/* Indications sur une branche */ +typedef struct _branch_info +{ + vmpa_t *jumps; /* Jalons de la branche */ + size_t count; /* Quantité de ces jalons */ + +} branch_info; + + +/* Indique si une adresse est retenue comme point de passage. */ +static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool); + +/* 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 *); + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : info = informations à consulter. * +* addr = adresse à rechercher. * +* fast = autorise une recherche rapide. * +* * +* Description : Indique si une adresse est retenue comme point de passage. * +* * +* Retour : true si le jalon est déjà dans la liste, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast) +{ + 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); + + else + { + ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); + result = (ptr != NULL); + } + + return result; + +} + + +/****************************************************************************** +* * +* 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] * +* * +* Description : Identifie les différents points de passage d'une branche. * +* * +* Retour : Jalons dans le flot d'exécution. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info) +{ + GArchInstruction *iter; /* Boucle de parcours #1 */ + 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)) + return; + + info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); + info->jumps[info->count - 1] = start; + + /* 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)) + { + if (!g_arch_instruction_has_destinations(iter)) + continue; + + dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + + for (i = 0; i < dcount; i++) + switch (types[i]) + { + case ILT_EXEC_FLOW: + case ILT_JUMP: + 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); + break; + + default: + break; + + } + + break; + + } + + /* Si on termine... */ + if (iter != NULL && !is_addr_in_branch(info, &end, false)) + { + info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); + info->jumps[info->count - 1] = end; + } + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier ensemble de jalons à parcourir. * +* b = second ensemble de jalons à parcourir. * +* * +* Description : Retrouve le point de ralliement entre deux branches. * +* * +* Retour : Adresse commune à deux branches. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b) +{ + vmpa_t result; /* Adresse trouvée à retourner */ + size_t i; /* Boucle de parcours */ + + /* 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)) + result = a->jumps[i]; + + return result; + +} + + + +#include "../../arch/processor.h" + + +/****************************************************************************** +* * +* 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. * +* ctx = contexte de soutien à associer à l'opération. * +* * +* Description : Procède à la décompilation basique d'un bloc déterminé. * +* * +* Retour : Instructions créées et enregistrées, ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop, GDecContext *ctx) +{ + GDecInstruction *result; /* Instructions décompilées */ + GArchInstruction *iter; /* Boucle de parcours */ + + GDecInstruction *pite; /* IfThenElse potientiel... */ + + 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 */ + vmpa_t addr; /* Adresse de la destination */ + + branch_info true_branch; /* Branche 'condition vraie' */ + branch_info false_branch; /* Branche 'condition fausse' */ + GDecInstruction *true_dinstr; /* Décompilation 'cond vraie' */ + GDecInstruction *false_dinstr; /* Décompilation 'cond fausse' */ + + vmpa_t next_addr; /* Prochaine instruction visée */ + + GDecInstruction *first; /* Première décompilation */ + GDecInstruction *dinstr; /* Nouvelle décompilation */ + + + GExeFormat *format; /* Format du binaire fourni */ + GArchProcessor *proc; /* Architecture du binaire */ + GDecContext *context; /* Contexte pour la décompil. */ + + + result = NULL; + + printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop); + + for (iter = g_arch_instruction_find_by_address(instrs, start, true); + iter != NULL; + ) + { + /* On s'arrêter si l'instruction est déjà décompilée */ + if (g_object_get_data(G_OBJECT(iter), "decomp_done") != NULL) break; + g_object_set_data(G_OBJECT(iter), "decomp_done", iter); + + pite = g_arch_instruction_decompile(iter, ctx); + + g_arch_instruction_get_location(iter, NULL, NULL, &addr); + printf(" --- decomp %p @ 0x%08llx\n", pite, addr); + + /* 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); + continue; + } + + /* Adaptations en fonction du type de bifurcation */ + + dcount = g_arch_instruction_get_destinations(iter, &dests, &types); + + next_addr = 0; + memset(&true_branch, 0, sizeof(branch_info)); + memset(&false_branch, 0, sizeof(branch_info)); + + for (i = 0; i < dcount; i++) + switch (types[i]) + { + case ILT_EXEC_FLOW: + case ILT_JUMP: + g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); + break; + + case ILT_JUMP_IF_TRUE: + g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); + find_next_jumps(instrs, addr, end, &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); + break; + + default: + next_addr = VMPA_MAX; + break; + + } + + 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); + + format = g_object_get_data(G_OBJECT(ctx), "format"); + proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); + + context = g_arch_processor_get_decomp_context(proc); + + g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); + g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); + g_dec_context_set_max_address(context, next_addr); + + true_dinstr = build_decompiled_block(instrs, true_branch.jumps[0], + end, next_addr, context); + + + context = g_arch_processor_get_decomp_context(proc); + + g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); + g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); + g_dec_context_set_max_address(context, next_addr); + + false_dinstr = build_decompiled_block(instrs, false_branch.jumps[0], + end, next_addr, context); + + + printf("{branch : %p (0x%08llx) | %p (0x%08llx)\n", + true_dinstr, true_branch.jumps[0], + false_dinstr, false_branch.jumps[0]); + + g_ite_instruction_set_branches(G_ITE_INSTRUCTION(pite), true_dinstr, false_dinstr); + + if (next_addr == end) break; + + } + + /* Détermination du prochain point de chute */ + + if (next_addr == stop) break; + + iter = g_arch_instruction_find_by_address(instrs, next_addr, true); + + } + + + + + first = g_dec_context_get_decomp_instrs(ctx); + + printf(" ... context instr : %p\n", first); + + for (dinstr = first; + dinstr != NULL; + dinstr = g_dec_instruction_get_next_iter(first, dinstr)) + { + if (result == NULL) result = g_expr_block_new(dinstr); + else g_expr_block_add_item(G_EXPR_BLOCK(result), dinstr); + + } + + printf(" ... return %p\n", result); + + return result; + +} diff --git a/src/analysis/decomp/il.h b/src/analysis/decomp/il.h new file mode 100644 index 0000000..4f38b4f --- /dev/null +++ b/src/analysis/decomp/il.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * il.h - prototypes pour la mise en place d'un langage intermédiaire + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DECOMP_IL_H +#define _ANALYSIS_DECOMP_IL_H + + +#include "../../arch/instruction.h" +#include "../../decomp/instruction.h" + + + +/* Procède à la décompilation basique d'un bloc déterminé. */ +GDecInstruction *build_decompiled_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t, GDecContext *); + + + +#endif /* _ANALYSIS_DECOMP_IL_H */ diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c new file mode 100644 index 0000000..926650d --- /dev/null +++ b/src/analysis/decomp/reduce.c @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * reduce.c - réduction de l'usage des [pseudo]-registres + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "reduce.h" + + +#if 0 + + + +/* Mémorisation de l'usage de chaque variable */ +typedef struct _var_usage +{ + GDecInstruction *var; /* Variable manipulée */ + + size_t ref_counter; /* Décompte des utilisations */ + GDecInstruction *creation; /* Emplacement de la création */ + GDecInstruction *usage; /* Lieu de dernère utilisation */ + +} var_usage; + +/* Réduction des usages */ +typedef struct _usage_reduc +{ + + + +} usage_reduc; + + +#endif + + diff --git a/src/analysis/decomp/reduce.h b/src/analysis/decomp/reduce.h new file mode 100644 index 0000000..aa13d7f --- /dev/null +++ b/src/analysis/decomp/reduce.h @@ -0,0 +1,30 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * reduce.h - prototypes pour la réduction de l'usage des [pseudo]-registres + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DECOMP_REDUCE_H +#define _ANALYSIS_DECOMP_REDUCE_H + + + + +#endif /* _ANALYSIS_DECOMP_REDUCE_H */ diff --git a/src/analysis/routine.c b/src/analysis/routine.c index a21b6e7..7a191c9 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -998,7 +998,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang, g_lang_output_start_routine_body(lang, buffer, line); if (routine->dinstr != NULL) - g_dec_instruction_print(routine->dinstr, buffer, NULL, lang); + g_dec_instruction_print(routine->dinstr, buffer, line, lang); g_lang_output_end_routine_body(lang, buffer); diff --git a/src/arch/archbase.c b/src/arch/archbase.c index 6241164..e422971 100644 --- a/src/arch/archbase.c +++ b/src/arch/archbase.c @@ -31,6 +31,37 @@ /****************************************************************************** * * +* Paramètres : a = première adresse à comparer. * +* b = seconde adresse à comparer. * +* * +* Description : Etablit la comparaison entre deux adresses. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int compare_vmpa(const vmpa_t *a, const vmpa_t *b) +{ + int result; /* Bilan à retourner */ + + if (*a < *b) + result = -1; + + else if (*a == *b) + result = 0; + + else + result = 1; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : addr = adresse virtuelle ou physique à traiter. * * msize = taille de cette adresse. * * buffer = chaîne de caractères à constituer. [OUT] * diff --git a/src/arch/archbase.h b/src/arch/archbase.h index 0886e26..b21d52c 100644 --- a/src/arch/archbase.h +++ b/src/arch/archbase.h @@ -80,6 +80,9 @@ typedef enum _AsmSyntax +/* Etablit la comparaison entre deux adresses. */ +int compare_vmpa(const vmpa_t *, const vmpa_t *); + /* Transforme une adresse en chaîne de caractères. */ size_t vmpa_to_string(vmpa_t, MemoryDataSize, char [VMPA_MAX_SIZE]); diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c index c7b5ee6..e5041cb 100644 --- a/src/arch/dalvik/context.c +++ b/src/arch/dalvik/context.c @@ -430,7 +430,7 @@ static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, { found = g_hash_table_lookup(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info))); - if (!assign && found != NULL) + if (/*!assign && */found != NULL) { g_object_ref(G_OBJECT(found)); result = G_DEC_INSTRUCTION(found); diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c index 43406c7..b274ead 100644 --- a/src/arch/dalvik/decomp/if.c +++ b/src/arch/dalvik/decomp/if.c @@ -93,3 +93,69 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte return result; } + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de comparaison d'opérandes. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + CompSignType sign; /* Type d'opération menée */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *op1; /* Premier opérande utilisé */ + GDecInstruction *op2; /* Second opérande utilisé */ + vmpa_t jmp; /* Adresse de saut */ + GDecInstruction *cond; /* Comparaison à restituer */ + + switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr))) + { + case DOP_IF_EQ: + sign = CST_EQ; + break; + case DOP_IF_NE: + sign = CST_NE; + break; + case DOP_IF_LT: + sign = CST_LT; + break; + case DOP_IF_GE: + sign = CST_GE; + break; + case DOP_IF_GT: + sign = CST_GT; + break; + case DOP_IF_LE: + sign = CST_LE; + break; + default: + sign = CST_COUNT; + break; + } + + operand = g_arch_instruction_get_operand(instr, 0); + op1 = g_dec_context_convert_register(ctx, operand, false); + + operand = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, (unsigned int)0); + op2 = g_imm_expression_new(operand); + + operand = g_arch_instruction_get_operand(instr, 2); + jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand);*/ + + cond = g_cond_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2)); + result = g_ite_instruction_new(G_DEC_EXPRESSION(cond), jmp, jmp); + + return result; + +} diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c index c3650b4..6f863be 100644 --- a/src/arch/dalvik/decomp/invoke.c +++ b/src/arch/dalvik/decomp/invoke.c @@ -144,6 +144,66 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr * Paramètres : instr = instruction d'origine à convertir. * * ctx = contexte de la phase de décompilation. * * * +* Description : Décompile une instruction de type 'invoke-static'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + size_t count; /* Quantité d'opérandes */ + GArchOperand *operand; /* Opérande de l'instruction */ + uint32_t index; /* Indice de l'élément visé */ + GDexFormat *format; /* Accès aux constantes */ + GBinRoutine *routine; /* Routine visée par l'appel */ + GDecInstruction *call; /* Représentation de l'appel */ + size_t i; /* Boucle de parcours #2 */ + GArchOperand *arg; /* Argument brut de l'appel */ + GDecInstruction *reg; /* Argument converti */ + + result = NULL; + + /* Récupération de la méthode */ + + count = g_arch_instruction_count_operands(instr); + operand = g_arch_instruction_get_operand(instr, count - 1); + + index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); + + format = G_DEX_FORMAT(g_object_get_data(G_OBJECT(ctx), "format")); + routine = get_routine_from_dex_pool(format, index); + if (routine == NULL) return NULL; + + call = g_routine_call_new(routine); + + /* Ajout des arguments */ + + operand = g_arch_instruction_get_operand(instr, 0); + count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); + + for (i = 0; i < count; i++) + { + arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i); + reg = g_dec_context_convert_register(ctx, arg, false); + + g_routine_call_add_arg(G_ROUTINE_CALL(call), reg); + + } + + return call; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * * Description : Décompile une instruction de type 'invoke-virtual'. * * * * Retour : Instruction mise en place ou NULL. * diff --git a/src/arch/dalvik/decomp/move.c b/src/arch/dalvik/decomp/move.c index f700737..9165447 100644 --- a/src/arch/dalvik/decomp/move.c +++ b/src/arch/dalvik/decomp/move.c @@ -33,6 +33,39 @@ * Paramètres : instr = instruction d'origine à convertir. * * ctx = contexte de la phase de décompilation. * * * +* Description : Décompile une instruction de type 'move'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *src; /* Registre de l'object */ + GDecInstruction *dest; /* Registre de destination */ + + operand = g_arch_instruction_get_operand(instr, 1); + src = g_dec_context_convert_register(ctx, operand, false); + + operand = g_arch_instruction_get_operand(instr, 0); + dest = g_dec_context_convert_register(ctx, operand, true); + + result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * * Description : Décompile une instruction de type 'move-object'. * * * * Retour : Instruction mise en place ou NULL. * diff --git a/src/arch/dalvik/decomp/translate.h b/src/arch/dalvik/decomp/translate.h index 7779ab7..b8753db 100644 --- a/src/arch/dalvik/decomp/translate.h +++ b/src/arch/dalvik/decomp/translate.h @@ -50,12 +50,18 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *, GDecContext /* Décompile une instruction de type 'invoke-direct'. */ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *, GDecContext *); +/* Décompile une instruction de type 'invoke-static'. */ +GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *, GDecContext *); + /* Décompile une instruction de type 'invoke-virtual'. */ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *, GDecContext *); /* Décompile une instruction de type 'iput'. */ GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *, GDecContext *); +/* Décompile une instruction de type 'move'. */ +GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *, GDecContext *); + /* Décompile une instruction de type 'move-object'. */ GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *, GDecContext *); @@ -84,6 +90,9 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *, GDecCo /* Décompile une instruction de comparaison d'opérandes. */ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *, GDecContext *); +/* Décompile une instruction de comparaison d'opérandes. */ +GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *, GDecContext *); + #endif /* _ANALYSIS_DECOMP_RTL_DALVIK_TRANSLATE_H */ diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index f0e679f..5f3a1f4 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -57,7 +57,7 @@ typedef struct _dalvik_instruction static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_NOP] = { 0x00, "nop", NULL }, - [DOP_MOVE] = { 0x01, "move" }, + [DOP_MOVE] = { 0x01, "move", dalvik_decomp_instr_move }, [DOP_MOVE_FROM_16] = { 0x02, "move/from16" }, [DOP_MOVE_16] = { 0x03, "move/16" }, [DOP_MOVE_WIDE] = { 0x04, "move-wide" }, @@ -112,12 +112,12 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_IF_GE] = { 0x35, "if-ge", dalvik_decomp_instr_if }, [DOP_IF_GT] = { 0x36, "if-gt", dalvik_decomp_instr_if }, [DOP_IF_LE] = { 0x37, "if-le", dalvik_decomp_instr_if }, - [DOP_IF_EQZ] = { 0x38, "if-eqz" }, - [DOP_IF_NEZ] = { 0x39, "if-nez" }, - [DOP_IF_LTZ] = { 0x3a, "if-ltz" }, - [DOP_IF_GEZ] = { 0x3b, "if-gez" }, - [DOP_IF_GTZ] = { 0x3c, "if-gtz" }, - [DOP_IF_LEZ] = { 0x3d, "if-lez" }, + [DOP_IF_EQZ] = { 0x38, "if-eqz", dalvik_decomp_instr_if_zero }, + [DOP_IF_NEZ] = { 0x39, "if-nez", dalvik_decomp_instr_if_zero }, + [DOP_IF_LTZ] = { 0x3a, "if-ltz", dalvik_decomp_instr_if_zero }, + [DOP_IF_GEZ] = { 0x3b, "if-gez", dalvik_decomp_instr_if_zero }, + [DOP_IF_GTZ] = { 0x3c, "if-gtz", dalvik_decomp_instr_if_zero }, + [DOP_IF_LEZ] = { 0x3d, "if-lez", dalvik_decomp_instr_if_zero }, [DOP_UNUSED_3E] = { 0x3e, NULL /* unused */ }, [DOP_UNUSED_3F] = { 0x3f, NULL /* unused */ }, [DOP_UNUSED_40] = { 0x40, NULL /* unused */ }, @@ -169,7 +169,7 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_INVOKE_VIRTUAL] = { 0x6e, "invoke-virtual", dalvik_decomp_instr_invoke_virtual }, [DOP_INVOKE_SUPER] = { 0x6f, "invoke-static" }, [DOP_INVOKE_DIRECT] = { 0x70, "invoke-direct", dalvik_decomp_instr_invoke_direct }, - [DOP_INVOKE_STATIC] = { 0x71, "invoke-static" }, + [DOP_INVOKE_STATIC] = { 0x71, "invoke-static", dalvik_decomp_instr_invoke_static }, [DOP_INVOKE_INTERFACE] = { 0x72, "invoke-interface" }, [DOP_UNUSED_73] = { 0x73, NULL /* unused */ }, [DOP_INVOKE_VIRTUAL_RANGE] = { 0x74, "invoke-virtual/range" }, diff --git a/src/decomp/expr/access.c b/src/decomp/expr/access.c index e2cbf19..277209a 100644 --- a/src/decomp/expr/access.c +++ b/src/decomp/expr/access.c @@ -55,7 +55,7 @@ static void g_access_expression_class_init(GAccessExpressionClass *); static void g_access_expression_init(GAccessExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_access_expression_print(const GAccessExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_access_expression_print(const GAccessExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -146,14 +146,18 @@ GDecInstruction *g_access_expression_new(GDecExpression *owner, GDecExpression * * * ******************************************************************************/ -static void g_access_expression_print(const GAccessExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_access_expression_print(const GAccessExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->owner), - buffer, line, output); + GBufferLine *result; /* Ligne à retourner */ - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->owner), + buffer, line, output); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target), - buffer, line, output); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT); + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target), + buffer, result, output); + + return result; } diff --git a/src/decomp/expr/arithm.c b/src/decomp/expr/arithm.c index 0ca73ac..d91e080 100644 --- a/src/decomp/expr/arithm.c +++ b/src/decomp/expr/arithm.c @@ -57,7 +57,7 @@ static void g_arithm_expression_class_init(GArithmExpressionClass *); static void g_arithm_expression_init(GArithmExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_arithm_expression_print(const GArithmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_arithm_expression_print(const GArithmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -151,12 +151,13 @@ GDecInstruction *g_arithm_expression_new(GDecExpression *op1, ArithmOperationTyp * * ******************************************************************************/ -static void g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { + GBufferLine *result; /* Ligne à retourner */ const char *sign; /* Symbole de l'opération */ - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op1), - buffer, line, output); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op1), + buffer, line, output); switch (expr->type) { @@ -189,9 +190,11 @@ static void g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer break; } - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op2), - buffer, line, output); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op2), + buffer, result, output); + + return result; } diff --git a/src/decomp/expr/array.c b/src/decomp/expr/array.c index c14374b..dc487ee 100644 --- a/src/decomp/expr/array.c +++ b/src/decomp/expr/array.c @@ -55,7 +55,7 @@ static void g_array_access_class_init(GArrayAccessClass *); static void g_array_access_init(GArrayAccess *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_array_access_print(const GArrayAccess *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_array_access_print(const GArrayAccess *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -146,16 +146,20 @@ GDecInstruction *g_array_access_new(GDecExpression *array, GDecExpression *index * * ******************************************************************************/ -static void g_array_access_print(const GArrayAccess *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_array_access_print(const GArrayAccess *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array), - buffer, line, output); + GBufferLine *result; /* Ligne à retourner */ - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array), + buffer, line, output); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->index), - buffer, line, output); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->index), + buffer, result, output); + + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW); + + return result; } diff --git a/src/decomp/expr/assign.c b/src/decomp/expr/assign.c index 0843776..fd86021 100644 --- a/src/decomp/expr/assign.c +++ b/src/decomp/expr/assign.c @@ -55,7 +55,7 @@ static void g_assign_expression_class_init(GAssignExpressionClass *); static void g_assign_expression_init(GAssignExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_assign_expression_print(const GAssignExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_assign_expression_print(const GAssignExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -146,15 +146,19 @@ GDecInstruction *g_assign_expression_new(GDecExpression *dest, GDecExpression *s * * ******************************************************************************/ -static void g_assign_expression_print(const GAssignExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_assign_expression_print(const GAssignExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest), - buffer, line, output); + GBufferLine *result; /* Ligne à retourner */ - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest), + buffer, line, output); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src), - buffer, line, output); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS); + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src), + buffer, result, output); + + return result; } diff --git a/src/decomp/expr/block.c b/src/decomp/expr/block.c index 1ec15a7..5124204 100644 --- a/src/decomp/expr/block.c +++ b/src/decomp/expr/block.c @@ -58,7 +58,7 @@ static void g_expr_block_class_init(GExprBlockClass *); static void g_expr_block_init(GExprBlock *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_expr_block_print(const GExprBlock *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_expr_block_print(const GExprBlock *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -147,19 +147,26 @@ GDecInstruction *g_expr_block_new(GDecInstruction *item) * * ******************************************************************************/ -static void g_expr_block_print(const GExprBlock *block, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_expr_block_print(const GExprBlock *block, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { + GBufferLine *result; /* Ligne à retourner */ size_t i; /* Boucle de parcours */ + result = g_lang_output_start_code_block(output, buffer, line, block->count); + for (i = 0; i < block->count; i++) { if (i > 0) - line = g_code_buffer_append_new_line_fixme(buffer); /* FIXME : n° de ligne */ + result = g_code_buffer_append_new_line_fixme(buffer); /* FIXME : n° de ligne */ - g_dec_instruction_print(block->list[i], buffer, line, output); + result = g_dec_instruction_print(block->list[i], buffer, result, output); } + result = g_lang_output_end_code_block(output, buffer, result, block->count); + + return result; + } diff --git a/src/decomp/expr/call.c b/src/decomp/expr/call.c index aaf9883..e518c6f 100644 --- a/src/decomp/expr/call.c +++ b/src/decomp/expr/call.c @@ -61,7 +61,7 @@ static void g_routine_call_class_init(GRoutineCallClass *); static void g_routine_call_init(GRoutineCall *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_routine_call_print(const GRoutineCall *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_routine_call_print(const GRoutineCall *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -150,8 +150,9 @@ GDecInstruction *g_routine_call_new(GBinRoutine *routine) * * ******************************************************************************/ -static void g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { + GBufferLine *result; /* Ligne à retourner */ const char *name; /* Désignation de la routine */ size_t i; /* Boucle de parcours */ @@ -162,20 +163,23 @@ static void g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, if (call->count > 0) { - g_dec_instruction_print(call->args[0], buffer, line, output); + result = g_dec_instruction_print(call->args[0], buffer, line, output); for (i = 1; i < call->count; i++) { - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); - g_dec_instruction_print(call->args[i], buffer, line, output); + g_dec_instruction_print(call->args[i], buffer, result, output); } } + else result = line; - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT); + + return result; } diff --git a/src/decomp/expr/cond.c b/src/decomp/expr/cond.c index 51309ca..4a9b63b 100644 --- a/src/decomp/expr/cond.c +++ b/src/decomp/expr/cond.c @@ -56,7 +56,7 @@ static void g_cond_expression_class_init(GCondExpressionClass *); static void g_cond_expression_init(GCondExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -149,14 +149,18 @@ GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDe * * ******************************************************************************/ -static void g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a), - buffer, line, output); + GBufferLine *result; /* Ligne à retourner */ - g_lang_output_write_comp_sign(output, line, expr->sign); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a), + buffer, line, output); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b), - buffer, line, output); + g_lang_output_write_comp_sign(output, result, expr->sign); + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b), + buffer, result, output); + + return result; } diff --git a/src/decomp/expr/immediate.c b/src/decomp/expr/immediate.c index a97c8bd..a17b2a1 100644 --- a/src/decomp/expr/immediate.c +++ b/src/decomp/expr/immediate.c @@ -54,7 +54,7 @@ static void g_imm_expression_class_init(GImmExpressionClass *); static void g_imm_expression_init(GImmExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_imm_expression_print(const GImmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_imm_expression_print(const GImmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -143,8 +143,10 @@ GDecInstruction *g_imm_expression_new(GImmOperand *operand) * * ******************************************************************************/ -static void g_imm_expression_print(const GImmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_imm_expression_print(const GImmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { g_arch_operand_print(G_ARCH_OPERAND(expr->operand), line, ASX_COUNT); + return line; + } diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c index e73cb3d..9da76e7 100644 --- a/src/decomp/expr/pseudo.c +++ b/src/decomp/expr/pseudo.c @@ -61,7 +61,7 @@ static void g_pseudo_register_class_init(GPseudoRegisterClass *); static void g_pseudo_register_init(GPseudoRegister *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_pseudo_register_print(const GPseudoRegister *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_pseudo_register_print(const GPseudoRegister *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -148,7 +148,7 @@ GDecInstruction *g_pseudo_register_new(void) * * ******************************************************************************/ -static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { char label[32]; char *name; @@ -165,6 +165,8 @@ static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buf g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW); } + return line; + } diff --git a/src/decomp/expr/return.c b/src/decomp/expr/return.c index e29f022..a9c10d9 100644 --- a/src/decomp/expr/return.c +++ b/src/decomp/expr/return.c @@ -54,7 +54,7 @@ static void g_return_expression_class_init(GReturnExpressionClass *); static void g_return_expression_init(GReturnExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_return_expression_print(const GReturnExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_return_expression_print(const GReturnExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -143,17 +143,22 @@ GDecInstruction *g_return_expression_new(GDecExpression *payload) * * ******************************************************************************/ -static void g_return_expression_print(const GReturnExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_return_expression_print(const GReturnExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { + GBufferLine *result; /* Ligne à retourner */ + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "return", 6, RTT_KEY_WORD); if (expr->payload != NULL) { g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->payload), - buffer, line, output); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->payload), + buffer, line, output); } + else result = line; + + return result; } diff --git a/src/decomp/expr/text.c b/src/decomp/expr/text.c index d62e689..8fa7e34 100644 --- a/src/decomp/expr/text.c +++ b/src/decomp/expr/text.c @@ -58,7 +58,7 @@ static void g_str_expression_class_init(GStrExpressionClass *); static void g_str_expression_init(GStrExpression *); /* Imprime pour l'écran un version humaine d'une expression. */ -static void g_str_expression_print(const GStrExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_str_expression_print(const GStrExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -148,10 +148,12 @@ GDecInstruction *g_str_expression_new(const char *value) * * ******************************************************************************/ -static void g_str_expression_print(const GStrExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_str_expression_print(const GStrExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, expr->value, expr->len, RTT_STRING); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING); + return line; + } diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c index f08df1e..7c68031 100644 --- a/src/decomp/instr/ite.c +++ b/src/decomp/instr/ite.c @@ -35,6 +35,9 @@ struct _GITEInstruction GDecExpression *cond; /* Condition prise en compte */ + GDecInstruction *true_branch; /* Condition vérifiée */ + GDecInstruction *false_branch; /* Condition non vérifiée */ + union { vmpa_t addr; /* Adresse de saut */ @@ -68,7 +71,7 @@ static void g_ite_instruction_class_init(GITEInstructionClass *); static void g_ite_instruction_init(GITEInstruction *); /* Imprime pour l'écran un version humaine d'une instruction. */ -static void g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); +static GBufferLine *g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -148,6 +151,28 @@ GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmp /****************************************************************************** * * +* Paramètres : cond = expression fixant le choix de l'aiguillage. * +* true_branch = instructions si la condition est vérifiée. * +* false_branch = instructions si la cond. n'est pas vérifiée. * +* * +* Description : Détermine le corps des différentes branches possibles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch) +{ + expr->true_branch = true_branch; + expr->false_branch = false_branch; + +} + + +/****************************************************************************** +* * * Paramètres : expr = instruction à transcrire en version humaine. * * buffer = tampon où doit se réaliser l'insertion. * * line = ligne d'impression prête à emploi ou NULL. * @@ -161,22 +186,24 @@ GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmp * * ******************************************************************************/ -static void g_ite_instruction_print(const GITEInstruction *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD); + GBufferLine *result; /* Ligne à retourner */ - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond), - buffer, line, output); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD); - /* - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest), - buffer, line, output); + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond), + buffer, line, output); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS); + if (expr->true_branch != NULL) + result = g_dec_instruction_print(expr->true_branch, buffer, result, output); - g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src), - buffer, line, output); - */ + if (expr->false_branch != NULL) + { + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "else", 4, RTT_KEY_WORD); + result = g_dec_instruction_print(expr->false_branch, buffer, result, output); + } + return result; } diff --git a/src/decomp/instr/ite.h b/src/decomp/instr/ite.h index cff073a..e53abe8 100644 --- a/src/decomp/instr/ite.h +++ b/src/decomp/instr/ite.h @@ -52,6 +52,9 @@ typedef struct _GITEInstructionClass GITEInstructionClass; /* Indique le type défini pour un aiguillage du flux d'exécution. */ GType g_ite_instruction_get_type(void); +/* Détermine le corps des différentes branches possibles. */ +void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *); + /* Exprime un aiguillage du flux en fonction d'une condition. */ GDecInstruction *g_ite_instruction_new(GDecExpression *, vmpa_t, vmpa_t); diff --git a/src/decomp/instruction-int.h b/src/decomp/instruction-int.h index 2721b7f..9b29162 100644 --- a/src/decomp/instruction-int.h +++ b/src/decomp/instruction-int.h @@ -31,8 +31,11 @@ +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +typedef void (* dec_instr_visit_fc) (GDecInstruction *, process_decomp_fc, void *, bool); + /* Imprime pour l'écran un version humaine d'une instruction. */ -typedef void (* dec_instr_print_fc) (GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); +typedef GBufferLine * (* dec_instr_print_fc) (const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); /* Définition d'une instruction décompilée (instance) */ @@ -44,6 +47,7 @@ struct _GDecInstruction vmpa_t address; /* Position associée */ + dec_instr_visit_fc visit; /* Visite des instructions */ dec_instr_print_fc print; /* Impression pour à l'écran */ }; diff --git a/src/decomp/instruction.c b/src/decomp/instruction.c index c48ac7b..2d42e71 100644 --- a/src/decomp/instruction.c +++ b/src/decomp/instruction.c @@ -79,6 +79,35 @@ static void g_dec_instruction_init(GDecInstruction *instr) /****************************************************************************** * * +* Paramètres : instr = première instruction à venir visiter. * +* process = procédure à appeler à chaque instruction visitée. * +* data = données quelconques associées au visiteur. * +* order = précise le sens de la visite. * +* * +* Description : Visite un ensemble hiérarchique d'instructions décompilées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_instruction_visit(GDecInstruction *instr, process_decomp_fc process, void *data, bool order) +{ + if (order) + process(instr, data); + + if (instr->visit) + instr->visit(instr, process, data, order); + + if (!order) + process(instr, data); + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction à transcrire en version humaine. * * buffer = tampon où doit se réaliser l'insertion. * * line = ligne d'impression prête à emploi ou NULL. * @@ -92,12 +121,9 @@ static void g_dec_instruction_init(GDecInstruction *instr) * * ******************************************************************************/ -void g_dec_instruction_print(const GDecInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +GBufferLine *g_dec_instruction_print(const GDecInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { - if (line == NULL) - line = g_code_buffer_append_new_line_fixme(buffer); /* FIXME : n° de ligne */ - - instr->print(instr, buffer, line, output); + return instr->print(instr, buffer, line, output); } diff --git a/src/decomp/instruction.h b/src/decomp/instruction.h index d8fe46c..810be79 100644 --- a/src/decomp/instruction.h +++ b/src/decomp/instruction.h @@ -48,11 +48,18 @@ typedef struct _GDecInstruction GDecInstruction; typedef struct _GDecInstructionClass GDecInstructionClass; +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +typedef void (* process_decomp_fc) (GDecInstruction *, void *); + + /* Indique le type défini pour une instruction décompilée. */ GType g_dec_instruction_get_type(void); +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +void g_dec_instruction_visit(GDecInstruction *, process_decomp_fc, void *, bool); + /* Imprime pour l'écran un version humaine d'une expression. */ -void g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); +GBufferLine *g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c index ae7fb70..f4466a5 100644 --- a/src/decomp/lang/java.c +++ b/src/decomp/lang/java.c @@ -84,6 +84,12 @@ static void g_java_output_start_routine_body(GJavaOutput *, GCodeBuffer *, GBuff /* Termine la définition du corps d'une routine. */ static void g_java_output_end_routine_body(GJavaOutput *, GCodeBuffer *); +/* Commence la définition d'un bloc de code. */ +static GBufferLine *g_java_output_start_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t); + +/* Termine la définition d'un bloc de code. */ +static GBufferLine *g_java_output_end_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t); + /* Indique le type défini pour une sortie en langage Java. */ @@ -142,6 +148,9 @@ static void g_java_output_init(GJavaOutput *output) lang->start_routine_body = (lgbufln_fc)g_java_output_start_routine_body; lang->end_routine_body = (lgbuf_fc)g_java_output_end_routine_body; + lang->start_code_block = (rlgbuflnsz_fc)g_java_output_start_code_block; + lang->end_code_block = (rlgbuflnsz_fc)g_java_output_end_code_block; + } @@ -465,11 +474,12 @@ static void g_java_output_end_routine_prototype(GJavaOutput *output, GCodeBuffer static void g_java_output_start_routine_body(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line) { + /* g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 2, RTT_HOOK); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK); g_code_buffer_inc_indentation(buffer); - + */ } @@ -489,11 +499,79 @@ static void g_java_output_start_routine_body(GJavaOutput *output, GCodeBuffer *b static void g_java_output_end_routine_body(GJavaOutput *output, GCodeBuffer *buffer) { GBufferLine *line; /* Nouvelle ligne à constituer */ - + /* g_code_buffer_dec_indentation(buffer); line = g_code_buffer_append_new_line_fixme(buffer); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK); + */ +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée. * +* count = nombre d'éléments du bloc. * +* * +* Description : Commence la définition d'un bloc de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_start_code_block(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count) +{ + GBufferLine *result; /* Nouvelle ligne à utiliser */ + + if (count > 1) + { + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK); + } + + g_code_buffer_inc_indentation(buffer); + + result = g_code_buffer_append_new_line_fixme(buffer); /* FIXME : n° de ligne */ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée. * +* count = nombre d'éléments du bloc. * +* * +* Description : Termine la définition d'un bloc de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_end_code_block(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count) +{ + GBufferLine *result; /* Nouvelle ligne à constituer */ + + g_code_buffer_dec_indentation(buffer); + + result = g_code_buffer_append_new_line_fixme(buffer); + + if (count > 1) + { + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + } + + return result; } diff --git a/src/decomp/output-int.h b/src/decomp/output-int.h index 6c5f588..8ee7dd4 100644 --- a/src/decomp/output-int.h +++ b/src/decomp/output-int.h @@ -50,6 +50,11 @@ typedef void (* lgbuf_fc) (GLangOutput *, GCodeBuffer *); /* Xxx. */ typedef void (* lgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *); +/* Xxx. */ +typedef GBufferLine * (* rlgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *); + +/* Xxx. */ +typedef GBufferLine * (* rlgbuflnsz_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, size_t); /* Sortie selon un langage de programmation (instance) */ @@ -73,7 +78,8 @@ struct _GLangOutput lgbufln_fc end_routine_proto; /* Fin de prototype */ lgbufln_fc start_routine_body; /* Début de définition */ lgbuf_fc end_routine_body; /* Fin de définition de corps */ - + rlgbuflnsz_fc start_code_block; /* Début de définition */ + rlgbuflnsz_fc end_code_block; /* Fin de définition de corps */ }; diff --git a/src/decomp/output.c b/src/decomp/output.c index fd10921..648dddc 100644 --- a/src/decomp/output.c +++ b/src/decomp/output.c @@ -373,3 +373,61 @@ void g_lang_output_end_routine_body(GLangOutput *output, GCodeBuffer *buffer) output->end_routine_body(output, buffer); } + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée. * +* count = nombre d'éléments du bloc. * +* * +* Description : Commence la définition d'un bloc de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_start_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count) +{ + GBufferLine *result; /* Nouvelle ligne à utiliser */ + + if (output->start_code_block != NULL) + result = output->start_code_block(output, buffer, line, count); + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée. * +* count = nombre d'éléments du bloc. * +* * +* Description : Termine la définition d'un bloc de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_end_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count) +{ + GBufferLine *result; /* Nouvelle ligne à utiliser */ + + if (output->end_code_block != NULL) + result = output->end_code_block(output, buffer, line, count); + else + result = NULL; + + return result; + +} diff --git a/src/decomp/output.h b/src/decomp/output.h index f9ccd1d..dc81a98 100644 --- a/src/decomp/output.h +++ b/src/decomp/output.h @@ -99,6 +99,11 @@ void g_lang_output_start_routine_body(GLangOutput *, GCodeBuffer *, GBufferLine /* Termine la définition du corps d'une routine. */ void g_lang_output_end_routine_body(GLangOutput *, GCodeBuffer *); +/* Commence la définition d'un bloc de code. */ +GBufferLine *g_lang_output_start_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t); + +/* Termine la définition d'un bloc de code. */ +GBufferLine *g_lang_output_end_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t); |