/* OpenIDA - Outil d'analyse de fichiers binaires
 * overjump.c - greffon assurant un désassemblage pour les architectures Intel
 *
 * Copyright (C) 2009 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 "overjump.h"


#include <malloc.h>
#include <stdlib.h>







/* Instance de désassemblage supportant les sauts */
typedef struct _overjump_instance
{
    off_t bin_length;                       /* Taille des données brutes   */
    uint8_t *bin_data;                      /* Données binaires brutes     */

    exe_format *format;                     /* Format du binaire           */
    void/*asm_processor*/ *proc;                    /* Architecture du binaire     */
    disass_options *options;                /* Options de désassemblage    */

    bin_part **parts;                       /* Parts binaires à ausculter  */
    size_t parts_count;                     /* Quantité de ces parts       */

} overjump_instance;


/* Localise une adresse virtuelle donnée. */
size_t get_bin_part_from_vmpa(overjump_instance *, vmpa_t, off_t *, off_t *, vmpa_t *);

/* Désassemble une ou plusieures adresses virtuelles. */
GRenderingLine *disassemble_address(overjump_instance *, vmpa_t, bool);



/******************************************************************************
*                                                                             *
*  Paramètres  : ref = espace de référencement global.                        *
*                                                                             *
*  Description : Initialise le greffon pour le désassemblage Intel.           *
*                                                                             *
*  Retour      : true.                                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

overjump_instance *create_overjump_instance(openida_binary *binary)
{
    overjump_instance *result;              /* Instance crée à renvoyer    */

    result = (overjump_instance *)calloc(1, sizeof(overjump_instance));

    result->bin_data = get_openida_binary_data(binary, &result->bin_length);

    result->format = get_openida_binary_format(binary);
    //result->proc = get_openida_binary_processor(binary);
    result->options = get_openida_binary_options(binary);

    result->parts = get_elf_default_code_parts(result->format, &result->parts_count);
    qsort(result->parts, result->parts_count, sizeof(bin_part *), compare_bin_parts);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instance = instance personnalisée du greffon à manipuler.    *
*                addr     = adresse en mémoire recherchée.                    *
*                pos      = position de la section à donner. [OUT]            *
*                size     = taille de la section à donner. [OUT]              *
*                base     = adresse virtuelle de la section à donner. [OUT]   *
*                                                                             *
*  Description : Localise une adresse virtuelle donnée.                       *
*                                                                             *
*  Retour      : Indice de la partie concernée, ou parts_count si non trouvée.*
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

size_t get_bin_part_from_vmpa(overjump_instance *instance, vmpa_t addr, off_t *pos, off_t *size, vmpa_t *base)
{
    size_t result;                          /* Indice à retourner          */

    for (result = 0; result < instance->parts_count; result++)
    {
        get_bin_part_values(instance->parts[result], pos, size, base);

        if (*base <= addr && addr < (*base + *size))
            break;

    }

    return result;

}






/******************************************************************************
*                                                                             *
*  Paramètres  : instance = instance personnalisée du greffon à manipuler.    *
*                addr     = adresse en mémoire recherchée.                    *
*                onlyone  = fixe une limite pour le désassemblage.            *
*                                                                             *
*  Description : Désassemble une ou plusieures adresses virtuelles.           *
*                                                                             *
*  Retour      : Liste de lignes de rendu transcrites.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GRenderingLine *disassemble_address(overjump_instance *instance, vmpa_t addr, bool onlyone)
{
    GRenderingLine *result;                 /* Liste à retourner           */
    off_t pos;                              /* Début de partie concernée   */
    off_t size;                             /* Taille de cette partie      */
    vmpa_t base;                            /* Adresse de base de la partie*/
    size_t index;                           /* Indice de la partie trouvée */



    off_t start;

    off_t npos;
    uint64_t offset;




    asm_instr *instr;
    GRenderingLine *line;


    result = NULL;

    index = get_bin_part_from_vmpa(instance, addr, &pos, &size, &base);


    start = pos + addr - base;
    npos = 0;


    offset = addr;

    /*
    instr = decode_instruction(instance->proc, &instance->bin_data[start],
                               &npos, size, start, offset);


    line = g_code_line_new(offset, instr, instance->options);
    g_rendering_line_add_to_lines(&result, line);

    */


    return result;

}






/******************************************************************************
*                                                                             *
*  Paramètres  : ref = espace de référencement global.                        *
*                                                                             *
*  Description : Initialise le greffon pour le désassemblage Intel.           *
*                                                                             *
*  Retour      : true.                                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

bool init_plugin(GObject *ref)
{

    printf("Init overjump\n");




    return true;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Fournit une indication sur le type d'opération(s) menée(s).  *
*                                                                             *
*  Retour      : Description d'une action.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

G_MODULE_EXPORT PluginAction get_plugin_action(void)
{
    return PGA_DISASSEMBLE;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : binary = binaire dont le contenu est à désassembler.         *
*                                                                             *
*  Description : S'occupe du désassemblage (pur) de code binaire.             *
*                                                                             *
*  Retour      : Lignes de code pour la représentation à insérer.             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

G_MODULE_EXPORT GRenderingLine *disassemble_binary_parts(openida_binary *binary)
{

    GRenderingLine *result;
    overjump_instance *instance;




    off_t start;
    off_t pos;
    off_t len;

    uint64_t base = 0;
    uint64_t offset = 0;

    GRenderingLine *line;

    asm_instr *instr;

    result = NULL;

    instance = create_overjump_instance(binary);


    result = disassemble_address(instance, get_exe_entry_point(instance->format), true);



#if 0

    get_bin_part_values(instance->parts[0], &pos, &len, &base);

    /* Décodage des instructions */

    start = pos;
    pos = 0;


    offset = base + pos;


    instr = decode_instruction(instance->proc, &instance->bin_data[start], &pos, len, start, offset);


    line = g_code_line_new(offset, instr, instance->options);
    g_rendering_line_add_to_lines(&result, line);



    disassemble_address(overjump_instance *instance, vmpa_t addr, bool onlyone);

#endif


    return result;

}