From 8b35a66464636d0c46237af7490a6ca6866ecc4d Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 23 Jul 2012 19:07:29 +0000 Subject: Improved decompilation of Dalvik bytecode. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@252 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 88 ++++++++++++++++++++ src/analysis/routine.c | 28 ++++++- src/analysis/routine.h | 3 + src/analysis/variable.c | 4 +- src/arch/dalvik/decomp/Makefile.am | 4 + src/arch/dalvik/decomp/array.c | 2 +- src/arch/dalvik/decomp/const.c | 43 ++++++++++ src/arch/dalvik/decomp/iget.c | 78 ++++++++++++++++++ src/arch/dalvik/decomp/invoke.c | 164 ++++++++++++++++++++++++------------- src/arch/dalvik/decomp/iput.c | 78 ++++++++++++++++++ src/arch/dalvik/decomp/move.c | 99 ++++++++++++++++++++++ src/arch/dalvik/decomp/new.c | 72 ++++++++++++++++ src/arch/dalvik/decomp/translate.h | 21 +++++ src/arch/dalvik/instruction.c | 22 ++--- src/arch/dalvik/opcodes/move.c | 2 +- src/arch/dalvik/operands/args.c | 43 +++++++++- src/arch/dalvik/operands/args.h | 8 +- src/arch/instruction.c | 15 ++++ src/decomp/context.c | 43 ++++++++++ src/decomp/context.h | 6 ++ src/decomp/expr/Makefile.am | 4 +- src/decomp/expr/access.c | 159 +++++++++++++++++++++++++++++++++++ src/decomp/expr/access.h | 60 ++++++++++++++ src/decomp/expr/assign.c | 38 +++++++++ src/decomp/expr/assign.h | 6 ++ src/decomp/expr/call.c | 60 ++++++++++++-- src/decomp/expr/call.h | 5 +- src/decomp/expr/pseudo.c | 39 ++++++++- src/decomp/expr/pseudo.h | 4 + src/decomp/expr/text.c | 157 +++++++++++++++++++++++++++++++++++ src/decomp/expr/text.h | 60 ++++++++++++++ src/decomp/instruction-int.h | 13 ++- src/decomp/instruction.c | 105 ++++++++++++++++++++++++ src/decomp/instruction.h | 20 +++++ src/decomp/lang/asm.c | 4 +- src/format/dex/method.c | 5 ++ src/format/format.c | 24 ++---- 37 files changed, 1476 insertions(+), 110 deletions(-) create mode 100644 src/arch/dalvik/decomp/iget.c create mode 100644 src/arch/dalvik/decomp/iput.c create mode 100644 src/arch/dalvik/decomp/move.c create mode 100644 src/arch/dalvik/decomp/new.c create mode 100644 src/decomp/expr/access.c create mode 100644 src/decomp/expr/access.h create mode 100644 src/decomp/expr/text.c create mode 100644 src/decomp/expr/text.h diff --git a/ChangeLog b/ChangeLog index a19fb10..f4c91e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,91 @@ +12-07-23 Cyrille Bagard + + * src/analysis/routine.c: + * src/analysis/routine.h: + Provide a wrapper for building constructors quickly and highlight + routines in code rendering. + + * src/analysis/variable.c: + Cut long names. + + * src/arch/dalvik/decomp/array.c: + Disable debug code. + + * src/arch/dalvik/decomp/const.c: + Load constant strings. + + * src/arch/dalvik/decomp/iget.c: + New entries: extend decompilation. + + * src/arch/dalvik/decomp/invoke.c: + Improve decompilation. + + * src/arch/dalvik/decomp/iput.c: + New entries: extend decompilation. + + * src/arch/dalvik/decomp/Makefile.am: + Add the iget.c, iput.c, move.c and new.c files + to libarchdalvikdecomp_la_SOURCES. + + * src/arch/dalvik/decomp/move.c: + * src/arch/dalvik/decomp/new.c: + New entries: extend decompilation. + + * src/arch/dalvik/decomp/translate.h: + * src/arch/dalvik/instruction.c: + Update decompilation methods. + + * src/arch/dalvik/opcodes/move.c: + Typo. + + * src/arch/dalvik/operands/args.c: + * src/arch/dalvik/operands/args.h: + Provide arguments on demand. + + * src/arch/instruction.c: + Link a new decompiled instruction with the others. + + * src/decomp/context.c: + * src/decomp/context.h: + Store and provide the list of current decompiled instructions. + + * src/decomp/expr/access.c: + * src/decomp/expr/access.h: + New entries: create an expression for accesses. + + * src/decomp/expr/assign.c: + * src/decomp/expr/assign.h: + Provide source and destination expressions. + + * src/decomp/expr/call.c: + * src/decomp/expr/call.h: + Add arguments when calling. + + * src/decomp/expr/Makefile.am: + Add the access.[ch] and text.[ch] files to libdecompexpr_la_SOURCES. + + * src/decomp/expr/pseudo.c: + * src/decomp/expr/pseudo.h: + Improve the rendering of variable, in case of fields. + + * src/decomp/expr/text.c: + * src/decomp/expr/text.h: + New entries: display data as text. + + * src/decomp/instruction.c: + * src/decomp/instruction.h: + * src/decomp/instruction-int.h: + Link all decompiled instructions. + + * src/decomp/lang/asm.c: + Highlight routines in code rendering. + + * src/format/dex/method.c: + Print debug information about used registers. + + * src/format/format.c: + Take delivery of decompiled instructions. + 12-07-15 Cyrille Bagard * pixmaps/chrysalide_128.png: diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 651b7c6..b4fc51f 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -140,6 +140,32 @@ GBinRoutine *g_binary_routine_new(void) } + +/****************************************************************************** +* * +* Paramètres : type = type mis en place par la future routine. * +* * +* Description : Crée une représentation de routine construisant une instance.* +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine *g_binary_routine_new_constructor(GOpenidaType *type) +{ + GBinRoutine *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BIN_ROUTINE, NULL); + + g_binary_routine_set_name(result, _g_openida_type_to_string(type, true)); + + return result; + +} + + /****************************************************************************** * * * Paramètres : routine = routine à effacer. * @@ -896,7 +922,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang, len = 3; } - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, len, RTT_RAW); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, len, RTT_COMMENT); diff --git a/src/analysis/routine.h b/src/analysis/routine.h index 59569fb..8a5085b 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -76,6 +76,9 @@ GType g_bin_routine_get_type(void); /* Crée une représentation de routine. */ GBinRoutine *g_binary_routine_new(void); +/* Crée une représentation de routine construisant une instance. */ +GBinRoutine *g_binary_routine_new_constructor(GOpenidaType *); + /* Etablit la comparaison ascendante entre deux routines. */ int g_binary_routine_compare(const GBinRoutine **, const GBinRoutine **); diff --git a/src/analysis/variable.c b/src/analysis/variable.c index 932d165..2da691d 100644 --- a/src/analysis/variable.c +++ b/src/analysis/variable.c @@ -251,12 +251,12 @@ char *g_binary_variable_to_string(const GBinVariable *var, bool simple) { char *result; /* Valeur à retourner */ - result = _g_openida_type_to_string(var->type, simple); + result = strdup(""); /* FIXME : arg _g_openida_type_to_string(var->type, simple);*/ if (var->name != NULL) { if (!g_openida_type_is_pointer(var->type, true)) - result = stradd(result, " "); + /*result = stradd(result, " ")*/; result = stradd(result, var->name); diff --git a/src/arch/dalvik/decomp/Makefile.am b/src/arch/dalvik/decomp/Makefile.am index fef68f6..7a7f068 100644 --- a/src/arch/dalvik/decomp/Makefile.am +++ b/src/arch/dalvik/decomp/Makefile.am @@ -8,7 +8,11 @@ libarchdalvikdecomp_la_SOURCES = \ array.c \ const.c \ if.c \ + iget.c \ invoke.c \ + iput.c \ + move.c \ + new.c \ ret.c \ translate.h diff --git a/src/arch/dalvik/decomp/array.c b/src/arch/dalvik/decomp/array.c index c5db396..a841986 100644 --- a/src/arch/dalvik/decomp/array.c +++ b/src/arch/dalvik/decomp/array.c @@ -55,7 +55,7 @@ GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *instr, result = NULL; - printf("PAssaage !\n"); + //printf("PAssaage !\n"); diff --git a/src/arch/dalvik/decomp/const.c b/src/arch/dalvik/decomp/const.c index 54b6403..dce6b35 100644 --- a/src/arch/dalvik/decomp/const.c +++ b/src/arch/dalvik/decomp/const.c @@ -24,8 +24,10 @@ #include "translate.h" +#include "../operands/pool.h" #include "../../../decomp/expr/assign.h" #include "../../../decomp/expr/immediate.h" +#include "../../../decomp/expr/text.h" @@ -60,3 +62,44 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecCo return result; } + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de type 'const-string'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_const_str(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *reg; /* Pseudo-registre redéfini */ + uint32_t index; /* Indice de la chaîne */ + GDexFormat *format; /* Accès aux constantes */ + const char *value; /* Chaîne de caractères */ + GDecInstruction *str; /* Chaîne décompilée */ + + operand = g_arch_instruction_get_operand(instr, 0); + reg = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 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")); + value = get_string_from_dex_pool(format, index); + + str = g_str_expression_new(value); + + result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(str)); + + return result; + +} diff --git a/src/arch/dalvik/decomp/iget.c b/src/arch/dalvik/decomp/iget.c new file mode 100644 index 0000000..8b8f9f0 --- /dev/null +++ b/src/arch/dalvik/decomp/iget.c @@ -0,0 +1,78 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * iget.c - décompilation des instructions manipulant des champs d'instance (chargement) + * + * 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 . + */ + + +#include "translate.h" + + +#include "../../../arch/dalvik/operands/pool.h" +#include "../../../decomp/expr/access.h" +#include "../../../decomp/expr/assign.h" +#include "../../../decomp/expr/pseudo.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de type 'iget'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *dest; /* Registre de destination */ + GDecInstruction *src; /* Registre de l'object */ + uint32_t index; /* Indice dans la table */ + GDexFormat *format; /* Accès aux constantes */ + GDecInstruction *field; /* Champ concerné par l'opérat°*/ + GBinVariable *var; /* Variable / champ accédé */ + GDecInstruction *access; /* Représentation de l'accès */ + + operand = g_arch_instruction_get_operand(instr, 0); + dest = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 1); + src = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 2); + index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); + format = G_DEX_FORMAT(g_object_get_data(G_OBJECT(ctx), "format")); + var = get_field_from_dex_pool(format, index); + + field = g_pseudo_register_new(); + g_pseudo_register_set_variable(G_PSEUDO_REGISTER(field), var); + + 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)); + + return result; + +} diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c index 7360659..a8772cd 100644 --- a/src/arch/dalvik/decomp/invoke.c +++ b/src/arch/dalvik/decomp/invoke.c @@ -24,8 +24,12 @@ #include "translate.h" +#include + + #include "../instruction.h" #include "../operand.h" +#include "../../../decomp/expr/access.h" #include "../../../decomp/expr/assign.h" #include "../../../decomp/expr/call.h" #include "../../../format/dex/pool.h" @@ -38,7 +42,7 @@ * Paramètres : instr = instruction d'origine à convertir. * * ctx = contexte de la phase de décompilation. * * * -* Description : Décompile une instruction de type 'invoke-virtual'. * +* Description : Décompile une instruction de type 'invoke-direct'. * * * * Retour : Instruction mise en place ou NULL. * * * @@ -46,112 +50,156 @@ * * ******************************************************************************/ -GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *instr, GDecContext *ctx) +GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ - - + GDecInstruction *iter; /* Boucle de parcours #1 */ + GDecInstruction *list; /* Instructions décompilées */ size_t count; /* Quantité d'opérandes */ - GArchOperand *op; /* Opérande de l'instruction */ + 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 */ + const char *name; /* Chaîne à afficher */ + GDecInstruction *src; /* Source de l'assignation */ + GDecInstruction *dest; /* Destination de l'assignat° */ + size_t i; /* Boucle de parcours #2 */ + GArchOperand *arg; /* Argument brut de l'appel */ + GDecInstruction *reg; /* Argument converti */ - const char *string; /* Chaîne à afficher */ - GOpenidaType *type; /* Type quelconque */ - char *tmp; /* Chaîne à afficher & libérer */ + result = NULL; + iter = NULL; + list = g_dec_context_get_decomp_instrs(ctx); + if (list == NULL) return NULL; + /* Récupération de la méthode */ - GArchOperand *operand; /* Opérande de l'instruction */ - GDecInstruction *reg; /* Pseudo-registre redéfini */ - GDecInstruction *imm; /* Valeur immédiate décompilée */ + count = g_arch_instruction_count_operands(instr); + operand = g_arch_instruction_get_operand(instr, count - 1); - GArchInstruction *iter; /* Boucle de parcours */ - vmpa_t max; /* Limite à ne pas dépasser */ + 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; - result = NULL; + /* Détermination de la routine-cible exacte */ + name = g_binary_routine_get_name(routine); - printf("PAssaage !\n"); + if (strcmp(name, "") != 0) + result = g_routine_call_new(routine); + else + { + src = NULL; /* Pour gcc... */ + for (iter = g_dec_instruction_get_last(list); + iter != NULL; + iter = g_dec_instruction_get_prev_iter(list, iter)) + { + if (!G_IS_ASSIGN_EXPRESSION(iter)) continue; + src = g_assign_expression_get_src(G_ASSIGN_EXPRESSION(iter)); + if (!G_IS_ROUTINE_CALL(src)) continue; + dest = g_assign_expression_get_dest(G_ASSIGN_EXPRESSION(iter)); + /* TODO : vérifier aussi la concordance des registres src && instr */ + break; - /* Récupération de la méthode */ + } - count = g_arch_instruction_count_operands(instr); - op = g_arch_instruction_get_operand(instr, count - 1); + if (iter == NULL) return NULL; - index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(op)); + result = src; - printf("POOL ?? %d -> %d\n", G_IS_DALVIK_POOL_OPERAND(op), index); + g_dec_instruction_delete(&list, iter); + g_dec_context_set_decomp_instrs(ctx, list); - 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; + } + /* Ajout des arguments */ -#if 0 - if (operand->cache.method == NULL) - g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, - "", 18, RTT_VAR_NAME); + operand = g_arch_instruction_get_operand(instr, 0); + count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); - else - { - tmp = g_binary_routine_to_string(operand->cache.method); + 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); - g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, - tmp, strlen(tmp), RTT_VAR_NAME); + g_routine_call_add_arg(G_ROUTINE_CALL(result), reg); - free(tmp); + } + return (iter != NULL ? iter : result); -#endif +} - result = g_routine_call_new(routine, true); - //GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object) - /* - operand = g_arch_instruction_get_operand(instr, 1); - reg = g_dec_context_convert_register(ctx, operand); +/****************************************************************************** +* * +* 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. * +* * +* Remarques : - * +* * +******************************************************************************/ - operand = g_arch_instruction_get_operand(instr, 1); - imm = g_imm_expression_new(G_IMM_OPERAND(operand)); +GDecInstruction *dalvik_decomp_instr_invoke_virtual(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 = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(imm)); - */ + 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; - /* Récupération d'un résultat ? */ + call = g_routine_call_new(routine); - iter = instr; - max = g_dec_context_get_max_address(ctx); + /* Ajout des arguments */ - iter = g_arch_instruction_get_next_iter(instr, iter, max); + operand = g_arch_instruction_get_operand(instr, 0); + count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand)); - if (iter != NULL) - switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(iter))) - { - case DOP_MOVE_RESULT: + 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); - operand = g_arch_instruction_get_operand(iter, 0); - reg = g_dec_context_convert_register(ctx, operand); + g_routine_call_add_arg(G_ROUTINE_CALL(call), reg); - result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(result)); + } - break; + /* Appel depuis le propriétaire */ - default: - break; + arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), 0); + reg = g_dec_context_convert_register(ctx, arg); - } + result = g_access_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(call)); return result; diff --git a/src/arch/dalvik/decomp/iput.c b/src/arch/dalvik/decomp/iput.c new file mode 100644 index 0000000..4db4770 --- /dev/null +++ b/src/arch/dalvik/decomp/iput.c @@ -0,0 +1,78 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * iput.c - décompilation des instructions manipulant des champs d'instance (déchargement) + * + * 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 . + */ + + +#include "translate.h" + + +#include "../../../arch/dalvik/operands/pool.h" +#include "../../../decomp/expr/access.h" +#include "../../../decomp/expr/assign.h" +#include "../../../decomp/expr/pseudo.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de type 'iput'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *dest; /* Registre de destination */ + GDecInstruction *src; /* Registre de l'object */ + uint32_t index; /* Indice dans la table */ + GDexFormat *format; /* Accès aux constantes */ + GDecInstruction *field; /* Champ concerné par l'opérat°*/ + GBinVariable *var; /* Variable / champ accédé */ + GDecInstruction *access; /* Représentation de l'accès */ + + operand = g_arch_instruction_get_operand(instr, 0); + src = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 1); + dest = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 2); + index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand)); + format = G_DEX_FORMAT(g_object_get_data(G_OBJECT(ctx), "format")); + var = get_field_from_dex_pool(format, index); + + field = g_pseudo_register_new(); + g_pseudo_register_set_variable(G_PSEUDO_REGISTER(field), var); + + access = g_access_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(field)); + result = g_assign_expression_new(G_DEC_EXPRESSION(access), G_DEC_EXPRESSION(src)); + + return result; + +} diff --git a/src/arch/dalvik/decomp/move.c b/src/arch/dalvik/decomp/move.c new file mode 100644 index 0000000..798b6b0 --- /dev/null +++ b/src/arch/dalvik/decomp/move.c @@ -0,0 +1,99 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * move.c - décompilation des opérations de déplacement + * + * 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 . + */ + + +#include "translate.h" + + +#include "../../../decomp/expr/assign.h" + + + +/****************************************************************************** +* * +* 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. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *dest; /* Registre de destination */ + GDecInstruction *src; /* Registre de l'object */ + + operand = g_arch_instruction_get_operand(instr, 0); + dest = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 1); + src = g_dec_context_convert_register(ctx, operand); + + 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-result'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GDecInstruction *list; /* Instructions décompilées */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *dest; /* Registre de destination */ + GDecInstruction *last; /* Instruction précédante */ + + list = g_dec_context_get_decomp_instrs(ctx); + if (list == NULL) return NULL; + + operand = g_arch_instruction_get_operand(instr, 0); + dest = g_dec_context_convert_register(ctx, operand); + + last = g_dec_instruction_get_last(list); + g_dec_instruction_delete(&list, last); + g_dec_context_set_decomp_instrs(ctx, list); + + result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(last)); + + return result; + +} diff --git a/src/arch/dalvik/decomp/new.c b/src/arch/dalvik/decomp/new.c new file mode 100644 index 0000000..1c4c06e --- /dev/null +++ b/src/arch/dalvik/decomp/new.c @@ -0,0 +1,72 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * new.c - décompilation des créations de nouvelles instances + * + * 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 . + */ + + +#include "translate.h" + + +#include "../../../arch/dalvik/operands/pool.h" +#include "../../../decomp/expr/assign.h" +#include "../../../decomp/expr/call.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de type 'new-instance'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + GArchOperand *operand; /* Opérande de l'instruction */ + GDecInstruction *dest; /* Registre de destination */ + uint32_t index; /* Indice dans la table */ + GDexFormat *format; /* Accès aux constantes */ + GOpenidaType *type; /* Type concerné par l'opérat° */ + GBinRoutine *constructor; /* Constructeur reconstruit */ + GDecInstruction *call; /* Appel au constructeur */ + + operand = g_arch_instruction_get_operand(instr, 0); + dest = g_dec_context_convert_register(ctx, operand); + + operand = g_arch_instruction_get_operand(instr, 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")); + type = get_type_from_dex_pool(format, index); + + constructor = g_binary_routine_new_constructor(type); + call = g_routine_call_new(constructor); + + result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(call)); + + return result; + +} diff --git a/src/arch/dalvik/decomp/translate.h b/src/arch/dalvik/decomp/translate.h index 11b11f7..7779ab7 100644 --- a/src/arch/dalvik/decomp/translate.h +++ b/src/arch/dalvik/decomp/translate.h @@ -41,9 +41,30 @@ GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *, GDec /* Décompile une instruction de type 'const'. */ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *, GDecContext *); +/* Décompile une instruction de type 'const-string'. */ +GDecInstruction *dalvik_decomp_instr_const_str(const GArchInstruction *, GDecContext *); + +/* Décompile une instruction de type 'iget'. */ +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-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-object'. */ +GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *, GDecContext *); + +/* Décompile une instruction de type 'move-result'. */ +GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *, GDecContext *); + +/* Décompile une instruction de type 'new-instance'. */ +GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *, GDecContext *); + /* Décompile une instruction de type 'return'. */ GDecInstruction *dalvik_decomp_instr_return(const GArchInstruction *, GDecContext *); diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index b593d51..7949225 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * instruction.c - gestion des instructions de la VM Dalvik * - * Copyright (C) 2010-2011 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * @@ -55,7 +55,7 @@ typedef struct _dalvik_instruction static dalvik_instruction _instructions[DOP_COUNT] = { - [DOP_NOP] = { 0x00, "nop" }, + [DOP_NOP] = { 0x00, "nop", NULL }, [DOP_MOVE] = { 0x01, "move" }, [DOP_MOVE_FROM_16] = { 0x02, "move/from16" }, @@ -63,12 +63,12 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_MOVE_WIDE_FROM_16] = { 0x05, "move-wide/from16" }, - [DOP_MOVE_OBJECT] = { 0x07, "move-object" }, + [DOP_MOVE_OBJECT] = { 0x07, "move-object", dalvik_decomp_instr_move_object }, [DOP_MOVE_OBJECT_FROM_16] = { 0x08, "move-object/from16" }, - [DOP_MOVE_RESULT] = { 0x0a, "move-result" }, - [DOP_MOVE_RESULT_WIDE] = { 0x0b, "move-result-wide" }, - [DOP_MOVE_RESULT_OBJECT] = { 0x0c, "move-result-object" }, + [DOP_MOVE_RESULT] = { 0x0a, "move-result", dalvik_decomp_instr_move_result }, + [DOP_MOVE_RESULT_WIDE] = { 0x0b, "move-result-wide", dalvik_decomp_instr_move_result }, + [DOP_MOVE_RESULT_OBJECT] = { 0x0c, "move-result-object", dalvik_decomp_instr_move_result }, [DOP_MOVE_EXCEPTION] = { 0x0d, "move-exception" }, [DOP_RETURN_VOID] = { 0x0e, "return-void", dalvik_decomp_instr_return_void }, [DOP_RETURN] = { 0x0f, "return", dalvik_decomp_instr_return }, @@ -82,7 +82,7 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_CONST_WIDE_32] = { 0x17, "const-wide/32" }, [DOP_CONST_WIDE] = { 0x18, "const-wide" }, [DOP_CONST_WIDE_HIGH16] = { 0x19, "const-wide/high16" }, - [DOP_CONST_STRING] = { 0x1a, "const-string" }, + [DOP_CONST_STRING] = { 0x1a, "const-string", dalvik_decomp_instr_const_str }, [DOP_CONST_STRING_JUMBO] = { 0x1b, "const-string/jumbo" }, [DOP_CONST_CLASS] = { 0x1c, "const-class" }, @@ -90,7 +90,7 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_ARRAY_LENGTH] = { 0x21, "array-length", dalvik_decomp_instr_array_length }, - [DOP_NEW_INSTANCE] = { 0x22, "new-instance" }, + [DOP_NEW_INSTANCE] = { 0x22, "new-instance", dalvik_decomp_instr_new_instance }, [DOP_NEW_ARRAY] = { 0x23, "new-array" }, @@ -135,14 +135,14 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_APUT_BYTE] = { 0x4f, "aput-byte", dalvik_decomp_instr_aput }, [DOP_APUT_CHAR] = { 0x50, "aput-char" }, [DOP_APUT_SHORT] = { 0x51, "aput-short" }, - [DOP_IGET] = { 0x52, "iget" }, + [DOP_IGET] = { 0x52, "iget", dalvik_decomp_instr_iget }, [DOP_IGET_WIDE] = { 0x53, "iget-wide" }, [DOP_IGET_OBJECT] = { 0x54, "iget-object" }, [DOP_IGET_BOOLEAN] = { 0x55, "iget-boolean" }, [DOP_IGET_BYTE] = { 0x56, "iget-byte" }, [DOP_IGET_CHAR] = { 0x57, "iget-char" }, [DOP_IGET_SHORT] = { 0x58, "iget-short" }, - [DOP_IPUT] = { 0x59, "iput" }, + [DOP_IPUT] = { 0x59, "iput", dalvik_decomp_instr_iput }, [DOP_IPUT_WIDE] = { 0x5a, "iput-wide" }, [DOP_IPUT_OBJECT] = { 0x5b, "iput-object" }, [DOP_IPUT_BOOLEAN] = { 0x5c, "iput-boolean" }, @@ -165,7 +165,7 @@ static dalvik_instruction _instructions[DOP_COUNT] = { [DOP_SPUT_SHORT] = { 0x6d, "sput-short" }, [DOP_INVOKE_VIRTUAL] = { 0x6e, "invoke-virtual", dalvik_decomp_instr_invoke_virtual }, [DOP_INVOKE_SUPER] = { 0x6f, "invoke-static" }, - [DOP_INVOKE_DIRECT] = { 0x70, "invoke-direct" }, + [DOP_INVOKE_DIRECT] = { 0x70, "invoke-direct", dalvik_decomp_instr_invoke_direct }, [DOP_INVOKE_STATIC] = { 0x71, "invoke-static" }, [DOP_INVOKE_INTERFACE] = { 0x72, "invoke-interface" }, diff --git a/src/arch/dalvik/opcodes/move.c b/src/arch/dalvik/opcodes/move.c index cb4e274..e6e1e6e 100644 --- a/src/arch/dalvik/opcodes/move.c +++ b/src/arch/dalvik/opcodes/move.c @@ -1,6 +1,6 @@ /* OpenIDA - Outil d'analyse de fichiers binaires - * move.c - décodage des opérations de multiplications + * move.c - décodage des opérations de déplacement * * Copyright (C) 2010-2012 Cyrille Bagard * diff --git a/src/arch/dalvik/operands/args.c b/src/arch/dalvik/operands/args.c index 367a718..16d995c 100644 --- a/src/arch/dalvik/operands/args.c +++ b/src/arch/dalvik/operands/args.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * args.c - listes d'opérandes rassemblées en arguments * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * @@ -187,3 +187,44 @@ void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg) operand->args[operand->count - 1] = arg; } + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à compléter. * +* * +* Description : Fournit le nombre d'arguments pris en charge. * +* * +* Retour : Nombre positif ou nul. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_dalvik_args_count(const GDalvikArgsOperand *operand) +{ + return operand->count; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à compléter. * +* index = indice de l'argument recherché. * +* * +* Description : Founit un élément de la liste d'arguments Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *operand, size_t index) +{ + /* BUG_ON(index >= operand->count) */ + + return operand->args[index]; + +} diff --git a/src/arch/dalvik/operands/args.h b/src/arch/dalvik/operands/args.h index 87ec9ae..70ca153 100644 --- a/src/arch/dalvik/operands/args.h +++ b/src/arch/dalvik/operands/args.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * args.h - prototypes pour les listes d'opérandes rassemblées en arguments * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012x Cyrille Bagard * * This file is part of OpenIDA. * @@ -56,6 +56,12 @@ GArchOperand *g_dalvik_args_operand_new(void); /* Ajoute un élément à la liste d'arguments Dalvik. */ void g_dalvik_args_operand_add(GDalvikArgsOperand *, GArchOperand *); +/* Fournit le nombre d'arguments pris en charge. */ +size_t g_dalvik_args_count(const GDalvikArgsOperand *); + +/* Founit un élément de la liste d'arguments Dalvik. */ +GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *, size_t); + #endif /* _ARCH_DALVIK_OPERANDS_ARGS_H */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 6bb10e8..2d1836b 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -700,10 +700,25 @@ void g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer *buffer GDecInstruction *g_arch_instruction_decompile(const GArchInstruction *instr, GDecContext *ctx) { GDecInstruction *result; /* Instruction à retourner */ + GDecInstruction *list; /* Instructions décompilées */ if (instr->decomp != NULL) + { result = instr->decomp(instr, ctx); + if (result != NULL) + { + list = g_dec_context_get_decomp_instrs(ctx); + + if (list == NULL) list = result; + else g_dec_instruction_add_to_list(&list, result); + + g_dec_context_set_decomp_instrs(ctx, list); + + } + + } + else result = NULL; diff --git a/src/decomp/context.c b/src/decomp/context.c index 6440c56..15215eb 100644 --- a/src/decomp/context.c +++ b/src/decomp/context.c @@ -27,6 +27,7 @@ #include +#include "instruction-int.h" #include "expr/pseudo.h" #include "../arch/operand.h" #include "../glibext/gnhash.h" @@ -40,6 +41,8 @@ struct _GDecContext vmpa_t max; /* Première adresse à écarter */ + GDecInstruction *list; /* Chaîne décompilée */ + GHashTable *machine; /* Correspondance reg./pseudo */ GHashTable *ssa; /* Remplacement des pseudos */ @@ -171,6 +174,46 @@ void g_dec_context_set_max_address(GDecContext *ctx, vmpa_t max) /****************************************************************************** * * +* Paramètres : ctx = instance à consulter. * +* * +* Description : Fournit le premier élément de la liste des instructions. * +* * +* Retour : Première instruction décompilée pour le contexte. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *ctx) +{ + return ctx->list; + + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* instr = première instruction décompilée pour le contexte. * +* * +* Description : Met à jour le premier élément de la liste des instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr) +{ + ctx->list = instr; + +} + + +/****************************************************************************** +* * * Paramètres : ctx = instance à consulter, voire mettre à jour. * * operand = opérande représentant un registre quelconque. * * * diff --git a/src/decomp/context.h b/src/decomp/context.h index 926a372..b7dd445 100644 --- a/src/decomp/context.h +++ b/src/decomp/context.h @@ -61,6 +61,12 @@ vmpa_t g_dec_context_get_max_address(const GDecContext *); /* Définit l'adresse où la décompilation n'est plus souhaitée. */ void g_dec_context_set_max_address(GDecContext *, vmpa_t); +/* Fournit le premier élément de la liste des instructions. */ +GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *tx); + +/* Met à jour le premier élément de la liste des instructions. */ +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); diff --git a/src/decomp/expr/Makefile.am b/src/decomp/expr/Makefile.am index 7507593..483a1f3 100644 --- a/src/decomp/expr/Makefile.am +++ b/src/decomp/expr/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libdecompexpr.la libdecompexpr_la_SOURCES = \ + access.h access.c \ arithm.h arithm.c \ array.h array.c \ assign.h assign.c \ @@ -10,7 +11,8 @@ libdecompexpr_la_SOURCES = \ cond.h cond.c \ immediate.h immediate.c \ pseudo.h pseudo.c \ - return.h return.c + return.h return.c \ + text.h text.c libdecompexpr_la_LDFLAGS = diff --git a/src/decomp/expr/access.c b/src/decomp/expr/access.c new file mode 100644 index 0000000..e2cbf19 --- /dev/null +++ b/src/decomp/expr/access.c @@ -0,0 +1,159 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * access.c - représentation des accès à des éléments d'entités + * + * Copyright (C) 2010 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 . + */ + + +#include "access.h" + + +#include "../expression-int.h" + + + +/* Définition d'un accès quelconque (instance) */ +struct _GAccessExpression +{ + GDecExpression parent; /* A laisser en premier */ + + GDecExpression *owner; /* Destination de l'accessat° */ + GDecExpression *target; /* Source de l'accessation */ + +}; + + +/* Définition d'un accès quelconque (classe) */ +struct _GAccessExpressionClass +{ + GDecExpressionClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des accessations quelconques. */ +static void g_access_expression_class_init(GAccessExpressionClass *); + +/* Initialise une instance d'accessation quelconque. */ +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 *); + + + +/* Indique le type défini pour un accès quelconque. */ +G_DEFINE_TYPE(GAccessExpression, g_access_expression, G_TYPE_DEC_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des accessations quelconques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_access_expression_class_init(GAccessExpressionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser. * +* * +* Description : Initialise une instance d'accessation quelconque. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_access_expression_init(GAccessExpression *expr) +{ + GDecInstruction *instr; /* Autre version de l'objet */ + + instr = G_DEC_INSTRUCTION(expr); + + instr->print = (dec_instr_print_fc)g_access_expression_print; + +} + + +/****************************************************************************** +* * +* Paramètres : owner = entité qui accueille la cible accédée. * +* target = élément du propriétaire auquel on accède. * +* * +* Description : Représente l'accès à un élément d'une entité. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_access_expression_new(GDecExpression *owner, GDecExpression *target) +{ + GAccessExpression *result; /* Expression à retourner */ + + result = g_object_new(G_TYPE_ACCESS_EXPRESSION, NULL); + + result->owner = owner; + result->target = target; + + return G_DEC_INSTRUCTION(result); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à transcrire en version humaine. * +* buffer = tampon où doit se réaliser l'insertion. * +* line = ligne d'impression prête à emploi ou NULL. * +* output = langage de programmation de sortie. * +* * +* Description : Imprime pour l'écran un version humaine d'une expression. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void 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); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT); + + g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target), + buffer, line, output); + +} diff --git a/src/decomp/expr/access.h b/src/decomp/expr/access.h new file mode 100644 index 0000000..9b4561f --- /dev/null +++ b/src/decomp/expr/access.h @@ -0,0 +1,60 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * access.h - prototypes pour la représentation des accès à des éléments d'entités + * + * Copyright (C) 2010 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 . + */ + + +#ifndef _DECOMP_EXPR_ACCESS_H +#define _DECOMP_EXPR_ACCESS_H + + +#include + + +#include "../expression.h" +#include "../instruction.h" + + + +#define G_TYPE_ACCESS_EXPRESSION g_access_expression_get_type() +#define G_ACCESS_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_access_expression_get_type(), GAccessExpression)) +#define G_IS_ACCESS_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_access_expression_get_type())) +#define G_ACCESS_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ACCESS_EXPRESSION, GAccessExpressionClass)) +#define G_IS_ACCESS_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ACCESS_EXPRESSION)) +#define G_ACCESS_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ACCESS_EXPRESSION, GAccessExpressionClass)) + + + +/* Définition d'un accès quelconque (instance) */ +typedef struct _GAccessExpression GAccessExpression; + +/* Définition d'un accès quelconque (classe) */ +typedef struct _GAccessExpressionClass GAccessExpressionClass; + + +/* Indique le type défini pour un accès quelconque. */ +GType g_access_expression_get_type(void); + +/* Représente l'accès à un élément d'une entité. */ +GDecInstruction *g_access_expression_new(GDecExpression *, GDecExpression *); + + + +#endif /* _DECOMP_EXPR_ACCESS_H */ diff --git a/src/decomp/expr/assign.c b/src/decomp/expr/assign.c index 29eb0f8..0843776 100644 --- a/src/decomp/expr/assign.c +++ b/src/decomp/expr/assign.c @@ -157,3 +157,41 @@ static void g_assign_expression_print(const GAssignExpression *expr, GCodeBuffer buffer, line, output); } + + +/****************************************************************************** +* * +* Paramètres : assign = expression à consulter. * +* * +* Description : Indique la destination d'une assignation. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_assign_expression_get_dest(const GAssignExpression *assign) +{ + return assign->dest; + +} + + +/****************************************************************************** +* * +* Paramètres : assign = expression à consulter. * +* * +* Description : Indique la source d'une assignation. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_assign_expression_get_src(const GAssignExpression *assign) +{ + return assign->src; + +} diff --git a/src/decomp/expr/assign.h b/src/decomp/expr/assign.h index 87d167e..ce441f6 100644 --- a/src/decomp/expr/assign.h +++ b/src/decomp/expr/assign.h @@ -55,6 +55,12 @@ GType g_assign_expression_get_type(void); /* Assigne le contenu d'une expression dans une autre. */ GDecInstruction *g_assign_expression_new(GDecExpression *, GDecExpression *); +/* Indique la destination d'une assignation. */ +GDecInstruction *g_assign_expression_get_dest(const GAssignExpression *); + +/* Indique la source d'une assignation. */ +GDecInstruction *g_assign_expression_get_src(const GAssignExpression *); + #endif /* _DECOMP_EXPR_ASSIGN_H */ diff --git a/src/decomp/expr/call.c b/src/decomp/expr/call.c index 05e596a..aaf9883 100644 --- a/src/decomp/expr/call.c +++ b/src/decomp/expr/call.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * call.c - encadrement des appels de routine * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * @@ -24,6 +24,7 @@ #include "call.h" +#include #include @@ -37,7 +38,9 @@ struct _GRoutineCall GDecExpression parent; /* A laisser en premier */ GBinRoutine *routine; /* Routine sollicitée */ - bool is_object; /* Nature de l'argument n°1 */ + + GDecInstruction **args; /* Arguments à associer */ + size_t count; /* Nombre d'arguments présents */ }; @@ -109,8 +112,7 @@ static void g_routine_call_init(GRoutineCall *expr) /****************************************************************************** * * -* Paramètres : routine = routine dont il est fait appel. * -* is_object = indique la nature du premier argument. * +* Paramètres : routine = routine dont il est fait appel. * * * * Description : Exprime un appel à une routine quelconque. * * * @@ -120,14 +122,13 @@ static void g_routine_call_init(GRoutineCall *expr) * * ******************************************************************************/ -GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object) +GDecInstruction *g_routine_call_new(GBinRoutine *routine) { GRoutineCall *result; /* Expression à retourner */ result = g_object_new(G_TYPE_ROUTINE_CALL, NULL); result->routine = routine; - result->is_object = is_object; return G_DEC_INSTRUCTION(result); @@ -136,7 +137,7 @@ GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object) /****************************************************************************** * * -* Paramètres : expr = expression à transcrire en version humaine. * +* Paramètres : call = expression à transcrire en version humaine. * * buffer = tampon où doit se réaliser l'insertion. * * line = ligne d'impression prête à emploi ou NULL. * * output = langage de programmation de sortie. * @@ -149,15 +150,56 @@ GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object) * * ******************************************************************************/ -static void g_routine_call_print(const GRoutineCall *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static void g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { const char *name; /* Désignation de la routine */ + size_t i; /* Boucle de parcours */ - name = g_binary_routine_get_name(expr->routine); + name = g_binary_routine_get_name(call->routine); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT); + if (call->count > 0) + { + 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_dec_instruction_print(call->args[i], buffer, line, output); + + } + + } + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT); } + + +/****************************************************************************** +* * +* Paramètres : call = expression d'appel à mettre à jour. * +* arg = nouvel argument à associer à l'appel. * +* * +* Description : Enregistre un nouvel argument pour l'appel de routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_routine_call_add_arg(GRoutineCall *call, GDecInstruction *arg) +{ + call->args = (GDecInstruction **)realloc(call->args, + ++call->count * sizeof(GDecInstruction *)); + + call->args[call->count - 1] = arg; + + /* TODO : synchroniser avec la routine (cf. constructeurs construits à la volée) */ + +} diff --git a/src/decomp/expr/call.h b/src/decomp/expr/call.h index 7515261..8856166 100644 --- a/src/decomp/expr/call.h +++ b/src/decomp/expr/call.h @@ -54,7 +54,10 @@ typedef struct _GRoutineCallClass GRoutineCallClass; GType g_routine_call_get_type(void); /* Exprime un appel à une routine quelconque. */ -GDecInstruction *g_routine_call_new(GBinRoutine *, bool); +GDecInstruction *g_routine_call_new(GBinRoutine *); + +/* Enregistre un nouvel argument pour l'appel de routine. */ +void g_routine_call_add_arg(GRoutineCall *, GDecInstruction *); diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c index 06ba184..bb5861d 100644 --- a/src/decomp/expr/pseudo.c +++ b/src/decomp/expr/pseudo.c @@ -24,6 +24,7 @@ #include "pseudo.h" +#include #include #include @@ -38,6 +39,7 @@ struct _GPseudoRegister GDecExpression parent; /* A laisser en premier */ size_t index; /* Position dans l'ensemble */ + GBinVariable *var; /* Variable plus précise */ }; @@ -148,10 +150,19 @@ GDecInstruction *g_pseudo_register_new(void) static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { char label[32]; - - snprintf(label, 32, "var%d", reg->index); - - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW); + char *name; + + if (reg->var != NULL) + { + name = g_binary_variable_to_string(reg->var, true); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, name, strlen(name), RTT_RAW); + free(name); + } + else + { + snprintf(label, 32, "var%zu", reg->index); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW); + } } @@ -174,3 +185,23 @@ void g_pseudo_register_set_index(GPseudoRegister *reg, size_t index) reg->index = index; } + + +/****************************************************************************** +* * +* Paramètres : reg = expression représentant un pseudo-registre à traiter. * +* var = indications supplémentaire quant à la variable. * +* * +* Description : Précise le nom et le type de la variable. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_pseudo_register_set_variable(GPseudoRegister *reg, GBinVariable *var) +{ + reg->var = var; + +} diff --git a/src/decomp/expr/pseudo.h b/src/decomp/expr/pseudo.h index 95612a9..dce6337 100644 --- a/src/decomp/expr/pseudo.h +++ b/src/decomp/expr/pseudo.h @@ -29,6 +29,7 @@ #include "../instruction.h" +#include "../../analysis/variable.h" @@ -57,6 +58,9 @@ GDecInstruction *g_pseudo_register_new(void); /* Définit un indice unique pour un pseudo-registre donné. */ void g_pseudo_register_set_index(GPseudoRegister *, size_t); +/* Précise le nom et le type de la variable. */ +void g_pseudo_register_set_variable(GPseudoRegister *, GBinVariable *); + #endif /* _DECOMP_EXPR_PSEUDO_H */ diff --git a/src/decomp/expr/text.c b/src/decomp/expr/text.c new file mode 100644 index 0000000..d62e689 --- /dev/null +++ b/src/decomp/expr/text.c @@ -0,0 +1,157 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * text.c - raccord avec les opérandes de chaînes de caractères + * + * 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 . + */ + + +#include "text.h" + + +#include + + +#include "../expression-int.h" + + + +/* Définition d'une expression de valeur immédiate (instance) */ +struct _GStrExpression +{ + GDecExpression parent; /* A laisser en premier */ + + char *value; /* Chaîne représentée */ + size_t len; /* Taille du texte */ + +}; + + +/* Définition d'une expression de valeur immédiate (classe) */ +struct _GStrExpressionClass +{ + GDecExpressionClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des expressions de valeur immédiate. */ +static void g_str_expression_class_init(GStrExpressionClass *); + +/* Initialise une instance d'expression de valeur immédiate. */ +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 *); + + + +/* Indique le type défini pour une expression de valeur immédiate. */ +G_DEFINE_TYPE(GStrExpression, g_str_expression, G_TYPE_DEC_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des expressions de valeur immédiate. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_str_expression_class_init(GStrExpressionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser. * +* * +* Description : Initialise une instance d'expression de valeur immédiate. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_str_expression_init(GStrExpression *expr) +{ + GDecInstruction *instr; /* Autre version de l'objet */ + + instr = G_DEC_INSTRUCTION(expr); + + instr->print = (dec_instr_print_fc)g_str_expression_print; + +} + + +/****************************************************************************** +* * +* Paramètres : value = chaîne de caractères à représenter. * +* * +* Description : Construit une expression à partir d'une valeur immédiate. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_str_expression_new(const char *value) +{ + GStrExpression *result; /* Expression à retourner */ + + result = g_object_new(G_TYPE_STR_EXPRESSION, NULL); + + result->value = strdup(value); + result->len = strlen(value); + + return G_DEC_INSTRUCTION(result); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à transcrire en version humaine. * +* buffer = tampon où doit se réaliser l'insertion. * +* line = ligne d'impression prête à emploi ou NULL. * +* output = langage de programmation de sortie. * +* * +* Description : Imprime pour l'écran un version humaine d'une expression. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void 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); + +} diff --git a/src/decomp/expr/text.h b/src/decomp/expr/text.h new file mode 100644 index 0000000..9e6df28 --- /dev/null +++ b/src/decomp/expr/text.h @@ -0,0 +1,60 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * text.h - prototypes pour le raccord avec les opérandes de chaînes de caractères + * + * 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 . + */ + + +#ifndef _DECOMP_EXPR_TEXT_H +#define _DECOMP_EXPR_TEXT_H + + +#include + + +#include "../instruction.h" + + + +#define G_TYPE_STR_EXPRESSION g_str_expression_get_type() +#define G_STR_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_str_expression_get_type(), GStrExpression)) +#define G_IS_STR_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_str_expression_get_type())) +#define G_STR_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STR_EXPRESSION, GStrExpressionClass)) +#define G_IS_STR_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STR_EXPRESSION)) +#define G_STR_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STR_EXPRESSION, GStrExpressionClass)) + + + +/* Définition d'une expression de valeur immédiate (instance) */ +typedef struct _GStrExpression GStrExpression; + +/* Définition d'une expression de valeur immédiate (classe) */ +typedef struct _GStrExpressionClass GStrExpressionClass; + + + +/* Indique le type défini pour une expression de valeur immédiate. */ +GType g_str_expression_get_type(void); + +/*Construit une expression à partir d'une valeur immédiate. */ +GDecInstruction *g_str_expression_new(const char *); + + + +#endif /* _DECOMP_EXPR_TEXT_H */ diff --git a/src/decomp/instruction-int.h b/src/decomp/instruction-int.h index 49a68fc..2721b7f 100644 --- a/src/decomp/instruction-int.h +++ b/src/decomp/instruction-int.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * instruction-int.h - prototypes pour la définition interne des instructions décompilées * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2012 Cyrille Bagard * * This file is part of OpenIDA. * @@ -27,6 +27,7 @@ #include "instruction.h" #include "../arch/archbase.h" +#include "../common/dllist.h" @@ -39,6 +40,8 @@ struct _GDecInstruction { GObject parent; /* A laisser en premier */ + DL_LIST_ITEM(flow); /* Maillon de liste chaînée */ + vmpa_t address; /* Position associée */ dec_instr_print_fc print; /* Impression pour à l'écran */ @@ -54,5 +57,13 @@ struct _GDecInstructionClass }; +#define dinstr_list_last(head) dl_list_last(head, GDecInstruction, flow) +#define dinstr_list_add_tail(new, head) dl_list_add_tail(new, head, GDecInstruction, flow) +#define dinstr_list_del(item, head) dl_list_del(item, head, GDecInstruction, flow) +#define dinstr_list_next_iter(iter, head) dl_list_next_iter(iter, head, GDecInstruction, flow) +#define dinstr_list_prev_iter(iter, head) dl_list_prev_iter(iter, head, GDecInstruction, flow) +#define dinstr_list_for_each(pos, head) dl_list_for_each(pos, head, GDecInstruction, flow) + + #endif /* _DECOMP_INSTRUCTION_INT_H */ diff --git a/src/decomp/instruction.c b/src/decomp/instruction.c index c1afa44..c48ac7b 100644 --- a/src/decomp/instruction.c +++ b/src/decomp/instruction.c @@ -72,6 +72,7 @@ static void g_dec_instruction_class_init(GDecInstructionClass *klass) static void g_dec_instruction_init(GDecInstruction *instr) { + DL_LIST_ITEM_INIT(&instr->flow); } @@ -99,3 +100,107 @@ void g_dec_instruction_print(const GDecInstruction *instr, GCodeBuffer *buffer, instr->print(instr, buffer, line, output); } + + +/* ---------------------------------------------------------------------------------- */ +/* TRAITEMENT DES INSTRUCTIONS PAR ENSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : list = liste d'instructions à consulter. * +* * +* Description : Fournit la dernière instruction décompilée de l'ensemble. * +* * +* Retour : Instruction en queue de liste. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_instruction_get_last(GDecInstruction *list) +{ + return dinstr_list_last(list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'instructions à compléter, ou NULL. * +* instr = nouvelle instruction à intégrer à l'ensemble. * +* * +* Description : Ajoute une instruction à un ensemble existant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_instruction_add_to_list(GDecInstruction **list, GDecInstruction *instr) +{ + dinstr_list_add_tail(instr, list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'instructions à modifier. * +* instr = instruction à faire disparaître. * +* * +* Description : Supprime une instruction de l'ensemble décompilé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_instruction_delete(GDecInstruction **list, GDecInstruction *instr) +{ + dinstr_list_del(instr, list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'instructions à consulter. * +* : iter = position actuelle dans la liste. * +* * +* Description : Fournit l'élement suivant un autre pour un parcours. * +* * +* Retour : Elément suivant ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_instruction_get_next_iter(const GDecInstruction *list, const GDecInstruction *iter) +{ + return dinstr_list_next_iter(iter, list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'instructions à consulter. * +* : iter = position actuelle dans la liste. * +* * +* Description : Fournit l'élement précédant un autre pour un parcours. * +* * +* Retour : Elément suivant ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_instruction_get_prev_iter(const GDecInstruction *list, const GDecInstruction *iter) +{ + return dinstr_list_prev_iter(iter, list); + +} diff --git a/src/decomp/instruction.h b/src/decomp/instruction.h index 9c8a935..d8fe46c 100644 --- a/src/decomp/instruction.h +++ b/src/decomp/instruction.h @@ -56,4 +56,24 @@ void g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine +/* -------------------- TRAITEMENT DES INSTRUCTIONS PAR ENSEMBLE -------------------- */ + + +/* Fournit la dernière instruction décompilée de l'ensemble. */ +GDecInstruction *g_dec_instruction_get_last(GDecInstruction *); + +/* Ajoute une instruction à un ensemble existant. */ +void g_dec_instruction_add_to_list(GDecInstruction **, GDecInstruction *); + +/* Supprime une instruction de l'ensemble décompilé. */ +void g_dec_instruction_delete(GDecInstruction **, GDecInstruction *); + +/* Fournit l'élement suivant un autre pour un parcours. */ +GDecInstruction *g_dec_instruction_get_next_iter(const GDecInstruction *, const GDecInstruction *); + +/* Fournit l'élement précédant un autre pour un parcours. */ +GDecInstruction *g_dec_instruction_get_prev_iter(const GDecInstruction *, const GDecInstruction *); + + + #endif /* _DECOMP_INSTRUCTION_H */ diff --git a/src/decomp/lang/asm.c b/src/decomp/lang/asm.c index 9ee8729..ab71cc0 100644 --- a/src/decomp/lang/asm.c +++ b/src/decomp/lang/asm.c @@ -238,7 +238,7 @@ static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *output, GCo result = g_code_buffer_append_new_line_fixme(buffer); /* TODO */ - g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_RAW); + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_COMMENT); return result; @@ -261,6 +261,6 @@ static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *output, GCo static void g_asm_output_end_routine_prototype(GAsmOutput *output, GCodeBuffer *buffer, GBufferLine *line) { - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_PUNCT); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_COMMENT); } diff --git a/src/format/dex/method.c b/src/format/dex/method.c index cca03a7..233ecb1 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -147,9 +147,14 @@ GDexMethod *g_dex_method_new(const GDexFormat *format, const encoded_method *see result->info = *seed; result->body = item; + printf(" ==== %s ====\n", g_binary_routine_get_name(routine)); + //printf(" method idx :: %d\n", seed->method_idx_diff); //printf(" code size :: %d\n", item.insns_size); + printf(" code regs :: %d\n", item.registers_size); + printf(" code ins :: %d\n", item.ins_size); + printf(" code outs :: %d\n", item.outs_size); //printf(" method idx :: %lld\n", *last); diff --git a/src/format/format.c b/src/format/format.c index 1a52e1e..930d8db 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -288,6 +288,7 @@ GDecInstruction *g_binary_format_decompile_routine(const GBinFormat *format, GBi vmpa_t max; /* Première adresse à écarter */ GDecContext *ctx; /* Contexte de décompilation */ GArchInstruction *iter; /* Boucle de parcours */ + GDecInstruction *first; /* Première décompilation */ GDecInstruction *dinstr; /* Nouvelle décompilation */ result = NULL; @@ -296,10 +297,6 @@ GDecInstruction *g_binary_format_decompile_routine(const GBinFormat *format, GBi max = g_binary_routine_get_address(routine) + g_binary_routine_get_size(routine); - printf("max :: 0x%08llx\n", max); - - //max = 0x00000a98ll; /* FIXME !!!! */ - ctx = g_dec_context_new(); g_object_set_data(G_OBJECT(ctx), "format", format); g_dec_context_set_max_address(ctx, max); @@ -308,25 +305,20 @@ GDecInstruction *g_binary_format_decompile_routine(const GBinFormat *format, GBi iter != NULL; iter = g_arch_instruction_get_next_iter(instr, iter, max)) { + g_arch_instruction_decompile(iter, ctx); + } + first = g_dec_context_get_decomp_instrs(ctx); - printf("DECOMP isntr :: %p\n", iter); - - - dinstr = g_arch_instruction_decompile(iter, ctx); - if (dinstr == NULL) continue; - - printf(" -> done :: %p\n", dinstr); - + 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); } - - - - g_binary_routine_set_decomp_instructions(routine, result); return result; -- cgit v0.11.2-87-g4458