/* OpenIDA - Outil d'analyse de fichiers binaires
 * artificial.c - instructions pures vues de l'esprit
 *
 * Copyright (C) 2009-2011 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 "artificial.h"


#include "immediate.h"
#include "instruction-int.h"



/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */


/* Définition générique d'une instruction d'architecture inconnue (instance) */
struct _GDbInstruction
{
    GArchInstruction parent;                /* A laisser en premier        */

#ifdef DEBUG
    bool skipped;                           /* Donnée traitée              */
#endif

};

/* Définition générique d'une instruction d'architecture inconnue (classe) */
struct _GDbInstructionClass
{
    GArchInstructionClass parent;           /* A laisser en premier        */

};


/* Initialise la classe générique des opérandes. */
static void g_db_instruction_class_init(GDbInstructionClass *);

/* Initialise une instance d'opérande d'architecture. */
static void g_db_instruction_init(GDbInstruction *);

/* Traduit une instruction en version humainement lisible. */
static const char *g_db_instruction_get_text(const GDbInstruction *, const GExeFormat *, AsmSyntax);

/* Informe sur une éventuelle référence à une autre instruction. */
static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *, vmpa_t *);

/* Indique si l'instruction correspond à un retour de fonction. */
static bool g_db_instruction_is_return(const GDbInstruction *);



/* ---------------------------------------------------------------------------------- */
/*                           INSTRUCTION INCONNUE / DONNEES                           */
/* ---------------------------------------------------------------------------------- */


/* Indique le type défini pour une instruction inconnue d'architecture. */
G_DEFINE_TYPE(GDbInstruction, g_db_instruction, G_TYPE_ARCH_INSTRUCTION);


/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe générique des opérandes.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_db_instruction_class_init(GDbInstructionClass *klass)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à initialiser.                              *
*                                                                             *
*  Description : Initialise une instance d'instruction d'architecture.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_db_instruction_init(GDbInstruction *instr)
{
    GArchInstruction *parent;               /* Instance parente            */

    parent = G_ARCH_INSTRUCTION(instr);

    parent->get_text = (get_instruction_text_fc)g_db_instruction_get_text;
    parent->get_link = (get_instruction_link_fc)g_db_instruction_get_link;
    parent->is_return = (is_instruction_return_fc)g_db_instruction_is_return;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : data = flux de données à analyser.                           *
*                pos  = position courante dans ce flux. [OUT]                 *
*                len  = taille totale des données à analyser.                 *
*                addr = adresse, virtuelle ou physique, de l'instruction.     *
*                proc = architecture ciblée par le désassemblage.             *
*                                                                             *
*  Description : Crée une instruction de type 'db' à partir de données.       *
*                                                                             *
*  Retour      : Instruction mise en place.                                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GArchInstruction *g_db_instruction_new_from_data(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GArchProcessor *proc)
{
    GArchInstruction *result;               /* Instruction à retourner     */
    GArchOperand *operand;                  /* Octet non décodé à afficher */

    result = g_object_new(G_TYPE_DB_INSTRUCTION, NULL);

    operand = g_imm_operand_new_from_data(g_arch_processor_get_instruction_size(proc),
                                          data, pos, len,
                                          g_arch_processor_get_endianness(proc));
    if (operand == NULL) goto gdinfd_error;

    g_imm_operand_pad(G_IMM_OPERAND(operand), true);

    g_arch_instruction_attach_extra_operand(result, operand);

    return result;

 gdinfd_error:

    g_object_unref(G_OBJECT(result));

    return NULL;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = instruction à traiter.                              *
*                format = format du binaire manipulé.                         *
*                syntax = type de représentation demandée.                    *
*                                                                             *
*  Description : Traduit une instruction en version humainement lisible.      *
*                                                                             *
*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static const char *g_db_instruction_get_text(const GDbInstruction *instr, const GExeFormat *format, AsmSyntax syntax)
{
    return "db";

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à consulter.                             *
*                addr  = eventuelle adresse associée à faire connaître. [OUT] *
*                                                                             *
*  Description : Informe sur une éventuelle référence à une autre instruction.*
*                                                                             *
*  Retour      : Type de lien trouvé ou ILT_NONE si aucun.                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *instr, vmpa_t *addr)
{
    return ILT_NONE;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à consulter.                             *
*                                                                             *
*  Description : Indique si l'instruction correspond à un retour de fonction. *
*                                                                             *
*  Retour      : true si l'instruction est un 'return' quelconque ou false.   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static bool g_db_instruction_is_return(const GDbInstruction *instr)
{
    return false;

}


#ifdef DEBUG

/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à mettre à jour.                         *
*                                                                             *
*  Description : Marque une donnée comme ayant été considérée au sein du code.*
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_db_instruction_mark_as_skipped(GDbInstruction *instr)
{
    instr->skipped = true;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à consulter.                             *
*                                                                             *
*  Description : Indique si une donnée fait partie du code exécutable.        *
*                                                                             *
*  Retour      : true si la donnée est intégrée dans le code, false sinon.    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

bool g_db_instruction_is_skipped(const GDbInstruction *instr)
{
    return instr->skipped;

}

#endif