/* Chrysalide - Outil d'analyse de fichiers binaires
* gbincontent.c - prototypes pour le chargement de données binaires en mémoire
*
* Copyright (C) 2015 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* 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 "gbincontent.h"
#include
#include
#include
#include
#include
#include
#include
/* Aire de contenu binaire */
typedef struct _binary_part
{
bin_t *data; /* Contenu binaire représenté */
mrange_t range; /* Couverture du binaire */
} binary_part;
/* Content de données binaires quelconques (instance) */
struct _GBinContent
{
GObject parent; /* A laisser en premier */
binary_part *parts; /* Parties prises en compte */
size_t count; /* Nombre de ces parties */
};
/* Content de données binaires quelconques (classe) */
struct _GBinContentClass
{
GObjectClass parent; /* A laisser en premier */
};
/* Initialise la classe des contenus de données binaires. */
static void g_binary_content_class_init(GBinContentClass *);
/* Initialise une instance de contenu de données binaires. */
static void g_binary_content_init(GBinContent *);
/* Supprime toutes les références externes. */
static void g_binary_content_dispose(GBinContent *);
/* Procède à la libération totale de la mémoire. */
static void g_binary_content_finalize(GBinContent *);
/* Indique le type défini par la GLib pour les contenus de données. */
G_DEFINE_TYPE(GBinContent, g_binary_content, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des contenus de données binaires. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_content_class_init(GBinContentClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_content_dispose;
object->finalize = (GObjectFinalizeFunc)g_binary_content_finalize;
}
/******************************************************************************
* *
* Paramètres : content = instance à initialiser. *
* *
* Description : Initialise une instance de contenu de données binaires. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_content_init(GBinContent *content)
{
}
/******************************************************************************
* *
* Paramètres : content = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_content_dispose(GBinContent *content)
{
G_OBJECT_CLASS(g_binary_content_parent_class)->dispose(G_OBJECT(content));
}
/******************************************************************************
* *
* Paramètres : content = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_content_finalize(GBinContent *content)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < content->count; i++)
free(content->parts[i].data);
if (content->parts != NULL)
free(content->parts);
G_OBJECT_CLASS(g_binary_content_parent_class)->finalize(G_OBJECT(content));
}
/******************************************************************************
* *
* Paramètres : filename = chemin d'accès au fichier à charger. *
* *
* Description : Charge en mémoire le contenu d'un fichier donné. *
* *
* Retour : Représentation de contenu à manipuler ou NULL en cas d'échec.*
* *
* Remarques : - *
* *
******************************************************************************/
GBinContent *g_binary_content_new_from_file(const char *filename)
{
GBinContent *result; /* Structure à retourner */
int fd; /* Descripteur du fichier */
struct stat info; /* Informations sur le fichier */
int ret; /* Bilan d'un appel */
void *content; /* Contenu brut du fichier */
vmpa2t base; /* Localisation des données */
/* Récupération des données */
fd = open(filename, O_RDONLY);
if (fd == -1)
{
perror("open");
goto gbcnff_error;
}
ret = fstat(fd, &info);
if (ret == -1)
{
close(fd);
perror("fstat");
goto gbcnff_error;
}
content = mmap(NULL, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (content == MAP_FAILED)
{
close(fd);
perror("mmap");
goto gbcnff_error;
}
/* Constitution du contenu officiel */
result = g_object_new(G_TYPE_BIN_CONTENT, NULL);
result->parts = (binary_part *)calloc(1, sizeof(binary_part));
result->count = 1;
result->parts[0].data = (bin_t *)malloc(info.st_size);
memcpy(result->parts[0].data, content, info.st_size);
munmap(content, info.st_size);
close(fd);
init_vmpa(&base, 0, VMPA_NO_VIRTUAL);
init_mrange(&result->parts[0].range, &base, info.st_size);
return result;
gbcnff_error:
return NULL;
}
/******************************************************************************
* *
* Paramètres : content = contenu binaire à venir lire. *
* addr = position de la tête de lecture. *
* length = quantité d'octets à lire. *
* out = réceptacle disponible pour ces données. [OUT] *
* *
* Description : Fournit une portion des données représentées. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_binary_content_get_raw(const GBinContent *content, const vmpa2t *addr, phys_t length, bin_t *out)
{
/* FIXME */
memcpy(out, &content->parts[0].data[get_phy_addr(addr)], length);
return true;
}
const bin_t *g_binary_content_get(GBinContent *content, off_t *length)
{
*length = content->parts[0].range.length;
return content->parts[0].data;
}