/* OpenIDA - Outil d'analyse de fichiers binaires
 * decompiler.c - encadrement des phases de décompilation
 *
 * Copyright (C) 2010 Cyrille Bagard
 *
 *  This file is part of OpenIDA.
 *
 *  OpenIDA is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenIDA is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar.  If not, see .
 */
#include "decompiler.h"
#include 
#include 
#include 
#include 
#include "../../decomp/output.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_ADDRESS);
    /* Introduction */
    line = g_lang_output_continue_comments(output, buffer,
                                           SL(_("Binary data decompiled by Chrysalide")));
    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
    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_ADDRESS);
    line = g_lang_output_continue_comments(output, buffer, NULL, 0);
    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
    /* 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_ADDRESS);
    free(content);
    /* Ligne de séparation */
    line = g_lang_output_continue_comments(output, buffer, NULL, 0);
    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
    /* Conclusion */
    line = g_lang_output_end_comments(output, buffer);
    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS);
    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 *instr;
    format = g_loaded_binary_get_format(binary);
    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
    routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &count);
    for (i = 0; i < count; i++)
    {
        context = g_arch_processor_get_decomp_context(proc);
        instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context);
        if (context != NULL)
            g_object_unref(context);
    }
}
/******************************************************************************
*                                                                             *
*  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();
    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);
    return result;
}