From 02c2cf555953f335a825e34c869c9999668fd42c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 24 Feb 2013 11:09:36 +0000 Subject: Refined comparisons decompilation and fixed some bugs. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@340 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 45 ++++++ src/analysis/decomp/Makefile.am | 1 + src/analysis/decomp/cmerge.c | 135 +++++++++++++++++ src/analysis/decomp/cmerge.h | 37 +++++ src/analysis/decomp/decompiler.c | 7 +- src/arch/dalvik/decomp/if.c | 29 ++-- src/decomp/expr/Makefile.am | 1 + src/decomp/expr/block.c | 27 ++++ src/decomp/expr/block.h | 3 + src/decomp/expr/comp.c | 311 +++++++++++++++++++++++++++++++++++++++ src/decomp/expr/comp.h | 60 ++++++++ src/decomp/expr/cond.c | 287 +++++++++++++++++++++++++++++++----- src/decomp/expr/cond.h | 18 ++- src/decomp/expression-int.h | 7 + src/decomp/expression.c | 63 +++++++- src/decomp/expression.h | 5 +- src/decomp/instr/ite.c | 57 ++++++- src/decomp/instr/ite.h | 9 +- src/decomp/lang/java.c | 77 +++++++++- src/decomp/output-int.h | 13 +- src/decomp/output.c | 53 ++++++- src/decomp/output.h | 30 +++- 22 files changed, 1199 insertions(+), 76 deletions(-) create mode 100644 src/analysis/decomp/cmerge.c create mode 100644 src/analysis/decomp/cmerge.h create mode 100644 src/decomp/expr/comp.c create mode 100644 src/decomp/expr/comp.h diff --git a/ChangeLog b/ChangeLog index 918e55a..0086536 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +13-02-24 Cyrille Bagard + + * src/analysis/decomp/cmerge.c: + * src/analysis/decomp/cmerge.h: + New entries: begin to merge conditions when possible. + + * src/analysis/decomp/decompiler.c: + Disable the broken decompilation. + + * src/analysis/decomp/Makefile.am: + Add the 'cmerge.[ch]' files to libanalysisdecomp_la_SOURCES. + + * src/arch/dalvik/decomp/if.c: + Fix a bug for xxZ opcodes. + + * src/decomp/expr/block.c: + * src/decomp/expr/block.h: + Provide a given item of blocks. + + * src/decomp/expr/comp.c: + * src/decomp/expr/comp.h: + New entries: define comparisons. + + * src/decomp/expr/cond.c: + * src/decomp/expr/cond.h: + Update code using the new comparison expressions. + + * src/decomp/expression.c: + * src/decomp/expression.h: + * src/decomp/expression-int.h: + Handle the need of negating expressions for conditions. + + * src/decomp/expr/Makefile.am: + Add the 'comp.[ch]' files to libdecompexpr_la_SOURCES. + + * src/decomp/instr/ite.c: + * src/decomp/instr/ite.h: + Update code. + + * src/decomp/lang/java.c: + * src/decomp/output.c: + * src/decomp/output.h: + * src/decomp/output-int.h: + Extend the kinds of output signs. + 13-02-10 Cyrille Bagard * src/analysis/disass/disassembler.c: diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am index 27388d6..0e3ffb4 100755 --- a/src/analysis/decomp/Makefile.am +++ b/src/analysis/decomp/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libanalysisdecomp.la libanalysisdecomp_la_SOURCES = \ + cmerge.h cmerge.c \ decompiler.h decompiler.c \ il.h il.c \ reduce.h reduce.c diff --git a/src/analysis/decomp/cmerge.c b/src/analysis/decomp/cmerge.c new file mode 100644 index 0000000..9838531 --- /dev/null +++ b/src/analysis/decomp/cmerge.c @@ -0,0 +1,135 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * cmerge.c - fusion des conditions successives + * + * Copyright (C) 2013 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 "cmerge.h" + + +#include "../../decomp/expr/block.h" +#include "../../decomp/expr/comp.h" +#include "../../decomp/expr/cond.h" +#include "../../decomp/instr/ite.h" + + + +/* Recherche des conditions successives pouvant être fusionnées. */ +static bool track_branch_conditions(GDecInstruction *, GDecInstruction *, DecInstrVisitFlags, void *); + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction visitée. * +* parent = instruction parente. * +* flags = moments des appels réalisés en retour. * +* data = adresse non utilisée ici. * +* * +* Description : Recherche des conditions successives pouvant être fusionnées.* +* * +* Retour : true afin d'aller jusqu'au terme du parcours. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool track_branch_conditions(GDecInstruction *instr, GDecInstruction *parent, DecInstrVisitFlags flags, void *data) +{ + GDecInstruction *true_branch; /* Branche 'vrai' */ + GDecInstruction *false_branch; /* Branche 'faux' */ + GDecInstruction *first; /* Première sous-instruction */ + GCondExpression *sub_cond; /* Expression conditionnelle */ + GCondExpression *top_cond; /* Expression conditionnelle */ + + if (!G_IS_ITE_INSTRUCTION(instr)) + goto tbc_done; + + g_ite_instruction_get_branches(G_ITE_INSTRUCTION(instr), &true_branch, &false_branch); + if (false_branch != NULL) goto tbc_done; + + /* count(block) == 1 */ + + first = g_expr_block_get_item(G_EXPR_BLOCK(true_branch), 0); + if (!G_IS_ITE_INSTRUCTION(first)) goto tbc_done; + + printf("got one!\n"); + + /* Récupération des informations inférieures */ + + sub_cond = g_ite_instruction_get_condition(G_ITE_INSTRUCTION(first)); + g_object_ref(G_OBJECT(sub_cond)); + + g_ite_instruction_get_branches(G_ITE_INSTRUCTION(first), &true_branch, &false_branch); + if (true_branch != NULL) g_object_ref(G_OBJECT(true_branch)); + if (false_branch != NULL) g_object_ref(G_OBJECT(false_branch)); + + /* Reconstitution d'une nouvelle instruction */ + + top_cond = g_ite_instruction_get_condition(G_ITE_INSTRUCTION(instr)); + + //g_cond_expression_add_condition(top_cond, sub_cond, COT_AND); + + //g_ite_instruction_set_branches(G_ITE_INSTRUCTION(instr), true_branch, false_branch); + + + + + printf("got one!\n"); + + /* +GDecExpression *g_ite_instruction_get_condition(const GITEInstruction *instr) + + + +GDecExpression *g_cond_expression_get_expression(const GCondExpression *cond) + + +void g_cond_expression_set_expression(GCondExpression *cond, GDecExpression *exp) + */ + + + tbc_done: + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instructions à traiter. * +* * +* Description : Fusionne les conditions qui s'enchaînent. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void merge_lonely_conditions(GDecInstruction *instr) +{ + return; + + g_dec_instruction_visit(instr, (dec_instr_visitor_cb)track_branch_conditions, + DVF_EXIT, NULL); + +} diff --git a/src/analysis/decomp/cmerge.h b/src/analysis/decomp/cmerge.h new file mode 100644 index 0000000..0b556c6 --- /dev/null +++ b/src/analysis/decomp/cmerge.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * cmerge.h - prototypes pour la fusion des conditions successives + * + * Copyright (C) 2013 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 _ANALYSIS_DECOMP_CMERGE_H +#define _ANALYSIS_DECOMP_CMERGE_H + + +#include "../../decomp/instruction.h" + + + +/* Fusionne les conditions qui s'enchaînent. */ +void merge_lonely_conditions(GDecInstruction *); + + + +#endif /* _ANALYSIS_DECOMP_CMERGE_H */ diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index c36811d..89f9d49 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -32,6 +32,7 @@ #include +#include "cmerge.h" #include "il.h" #include "reduce.h" #include "../../decomp/output.h" @@ -184,7 +185,9 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); - reduce_used_variables(dinstrs); + //merge_lonely_conditions(dinstrs); + + /////reduce_used_variables(dinstrs); g_expr_block_set_border_behavior(G_EXPR_BLOCK(dinstrs), BBB_FORCE_ON); @@ -228,7 +231,7 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi build_decomp_prologue(result, filename); - prepare_all_routines_for_decomp(binary, filename); + //prepare_all_routines_for_decomp(binary, filename); diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c index f7591b9..c82413d 100644 --- a/src/arch/dalvik/decomp/if.c +++ b/src/arch/dalvik/decomp/if.c @@ -25,6 +25,7 @@ #include "../instruction.h" +#include "../../../decomp/expr/comp.h" #include "../../../decomp/expr/cond.h" #include "../../../decomp/expr/immediate.h" #include "../../../decomp/instr/ite.h" @@ -53,7 +54,8 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ vmpa_t jmp; /* Adresse de saut */ - GDecInstruction *cond; /* Comparaison à restituer */ + GDecInstruction *comp; /* Comparaison à restituer */ + GDecInstruction *cond; /* Transformation en condition */ switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr))) { @@ -91,8 +93,9 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte operand = g_arch_instruction_get_operand(instr, 2); 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); + comp = g_comp_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2)); + cond = g_cond_expression_new(comp); + result = g_ite_instruction_new(cond, jmp, jmp); return result; @@ -122,26 +125,27 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec GDecInstruction *op1; /* Premier opérande utilisé */ GDecInstruction *op2; /* Second opérande utilisé */ vmpa_t jmp; /* Adresse de saut */ - GDecInstruction *cond; /* Comparaison à restituer */ + GDecInstruction *comp; /* Comparaison à restituer */ + GDecInstruction *cond; /* Transformation en condition */ switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr))) { - case DOP_IF_EQ: + case DOP_IF_EQZ: sign = CST_EQ; break; - case DOP_IF_NE: + case DOP_IF_NEZ: sign = CST_NE; break; - case DOP_IF_LT: + case DOP_IF_LTZ: sign = CST_LT; break; - case DOP_IF_GE: + case DOP_IF_GEZ: sign = CST_GE; break; - case DOP_IF_GT: + case DOP_IF_GTZ: sign = CST_GT; break; - case DOP_IF_LE: + case DOP_IF_LEZ: sign = CST_LE; break; default: @@ -160,8 +164,9 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec operand = g_arch_instruction_get_operand(instr, 2); 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); + comp = g_comp_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2)); + cond = g_cond_expression_new(comp); + result = g_ite_instruction_new(cond, jmp, jmp); return result; diff --git a/src/decomp/expr/Makefile.am b/src/decomp/expr/Makefile.am index 483a1f3..3ff6cb5 100644 --- a/src/decomp/expr/Makefile.am +++ b/src/decomp/expr/Makefile.am @@ -8,6 +8,7 @@ libdecompexpr_la_SOURCES = \ assign.h assign.c \ block.h block.c \ call.h call.c \ + comp.h comp.c \ cond.h cond.c \ immediate.h immediate.c \ pseudo.h pseudo.c \ diff --git a/src/decomp/expr/block.c b/src/decomp/expr/block.c index 7c2387a..6b811f6 100644 --- a/src/decomp/expr/block.c +++ b/src/decomp/expr/block.c @@ -333,6 +333,33 @@ void g_expr_block_add_item(GExprBlock *block, GDecInstruction *item) /****************************************************************************** * * +* Paramètres : block = ensemble à consulter. * +* index = indice de l'instruction décompilée recherchée. * +* * +* Description : Fournit une instruction décompilée donnée du conteneur. * +* * +* Retour : Instruction décompilée, ou NULL si l'indice n'est pas valide.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_expr_block_get_item(const GExprBlock *block, size_t index) +{ + GDecInstruction *result; /* Elément à retourner */ + + result = NULL; + + if (index < block->count) + result = block->list[index]; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : block = ensemble à faire évoluer. * * item = nouvel élément à retirer de l'ensemble. * * * diff --git a/src/decomp/expr/block.h b/src/decomp/expr/block.h index b0788dd..92ac9f9 100644 --- a/src/decomp/expr/block.h +++ b/src/decomp/expr/block.h @@ -73,6 +73,9 @@ void g_expr_block_set_border_behavior(GExprBlock *, BlockBordeBehavior); /* Ajoute une instruction décompilée au conteneur existant. */ void g_expr_block_add_item(GExprBlock *, GDecInstruction *); +/* Fournit une instruction décompilée donnée du conteneur. */ +GDecInstruction *g_expr_block_get_item(const GExprBlock *, size_t); + /* Supprime une instruction décompilée du conteneur existant. */ void g_expr_block_delete_item(GExprBlock *, GDecInstruction *); diff --git a/src/decomp/expr/comp.c b/src/decomp/expr/comp.c new file mode 100644 index 0000000..3852aa8 --- /dev/null +++ b/src/decomp/expr/comp.c @@ -0,0 +1,311 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * comp.c - représentation des comparaisons + * + * Copyright (C) 2013 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 "comp.h" + + +#include "../expression-int.h" + + + +/* Définition d'une comparaison binaire quelconque (instance) */ +struct _GCompExpression +{ + GDecExpression parent; /* A laisser en premier */ + + GDecExpression *a; /* Premier élément à comparer */ + CompSignType sign; /* Méthode de comparaison */ + GDecExpression *b; /* Second élément à comparer */ + +}; + + +/* Définition d'une comparaison binaire quelconque (classe) */ +struct _GCompExpressionClass +{ + GDecExpressionClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des comparaisons binaires quelconques. */ +static void g_comp_expression_class_init(GCompExpressionClass *); + +/* Initialise une instance de comparaison binaire quelconque. */ +static void g_comp_expression_init(GCompExpression *); + +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +static bool g_comp_expression_visit(GCompExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *); + +/* Remplace une instruction décompilée par une autre. */ +static bool g_comp_expression_replace(GCompExpression *, GDecInstruction *, GDecInstruction *); + +/* Imprime pour l'écran un version humaine d'une expression. */ +static GBufferLine *g_comp_expression_print(const GCompExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); + +/* Réalise une négation sur une expression décompilée. */ +static bool g_comp_expression_negate(GCompExpression *); + + + +/* Indique le type défini pour une comparaison binaire quelconque. */ +G_DEFINE_TYPE(GCompExpression, g_comp_expression, G_TYPE_DEC_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des comparaisons binaires quelconques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comp_expression_class_init(GCompExpressionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à initialiser. * +* * +* Description : Initialise une instance de comparaison binaire quelconque. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comp_expression_init(GCompExpression *expr) +{ + GDecInstruction *instr; /* Autre version de l'objet */ + GDecExpression *base; /* Autre version de l'objet */ + + instr = G_DEC_INSTRUCTION(expr); + + instr->visit = (dec_instr_visit_fc)g_comp_expression_visit; + instr->replace = (dec_instr_replace_fc)g_comp_expression_replace; + instr->print = (dec_instr_print_fc)g_comp_expression_print; + + base = G_DEC_EXPRESSION(expr); + + base->negate = (dec_expr_negate_fc)g_comp_expression_negate; + +} + + +/****************************************************************************** +* * +* Paramètres : a = second élément à comparer. * +* sign = choix de la méthode de comparaison. * +* b = second élément à comparer. * +* * +* Description : Exprime une comparaison binaire quelconque. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecExpression *g_comp_expression_new(GDecExpression *a, CompSignType sign, GDecExpression *b) +{ + GCompExpression *result; /* Expression à retourner */ + + result = g_object_new(G_TYPE_COMP_EXPRESSION, NULL); + + result->a = a; + result->sign = sign; + result->b = b; + + return G_DEC_EXPRESSION(result); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première instruction à venir visiter. * +* callback = procédure à appeler à chaque instruction visitée. * +* flags = moments des appels à réaliser en retour. * +* data = données quelconques associées au visiteur. * +* * +* Description : Visite un ensemble hiérarchique d'instructions décompilées. * +* * +* Retour : true si le parcours a été jusqu'à son terme, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_comp_expression_visit(GCompExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data) +{ + bool result; /* Bilan à retourner */ + + result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->a), G_DEC_INSTRUCTION(expr), + callback, flags, data); + + if (result) + result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->b), G_DEC_INSTRUCTION(expr), + callback, flags, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première instruction à venir ausculter. * +* old = instruction décompilée à venir remplacer. * +* new = instruction décompilée à utiliser dorénavant. * +* * +* Description : Remplace une instruction décompilée par une autre. * +* * +* Retour : true si un remplacement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_comp_expression_replace(GCompExpression *expr, GDecInstruction *old, GDecInstruction *new) +{ + bool result; /* Bilan à retourner */ + + if (expr->a == G_DEC_EXPRESSION(old)) + { + g_object_unref(G_OBJECT(expr->a)); + g_object_ref(G_OBJECT(new)); + expr->a = G_DEC_EXPRESSION(new); + + result = true; + + } + else + result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->a), old, new); + + if (expr->b == G_DEC_EXPRESSION(old)) + { + g_object_unref(G_OBJECT(expr->b)); + g_object_ref(G_OBJECT(new)); + expr->b = G_DEC_EXPRESSION(new); + + result = true; + + } + else + result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->b), old, new); + + return 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 GBufferLine *g_comp_expression_print(const GCompExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +{ + GBufferLine *result; /* Ligne à retourner */ + + result = line; + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a), + buffer, result, output); + + g_lang_output_write_comp_sign(output, result, expr->sign); + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b), + buffer, result, output); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à traiter. * +* * +* Description : Réalise une négation sur une expression décompilée. * +* * +* Retour : true si la négation a été gérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_comp_expression_negate(GCompExpression *expr) +{ + bool result; /* Bilan à retourner */ + + result = true; + + switch (expr->sign) + { + case CST_EQ: + expr->sign = CST_NE; + break; + case CST_NE: + expr->sign = CST_EQ; + break; + case CST_LT: + expr->sign = CST_GE; + break; + case CST_GE: + expr->sign = CST_LT; + break; + case CST_GT: + expr->sign = CST_LE; + break; + case CST_LE: + expr->sign = CST_GT; + break; + default: + result = false; + break; + + } + + return result; + +} diff --git a/src/decomp/expr/comp.h b/src/decomp/expr/comp.h new file mode 100644 index 0000000..8599aa0 --- /dev/null +++ b/src/decomp/expr/comp.h @@ -0,0 +1,60 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * comp.h - prototypes pour la représentation des comparaisons + * + * Copyright (C) 2013 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_COMP_H +#define _DECOMP_EXPR_COMP_H + + +#include + + +#include "../expression.h" +#include "../output.h" + + + +#define G_TYPE_COMP_EXPRESSION g_comp_expression_get_type() +#define G_COMP_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_comp_expression_get_type(), GCompExpression)) +#define G_IS_COMP_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_comp_expression_get_type())) +#define G_COMP_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMP_EXPRESSION, GCompExpressionClass)) +#define G_IS_COMP_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMP_EXPRESSION)) +#define G_COMP_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMP_EXPRESSION, GCompExpressionClass)) + + + +/* Définition d'une comparaison binaire quelconque (instance) */ +typedef struct _GCompExpression GCompExpression; + +/* Définition d'une comparaison binaire quelconque (classe) */ +typedef struct _GCompExpressionClass GCompExpressionClass; + + +/* Indique le type défini pour une comparaison binaire quelconque. */ +GType g_comp_expression_get_type(void); + +/* Exprime une comparaison binaire quelconque. */ +GDecExpression *g_comp_expression_new(GDecExpression *, CompSignType, GDecExpression *); + + + +#endif /* _DECOMP_EXPR_COMP_H */ diff --git a/src/decomp/expr/cond.c b/src/decomp/expr/cond.c index fab2c17..c776059 100644 --- a/src/decomp/expr/cond.c +++ b/src/decomp/expr/cond.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * cond.c - représentation des conditions * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -24,6 +24,9 @@ #include "cond.h" +#include + + #include "../expression-int.h" @@ -33,9 +36,17 @@ struct _GCondExpression { GDecExpression parent; /* A laisser en premier */ - GDecExpression *a; /* Premier élément à comparer */ - CompSignType sign; /* Méthode de comparaison */ - GDecExpression *b; /* Second élément à comparer */ + CondOperatorType operator; /* Opérateur de la liste */ + + union + { + GDecExpression *exp; /* Expression analysée de base */ + struct + { + GCondExpression **conds; /* Liste d'expressions */ + size_t count; /* Taille de cette liste */ + }; + }; }; @@ -64,6 +75,9 @@ static bool g_cond_expression_replace(GCondExpression *, GDecInstruction *, GDec /* Imprime pour l'écran un version humaine d'une expression. */ static GBufferLine *g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); +/* Réalise une négation sur une expression décompilée. */ +static bool g_cond_expression_negate(GCondExpression *); + /* Indique le type défini pour une condition binaire quelconque. */ @@ -90,7 +104,7 @@ static void g_cond_expression_class_init(GCondExpressionClass *klass) /****************************************************************************** * * -* Paramètres : expr = instance à initialiser. * +* Paramètres : cond = instance à initialiser. * * * * Description : Initialise une instance de condition binaire quelconque. * * * @@ -100,24 +114,29 @@ static void g_cond_expression_class_init(GCondExpressionClass *klass) * * ******************************************************************************/ -static void g_cond_expression_init(GCondExpression *expr) +static void g_cond_expression_init(GCondExpression *cond) { GDecInstruction *instr; /* Autre version de l'objet */ + GDecExpression *expr; /* Autre version de l'objet */ - instr = G_DEC_INSTRUCTION(expr); + instr = G_DEC_INSTRUCTION(cond); instr->visit = (dec_instr_visit_fc)g_cond_expression_visit; instr->replace = (dec_instr_replace_fc)g_cond_expression_replace; instr->print = (dec_instr_print_fc)g_cond_expression_print; + expr = G_DEC_EXPRESSION(cond); + + expr->negate = (dec_expr_negate_fc)g_cond_expression_negate; + + cond->operator = COT_NONE; + } /****************************************************************************** * * -* Paramètres : a = second élément à comparer. * -* sign = choix de la méthode de comparaison. * -* b = second élément à comparer. * +* Paramètres : exp = expression sur laquelle repose la condition. * * * * Description : Exprime une condition binaire quelconque. * * * @@ -127,17 +146,15 @@ static void g_cond_expression_init(GCondExpression *expr) * * ******************************************************************************/ -GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDecExpression *b) +GDecExpression *g_cond_expression_new(GDecExpression *exp) { GCondExpression *result; /* Expression à retourner */ result = g_object_new(G_TYPE_COND_EXPRESSION, NULL); - result->a = a; - result->sign = sign; - result->b = b; + result->exp = exp; - return G_DEC_INSTRUCTION(result); + return G_DEC_EXPRESSION(result); } @@ -160,14 +177,23 @@ GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDe static bool g_cond_expression_visit(GCondExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data) { bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ - result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->a), G_DEC_INSTRUCTION(expr), - callback, flags, data); - - if (result) - result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->b), G_DEC_INSTRUCTION(expr), + if (expr->operator == COT_NONE) + result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->exp), G_DEC_INSTRUCTION(expr), callback, flags, data); + else + { + result = true; + + for (i = 0; i < expr->count && result; i++) + result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->conds[i]), + G_DEC_INSTRUCTION(expr), + callback, flags, data); + + } + return result; } @@ -190,30 +216,44 @@ static bool g_cond_expression_visit(GCondExpression *expr, dec_instr_visitor_cb static bool g_cond_expression_replace(GCondExpression *expr, GDecInstruction *old, GDecInstruction *new) { bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ - if (expr->a == G_DEC_EXPRESSION(old)) + if (expr->operator == COT_NONE) { - g_object_unref(G_OBJECT(expr->a)); - g_object_ref(G_OBJECT(new)); - expr->a = G_DEC_EXPRESSION(new); + if (expr->exp == G_DEC_EXPRESSION(old)) + { + g_object_unref(G_OBJECT(expr->exp)); + g_object_ref(G_OBJECT(new)); + expr->exp = G_DEC_EXPRESSION(new); - result = true; + result = true; + + } + else + result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->exp), old, new); } else - result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->a), old, new); - - if (expr->b == G_DEC_EXPRESSION(old)) { - g_object_unref(G_OBJECT(expr->b)); - g_object_ref(G_OBJECT(new)); - expr->b = G_DEC_EXPRESSION(new); + result = false; - result = true; + for (i = 0; i < expr->count; i++) + { + if (expr->conds[i] == G_COND_EXPRESSION(old)) + { + g_object_unref(G_OBJECT(expr->conds[i])); + g_object_ref(G_OBJECT(new)); + expr->conds[i] = G_COND_EXPRESSION(new); + + result = true; + + } + else + result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->conds[i]), old, new); + + } } - else - result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->b), old, new); return result; @@ -238,15 +278,184 @@ static bool g_cond_expression_replace(GCondExpression *expr, GDecInstruction *ol static GBufferLine *g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) { GBufferLine *result; /* Ligne à retourner */ + size_t i; /* Boucle de parcours */ - result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a), - buffer, line, output); + result = g_lang_output_encapsulate_condition(output, buffer, line, true); - g_lang_output_write_comp_sign(output, result, expr->sign); + if (expr->operator == COT_NONE) + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->exp), + buffer, result, output); - result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b), - buffer, result, output); + else + for (i = 0; i < expr->count; i++) + { + if (i > 0) + g_lang_output_write_cond_operator(output, result, expr->operator); + + result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->conds[i]), + buffer, result, output); + + } + + result = g_lang_output_encapsulate_condition(output, buffer, result, false); return result; } + + +/****************************************************************************** +* * +* Paramètres : cond = instance à traiter. * +* * +* Description : Réalise une négation sur une expression décompilée. * +* * +* Retour : true si la négation a été gérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_cond_expression_negate(GCondExpression *cond) +{ + size_t i; /* Boucle de parcours */ + + if (cond->operator == COT_NONE) + g_dec_expression_negate(cond->exp); + + else + { + cond->operator = (cond->operator == COT_AND ? COT_OR : COT_AND); + + for (i = 0; i < cond->count; i++) + g_dec_expression_negate(G_DEC_EXPRESSION(cond->conds[i])); + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : cond = instance à consulter. * +* * +* Description : Fournit l'opération logique entre les comparaisons. * +* * +* Retour : Opération liant les différentes parties, ou COT_NONE. * +* * +* Remarques : - * +* * +******************************************************************************/ + +CondOperatorType g_cond_expression_get_operator(const GCondExpression *cond) +{ + return cond->operator; + +} + + +/****************************************************************************** +* * +* Paramètres : cond = instance à consulter. * +* * +* Description : Fournit l'expression d'une condition. * +* * +* Retour : Expression sur laquelle repose la condition. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecExpression *g_cond_expression_get_expression(const GCondExpression *cond) +{ + return cond->exp; + +} + + +/****************************************************************************** +* * +* Paramètres : cond = instance à modifier. * +* exp = expression sur laquelle repose la condition. * +* * +* Description : Définit l'expression d'une condition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_cond_expression_set_expression(GCondExpression *cond, GDecExpression *exp) +{ + if (cond->exp != NULL) + g_object_unref(G_OBJECT(cond->exp)); + + cond->exp = exp; + +} + + +/****************************************************************************** +* * +* Paramètres : cond = instance à compléter. * +* extra = condition à rajouter. * +* op = lien avec le reste de la condition. * +* * +* Description : Etend l'expression d'une condition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_cond_expression_add_condition(GCondExpression *cond, GCondExpression *extra, CondOperatorType op) +{ + GCondExpression *existing; /* Expr. première revalorisée */ + + if (cond->operator == COT_NONE) + { + existing = G_COND_EXPRESSION(g_cond_expression_new(cond->exp)); + goto gceac_replace_existing; + } + else + { + if (cond->operator == op) + { + cond->conds = (GCondExpression **)calloc(++cond->count, sizeof(GCondExpression)); + cond->conds[cond->count - 1] = extra; + } + else + { + existing = G_COND_EXPRESSION(g_cond_expression_new(NULL)); + + existing->operator = cond->operator; + existing->conds = cond->conds; + existing->count = cond->count; + + goto gceac_replace_existing; + + } + + } + + gceac_done: + + return; + + gceac_replace_existing: + + cond->operator = op; + + cond->conds = (GCondExpression **)calloc(2, sizeof(GCondExpression)); + cond->conds[0] = existing; + cond->conds[1] = extra; + + cond->count = 2; + + goto gceac_done; + +} diff --git a/src/decomp/expr/cond.h b/src/decomp/expr/cond.h index b6fd073..a4d1ee7 100644 --- a/src/decomp/expr/cond.h +++ b/src/decomp/expr/cond.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * cond.h - prototypes pour la représentation des conditions * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -29,7 +29,7 @@ #include "../expression.h" -#include "../instruction.h" +#include "../output.h" @@ -53,7 +53,19 @@ typedef struct _GCondExpressionClass GCondExpressionClass; GType g_cond_expression_get_type(void); /* Exprime une condition binaire quelconque. */ -GDecInstruction *g_cond_expression_new(GDecExpression *, CompSignType, GDecExpression *); +GDecExpression *g_cond_expression_new(GDecExpression *); + +/* Fournit l'opération logique entre les comparaisons. */ +CondOperatorType g_cond_expression_get_operator(const GCondExpression *); + +/* Fournit l'expression d'une condition. */ +GDecExpression *g_cond_expression_get_expression(const GCondExpression *); + +/* Définit l'expression d'une condition. */ +void g_cond_expression_set_expression(GCondExpression *, GDecExpression *); + +/* Etend l'expression d'une condition. */ +void g_cond_expression_add_condition(GCondExpression *, GCondExpression *, CondOperatorType); diff --git a/src/decomp/expression-int.h b/src/decomp/expression-int.h index dacd9b8..ba15ce3 100644 --- a/src/decomp/expression-int.h +++ b/src/decomp/expression-int.h @@ -30,11 +30,18 @@ +/* Réalise une négation sur une expression décompilée. */ +typedef bool (* dec_expr_negate_fc) (GDecExpression *); + + /* Définition d'une expression décompilée (instance) */ struct _GDecExpression { GDecInstruction parent; /* A laisser en premier */ + dec_expr_negate_fc negate; /* Négation de l'expression */ + dec_instr_print_fc original_print; /* Eventuelle version négative */ + }; diff --git a/src/decomp/expression.c b/src/decomp/expression.c index 82a2b4a..783f78f 100644 --- a/src/decomp/expression.c +++ b/src/decomp/expression.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * expression.c - gestion des expressions décompilées * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -34,6 +34,9 @@ static void g_dec_expression_class_init(GDecExpressionClass *); /* Initialise une instance d'expression décompilée. */ static void g_dec_expression_init(GDecExpression *); +/* Imprime pour l'écran la négation d'une expression décompilée. */ +static GBufferLine *g_dec_expression_neg_print(const GDecExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *); + /* Indique le type défini pour une expression décompilée. */ @@ -74,3 +77,61 @@ static void g_dec_expression_init(GDecExpression *expr) { } + + +/****************************************************************************** +* * +* 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 la négation d'une expression décompilée.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_dec_expression_neg_print(const GDecExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +{ + GBufferLine *result; /* Ligne à retourner */ + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD); + + result = expr->original_print(G_DEC_INSTRUCTION(expr), buffer, line, output); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = instance à traiter. * +* * +* Description : Réalise une négation sur une expression décompilée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_expression_negate(GDecExpression *expr) +{ + bool status; /* Réussite de l'opération ? */ + + if (expr->negate != NULL) + status = expr->negate(expr); + else + status = false; + + if (!status) + { + expr->original_print = G_DEC_INSTRUCTION(expr)->print; + G_DEC_INSTRUCTION(expr)->print = (dec_instr_print_fc)g_dec_expression_neg_print; + } + +} diff --git a/src/decomp/expression.h b/src/decomp/expression.h index 4a56c24..01eaa66 100644 --- a/src/decomp/expression.h +++ b/src/decomp/expression.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * expression.h - prototypes pour la gestion des expressions décompilées * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -48,6 +48,9 @@ typedef struct _GDecExpressionClass GDecExpressionClass; /* Indique le type défini pour une expression décompilée. */ GType g_dec_expression_get_type(void); +/* Réalise une négation sur une expression décompilée. */ +void g_dec_expression_negate(GDecExpression *); + #endif /* _DECOMP_EXPRESSION_H */ diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c index 60627a6..5cdeb87 100644 --- a/src/decomp/instr/ite.c +++ b/src/decomp/instr/ite.c @@ -33,9 +33,7 @@ struct _GITEInstruction { GDecInstruction parent; /* A laisser en premier */ - bool inverse; /* Condition inversée */ - - GDecExpression *cond; /* Condition prise en compte */ + GCondExpression *cond; /* Condition prise en compte */ GDecInstruction *true_branch; /* Condition vérifiée */ GDecInstruction *false_branch; /* Condition non vérifiée */ @@ -144,7 +142,7 @@ static void g_ite_instruction_init(GITEInstruction *instr) * * ******************************************************************************/ -GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmpa_t if_false) +GDecInstruction *g_ite_instruction_new(GCondExpression *cond, vmpa_t if_true, vmpa_t if_false) { GITEInstruction *result; /* Expression à retourner */ @@ -245,9 +243,6 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD); - if (instr->inverse) - g_buffer_line_insert_text(line /* FIXME */, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD); - result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cond), buffer, line, output); @@ -266,6 +261,25 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB /****************************************************************************** * * +* Paramètres : instr = instruction fixant le choix de l'aiguillage. * +* * +* Description : Fournit la condition régissant la suite de l'exécution. * +* * +* Retour : Condition mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCondExpression *g_ite_instruction_get_condition(const GITEInstruction *instr) +{ + return instr->cond; + +} + + +/****************************************************************************** +* * * Paramètres : instr = expression fixant le choix de l'aiguillage. * * true_branch = instructions si la condition est vérifiée. * * false_branch = instructions si la cond. n'est pas vérifiée. * @@ -280,10 +294,12 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB void g_ite_instruction_set_branches(GITEInstruction *instr, GDecInstruction *true_branch, GDecInstruction *false_branch) { + if (instr->true_branch != NULL) g_object_unref(G_OBJECT(instr->true_branch)); + if (instr->false_branch != NULL) g_object_unref(G_OBJECT(instr->false_branch)); if (true_branch == NULL) { - instr->inverse = true; + g_dec_expression_negate(G_DEC_EXPRESSION(instr->cond)); instr->true_branch = false_branch; instr->false_branch = true_branch; @@ -296,3 +312,28 @@ void g_ite_instruction_set_branches(GITEInstruction *instr, GDecInstruction *tru } } + + +/****************************************************************************** +* * +* Paramètres : instr = instruction fixant le choix de l'aiguillage. * +* true_branch = instrs. si la condition est vérifiée. [OUT] * +* false_branch = instrs. si la cond. n'est pas vérifiée. [OUT] * +* * +* Description : Fournit le corps des différentes branches possibles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_ite_instruction_get_branches(const GITEInstruction *instr, GDecInstruction **true_branch, GDecInstruction **false_branch) +{ + if (true_branch != NULL) + *true_branch = instr->true_branch; + + if (false_branch != NULL) + *false_branch = instr->false_branch; + +} diff --git a/src/decomp/instr/ite.h b/src/decomp/instr/ite.h index 7137452..91c18ae 100644 --- a/src/decomp/instr/ite.h +++ b/src/decomp/instr/ite.h @@ -30,6 +30,7 @@ #include "../expression.h" #include "../instruction.h" +#include "../expr/cond.h" @@ -53,11 +54,17 @@ typedef struct _GITEInstructionClass GITEInstructionClass; GType g_ite_instruction_get_type(void); /* Exprime un aiguillage du flux en fonction d'une condition. */ -GDecInstruction *g_ite_instruction_new(GDecExpression *, vmpa_t, vmpa_t); +GDecInstruction *g_ite_instruction_new(GCondExpression *, vmpa_t, vmpa_t); + +/* Fournit la condition régissant la suite de l'exécution. */ +GCondExpression *g_ite_instruction_get_condition(const GITEInstruction *); /* Détermine le corps des différentes branches possibles. */ void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *); +/* Fournit le corps des différentes branches possibles. */ +void g_ite_instruction_get_branches(const GITEInstruction *, GDecInstruction **, GDecInstruction **); + #endif /* _DECOMP_INSTR_ITE_H */ diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c index f4466a5..65383b0 100644 --- a/src/decomp/lang/java.c +++ b/src/decomp/lang/java.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * java.c - sorties en langage Java * - * Copyright (C) 2010-2012 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -66,6 +66,9 @@ static GBufferLine *g_java_output_write_comments(GJavaOutput *, GCodeBuffer *, c /* Imprime dans un tampon donné une méthode de comparaison. */ static void g_java_output_write_comp_sign(GJavaOutput *, GBufferLine *, CompSignType); +/* Imprime dans un tampon donné un opérateur logique. */ +static void g_java_output_write_cond_operator(GLangOutput *, GBufferLine *, CondOperatorType); + /* Débute la définition d'une classe. */ static GBufferLine *g_java_output_start_class(GJavaOutput *, GCodeBuffer *, const GDataType *); @@ -90,6 +93,9 @@ static GBufferLine *g_java_output_start_code_block(GJavaOutput *, GCodeBuffer *, /* Termine la définition d'un bloc de code. */ static GBufferLine *g_java_output_end_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t); +/* Emballe une expression conditionelle. */ +static GBufferLine *g_java_output_encapsulate_condition(GLangOutput *, GCodeBuffer *, GBufferLine *, bool); + /* Indique le type défini pour une sortie en langage Java. */ @@ -139,6 +145,7 @@ static void g_java_output_init(GJavaOutput *output) lang->write_comments = (write_comments_fc)g_java_output_write_comments; lang->comp_sign = (write_comp_sign_fc)g_java_output_write_comp_sign; + lang->cond_op = (write_cond_op_fc)g_java_output_write_cond_operator; lang->start_class = (rlgbuftp_fc)g_java_output_start_class; lang->end_class = (lgbuf_fc)g_java_output_end_class; @@ -150,6 +157,7 @@ static void g_java_output_init(GJavaOutput *output) lang->start_code_block = (rlgbuflnsz_fc)g_java_output_start_code_block; lang->end_code_block = (rlgbuflnsz_fc)g_java_output_end_code_block; + lang->encaps_cond = (lo_buf_ln_bool_fc)g_java_output_encapsulate_condition; } @@ -342,6 +350,42 @@ static void g_java_output_write_comp_sign(GJavaOutput *output, GBufferLine *line /****************************************************************************** * * * Paramètres : output = encadrant de l'impression en langage de prog. * +* line = tampon de sortie à disposition. * +* op = opérateur logique à imprimer. * +* * +* Description : Imprime dans un tampon donné un opérateur logique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op) +{ + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + + switch (op) + { + case COT_AND: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "&&", 2, RTT_SIGNS); + break; + case COT_OR: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "||", 2, RTT_SIGNS); + break; + default: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "??", 2, RTT_SIGNS); + break; + } + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * * buffer = tampon de sortie à disposition. * * type = désignation de la classe à définir. * * * @@ -575,3 +619,34 @@ static GBufferLine *g_java_output_end_code_block(GJavaOutput *output, GCodeBuffe return result; } + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée.* +* opening = précise si la condition débute ou se termine. * +* * +* Description : Emballe une expression conditionelle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_encapsulate_condition(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, bool opening) +{ + GBufferLine *result; /* Nouvelle ligne à utiliser */ + + result = line; + + if (opening) + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "(", 1, RTT_HOOK); + else + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_HOOK); + + return result; + +} diff --git a/src/decomp/output-int.h b/src/decomp/output-int.h index 8ee7dd4..95b891b 100644 --- a/src/decomp/output-int.h +++ b/src/decomp/output-int.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * output-int.h - définitions internes pour les sorties en langage de programmation * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -38,6 +38,9 @@ typedef GBufferLine * (* write_comments_fc) (GLangOutput *, GCodeBuffer *, const /* Imprime dans un tampon donné une méthode de comparaison. */ typedef void (* write_comp_sign_fc) (GLangOutput *, GBufferLine *, CompSignType); +/* Imprime dans un tampon donné un opérateur logique. */ +typedef void (* write_cond_op_fc) (GLangOutput *, GBufferLine *, CondOperatorType); + /* Débute la documentation d'une routine. */ typedef GBufferLine * (* start_rtn_info_fc) (const GLangOutput *, GCodeBuffer *); @@ -57,6 +60,11 @@ typedef GBufferLine * (* rlgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine typedef GBufferLine * (* rlgbuflnsz_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, size_t); +/* Xxx. */ +typedef GBufferLine * (* lo_buf_ln_bool_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, bool); + + + /* Sortie selon un langage de programmation (instance) */ struct _GLangOutput { @@ -68,6 +76,7 @@ struct _GLangOutput write_comments_fc write_comments; /* Commentaires sur une ligne */ write_comp_sign_fc comp_sign; /* Méthde de comparaison */ + write_cond_op_fc cond_op; /* Opérateur logique */ rlgbuftp_fc start_class; /* Début de définition */ lgbuf_fc end_class; /* Fin de définition de classe */ @@ -80,6 +89,8 @@ struct _GLangOutput lgbuf_fc end_routine_body; /* Fin de définition de corps */ rlgbuflnsz_fc start_code_block; /* Début de définition */ rlgbuflnsz_fc end_code_block; /* Fin de définition de corps */ + lo_buf_ln_bool_fc encaps_cond; /* Emballe une condition */ + }; diff --git a/src/decomp/output.c b/src/decomp/output.c index 5689319..c358653 100644 --- a/src/decomp/output.c +++ b/src/decomp/output.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * output.c - sorties en langage de programmation * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -206,6 +206,28 @@ void g_lang_output_write_comp_sign(GLangOutput *output, GBufferLine *line, CompS /****************************************************************************** * * * Paramètres : output = encadrant de l'impression en langage de prog. * +* line = tampon de sortie à disposition. * +* op = opérateur logique à imprimer. * +* * +* Description : Imprime dans un tampon donné un opérateur logique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_lang_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op) +{ + if (output->cond_op != NULL) + output->cond_op(output, line, op); + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * * buffer = tampon de sortie à disposition. * * type = désignation de la classe à définir. * * * @@ -430,3 +452,32 @@ GBufferLine *g_lang_output_end_code_block(GLangOutput *output, GCodeBuffer *buff return result; } + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée.* +* opening = précise si la condition débute ou se termine. * +* * +* Description : Emballe une expression conditionelle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_encapsulate_condition(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, bool opening) +{ + GBufferLine *result; /* Nouvelle ligne à utiliser */ + + if (output->encaps_cond != NULL) + result = output->encaps_cond(output, buffer, line, opening); + else + result = NULL; + + return result; + +} diff --git a/src/decomp/output.h b/src/decomp/output.h index dc81a98..63f586a 100644 --- a/src/decomp/output.h +++ b/src/decomp/output.h @@ -63,20 +63,35 @@ GBufferLine *g_lang_output_write_comments(GLangOutput *, GCodeBuffer *, const ch /* Liste des signes binaires de comparaison */ typedef enum _CompSignType { - CST_EQ, /* == */ - CST_NE, /* != */ - CST_LT, /* < */ - CST_GE, /* >= */ - CST_GT, /* > */ - CST_LE, /* <= */ + CST_EQ, /* == */ + CST_NE, /* != */ + CST_LT, /* < */ + CST_GE, /* >= */ + CST_GT, /* > */ + CST_LE, /* <= */ CST_COUNT } CompSignType; +/* Liste des signes binaires de comparaison */ +typedef enum _CondOperatorType +{ + COT_NONE, /* pas de condition */ + COT_AND, /* && */ + COT_OR, /* || */ + + COT_COUNT + +} CondOperatorType; + + /* Imprime dans un tampon donné une méthode de comparaison. */ void g_lang_output_write_comp_sign(GLangOutput *, GBufferLine *, CompSignType); +/* Imprime dans un tampon donné un opérateur logique. */ +void g_lang_output_write_cond_operator(GLangOutput *, GBufferLine *, CondOperatorType); + /* Débute la définition d'une classe. */ GBufferLine *g_lang_output_start_class(GLangOutput *, GCodeBuffer *, const void *); @@ -105,6 +120,9 @@ GBufferLine *g_lang_output_start_code_block(GLangOutput *, GCodeBuffer *, GBuffe /* Termine la définition d'un bloc de code. */ GBufferLine *g_lang_output_end_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t); +/* Emballe une expression conditionelle. */ +GBufferLine *g_lang_output_encapsulate_condition(GLangOutput *, GCodeBuffer *, GBufferLine *, bool); + typedef unsigned int lang_t; -- cgit v0.11.2-87-g4458