/* OpenIDA - Outil d'analyse de fichiers binaires
 * part.h - manipulation des parties de code
 *
 * 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 "part.h"


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



/* Bloc de données binaires quelconques (instance) */
struct _GBinPart
{
    GObject parent;                         /* A laisser en premier        */

    char *name;                             /* Désignation humaine         */

    off_t offset;                           /* Position physique           */
    off_t size;                             /* Taille de la partie         */
    vmpa_t addr;                            /* Adresse associée            */

#ifdef DEBUG
    unsigned int valid;                     /* Instructions reconnues      */
    unsigned int db;                        /* Instructions non traduites  */
#endif

};

/* Bloc de données binaires quelconques (classe) */
struct _GBinPartClass
{
    GObjectClass parent;                    /* A laisser en premier        */

};


/* Initialise la classe des blocs de données binaires. */
static void g_binary_part_class_init(GBinPartClass *);

/* Initialise une instance de bloc de données binaires. */
static void g_binary_part_init(GBinPart *);



/* Indique le type défini par la GLib pour les blocs de doonées. */
G_DEFINE_TYPE(GBinPart, g_binary_part, G_TYPE_OBJECT);


/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe des blocs de données binaires.          *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_binary_part_class_init(GBinPartClass *klass)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : line = instance à initialiser.                               *
*                                                                             *
*  Description : Initialise une instance de bloc de données binaires.         *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_binary_part_init(GBinPart *line)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Crée une description de partie de code vierge.               *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBinPart *g_binary_part_new(void)
{
    GBinPart *result;                   /* Structure à retourner       */

    result = g_object_new(G_TYPE_BIN_PART, NULL);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : src = partie de code à copier.                               *
*                                                                             *
*  Description : Crée une description de partie de code à partir d'une autre. *
*                                                                             *
*  Retour      : Partie de code copiée.                                       *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBinPart *g_binary_part_dump(const GBinPart *src)
{
    GBinPart *result;                   /* Structure à retourner       */

    result = g_object_new(G_TYPE_BIN_PART, NULL);

    result->name = (src->name != NULL ? strdup(src->name) : NULL);

    result->offset = result->offset;
    result->size = result->size;
    result->addr = result->addr;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : node = noeud XML contenant les données à charger.            *
*                                                                             *
*  Description : Crée une description de partie de code vierge à partir d'XML.*
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBinPart *g_binary_part_load_from_xml(xmlNodePtr node)
{
    GBinPart *result;                   /* Structure à retourner       */
    char *value;                        /* Propriété lue depuis le XML */

    result = g_binary_part_new();

    result->name = qck_get_node_prop_value(node, "name");
    if (result->name == NULL) goto gbplfx_error;

    value = qck_get_node_prop_value(node, "offset");
    if (value == NULL) goto gbplfx_error;

    result->offset = atoi(value);
    free(value);

    value = qck_get_node_prop_value(node, "size");
    if (value == NULL) goto gbplfx_error;

    result->size = atoi(value);
    free(value);

    return result;

 gbplfx_error:

    g_object_unref(G_OBJECT(result));

    return NULL;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part   = description de partie à sauvegarder.                *
*                xdoc   = structure XML chargée.                              *
*                parent = noeud XML où rattacher le futur nouveau noeud.      *
*                                                                             *
*  Description : Enregistre les informations d'une partie de code dans du XML.*
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

bool g_binary_part_save_to_xml(const GBinPart *part, xmlDocPtr xdoc, xmlNodePtr parent)
{
    bool result;                            /* Bilan à retourner           */
    xmlNodePtr node;                        /* Nouveau noeud créé          */

    result = true;

    node = add_node_to_node(xdoc, parent, "Part");
    if (node == NULL) return false;

    result = _add_string_attribute_to_node(node, "name", part->name);
    result &= add_long_attribute_to_node(node, "offset", part->offset);
    result &= add_long_attribute_to_node(node, "size", part->size);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part = description de partie à mettre à jour.                *
*                name = nom à donner à la partie.                             *
*                                                                             *
*  Description : Attribue une description humaine à une partie de code.       *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_set_name(GBinPart *part, const char *name)
{
    if (part->name != NULL) free(part->name);

    part->name = strdup(name);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part = description de partie à mettre à jour.                *
*                                                                             *
*  Description : Fournit la description attribuée à une partie de code.       *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

const char *g_binary_part_get_name(const GBinPart *part)
{
    return part->name;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part   = description de partie à mettre à jour.              *
*                offset = position de la section à conserver.                 *
*                size   = taille de la section à conserver.                   *
*                addr   = adresse de la section à conserver.                  *
*                                                                             *
*  Description : Définit les valeurs utiles d'une partie de code.             *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_set_values(GBinPart *part, off_t offset, off_t size, vmpa_t addr)
{
    part->offset = offset;
    part->size = size;
    part->addr = addr;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part = description de partie à mettre à jour.                *
*                addr = adresse de la section à conserver.                    *
*                                                                             *
*  Description : Définit l'adresse virtuelle d'une partie de code.            *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_set_address(GBinPart *part, vmpa_t addr)
{
    part->addr = addr;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part   = description de partie à consulter.                  *
*                offset = position de la section à donner ou NULL. [OUT]      *
*                size   = taille de la section à donner ou NULL. [OUT]        *
*                addr   = adresse de la section à donner ou NULL. [OUT]       *
*                                                                             *
*  Description : Fournit les valeurs utiles d'une partie de code.             *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_get_values(const GBinPart *part, off_t *offset, off_t *size, vmpa_t *addr)
{
    if (offset != NULL) *offset = part->offset;
    if (size != NULL) *size = part->size;
    if (addr != NULL) *addr = part->addr;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : a = premières informations à consulter.                      *
*                b = secondes informations à consulter.                       *
*                                                                             *
*  Description : Etablit la comparaison entre deux blocs binaires.            *
*                                                                             *
*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

int g_binary_part_compare(const GBinPart **a, const GBinPart **b)
{
    int result;                             /* Bilan à renvoyer            */

    if ((*a)->offset < (*b)->offset) result = -1;
    else if((*a)->offset > (*b)->offset) result = 1;
    else result = 0;

    return result;

}

#ifdef DEBUG

/******************************************************************************
*                                                                             *
*  Paramètres  : part  = description de partie à mettre à jour.               *
*                valid = quantité d'instructions décodées pour cette partie.  *
*                db    = quantité d'instructions non traduites ici.           *
*                                                                             *
*  Description : Mémorise un bilan de désassemblage.                          *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_set_checkup(GBinPart *part, unsigned int valid, unsigned int db)
{
    part->valid = valid;
    part->db = db;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : part  = description de partie à mettre à jour.               *
*                valid = quantité d'instructions décodées ici. [OUT]          *
*                db    = quantité d'instructions non traduites ici. [OUT]     *
*                                                                             *
*  Description : Mémorise un bilan de désassemblage.                          *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_part_get_checkup(const GBinPart *part, unsigned int *valid, unsigned int *db)
{
    *valid = part->valid;
    *db = part->db;

}

#endif