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