diff options
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/Makefile.am | 2 | ||||
| -rw-r--r-- | src/analysis/binary.c | 33 | ||||
| -rw-r--r-- | src/analysis/binary.h | 3 | ||||
| -rw-r--r-- | src/analysis/decomp/Makefile.am | 20 | ||||
| -rw-r--r-- | src/analysis/decomp/cmerge.c | 135 | ||||
| -rw-r--r-- | src/analysis/decomp/cmerge.h | 37 | ||||
| -rw-r--r-- | src/analysis/decomp/decompiler.c | 247 | ||||
| -rw-r--r-- | src/analysis/decomp/decompiler.h | 37 | ||||
| -rw-r--r-- | src/analysis/decomp/il.c | 772 | ||||
| -rw-r--r-- | src/analysis/decomp/il.h | 50 | ||||
| -rw-r--r-- | src/analysis/decomp/reduce.c | 422 | ||||
| -rw-r--r-- | src/analysis/decomp/reduce.h | 37 | ||||
| -rw-r--r-- | src/analysis/routine.c | 45 | ||||
| -rw-r--r-- | src/analysis/routine.h | 6 | 
14 files changed, 0 insertions, 1846 deletions
| diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am index 3ba21a3..e1e15e4 100644 --- a/src/analysis/Makefile.am +++ b/src/analysis/Makefile.am @@ -24,8 +24,6 @@ libanalysis_la_LIBADD =					\  	human/libanalysishuman.la			\  	types/libanalysistypes.la -#	decomp/libanalysisdecomp.la -  libanalysis_la_LDFLAGS =  diff --git a/src/analysis/binary.c b/src/analysis/binary.c index db3f509..1c6393a 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -38,7 +38,6 @@  #include "loaded-int.h"  #include "routine.h"  #include "db/client.h" -//#include "decomp/decompiler.h"  #include "disass/disassembler.h"  #include "../arch/storage.h"  #include "../common/extstr.h" @@ -1360,38 +1359,6 @@ GBufferCache *g_loaded_binary_get_disassembled_cache(const GLoadedBinary *binary  } -/****************************************************************************** -*                                                                             * -*  Paramètres  : binary = élément binaire à consulter.                        * -*                index  = indice du fichier à retrouver.                      * -*                                                                             * -*  Description : Fournit le tampon associé au contenu d'un fichier source.    * -*                                                                             * -*  Retour      : Tampon mis en place ou NULL si aucun (!).                    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#if 0 -GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *binary, size_t index) -{ -    GCodeBuffer *result;                    /* Tampon à retourner          */ - -    if (binary->decbuf_count == 0) -        result = NULL; - -    else if (index >= binary->decbuf_count) -        result = binary->dec_buffers[binary->defsrc]; - -    else -        result = binary->dec_buffers[index]; - -    return result; - -} -#endif - -  /* ---------------------------------------------------------------------------------- */  /*                        GESTION SOUS FORME DE CONTENU CHARGE                        */ diff --git a/src/analysis/binary.h b/src/analysis/binary.h index cbaab41..648da10 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -164,9 +164,6 @@ GArchProcessor *g_loaded_binary_get_processor(const GLoadedBinary *);  /* Fournit le tampon associé au contenu assembleur d'un binaire. */  GBufferCache *g_loaded_binary_get_disassembled_cache(const GLoadedBinary *); -/* Fournit le tampon associé au contenu d'un fichier source. */ -//GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *, size_t); - diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am deleted file mode 100644 index 8a9e976..0000000 --- a/src/analysis/decomp/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ - -noinst_LTLIBRARIES = libanalysisdecomp.la - -libanalysisdecomp_la_SOURCES =			\ -	cmerge.h cmerge.c					\ -	decompiler.h decompiler.c			\ -	il.h il.c							\ -	reduce.h reduce.c - -libanalysisdecomp_la_LDFLAGS =  - - -devdir = $(includedir)/chrysalide/$(subdir:src/%=%) - -dev_HEADERS = $(libanalysisdecomp_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/analysis/decomp/cmerge.c b/src/analysis/decomp/cmerge.c deleted file mode 100644 index 6777263..0000000 --- a/src/analysis/decomp/cmerge.c +++ /dev/null @@ -1,135 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * cmerge.c - fusion des conditions successives - * - * Copyright (C) 2013-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#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 deleted file mode 100644 index bd89604..0000000 --- a/src/analysis/decomp/cmerge.h +++ /dev/null @@ -1,37 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * cmerge.h - prototypes pour la fusion des conditions successives - * - * Copyright (C) 2013-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#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 deleted file mode 100644 index 03d2b70..0000000 --- a/src/analysis/decomp/decompiler.c +++ /dev/null @@ -1,247 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * decompiler.c - encadrement des phases de décompilation - * - * Copyright (C) 2010-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "decompiler.h" - - -#include <malloc.h> -#include <stdio.h> -#include <string.h> - - -#include <i18n.h> - - -#include "cmerge.h" -#include "il.h" -#include "reduce.h" -#include "../../decomp/output.h" -#include "../../decomp/expr/block.h" -#include "../../decomp/lang/java.h"    /* FIXME : remme ! */ -#include "../../format/format.h" - - - -/* Construit la description d'introduction de la décompilation. */ -static void build_decomp_prologue(GCodeBuffer *, const char *); - -/* S'assure de la transcription de routines en expressions. */ -static void prepare_all_routines_for_decomp(const GLoadedBinary *, const char *); - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : buffer   = tampon de destination pour le texte.              * -*                filename = nom du fichier ciblé à décompiler.                * -*                                                                             * -*  Description : Construit la description d'introduction de la décompilation. * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void build_decomp_prologue(GCodeBuffer *buffer, const char *filename) -{ -    GLangOutput *output;                    /* Modèle de sortie adéquat    */ -    GBufferLine *line;                      /* Ligne de destination        */ -    size_t len;                             /* Taille du texte             */ -    char *content;                          /* Contenu textuel d'une ligne */ - -    output = g_java_output_new(); - -    line = g_lang_output_start_comments(output, buffer); -    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    /* Introduction */ - -    line = g_lang_output_continue_comments(output, buffer, -                                           SL(_("Binary data decompiled by Chrysalide"))); -    g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    line = g_lang_output_continue_comments(output, buffer, -                                           SL(_("Chrysalide is free software - © 2008-2012 Cyrille Bagard"))); -    g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    line = g_lang_output_continue_comments(output, buffer, NULL, 0); -    g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    /* Fichier */ - -    if (filename == NULL) -        filename = _("whole binary"); - -    len = strlen(_("File: ")) + strlen(filename) + 1; -    content = (char *)calloc(len, sizeof(char)); - -    snprintf(content, len, "%s%s", _("File: "), filename); - -    line = g_lang_output_continue_comments(output, buffer, content, len - 1); -    g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    free(content); - -    /* Ligne de séparation */ - -    line = g_lang_output_continue_comments(output, buffer, NULL, 0); -    g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    /* Conclusion */ - -    line = g_lang_output_end_comments(output, buffer); -    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL); - -    g_object_unref(G_OBJECT(output)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : binary   = représentation de binaire chargé.                 * -*                filename = nom du fichier source à cibler.                   * -*                                                                             * -*  Description : S'assure de la transcription de routines en expressions.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const char *filename) -{ -    GExeFormat *format;                     /* Format du binaire fourni    */ -    GArchProcessor *proc;                   /* Architecture du binaire     */ - -    GBinRoutine **routines; -    size_t count; - -    size_t i; - -    //GDecContext *context;                   /* Contexte pour la décompil.  */ -    GDecInstruction *dinstrs; - -    //GArchInstruction *instrs;                /* Instructions natives        */ - -    //vmpa_t max;                             /* Première adresse à écarter  */ - -    format = g_loaded_binary_get_format(binary); -    proc = NULL;//get_arch_processor_from_format(G_EXE_FORMAT(format)); - - -    routines = NULL; //g_binary_format_get_routines(G_BIN_FORMAT(format), &count); -    count = 0; - - - -    for (i = 0; i < count; i++) -    { -        /* -        context = g_arch_processor_get_decomp_context(proc); - -        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_XXX_binary_routine_get_address(routines[i]) -            + g_XXX_binary_routine_get_size(routines[i]); -        */ -        //printf("\n##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i])); - - -        dinstrs = decompiled_routine_instructions(routines[i], format, proc); - -        /* -        dinstrs = build_decompiled_block(instrs, -                                         g_XXX_binary_routine_get_address(routines[i]), -                                         max, VMPA_MAX, context); -        */ - -        //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context); - - -        //merge_lonely_conditions(dinstrs); - -        /////reduce_used_variables(dinstrs); - -         -        g_expr_block_set_border_behavior(G_EXPR_BLOCK(dinstrs), BBB_FORCE_ON); - -        g_binary_routine_set_decomp_instructions(routines[i], dinstrs); - - -        /* -        if (context != NULL) -            g_object_unref(context); -        */ - -    } - -    g_object_unref(G_OBJECT(format)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : binary   = représentation de binaire chargé.                 * -*                filename = nom du fichier source à cibler.                   * -*                                                                             * -*  Description : Procède à la décompilation des routines d'un fichier donné.  * -*                                                                             * -*  Retour      : Tampon de code mis en place.                                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *filename) -{ -    GCodeBuffer *result;                    /* Tampon constitué à renvoyer */ -    GExeFormat *format;                     /* Format du binaire fourni    */ - -    result = g_code_buffer_new(BLC_ASSEMBLY_HEAD); - - -    build_decomp_prologue(result, filename); - -    //prepare_all_routines_for_decomp(binary, filename); - - - - -    format = g_loaded_binary_get_format(binary); - -    g_binary_format_decompile(G_BIN_FORMAT(format), result, filename); - -    g_object_unref(G_OBJECT(format)); - -    return result; - -} diff --git a/src/analysis/decomp/decompiler.h b/src/analysis/decomp/decompiler.h deleted file mode 100644 index 12a3fb4..0000000 --- a/src/analysis/decomp/decompiler.h +++ /dev/null @@ -1,37 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * decompiler.h - prototypes pour l'encadrement des phases de décompilation - * - * Copyright (C) 2010-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_DECOMP_DECOMPILER_H -#define _ANALYSIS_DECOMP_DECOMPILER_H - - -#include "../binary.h" - - - -/* Procède à la décompilation des routines d'un fichier donné. */ -GCodeBuffer *decompile_all_from_file(const GLoadedBinary *, const char *); - - - -#endif  /* _ANALYSIS_DECOMP_DECOMPILER_H */ diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c deleted file mode 100644 index cbc0c37..0000000 --- a/src/analysis/decomp/il.c +++ /dev/null @@ -1,772 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * il.h - mise en place d'un langage intermédiaire - * - * Copyright (C) 2012-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "il.h" - - -#include <malloc.h> - - -#include "../blocks/flow.h" -#include "../blocks/virtual.h" -#include "../../decomp/expr/block.h" -#include "../../decomp/expr/immediate.h" -#include "../../decomp/instr/ite.h" -#include "../../decomp/instr/keyword.h" -#include "../../decomp/instr/switch.h" - - - -/* --------------------- GESTION DES CONTEXTES DE DECOMPILATION --------------------- */ - - -/* Détermine les registres utilisés avant leur initialisation. */ -static bool track_used_registers(GFlowBlock *, BlockFollowPosition, GRAccessList **); - -/* Etablit le relévé des allocations de registre. */ -static void setup_awaited_regs_allocation(const GInstrBlock *, vmpa_t); - -/* Etablit la liste de tous les allocations attendues. */ -static bool merge_all_awaited_regs(GInstrBlock *, BlockVisitOrder, GRAccessList *); - -/* Met en place un contexte adapté aux sous-blocs d'un bloc. */ -static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *, GHashTable *); - - - -/* -------------------------- ENCADREMENT DES INSTRUCTIONS -------------------------- */ - - -/* Retrouve et rassemble les instructions décompilées. */ -static GDecInstruction *merge_decompiled_instructions(GDecInstruction *, GDecInstruction *); - -/* Procède à la décompilation d'un bloc déterminé. */ -static GDecInstruction *decompiled_instructions_block(GFlowBlock *, GDecContext *); - -/* Procède à la décompilation d'un ensemble de blocs déterminé. */ -static GDecInstruction *decompiled_instructions_blocks(GVirtualBlock *, GDecContext *); - -/* Procède à la décompilation d'un bloc basique quelconque. */ -static GDecInstruction *decompiled_basic_block(GInstrBlock *, GDecContext *); - - - -/* --------------------------- DECOMPILATIONS SPECIFIQUES --------------------------- */ - - -/* Procède à la décompilation des éléments d'un 'if then else'. */ -static void build_ite_branches(GITEInstruction *, GFlowBlock *, GDecContext *); - -/* Termine le traitement d'un cas de 'switch'. */ -static void close_case_decomp_instructions(GDecInstruction *, GInstrBlock *, GArchInstruction **, size_t, size_t); - -/* Procède à la décompilation des éléments d'un 'switch'. */ -static void build_switch_branches(GSwitchInstruction *, GFlowBlock *, GDecContext *); - - - -/* ---------------------------------------------------------------------------------- */ -/*                       GESTION DES CONTEXTES DE DECOMPILATION                       */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block  = bloc d'instructions visité.                         * -*                pos    = indication sur la position du parcours.             * -*                needed = suivi de l'usage des registres entre les blocs.     * -*                                                                             * -*  Description : Détermine les registres utilisés avant leur initialisation.  * -*                                                                             * -*  Retour      : true pour mener un parcours complet.                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRAccessList **needed) -{ -    GRAccessList *old;                      /* Ancienne liste remplacée    */ -    const GRAccessList *accesses;           /* Accès divers aux registres  */ -    size_t count;                           /* Taille d'un parcours        */ -    GRAccessList *awaited;                  /* Satisfactions des besoins   */ -    reg_access *access;                     /* Accès à un registre         */ -    size_t i;                               /* Boucle de parcours          */ -    reg_access *found;                      /* Besoin trouvé ou non        */ - -    switch (pos) -    { -        case BFP_ENTER: -            g_object_set_data(G_OBJECT(block), "needed_regs", *needed); -            break; - -        case BFP_FOLLOW: -            *needed = g_raccess_list_new(); -            break; - -        case BFP_BACK: - -            old = *needed; -            *needed = G_RACCESS_LIST(g_object_get_data(G_OBJECT(block), "needed_regs")); - -            g_raccess_list_merge(*needed, old); -            g_object_unref(G_OBJECT(old)); - -            break; - -        case BFP_EXIT: - -            g_object_set_data(G_OBJECT(block), "needed_regs", NULL); - -            accesses = g_flow_block_list_regs_accesses(block); -            count = g_raccess_list_count(accesses); - -            awaited = g_flow_block_list_awaited_regs(block); - -            for (i = 0; i < count; i++) -            { -                access = g_raccess_list_get(accesses, i); - -                /* Enregistrement des contributions possibles */ - -                found = g_raccess_list_find(*needed, access->reg); - -                if (found != NULL) -                { -                    /** -                     * Si un autre bloc avait déjà un besoin, on ne prend note -                     * qu'une seule fois ! -                     */ -                    if (g_raccess_list_find(awaited, access->reg) == NULL) -                        g_raccess_list_add(awaited, access); - -                    g_raccess_list_delete(*needed, found); - -                } - -                /* Ajoute les besoins du bloc */ -                if (access->first_access == RAT_READ) -                    g_raccess_list_add(*needed, access); - -            } - -            /* -            do -            { -                vmpa_t start, end; - -                g_flow_block_get_boundary_addresses(block, &start, &end); - -                printf(" -> flow (%d) : 0x%08x - 0x%08x  |  needed = %zu - provided = %zu\n", -                       pos, start, end, -                       g_raccess_list_count(*needed), g_raccess_list_count(awaited)); - -            } -            while (0); -            */ - -            break; - -    } - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : list  = ensemble des instructions d'assemblage à traiter.    * -*                start = adresse de départ de la routine visée.               * -*                                                                             * -*  Description : Etablit le relévé des allocations de registre.               * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start) -{ -    GInstrBlock *first;                     /* Bloc de départ du flot      */ -    GRAccessList *needed;                   /* Registres inter-blocs       */ - -    first = g_instr_block_find_by_addr(list, start, true); - -    needed = g_raccess_list_new(); - -    g_flow_block_follow(G_FLOW_BLOCK(first), list, BFP_ENTER | BFP_EXIT | BFP_EXIT, -                        (flow_block_follow_cb)track_used_registers, &needed); - -    g_object_unref(G_OBJECT(needed)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = bloc d'instructions concerné par la visite.          * -*                order = position dans la visite.                             * -*                list  = liste à compléter.                                   * -*                                                                             * -*  Description : Etablit la liste de tous les allocations attendues.          * -*                                                                             * -*  Retour      : true pour parcourir tous les blocs.                          * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool merge_all_awaited_regs(GInstrBlock *block, BlockVisitOrder order, GRAccessList *list) -{ -    const GRAccessList *awaited;            /* Registres conséquents       */ - -    if (G_IS_FLOW_BLOCK(block)) -    { -        awaited = g_flow_block_list_regs_accesses(G_FLOW_BLOCK(block)); -        g_raccess_list_merge(list, awaited); -    } - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ctx    = contexte de décompilation courant.                  * -*                block  = block regroupant les branches de division.          * -*                shared = liste des allocations passées de registres attendus.* -*                                                                             * -*  Description : Met en place un contexte adapté aux sous-blocs d'un bloc.    * -*                                                                             * -*  Retour      : Nouveau contexte près à emploi.                              * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block, GHashTable *shared) -{ -    GDecContext *result;                    /* Contexte à retourner        */ -    GRAccessList *list;                     /* Allocations attendues       */ - -    result = g_dec_context_dup(ctx); - -    list = g_raccess_list_new(); -    g_instr_block_visit(block, (instr_block_visitor_cb)merge_all_awaited_regs, list); -    g_dec_context_set_awaited(result, list); -    g_object_unref(G_OBJECT(list)); - -    g_dec_context_set_shared_allocs(result, shared); - -    return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                            ENCADREMENT DES INSTRUCTIONS                            */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : group = groupe d'instructions à compléter ou constituer.     * -*                list  = liste d'instructions à intégrer.                     * -*                                                                             * -*  Description : Retrouve et rassemble les instructions décompilées.          * -*                                                                             * -*  Retour      : Groupe fourni ou nouveau groupe créé pour l'occasion.        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GDecInstruction *merge_decompiled_instructions(GDecInstruction *group, GDecInstruction *list) -{ -    GExprBlock *block;                      /* Autre vision du groupe      */ -    GDecInstruction *iter;                  /* Boucle de parcours          */ - -    if (group == NULL) block = NULL; -    else block = G_EXPR_BLOCK(group); - -    for (iter = list; -         iter != NULL; -         iter = g_dec_instruction_get_next_iter(list, iter)) -    { -        if (block == NULL) -            block = G_EXPR_BLOCK(g_expr_block_new(iter)); -        else -            g_expr_block_add_item(block, iter); - -    } - -    return G_DEC_INSTRUCTION(block); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = ensemble des instructions d'assemblage à traiter.    * -*                ctx   = contexte de soutien à associer à l'opération.        * -*                                                                             * -*  Description : Procède à la décompilation d'un bloc déterminé.              * -*                                                                             * -*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecContext *ctx) -{ -    GArchInstruction *instrs;               /* Liste d'instructions natives*/ -    GArchInstruction *first;                /* Première instruction du lot */ -    vmpa_t max;                             /* Adresse de fin du bloc      */ -    GArchInstruction *iter;                 /* Boucle de parcours #1       */ -    GDecInstruction *decomp;                /* Dernier résultat de décomp. */ - -    instrs = NULL; // FIXME g_flow_block_get_all_instructions_list(block); -    g_flow_block_get_boundary(block, &first, NULL); - -    g_flow_block_get_boundary_addresses(block, NULL, &max); -    max++; - -    /* Décompilation du corps du bloc */ - -    for (iter = first; -         iter != NULL; -         iter = g_arch_instruction_get_next_iter(instrs, iter, max)) -    { -        decomp = g_arch_instruction_decompile(iter, ctx); -    } - -    /* Post-traitement selon les types de lien */ - -    /* if ... then ... else ... */ -    if (G_IS_ITE_INSTRUCTION(decomp)) -        build_ite_branches(G_ITE_INSTRUCTION(decomp), block, ctx); - -    /* switch ... case ... */ -    else if (G_IS_SWITCH_INSTRUCTION(decomp)) -        build_switch_branches(G_SWITCH_INSTRUCTION(decomp), block, ctx); - -    /* Renvoi des instructions mises en place */ - -    return g_dec_context_get_decomp_instrs(ctx); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = ensemble des instructions d'assemblage à traiter.    * -*                ctx   = contexte de soutien à associer à l'opération.        * -*                                                                             * -*  Description : Procède à la décompilation d'un ensemble de blocs déterminé. * -*                                                                             * -*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GDecInstruction *decompiled_instructions_blocks(GVirtualBlock *block, GDecContext *ctx) -{ -    GDecInstruction *result;                /* Instructions à renvoyer     */ -    size_t count;                           /* Nombre de sous-blocs        */ -    size_t i;                               /* Boucle de parcours          */ -    GInstrBlock *sub_block;                 /* Sous-bloc à traiter         */ -    GDecInstruction *dinstrs;               /* Instructions décompilées    */ - -    result = NULL; - -    count = g_virtual_block_count_children(block); - -    for (i = 0; i < count; i++) -    { -        sub_block = g_virtual_block_get_child(block, i); - -        /** -         * Les groupes de blocs sont forcément rattachés à une instruction, -         * donc ils sont décompilés depuis ces instructions, pas ici. -         */ -        if (!G_IS_FLOW_BLOCK(sub_block)) continue; - -        /* FIXME */ -        //g_dec_context_set_decomp_instrs(ctx, NULL); - -        dinstrs = decompiled_instructions_block(G_FLOW_BLOCK(sub_block), ctx); -        //result = merge_decompiled_instructions(result, dinstrs); - -    } - -    result = merge_decompiled_instructions(result, dinstrs); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = ensemble des instructions d'assemblage à traiter.    * -*                ctx   = contexte de soutien à associer à l'opération.        * -*                                                                             * -*  Description : Procède à la décompilation d'un bloc basique quelconque.     * -*                                                                             * -*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GDecInstruction *decompiled_basic_block(GInstrBlock *block, GDecContext *ctx) -{ -    GDecInstruction *result;                /* Instructions à retourner    */ - -    if (G_IS_VIRTUAL_BLOCK(block)) -        result = decompiled_instructions_blocks(G_VIRTUAL_BLOCK(block), ctx); - -    else -    { -        result = decompiled_instructions_block(G_FLOW_BLOCK(block), ctx); - -        if (!G_IS_EXPR_BLOCK(result)) -            result = merge_decompiled_instructions(NULL, result); - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : routine = routine dont le corps est à traiter.               * -*                format  = format du binaire contenant les instructions.      * -*                proc    = architecture du code machine.                      * -*                                                                             * -*  Description : Procède à la décompilation d'une routinée déterminée.        * -*                                                                             * -*  Retour      : Instructions créées ou NULL si erreur.                       * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeFormat *format, GArchProcessor *proc) -{ -    GDecInstruction *result;                /* Instructions à retourner    */ -    GDecContext *context;                   /* Contexte pour la décompil.  */ -    GInstrBlock *blocks;                    /* Blocs basiques de routine   */ -    const mrange_t *range;                  /* Emplacement du symbole      */ - -    context = g_arch_processor_get_decomp_context(proc); -    g_dec_context_set_info(context, routine, format); - -    blocks = g_binary_routine_get_basic_blocks(routine); - -    range = g_binary_symbol_get_range(G_BIN_SYMBOL(routine)); -    setup_awaited_regs_allocation(blocks, get_mrange_addr(range)->physical); - -    result = decompiled_basic_block(blocks, context); - -    g_object_unref(context); - -    return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                             DECOMPILATIONS SPECIFIQUES                             */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : decomp = instruction 'if ... then ... else' à compléter.     * -*                block  = ensemble des instructions d'assemblage traitées.    * -*                ctx    = contexte de soutien à associer à l'opération.       * -*                                                                             * -*  Description : Procède à la décompilation des éléments d'un 'if then else'. * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void build_ite_branches(GITEInstruction *decomp, GFlowBlock *block, GDecContext *ctx) -{ -    GArchInstruction *last;                 /* Dernière instruction du lot */ -    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */ -    GHashTable *sub_shared;                 /* Allocations communes        */ -    GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */ -    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */ -    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */ -    GArchInstruction *next;                 /* Instruction de branchement  */ -    vmpa_t next_addr;                       /* Adresse de cette instruct°  */ -    GInstrBlock *next_block;                /* Sous-bloc basique direct    */ - -    g_flow_block_get_boundary(block, NULL, &last); - -    sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); -    sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, -                                       (GEqualFunc)NULL,//g_arch_register_equal, -                                       g_object_unref, g_object_unref); - -    true_dinstr = NULL; -    false_dinstr = NULL; - -    /* Branche 'true' */ -    next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE); -    if (next != NULL) -    { -        g_arch_instruction_get_location(next, NULL, NULL, &next_addr); -        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false); - -        if (next_block != NULL) -        { -            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); -            true_dinstr = decompiled_basic_block(next_block, sub_ctx); -            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); -            g_object_unref(G_OBJECT(sub_ctx)); -        } - -        g_object_unref(G_OBJECT(next)); - -    } - -    /* Branche 'false' */ -    next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE); -    if (next != NULL) -    { -        g_arch_instruction_get_location(next, NULL, NULL, &next_addr); -        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false); - -        if (next_block != NULL) -        { -            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); -            false_dinstr = decompiled_basic_block(next_block, sub_ctx); -            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); -            g_object_unref(G_OBJECT(sub_ctx)); -        } - -        g_object_unref(G_OBJECT(next)); - -    } - -    g_ite_instruction_set_branches(decomp, true_dinstr, false_dinstr); - -    g_hash_table_unref(sub_shared); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : case_dinstr = instructions d'un cas de 'switch' décompilées. * -*                case_block  = bloc d'instructions assembleur correspondantes.* -*                cases       = listes des instructions des différents cas.    * -*                current     = indice du cas courant.                         * -*                ccount      = nombre de cas présents dans le 'switch'.       * -*                                                                             * -*  Description : Termine le traitement d'un cas de 'switch'.                  * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void close_case_decomp_instructions(GDecInstruction *case_dinstr, GInstrBlock *case_block, GArchInstruction **cases, size_t current, size_t ccount) -{ -    vmpa_t *cases_addr;                     /* Adresses des cas du 'switch'*/ -    size_t i;                               /* Boucle de parcours #1       */ -    GInstrBlock **leafs;                    /* Blocs terminaux du cas      */ -    size_t lcount;                          /* Nombre de blocs terminaux   */ -    vmpa_t common_addr;                     /* Adresse commune de suite    */ -    bool is_common;                         /* Suite commune ?             */ -    GArchInstruction *last;                 /* Dernière instruction de bloc*/ -    size_t dcount;                          /* Nombre de liens de dest.    */ -    size_t j;                               /* Boucle de parcours #2       */ -    const instr_link_t *dest;               /* Instr. visée par une autre  */ -    vmpa_t addr;                            /* Adresse d'une instruction   */ -    bool jump_to_case;                      /* Suite dans le cas suivant ? */ - -    /* Etablit la liste des adresses des cas */ - -    cases_addr = (vmpa_t *)calloc(ccount, sizeof(vmpa_t)); - -    for (i = 0; i < ccount; i++) -        g_arch_instruction_get_location(cases[i], NULL, NULL, &cases_addr[i]); - -    /* Récupère la (les) fin(s) du cas présent */ - -    leafs = NULL; -    lcount = 0; - -    g_instr_block_list_leafs_blocks(case_block, &leafs, &lcount); - -    /* Procède à une première analyse de la suite */ - -    common_addr = VMPA_MAX; -    is_common = true; - -    for (i = 0; i < lcount && is_common; i++) -    { -        g_flow_block_get_boundary(G_FLOW_BLOCK(leafs[i]), NULL, &last); - -        g_arch_instruction_lock_dest(last); -        dcount = g_arch_instruction_count_destinations(last); - -        for (j = 0; j < dcount && is_common; j++) -        { -            dest = g_arch_instruction_get_destination(last, j); - -            g_arch_instruction_get_location(dest->linked, NULL, NULL, &addr); - -            if (common_addr == VMPA_MAX) -                common_addr = addr; -            else -                is_common = (common_addr == addr); - -            unref_instr_link(dest); - -        } - -        g_arch_instruction_unlock_dest(last); - -    } - -    /* La sortie du cas est unique ! */ -    if (is_common) -    { -        if (common_addr == VMPA_MAX) -            goto ecdi_exit; - -        jump_to_case = false; - -        for (i = 0; i < ccount && !jump_to_case; i++) -            if (i != current) -                jump_to_case = (cases_addr[i] == common_addr); - -        if (!jump_to_case) -            g_expr_block_add_item(G_EXPR_BLOCK(case_dinstr), g_keyword_instruction_new(DKW_BREAK)); - -    } - -    /* ... ou il faut suivre les différentes branches... */ -    else -    { - -        /* TODO */ - -    } - - ecdi_exit: - -    free(cases_addr); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : decomp = instruction 'switch' à compléter.                   * -*                block  = ensemble des instructions d'assemblage traitées.    * -*                ctx    = contexte de soutien à associer à l'opération.       * -*                                                                             * -*  Description : Procède à la décompilation des éléments d'un 'switch'.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void build_switch_branches(GSwitchInstruction *decomp, GFlowBlock *block, GDecContext *ctx) -{ -#if 0 - -    GArchInstruction *last;                 /* Dernière instruction du lot */ -    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */ -    GHashTable *sub_shared;                 /* Allocations communes        */ -    GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */ -    vmpa_t next_addr;                       /* Adresse de cette instruct°  */ -    GInstrBlock *next_block;                /* Sous-bloc basique direct    */ -    GArchInstruction **dests;               /* Instr. visée par une autre  */ -    link_extra_info *info;                  /* Compléments pour les liens  */ -    size_t dcount;                          /* Nombre de liens de dest.    */ -    size_t i;                               /* Boucle de parcours #2       */ -    GDecInstruction *case_dinstr;           /* Décompilation 'case'        */ -    GDecExpression *case_value;             /* Valeur d'aiguillage         */ - -    g_flow_block_get_boundary(block, NULL, &last); - -    sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); -    sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, -                                       (GEqualFunc)g_arch_register_equal, -                                       g_object_unref, g_object_unref); - -    dcount = g_arch_instruction_get_destinations(last, &dests, NULL, &info); - -    for (i = 0; i < dcount; i++) -    { -        g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); -        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false); - -        if (next_block != NULL) -        { -            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); -            case_dinstr = decompiled_basic_block(next_block, sub_ctx); -            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); -            g_object_unref(G_OBJECT(sub_ctx)); - -            close_case_decomp_instructions(case_dinstr, next_block, dests, i, dcount); -            g_expr_block_set_border_behavior(G_EXPR_BLOCK(case_dinstr), BBB_FORCE_OFF); - -            if (info[i].imm != NULL) -            { -                case_value = G_DEC_EXPRESSION(g_imm_expression_new(info[i].imm)); -                g_switch_instruction_add_case(G_SWITCH_INSTRUCTION(decomp), -                                              case_value, case_dinstr, next_addr); -            } -            else g_switch_instruction_set_default_case(G_SWITCH_INSTRUCTION(decomp), -                                                       case_dinstr); - -        } - -    } - -    g_hash_table_unref(sub_shared); -#endif -} diff --git a/src/analysis/decomp/il.h b/src/analysis/decomp/il.h deleted file mode 100644 index ed901e6..0000000 --- a/src/analysis/decomp/il.h +++ /dev/null @@ -1,50 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * il.h - prototypes pour la mise en place d'un langage intermédiaire - * - * Copyright (C) 2012-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_DECOMP_IL_H -#define _ANALYSIS_DECOMP_IL_H - - -#include "../routine.h" -#include "../../arch/processor.h" - - - -/* Procède à la décompilation d'une routinée déterminée. */ -GDecInstruction *decompiled_routine_instructions(GBinRoutine *, GExeFormat *, GArchProcessor *); - - - - -#if 0 -#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 - - -#endif  /* _ANALYSIS_DECOMP_IL_H */ diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c deleted file mode 100644 index b630bc7..0000000 --- a/src/analysis/decomp/reduce.c +++ /dev/null @@ -1,422 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * reduce.c - réduction de l'usage des [pseudo]-registres - * - * Copyright (C) 2012-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "reduce.h" - - -#include <malloc.h> - - -#include "../../decomp/expr/assign.h" -#include "../../decomp/expr/block.h" -#include "../../decomp/expr/immediate.h" -#include "../../decomp/expr/pseudo.h" - - - -/* ------------------------ DECOMPTE DES USAGES DE VARIABLES ------------------------ */ - - -/* Mémorisation de l'usage d'une variable */ -typedef struct _assigned_value -{ -    GDecInstruction *value;                 /* Valeur de cette variable    */ - -    GDecInstruction *assign;                /* Lieu d'assignation          */ -    GDecInstruction *parent;                /* Zone à nettoyer au besoin   */ - -    size_t used_counter;                    /* Décompte des utilisations   */ -    size_t shared_counter;                  /* Partage entre tables        */ - -} assigned_value; - - -/* Conserve tous les éléments concernant une assignation. */ -static assigned_value *memorize_assigned_value(GDecInstruction *, GDecInstruction *, GDecInstruction *); - -/* Met (éventuellement) fin à un suivi d'assignation. */ -static void forget_assigned_value(assigned_value *); - -/* Constitue un lieu de conservation d'associations pour bloc. */ -static GHashTable *create_tracking_table(GHashTable *); - -/* Met à jour les décomptes des différentes assignations. */ -static void merge_usages(GHashTable *, GHashTable *); - -/* Prend notre d'une assignation d'une valeur à une variable. */ -static void note_new_variable(GHashTable *, GDecInstruction *, assigned_value *); - - - -/* ---------------------- VISITES DES INSTRUCTIONS DECOMPILEES ---------------------- */ - - -/* Prend note de tous les accès aux différentes variables. */ -static void collect_used_variables(GDecInstruction *, GDecInstruction *, GHashTable *); - -/* Procède au remplacement de variables à rejeter. */ -static void replace_useless_variable(GDecInstruction *, GHashTable *); - -/* Visite un groupe d'instructions décompilées. */ -static bool visit_instructions_block(GDecInstruction *, GDecInstruction *, DecInstrVisitFlags, GHashTable **); - - - -/* ---------------------------------------------------------------------------------- */ -/*                          DECOMPTE DES USAGES DE VARIABLES                          */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : value  = nouvelle valeur assignée à suivre.                  * -*                assign = instruction où la valeur est assignée.              * -*                parent = bloc d'instructions à soulager en cas d'effacement. * -*                table  = mémorisation des usages de variables.               * -*                                                                             * -*  Description : Conserve tous les éléments concernant une assignation.       * -*                                                                             * -*  Retour      : Structure mise en place.                                     * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static assigned_value *memorize_assigned_value(GDecInstruction *value, GDecInstruction *assign, GDecInstruction *parent) -{ -    assigned_value *result;                 /* Mémorisation à retourner    */ - -    result = (assigned_value *)calloc(1, sizeof(assigned_value)); - -    g_object_ref(G_OBJECT(value)); -    result->value = value; - -    g_object_ref(G_OBJECT(assign)); -    g_object_ref(G_OBJECT(parent)); -    result->assign = assign; -    result->parent = parent; - -    result->used_counter = 0; -    result->shared_counter = 0; - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : val = structure à libérer de la mémoire.                     * -*                                                                             * -*  Description : Met (éventuellement) fin à un suivi d'assignation.           * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void forget_assigned_value(assigned_value *val) -{ -    if (--val->shared_counter == 0) -    { -        g_object_unref(G_OBJECT(val->value)); - -        g_object_unref(G_OBJECT(val->assign)); -        g_object_unref(G_OBJECT(val->parent)); - -        free(val); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : parent = éventuel bloc d'instructions parent ou NULL.        * -*                                                                             * -*  Description : Constitue un lieu de conservation d'associations pour bloc.  * -*                                                                             * -*  Retour      : Table prête à emploi.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GHashTable *create_tracking_table(GHashTable *parent) -{ -    GHashTable *result;                     /* Création à retourner        */ -    GHashTableIter iter;                    /* Boucle de parcours          */ -    GDecInstruction *var;                   /* Variable assignée           */ -    assigned_value *val;                    /* Valeur assignée             */ - -    result = g_hash_table_new_full(NULL, NULL, g_object_unref, -                                   (GDestroyNotify)forget_assigned_value); - -    if (parent != NULL) -    { -        g_hash_table_iter_init(&iter, parent); - -        while (g_hash_table_iter_next(&iter, (gpointer *)&var, (gpointer *)&val)) -            note_new_variable(result, var, val); - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : table = conservation des associations variable <-> valeur.   * -*                sub   = conservation issue d'un sous bloc.                   * -*                                                                             * -*  Description : Met à jour les décomptes des différentes assignations.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void merge_usages(GHashTable *table, GHashTable *sub) -{ -    GHashTableIter iter;                    /* Boucle de parcours          */ -    GDecInstruction *var;                   /* Variable assignée           */ -    assigned_value *val;                    /* Valeur assignée             */ -    assigned_value *update;                 /* Même valeur, mise à jour    */ - -    g_hash_table_iter_init(&iter, table); - -    while (g_hash_table_iter_next(&iter, (gpointer *)&var, (gpointer *)&val)) -    { -        update = (assigned_value *)g_hash_table_lookup(sub, var); - -        val->used_counter = update->used_counter; - -        g_hash_table_remove(sub, var); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : table = conservation des associations variable <-> valeur.   * -*                var   = variable en place à suivre.                          * -*                val   = valeur associée.                                     * -*                                                                             * -*  Description : Prend notre d'une assignation d'une valeur à une variable.   * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void note_new_variable(GHashTable *table, GDecInstruction *var, assigned_value *val) -{ -    g_object_ref(G_OBJECT(var)); -    val->shared_counter++; - -    g_hash_table_insert(table, var, val); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                        VISITES DES INSTRUCTIONS DECOMPILEES                        */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instr  = instruction visitée.                                * -*                parent = instruction parente.                                * -*                table  = mémorisation des usages de variables.               * -*                                                                             * -*  Description : Prend note de tous les accès aux différentes variables.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void collect_used_variables(GDecInstruction *instr, GDecInstruction *parent, GHashTable *table) -{ -    GAssignExpression *assign;              /* Instruction d'assignation   */ -    GDecInstruction *dest;                  /* Variable de destination     */ -    bool valid;                             /* Destination valide ?        */ -    GDecInstruction *src;                   /* Valeur de source            */ -    assigned_value *value;                  /* Valeur et ses informations  */ - -    if (G_IS_ASSIGN_EXPRESSION(instr)) -    { -        assign = G_ASSIGN_EXPRESSION(instr); - -        dest = G_DEC_INSTRUCTION(g_assign_expression_get_dest(assign)); - -        if (G_IS_PSEUDO_REGISTER(dest)) -            valid = (g_pseudo_register_get_usage(G_PSEUDO_REGISTER(dest)) == PRU_LOCAL); -        else -            valid = true; - -        if (valid) -        { -            src = G_DEC_INSTRUCTION(g_assign_expression_get_src(assign)); - -            value = memorize_assigned_value(src, instr, parent); -            note_new_variable(table, dest, value); - -        } - -    } -    else -    { -        value = (assigned_value *)g_hash_table_lookup(table, instr); - -        if (value != NULL) -            value->used_counter++; - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = bloc d'instructions décompilées à traiter.           * -*                table = mémorisation des usages de variables.                * -*                                                                             * -*  Description : Procède au remplacement de variables à rejeter.              * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void replace_useless_variable(GDecInstruction *block, GHashTable *table) -{ -    GHashTableIter iter;                    /* Boucle de parcours          */ -    GDecInstruction *var;                   /* Variable assignée           */ -    assigned_value *val;                    /* Valeur assignée             */ -    bool replace;                           /* Ordre de remplacement       */ - -    g_hash_table_iter_init(&iter, table); - -    while (g_hash_table_iter_next(&iter, (gpointer *)&var, (gpointer *)&val)) -    { -        replace = (G_IS_IMM_EXPRESSION(val->value) && (val->used_counter > 1)); -        replace |= (val->used_counter == 2);    /* 1 assign. + 1 usage */ - -        if (!replace) continue; - -        g_expr_block_delete_item(G_EXPR_BLOCK(val->parent), val->assign); - -        g_dec_instruction_replace(block, var, val->value); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instr  = instruction visitée.                                * -*                parent = instruction parente.                                * -*                flags  = moments des appels réalisés en retour.              * -*                table  = mémorisation des usages de variables.               * -*                                                                             * -*  Description : Visite un groupe d'instructions décompilées.                 * -*                                                                             * -*  Retour      : true afin d'aller jusqu'au terme du parcours.                * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool visit_instructions_block(GDecInstruction *instr, GDecInstruction *parent, DecInstrVisitFlags flags, GHashTable **table) -{ -    GHashTable *sub;                        /* Associations pour sous-bloc */ - -    if (G_IS_EXPR_BLOCK(instr)) -    { -        /* Entrée dans un bloc : on crée un contexte propre au bloc ! */ -        if (flags == DVF_ENTER) -        { -            g_object_set_data(G_OBJECT(instr), "var_collect", *table); -            *table = create_tracking_table(*table); -        } - -        /* Sortie du bloc : actions locales + purge ! */ -        else if (flags == DVF_EXIT) -        { -            sub = *table; -            *table = (GHashTable *)g_object_get_data(G_OBJECT(instr), "var_collect"); - -            if (*table != NULL) -                merge_usages(*table, sub); - -            replace_useless_variable(instr, sub); -            g_hash_table_unref(sub); - -        } - -    } - -    else if (flags == DVF_ENTER) -        collect_used_variables(instr, parent, *table); - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instr = instructions à traiter.                              * -*                                                                             * -*  Description : Réduit le nombre de variables utilisées, via propagations.   * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void reduce_used_variables(GDecInstruction *instr) -{ -    GHashTable *table; - -    table = NULL; - -    g_dec_instruction_visit(instr, (dec_instr_visitor_cb)visit_instructions_block, -                            DVF_ENTER | DVF_EXIT, &table); - -} diff --git a/src/analysis/decomp/reduce.h b/src/analysis/decomp/reduce.h deleted file mode 100644 index fe5fa99..0000000 --- a/src/analysis/decomp/reduce.h +++ /dev/null @@ -1,37 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * reduce.h - prototypes pour la réduction de l'usage des [pseudo]-registres - * - * Copyright (C) 2012-2017 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  Chrysalide 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. - * - *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_DECOMP_REDUCE_H -#define _ANALYSIS_DECOMP_REDUCE_H - - -#include "../../decomp/instruction.h" - - - -/* Réduit le nombre de variables utilisées, via propagations. */ -void reduce_used_variables(GDecInstruction *instr); - - - -#endif  /* _ANALYSIS_DECOMP_REDUCE_H */ diff --git a/src/analysis/routine.c b/src/analysis/routine.c index edb9cb3..44e75c9 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -63,7 +63,6 @@ struct _GBinRoutine      size_t locals_count;                    /* Nombre de variables locales */      GBlockList *blocks;                     /* Blocs basiques d'instruct°  */ -    //GDecInstruction *dinstr;                /* Instructions décompilées    */  }; @@ -742,50 +741,6 @@ void g_binary_routine_set_basic_blocks(GBinRoutine *routine, GBlockList *blocks)  /******************************************************************************  *                                                                             *  *  Paramètres  : routine = routine à consulter.                               * -*                                                                             * -*  Description : Fournit les instructions décompilées correspondantes.        * -*                                                                             * -*  Retour      : Ensemble d'instructions décompilées ou NULL.                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#if 0 -GDecInstruction *g_binary_routine_get_decomp_instructions(const GBinRoutine *routine) -{ -    return routine->dinstr; - -} -#endif - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : routine = routine à mettre à jour.                           * -*                instr   = série d'instructions à conserver.                  * -*                                                                             * -*  Description : Définit les instructions décompilées de la routine.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#if 0 -void g_binary_routine_set_decomp_instructions(GBinRoutine *routine, GDecInstruction *instr) -{ -    if (routine->dinstr != NULL) -        g_object_unref(G_OBJECT(routine->dinstr)); - -    routine->dinstr = instr; - -} -#endif - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : routine = routine à consulter.                               *  *                include = doit-on inclure les espaces de noms ?              *  *                                                                             *  *  Description : Décrit le prototype de la routine sous forme de caractères.  * diff --git a/src/analysis/routine.h b/src/analysis/routine.h index 1a2cd92..35480c2 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -122,12 +122,6 @@ GBlockList *g_binary_routine_get_basic_blocks(const GBinRoutine *);  /* Définit les blocs basiques de la routine. */  void g_binary_routine_set_basic_blocks(GBinRoutine *, GBlockList *); -/* Fournit les instructions décompilées correspondantes. */ -//GDecInstruction *g_binary_routine_get_decomp_instructions(const GBinRoutine *); - -/* Définit les instructions décompilées de la routine. */ -//void g_binary_routine_set_decomp_instructions(GBinRoutine *, GDecInstruction *); -  /* Décrit le prototype de la routine sous forme de caractères. */  char *g_binary_routine_to_string(const GBinRoutine *, bool); | 
