From 37fd2f1329c56078bc8a8b2fc955aa001c109c01 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 20 Jan 2013 13:10:06 +0000 Subject: Took care of shared allocations between blocks when converting registers. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@326 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 46 +++++++++ src/analysis/blocks/raccess.c | 2 +- src/analysis/blocks/raccess.h | 2 +- src/analysis/decomp/decompiler.c | 2 +- src/analysis/decomp/il.c | 86 +++++++++++------ src/analysis/disass/macro.c | 4 +- src/arch/dalvik/context.c | 73 ++++++++++++-- src/arch/dalvik/decomp/aget.c | 9 +- src/arch/dalvik/decomp/aput.c | 9 +- src/arch/dalvik/decomp/arithm.c | 23 +++-- src/arch/dalvik/decomp/array.c | 7 +- src/arch/dalvik/decomp/const.c | 10 +- src/arch/dalvik/decomp/if.c | 16 ++- src/arch/dalvik/decomp/iget.c | 7 +- src/arch/dalvik/decomp/invoke.c | 17 +++- src/arch/dalvik/decomp/iput.c | 7 +- src/arch/dalvik/decomp/move.c | 19 +++- src/arch/dalvik/decomp/new.c | 5 +- src/arch/dalvik/decomp/ret.c | 5 +- src/arch/dalvik/register.c | 23 +++++ src/arch/register-int.h | 4 + src/arch/register.c | 43 +++++++++ src/arch/register.h | 6 ++ src/decomp/context-int.h | 16 ++- src/decomp/context.c | 203 ++++++++++++++++++++++++++++++++++++++- src/decomp/context.h | 18 +++- 26 files changed, 583 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index 620779f..b5b4590 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +13-01-20 Cyrille Bagard + + * src/analysis/blocks/raccess.c: + * src/analysis/blocks/raccess.h: + Typo: constify the source list when merging two lists. + + * src/analysis/decomp/decompiler.c: + Disable (again) debug output. + + * src/analysis/decomp/il.c: + Build awaited registers lists and attach them to decompilation contexts. + Share the allocation list between these contexts. + + * src/analysis/disass/macro.c: + Disable (again) debug output. + + * src/arch/dalvik/context.c: + Take care of shared allocations between blocks when converting registers. + + * src/arch/dalvik/decomp/aget.c: + * src/arch/dalvik/decomp/aput.c: + * src/arch/dalvik/decomp/arithm.c: + * src/arch/dalvik/decomp/array.c: + * src/arch/dalvik/decomp/const.c: + * src/arch/dalvik/decomp/if.c: + * src/arch/dalvik/decomp/iget.c: + * src/arch/dalvik/decomp/invoke.c: + * src/arch/dalvik/decomp/iput.c: + * src/arch/dalvik/decomp/move.c: + * src/arch/dalvik/decomp/new.c: + * src/arch/dalvik/decomp/ret.c: + Update code: provide the address of the decompiled instruction when + converting registers into variables. + + * src/arch/dalvik/register.c: + * src/arch/register.c: + * src/arch/register.h: + * src/arch/register-int.h: + Provide more functions about registers for GLib: equal() and hash(). + + * src/decomp/context.c: + * src/decomp/context.h: + * src/decomp/context-int.h: + Define lists tracking awaited and allocated [shared] registers. Provides + functions to access them from all context implementations. + 13-01-17 Cyrille Bagard * src/analysis/decomp/il.c: diff --git a/src/analysis/blocks/raccess.c b/src/analysis/blocks/raccess.c index 7fe084c..4c76e22 100644 --- a/src/analysis/blocks/raccess.c +++ b/src/analysis/blocks/raccess.c @@ -190,7 +190,7 @@ GRAccessList *g_raccess_list_new(void) * * ******************************************************************************/ -void g_raccess_list_merge(GRAccessList *list, GRAccessList *src) +void g_raccess_list_merge(GRAccessList *list, const GRAccessList *src) { size_t count; /* Taille d'un parcours */ size_t i; /* Boucle de parcours */ diff --git a/src/analysis/blocks/raccess.h b/src/analysis/blocks/raccess.h index cc2fd00..843933b 100644 --- a/src/analysis/blocks/raccess.h +++ b/src/analysis/blocks/raccess.h @@ -77,7 +77,7 @@ GType g_raccess_list_get_type(void); GRAccessList *g_raccess_list_new(void); /* Intègre une liste d'accès à des registres dans une autre. */ -void g_raccess_list_merge(GRAccessList *, GRAccessList *); +void g_raccess_list_merge(GRAccessList *, const GRAccessList *); /* Compare un accès registre avec un autre. */ int compare_reg_accesses(const reg_access *, const reg_access *); diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index 71a9286..a61e7c7 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -169,7 +169,7 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c 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])); + //printf("\n##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i])); dinstrs = decompiled_routine_instructions(routines[i], format, proc); diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c index 642c921..64f6398 100644 --- a/src/analysis/decomp/il.c +++ b/src/analysis/decomp/il.c @@ -40,8 +40,11 @@ static bool track_used_registers(GFlowBlock *, BlockFollowPosition, GRAccessList /* Etablit le relévé des allocations de registre. */ static void setup_awaited_regs_allocation(const GInstrBlock *, vmpa_t); +/* Etablit la liste de tous les allocations attendues. */ +static bool merge_all_awaited_regs(GInstrBlock *, BlockVisitOrder, GRAccessList *); + /* Met en place un contexte adapté aux sous-blocs d'un bloc. */ -static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *); +static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *, GHashTable *); @@ -147,7 +150,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA } - + /* do { vmpa_t start, end; @@ -160,7 +163,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA } while (0); - + */ break; @@ -203,8 +206,38 @@ static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start) /****************************************************************************** * * -* Paramètres : ctx = contexte de décompilation courant. * -* block = block regroupant les branches de division. * +* Paramètres : block = bloc d'instructions concerné par la visite. * +* order = position dans la visite. * +* list = liste à compléter. * +* * +* Description : Etablit la liste de tous les allocations attendues. * +* * +* Retour : true pour parcourir tous les blocs. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool merge_all_awaited_regs(GInstrBlock *block, BlockVisitOrder order, GRAccessList *list) +{ + const GRAccessList *awaited; /* Registres conséquents */ + + if (G_IS_FLOW_BLOCK(block)) + { + awaited = g_flow_block_list_regs_accesses(G_FLOW_BLOCK(block)); + g_raccess_list_merge(list, awaited); + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = contexte de décompilation courant. * +* block = block regroupant les branches de division. * +* shared = liste des allocations passées de registres attendus.* * * * Description : Met en place un contexte adapté aux sous-blocs d'un bloc. * * * @@ -214,17 +247,26 @@ static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start) * * ******************************************************************************/ -static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block) +static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block, GHashTable *shared) { + GDecContext *result; /* Contexte à retourner */ + GRAccessList *list; /* Allocations attendues */ + result = g_dec_context_dup(ctx); - return g_dec_context_dup(ctx); + list = g_raccess_list_new(); + g_instr_block_visit(block, (instr_block_visitor_cb)merge_all_awaited_regs, list); + g_dec_context_set_awaited(result, list); + g_object_unref(G_OBJECT(list)); + g_dec_context_set_shared_allocs(result, shared); + return result; } + /* ---------------------------------------------------------------------------------- */ /* ENCADREMENT DES INSTRUCTIONS */ /* ---------------------------------------------------------------------------------- */ @@ -282,8 +324,6 @@ static GDecInstruction *merge_decompiled_instructions(GDecInstruction *group, GD static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecContext *ctx) { - GDecInstruction *res; - GArchInstruction *instrs; /* Liste d'instructions natives*/ GArchInstruction *first; /* Première instruction du lot */ GArchInstruction *last; /* Dernière instruction du lot */ @@ -291,12 +331,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon GArchInstruction *iter; /* Boucle de parcours */ GDecInstruction *decomp; /* Dernier résultat de décomp. */ GInstrBlock *sub_parent; /* Groupe des sous-branches */ + GHashTable *sub_shared; /* Allocations communes */ GDecContext *sub_ctx; /* Sous-contexte pour branche */ GDecInstruction *true_dinstr; /* Décompilation 'cond vraie' */ GDecInstruction *false_dinstr; /* Décompilation 'cond fausse' */ GArchInstruction *next; /* Instruction de branchement */ vmpa_t next_addr; /* Adresse de cette instruct° */ - //GInstrBlock *next_parent; /* Bloc basique correspondant */ GInstrBlock *next_block; /* Sous-bloc basique direct */ instrs = g_flow_block_get_all_instructions_list(block); @@ -316,14 +356,13 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon /* Post-traitement selon les types de lien */ - - //res = g_dec_context_get_decomp_instrs(ctx); - - /* if ... then ... else ... */ if (G_IS_ITE_INSTRUCTION(decomp)) { sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); + sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, + (GEqualFunc)g_arch_register_equal, + g_object_unref, g_object_unref); true_dinstr = NULL; @@ -335,9 +374,9 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon if (next_block != NULL) { - sub_ctx = create_new_context_for_sub_block(ctx, sub_parent); + sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); true_dinstr = decompiled_basic_block(next_block, sub_ctx); - /* TODO : merge awaited */ + g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); g_object_unref(G_OBJECT(sub_ctx)); } @@ -353,29 +392,22 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon if (next_block != NULL) { - sub_ctx = create_new_context_for_sub_block(ctx, sub_parent); + sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); false_dinstr = decompiled_basic_block(next_block, sub_ctx); - /* TODO : merge awaited */ + g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); g_object_unref(G_OBJECT(sub_ctx)); } } - printf(" -> ite : %p + %p\n", true_dinstr, false_dinstr); - - printf(" -> ite : %s + %s\n", - true_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(true_dinstr)) : "none", - false_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(false_dinstr)) : "none"); - - g_ite_instruction_set_branches(G_ITE_INSTRUCTION(decomp), true_dinstr, false_dinstr); + g_hash_table_unref(sub_shared); + } /* Renvoi des instructions mises en place */ - //return res; - return g_dec_context_get_decomp_instrs(ctx); } diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 8652b27..60d99da 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -655,14 +655,14 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines, end = start + g_binary_routine_get_size(routines[i]); - printf("==== %s ====\n", g_binary_routine_to_string(routines[i])); + //printf("==== %s ====\n", g_binary_routine_to_string(routines[i])); block = build_instruction_block(list, start, end, VMPA_MAX); g_binary_routine_set_basic_blocks(routines[i], block); - g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 }); + //g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 }); gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c index e80ead3..7918467 100644 --- a/src/arch/dalvik/context.c +++ b/src/arch/dalvik/context.c @@ -123,8 +123,11 @@ static void g_dalvik_dcontext_finalize(GDalvikDContext *); /* Duplique un contexte de compilation. */ static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *); +/* Propage un registre alloué et attendu par la suite. */ +static void g_dalvik_context_spread_allocated_shared_reg(GDalvikDContext *, GDalvikRegister *, GDecInstruction *); + /* Convertit un registre machine en un pseudo-registre. */ -static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *, GDalvikRegisterOperand *, bool); +static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *, GDalvikRegisterOperand *, bool, vmpa_t); @@ -335,6 +338,7 @@ static void g_dalvik_dcontext_init(GDalvikDContext *ctx) parent = G_DEC_CONTEXT(ctx); parent->dup = (dup_dec_context_fc)g_dalvik_dcontext_dup; + parent->spread = (spread_reg_fc)g_dalvik_context_spread_allocated_shared_reg; parent->convert_reg = (convert_register_fc)g_dalvik_dcontext_convert_register; } @@ -443,9 +447,46 @@ static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *orig) /****************************************************************************** * * +* Paramètres : parent = instance à éventuellement compléter. * +* child = instance à venir consulter. * +* * +* Description : Propage un registre alloué et attendu par la suite. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_context_spread_allocated_shared_reg(GDalvikDContext *ctx, GDalvikRegister *reg, GDecInstruction *dinstr) +{ + GDexFormat *format; /* Recherche de méthode */ + GBinRoutine *routine; /* Objet des recherches */ + GDexMethod *method; /* Méthode décompilée */ + uint16_t index; /* Identifiant du registre */ + DexVariableIndex info; /* Nature du registre */ + + format = G_DEX_FORMAT(G_DEC_CONTEXT(ctx)->format); + routine = G_DEC_CONTEXT(ctx)->routine; + + method = g_dex_format_find_method_by_address(format, g_binary_routine_get_address(routine)); + + index = g_dalvik_register_get_index(reg); + info = g_dex_method_get_variable(method, index); + + g_object_ref(G_OBJECT(dinstr)); + g_hash_table_insert(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)), dinstr); + ctx->locals_count++; + +} + + +/****************************************************************************** +* * * Paramètres : ctx = instance à consulter, voire mettre à jour. * * operand = opérande représentant un registre quelconque. * * assign = précise le sort prochain du registre. * +* addr = adresse de l'instruction décompilée. * * * * Description : Convertit un registre machine en un pseudo-registre. * * * @@ -455,7 +496,7 @@ static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *orig) * * ******************************************************************************/ -static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, GDalvikRegisterOperand *operand, bool assign) +static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, GDalvikRegisterOperand *operand, bool assign, vmpa_t addr) { GDecInstruction *result; /* Instance à retourner */ GDexFormat *format; /* Recherche de méthode */ @@ -522,17 +563,37 @@ 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); } else { - result = g_pseudo_register_new(); - g_pseudo_register_set_basename(G_PSEUDO_REGISTER(result), "var"); - g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->locals_count); + /* + if (!assign) + { + printf("bug"); + exit(0); + } + */ + + result = g_dec_context_get_awaited_alloc(G_DEC_CONTEXT(ctx), G_ARCH_REGISTER(reg), addr); + + if (result == NULL) + { + result = g_pseudo_register_new(); + g_pseudo_register_set_basename(G_PSEUDO_REGISTER(result), "var"); + g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->locals_count); + + g_dec_context_notify_reg_alloc(G_DEC_CONTEXT(ctx), G_ARCH_REGISTER(reg), + result, addr); + + } + else + g_object_ref(G_OBJECT(result)); + g_object_ref(G_OBJECT(result)); g_hash_table_insert(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)), result); ctx->locals_count++; diff --git a/src/arch/dalvik/decomp/aget.c b/src/arch/dalvik/decomp/aget.c index 0fa66eb..4ca012b 100644 --- a/src/arch/dalvik/decomp/aget.c +++ b/src/arch/dalvik/decomp/aget.c @@ -45,20 +45,23 @@ GDecInstruction *dalvik_decomp_instr_aget(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *array; /* Tableau accédé */ GDecInstruction *index; /* Indice de cellule considérée*/ GDecInstruction *content; /* Contenu de cellule visé */ GDecInstruction *access; /* Représentation de l'accès */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - array = g_dec_context_convert_register(ctx, operand, false); + array = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); - index = g_dec_context_convert_register(ctx, operand, false); + index = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 0); - content = g_dec_context_convert_register(ctx, operand, true); + content = g_dec_context_convert_register(ctx, operand, true, addr); access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index)); result = g_assign_expression_new(G_DEC_EXPRESSION(content), G_DEC_EXPRESSION(access)); diff --git a/src/arch/dalvik/decomp/aput.c b/src/arch/dalvik/decomp/aput.c index 41bd89f..8d648e4 100644 --- a/src/arch/dalvik/decomp/aput.c +++ b/src/arch/dalvik/decomp/aput.c @@ -45,20 +45,23 @@ GDecInstruction *dalvik_decomp_instr_aput(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *content; /* Contenu de cellule visé */ GDecInstruction *array; /* Tableau accédé */ GDecInstruction *index; /* Indice de cellule considérée*/ GDecInstruction *access; /* Représentation de l'accès */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - content = g_dec_context_convert_register(ctx, operand, false); + content = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 1); - array = g_dec_context_convert_register(ctx, operand, false); + array = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); - index = g_dec_context_convert_register(ctx, operand, false); + index = g_dec_context_convert_register(ctx, operand, false, addr); access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index)); result = g_assign_expression_new(G_DEC_EXPRESSION(access), G_DEC_EXPRESSION(content)); diff --git a/src/arch/dalvik/decomp/arithm.c b/src/arch/dalvik/decomp/arithm.c index a217adf..464694f 100644 --- a/src/arch/dalvik/decomp/arithm.c +++ b/src/arch/dalvik/decomp/arithm.c @@ -48,6 +48,7 @@ GDecInstruction *dalvik_decomp_instr_arithm(const GArchInstruction *instr, GDecC { GDecInstruction *result; /* Instruction à retourner */ ArithmOperationType type; /* Type d'opération menée */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ @@ -85,14 +86,16 @@ GDecInstruction *dalvik_decomp_instr_arithm(const GArchInstruction *instr, GDecC break; } + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - op1 = g_dec_context_convert_register(ctx, operand, false); + op1 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); - op2 = g_dec_context_convert_register(ctx, operand, false); + op2 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2)); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm)); @@ -119,6 +122,7 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr, { GDecInstruction *result; /* Instruction à retourner */ ArithmOperationType type; /* Type d'opération menée */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *dest; /* Enregistrement du résultat */ @@ -153,11 +157,13 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr, break; } + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - op1 = g_dec_context_convert_register(ctx, operand, false); + op1 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); arithm = g_arithm_expression_new(G_DEC_EXPRESSION(dest), type, G_DEC_EXPRESSION(op1)); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm)); @@ -184,6 +190,7 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G { GDecInstruction *result; /* Instruction à retourner */ ArithmOperationType type; /* Type d'opération menée */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ @@ -225,14 +232,16 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G break; } + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - op1 = g_dec_context_convert_register(ctx, operand, false); + op1 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); op2 = g_imm_expression_new(G_IMM_OPERAND(operand)); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2)); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm)); diff --git a/src/arch/dalvik/decomp/array.c b/src/arch/dalvik/decomp/array.c index 3422461..217cab3 100644 --- a/src/arch/dalvik/decomp/array.c +++ b/src/arch/dalvik/decomp/array.c @@ -45,17 +45,20 @@ GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *reg; /* Pseudo-registre redéfini */ GDecInstruction *len; /* Enregistrement de taille */ GDecInstruction *dest; /* Destination de la création */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - reg = g_dec_context_convert_register(ctx, operand, false); + reg = g_dec_context_convert_register(ctx, operand, false, addr); len = g_dalvik_alength_new(G_DEC_EXPRESSION(reg)); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(len)); diff --git a/src/arch/dalvik/decomp/const.c b/src/arch/dalvik/decomp/const.c index 98133ac..a451b55 100644 --- a/src/arch/dalvik/decomp/const.c +++ b/src/arch/dalvik/decomp/const.c @@ -47,12 +47,15 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *reg; /* Pseudo-registre redéfini */ GDecInstruction *imm; /* Valeur immédiate décompilée */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - reg = g_dec_context_convert_register(ctx, operand, true); + reg = g_dec_context_convert_register(ctx, operand, true, addr); operand = g_arch_instruction_get_operand(instr, 1); imm = g_imm_expression_new(G_IMM_OPERAND(operand)); @@ -80,14 +83,17 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecCo GDecInstruction *dalvik_decomp_instr_const_str(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *reg; /* Pseudo-registre redéfini */ uint32_t index; /* Indice de la chaîne */ const char *value; /* Chaîne de caractères */ GDecInstruction *str; /* Chaîne décompilée */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - reg = g_dec_context_convert_register(ctx, operand, true); + reg = g_dec_context_convert_register(ctx, operand, true, addr); operand = g_arch_instruction_get_operand(instr, 1); index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c index b274ead..6a156ec 100644 --- a/src/arch/dalvik/decomp/if.c +++ b/src/arch/dalvik/decomp/if.c @@ -47,6 +47,7 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte { GDecInstruction *result; /* Instruction à retourner */ CompSignType sign; /* Type d'opération menée */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ @@ -78,14 +79,16 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte break; } + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - op1 = g_dec_context_convert_register(ctx, operand, false); + op1 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 1); - op2 = g_dec_context_convert_register(ctx, operand, false); + op2 = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); - jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand);*/ + jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/ 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); @@ -113,6 +116,7 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec { GDecInstruction *result; /* Instruction à retourner */ CompSignType sign; /* Type d'opération menée */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ @@ -144,14 +148,16 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec break; } + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - op1 = g_dec_context_convert_register(ctx, operand, false); + op1 = g_dec_context_convert_register(ctx, operand, false, addr); 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);*/ + jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/ 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); diff --git a/src/arch/dalvik/decomp/iget.c b/src/arch/dalvik/decomp/iget.c index 5d1cf65..9cf603d 100644 --- a/src/arch/dalvik/decomp/iget.c +++ b/src/arch/dalvik/decomp/iget.c @@ -47,6 +47,7 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *src; /* Registre de l'object */ uint32_t index; /* Indice dans la table */ @@ -55,8 +56,10 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecCon GDecInstruction *dest; /* Registre de destination */ GDecInstruction *access; /* Représentation de l'accès */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - src = g_dec_context_convert_register(ctx, operand, false); + src = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); @@ -66,7 +69,7 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecCon g_pseudo_register_set_variable(G_PSEUDO_REGISTER(field), var); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); access = g_access_expression_new(G_DEC_EXPRESSION(src), G_DEC_EXPRESSION(field)); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(access)); diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c index 7337ccc..4b2f20f 100644 --- a/src/arch/dalvik/decomp/invoke.c +++ b/src/arch/dalvik/decomp/invoke.c @@ -62,6 +62,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr const char *name; /* Chaîne à afficher */ GDecInstruction *src; /* Source de l'assignation */ GDecInstruction *dest; /* Destination de l'assignat° */ + vmpa_t addr; /* Adresse de l'instruction */ size_t i; /* Boucle de parcours #2 */ GArchOperand *arg; /* Argument brut de l'appel */ GDecInstruction *reg; /* Argument converti */ @@ -123,10 +124,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr operand = g_arch_instruction_get_operand(instr, 0); count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + for (i = 1; i < count; i++) { arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i); - reg = g_dec_context_convert_register(ctx, arg, false); + reg = g_dec_context_convert_register(ctx, arg, false, addr); g_routine_call_add_arg(G_ROUTINE_CALL(result), reg); @@ -158,6 +161,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr uint32_t index; /* Indice de l'élément visé */ GBinRoutine *routine; /* Routine visée par l'appel */ GDecInstruction *call; /* Représentation de l'appel */ + vmpa_t addr; /* Adresse de l'instruction */ size_t i; /* Boucle de parcours #2 */ GArchOperand *arg; /* Argument brut de l'appel */ GDecInstruction *reg; /* Argument converti */ @@ -181,10 +185,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr operand = g_arch_instruction_get_operand(instr, 0); count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + 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); + reg = g_dec_context_convert_register(ctx, arg, false, addr); g_routine_call_add_arg(G_ROUTINE_CALL(call), reg); @@ -216,6 +222,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst uint32_t index; /* Indice de l'élément visé */ GBinRoutine *routine; /* Routine visée par l'appel */ GDecInstruction *call; /* Représentation de l'appel */ + vmpa_t addr; /* Adresse de l'instruction */ size_t i; /* Boucle de parcours #2 */ GArchOperand *arg; /* Argument brut de l'appel */ GDecInstruction *reg; /* Argument converti */ @@ -239,10 +246,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst operand = g_arch_instruction_get_operand(instr, 0); count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + for (i = 1; i < count; i++) { arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i); - reg = g_dec_context_convert_register(ctx, arg, false); + reg = g_dec_context_convert_register(ctx, arg, false, addr); g_routine_call_add_arg(G_ROUTINE_CALL(call), reg); @@ -251,7 +260,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst /* Appel depuis le propriétaire */ arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), 0); - reg = g_dec_context_convert_register(ctx, arg, false); + reg = g_dec_context_convert_register(ctx, arg, false, addr); result = g_access_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(call)); diff --git a/src/arch/dalvik/decomp/iput.c b/src/arch/dalvik/decomp/iput.c index fedb00e..ed0830c 100644 --- a/src/arch/dalvik/decomp/iput.c +++ b/src/arch/dalvik/decomp/iput.c @@ -47,6 +47,7 @@ GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *dest; /* Registre de destination */ GDecInstruction *src; /* Registre de l'object */ @@ -55,11 +56,13 @@ GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *instr, GDecCon GBinVariable *var; /* Variable / champ accédé */ GDecInstruction *access; /* Représentation de l'accès */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - src = g_dec_context_convert_register(ctx, operand, false); + src = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 1); - dest = g_dec_context_convert_register(ctx, operand, false); + dest = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 2); index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); diff --git a/src/arch/dalvik/decomp/move.c b/src/arch/dalvik/decomp/move.c index 9165447..a502952 100644 --- a/src/arch/dalvik/decomp/move.c +++ b/src/arch/dalvik/decomp/move.c @@ -44,15 +44,18 @@ GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *src; /* Registre de l'object */ GDecInstruction *dest; /* Registre de destination */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - src = g_dec_context_convert_register(ctx, operand, false); + src = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src)); @@ -77,15 +80,18 @@ GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecCon GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *src; /* Registre de l'object */ GDecInstruction *dest; /* Registre de destination */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); - src = g_dec_context_convert_register(ctx, operand, false); + src = g_dec_context_convert_register(ctx, operand, false, addr); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src)); @@ -111,6 +117,7 @@ GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *instr, { GDecInstruction *result; /* Instruction à retourner */ GDecInstruction *list; /* Instructions décompilées */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *last; /* Instruction précédante */ GDecInstruction *dest; /* Registre de destination */ @@ -122,8 +129,10 @@ GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *instr, g_dec_instruction_delete(&list, last); g_dec_context_set_decomp_instrs(ctx, list); + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(last)); diff --git a/src/arch/dalvik/decomp/new.c b/src/arch/dalvik/decomp/new.c index 75dc259..e30feb2 100644 --- a/src/arch/dalvik/decomp/new.c +++ b/src/arch/dalvik/decomp/new.c @@ -46,6 +46,7 @@ GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ uint32_t index; /* Indice dans la table */ GDataType *type; /* Type concerné par l'opérat° */ @@ -53,6 +54,8 @@ GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr, GDecInstruction *call; /* Appel au constructeur */ GDecInstruction *dest; /* Registre de destination */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 1); index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); type = get_type_from_dex_pool(G_DEX_FORMAT(g_dec_context_get_format(ctx)), index); @@ -61,7 +64,7 @@ GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr, call = g_routine_call_new(constructor); operand = g_arch_instruction_get_operand(instr, 0); - dest = g_dec_context_convert_register(ctx, operand, true); + dest = g_dec_context_convert_register(ctx, operand, true, addr); result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(call)); diff --git a/src/arch/dalvik/decomp/ret.c b/src/arch/dalvik/decomp/ret.c index b7c5414..47179f3 100644 --- a/src/arch/dalvik/decomp/ret.c +++ b/src/arch/dalvik/decomp/ret.c @@ -44,11 +44,14 @@ GDecInstruction *dalvik_decomp_instr_return(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + vmpa_t addr; /* Adresse de l'instruction */ GArchOperand *operand; /* Opérande de l'instruction */ GDecInstruction *reg; /* Pseudo-registre redéfini */ + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + operand = g_arch_instruction_get_operand(instr, 0); - reg = g_dec_context_convert_register(ctx, operand, false); + reg = g_dec_context_convert_register(ctx, operand, false, addr); result = g_return_expression_new(G_DEC_EXPRESSION(reg)); diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c index db4186a..4e91cd4 100644 --- a/src/arch/dalvik/register.c +++ b/src/arch/dalvik/register.c @@ -58,6 +58,9 @@ static void g_dalvik_register_class_init(GDalvikRegisterClass *); /* Initialise une instance de registre Dalvik. */ static void g_dalvik_register_init(GDalvikRegister *); +/* Produit une empreinte à partir d'un registre. */ +static guint g_dalvik_register_hash(const GDalvikRegister *); + /* Indique le type défini pour une représentation d'un registre Dalvik. */ @@ -100,6 +103,7 @@ static void g_dalvik_register_init(GDalvikRegister *reg) base = G_ARCH_REGISTER(reg); + base->hash = (reg_hash_fc)g_dalvik_register_hash; base->compare = (reg_compare_fc)g_dalvik_register_compare; base->print = (reg_print_fc)g_dalvik_register_print; @@ -152,6 +156,25 @@ uint16_t g_dalvik_register_get_index(const GDalvikRegister *reg) /****************************************************************************** * * +* Paramètres : reg = opérande à consulter pour le calcul. * +* * +* Description : Produit une empreinte à partir d'un registre. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_dalvik_register_hash(const GDalvikRegister *reg) +{ + return reg->index; + +} + + +/****************************************************************************** +* * * Paramètres : a = premier opérande à consulter. * * b = second opérande à consulter. * * * diff --git a/src/arch/register-int.h b/src/arch/register-int.h index 00773f3..8ff7a9a 100644 --- a/src/arch/register-int.h +++ b/src/arch/register-int.h @@ -29,6 +29,9 @@ +/* Produit une empreinte à partir d'un registre. */ +typedef guint (* reg_hash_fc) (const GArchRegister *); + /* Compare un registre avec un autre. */ typedef int (* reg_compare_fc) (const GArchRegister *, const GArchRegister *); @@ -48,6 +51,7 @@ struct _GArchRegister { GObject parent; /* A laisser en premier */ + reg_hash_fc hash; /* Production d'empreinte */ reg_compare_fc compare; /* Comparaison de registres */ reg_print_fc print; /* Impression du registre */ reg_is_base_pointer_fc is_bp; /* Correspondance avec ebp */ diff --git a/src/arch/register.c b/src/arch/register.c index 6631d4b..7c4f193 100644 --- a/src/arch/register.c +++ b/src/arch/register.c @@ -78,6 +78,25 @@ static void g_arch_register_init(GArchRegister *reg) /****************************************************************************** * * +* Paramètres : reg = opérande à consulter pour le calcul. * +* * +* Description : Produit une empreinte à partir d'un registre. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +guint g_arch_register_hash(const GArchRegister *reg) +{ + return reg->hash(reg); + +} + + +/****************************************************************************** +* * * Paramètres : a = premier opérande à consulter. * * b = second opérande à consulter. * * * @@ -98,6 +117,30 @@ int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b) /****************************************************************************** * * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* * +* Description : Détermine si un registre est égal à un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gboolean g_arch_register_equal(const GArchRegister *a, const GArchRegister *b) +{ + int ret; /* Comparaison détaillée */ + + ret = g_arch_register_compare(a, b); + + return (ret == 0 ? TRUE : FALSE); + +} + + +/****************************************************************************** +* * * Paramètres : reg = registre à transcrire. * * line = ligne tampon où imprimer l'opérande donné. * * syntax = type de représentation demandée. * diff --git a/src/arch/register.h b/src/arch/register.h index a163ad3..e3c95b4 100644 --- a/src/arch/register.h +++ b/src/arch/register.h @@ -52,9 +52,15 @@ typedef struct _GArchRegisterClass GArchRegisterClass; /* Indique le type défini pour une représentation d'un registre. */ GType g_arch_register_get_type(void); +/* Produit une empreinte à partir d'un registre. */ +guint g_arch_register_hash(const GArchRegister *); + /* Compare un registre avec un autre. */ int g_arch_register_compare(const GArchRegister *, const GArchRegister *); +/* Détermine si un registre est égal à un autre. */ +gboolean g_arch_register_equal(const GArchRegister *, const GArchRegister *); + /* Traduit un registre en version humainement lisible. */ void g_arch_register_print(const GArchRegister *, GBufferLine *, AsmSyntax); diff --git a/src/decomp/context-int.h b/src/decomp/context-int.h index 7e5b1b0..974f5ae 100644 --- a/src/decomp/context-int.h +++ b/src/decomp/context-int.h @@ -36,8 +36,12 @@ /* Duplique un contexte de compilation. */ typedef GDecContext * (* dup_dec_context_fc) (GDecContext *); +/* Propage un registre alloué et attendu par la suite. */ +typedef void (* spread_reg_fc) (GDecContext *, GArchRegister *, GDecInstruction *); + /* Convertit un registre machine en un pseudo-registre. */ -typedef GDecInstruction * (* convert_register_fc) (GDecContext *, gpointer, bool); +typedef GDecInstruction * (* convert_register_fc) (GDecContext *, gpointer, bool, vmpa_t); + /* Définition d'une context décompilée (instance) */ @@ -46,11 +50,15 @@ struct _GDecContext GObject parent; /* A laisser en premier */ dup_dec_context_fc dup; /* Duplication de contexte */ + spread_reg_fc spread; /* Propagation des allocations */ convert_register_fc convert_reg; /* Traduction des registres */ GExeFormat *format; /* Format binaire concerné */ GBinRoutine *routine; /* Routine visée par l'opérat° */ + GRAccessList *awaited; /* Allocations attendues */ + GHashTable *shared; /* Allocations à propager */ + GDecInstruction *list; /* Chaîne décompilée */ }; @@ -67,6 +75,12 @@ struct _GDecContextClass /* Duplique partiellement un contexte de compilation. */ void _g_dec_context_dup(GDecContext *, GDecContext *); +/* Sauvegarde une conversion de registre si elle est attendue. */ +void g_dec_context_notify_reg_alloc(GDecContext *, GArchRegister *, GDecInstruction *, vmpa_t); + +/* Fournit une conversiond de registre déjà faite et attendue. */ +GDecInstruction *g_dec_context_get_awaited_alloc(GDecContext *, GArchRegister *, vmpa_t); + #endif /* _DECOMP_CONTEXT_INT_H */ diff --git a/src/decomp/context.c b/src/decomp/context.c index 025c0d2..ef5c25e 100644 --- a/src/decomp/context.c +++ b/src/decomp/context.c @@ -89,6 +89,11 @@ static void g_dec_context_class_init(GDecContextClass *class) static void g_dec_context_init(GDecContext *ctx) { + ctx->awaited = g_raccess_list_new(); + + ctx->shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, + (GEqualFunc)g_arch_register_equal, + g_object_unref, g_object_unref); } @@ -113,6 +118,9 @@ static void g_dec_context_dispose(GDecContext *ctx) if (ctx->routine != NULL) g_object_unref(G_OBJECT(ctx->routine)); + g_object_unref(G_OBJECT(ctx->awaited)); + g_hash_table_unref(ctx->shared); + G_OBJECT_CLASS(g_dec_context_parent_class)->dispose(G_OBJECT(ctx)); } @@ -227,6 +235,135 @@ GExeFormat *g_dec_context_get_format(const GDecContext *ctx) { return ctx->format; +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* awaited = liste des registres impliqués dans plusieurs blocs.* +* * +* Description : Définit la liste des registrés utilisés dans plusieurs blocs.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_set_awaited(GDecContext *ctx, GRAccessList *awaited) +{ + g_object_unref(G_OBJECT(ctx->awaited)); + + g_object_ref(G_OBJECT(awaited)); + ctx->awaited = awaited; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter. * +* * +* Description : Fournit la liste des registrés utilisés dans plusieurs blocs.* +* * +* Retour : Liste des registres impliqués dans plusieurs blocs. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GRAccessList *g_dec_context_get_awaited(const GDecContext *ctx) +{ + return ctx->awaited; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* shared = liste des allocations passées de registres attendus.* +* * +* Description : Définit la liste des registrés déjà alloués et attendus. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_set_shared_allocs(GDecContext *ctx, GHashTable *shared) +{ + g_hash_table_unref(ctx->shared); + + g_hash_table_ref(shared); + ctx->shared = shared; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter. * +* * +* Description : Fournit la liste des registrés déjà alloués et attendus. * +* * +* Retour : Liste des allocations passées de registres attendus. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GHashTable *g_dec_context_get_shared_allocs(const GDecContext *ctx) +{ + return ctx->shared; + +} + + +/****************************************************************************** +* * +* Paramètres : parent = instance à éventuellement compléter. * +* child = instance à venir consulter. * +* * +* Description : Propage les registres alloués et attendus par la suite. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_spread_allocated_shared_regs(GDecContext *parent, GDecContext *child) +{ + GHashTableIter iter; /* Boucle de parcours */ + GArchRegister *reg; /* Registre converti */ + GDecInstruction *dinstr; /* Expression décompilée */ + + g_hash_table_iter_init(&iter, child->shared); + + while (g_hash_table_iter_next(&iter, (gpointer *)®, (gpointer *)&dinstr)) + { + /** + * La liste des allocations attendues du bloc virtuel parent, et donc de + * son contexte associé, englobe les attentes des blocs contenus. + * Même si ce bloc parent n'est pas responsable directement de ces allocations, + * on fait remonter ces dernières pour la propagation dans les blocs suivants + * le bloc parent. + */ + if (g_raccess_list_find(parent->awaited, reg) != NULL) + { + g_object_ref(G_OBJECT(reg)); + g_object_ref(G_OBJECT(dinstr)); + + g_hash_table_insert(parent->shared, reg, dinstr); + + } + + parent->spread(parent, reg, dinstr); + + } } @@ -276,6 +413,7 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr) * Paramètres : ctx = instance à consulter, voire mettre à jour. * * operand = opérande représentant un registre quelconque. * * assign = précise le sort prochain du registre. * +* addr = adresse de l'instruction décompilée. * * * * Description : Convertit un registre machine en un pseudo-registre. * * * @@ -285,8 +423,69 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr) * * ******************************************************************************/ -GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign) +GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign, vmpa_t addr) +{ + return ctx->convert_reg(ctx, operand, assign, addr); + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter, voire mettre à jour. * +* reg = registre à l'origine de l'allocation. * +* dinstr = élément décompilé résultant. * +* addr = adresse de l'instruction décompilée. * +* * +* Description : Sauvegarde une conversion de registre si elle est attendue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_notify_reg_alloc(GDecContext *ctx, GArchRegister *reg, GDecInstruction *dinstr, vmpa_t addr) +{ + reg_access *access; /* Attente rélle si existante */ + + access = g_raccess_list_find(ctx->awaited, reg); + + if (access != NULL && access->last_write == addr) + { + g_object_ref(G_OBJECT(reg)); + g_object_ref(G_OBJECT(dinstr)); + + g_hash_table_insert(ctx->shared, reg, dinstr); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter, voire mettre à jour. * +* reg = registre à convertir prochainement. * +* addr = adresse de l'instruction décompilée. * +* * +* Description : Fournit une conversiond de registre déjà faite et attendue. * +* * +* Retour : Elément déjà décompilé dans une autre branche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_context_get_awaited_alloc(GDecContext *ctx, GArchRegister *reg, vmpa_t addr) { - return ctx->convert_reg(ctx, operand, assign); + reg_access *access; /* Attente rélle si existante */ + + access = g_raccess_list_find(ctx->awaited, reg); + if (access == NULL) return NULL; + + if (access->last_write != addr) return NULL; + + return G_DEC_INSTRUCTION(g_hash_table_lookup(ctx->shared, reg)); } diff --git a/src/decomp/context.h b/src/decomp/context.h index 94b3270..d1b1ac9 100644 --- a/src/decomp/context.h +++ b/src/decomp/context.h @@ -31,6 +31,7 @@ #include "instruction.h" #include "../arch/archbase.h" #include "../format/executable.h" +#include "../analysis/blocks/raccess.h" /** @@ -74,6 +75,21 @@ void g_dec_context_set_info(GDecContext *, GBinRoutine *, GExeFormat *); /* Fournit le format binaire associé au contexte. */ GExeFormat *g_dec_context_get_format(const GDecContext *); +/* Définit la liste des registrés utilisés dans plusieurs blocs. */ +void g_dec_context_set_awaited(GDecContext *, GRAccessList *); + +/* Fournit la liste des registrés utilisés dans plusieurs blocs. */ +const GRAccessList *g_dec_context_get_awaited(const GDecContext *); + +/* Définit la liste des registrés déjà alloués et attendus. */ +void g_dec_context_set_shared_allocs(GDecContext *, GHashTable *); + +/* Fournit la liste des registrés déjà alloués et attendus. */ +GHashTable *g_dec_context_get_shared_allocs(const GDecContext *); + +/* Propage les registres alloués et attendus par la suite. */ +void g_dec_context_spread_allocated_shared_regs(GDecContext *, GDecContext *); + /* Fournit le premier élément de la liste des instructions. */ GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *tx); @@ -81,7 +97,7 @@ GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *tx); void g_dec_context_set_decomp_instrs(GDecContext *, GDecInstruction *); /* Convertit un registre machine en un pseudo-registre. */ -GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer, bool); +GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer, bool, vmpa_t); -- cgit v0.11.2-87-g4458