/* OpenIDA - Outil d'analyse de fichiers binaires
* format.c - support des différents formats binaires
*
* 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 .
*/
#include "format.h"
#include
#include "format-int.h"
#include "dwarf/dwarf.h"
#include "elf/elf.h"
#include "pe/pe.h"
#include "../panels/log.h"
#ifndef _
# define _(str) str
#endif
/* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */
/* Initialise la classe des formats binaires génériques. */
static void g_binary_format_class_init(GBinFormatClass *);
/* Initialise une instance de format binaire générique. */
static void g_binary_format_init(GBinFormat *);
/* ----------------------- MANIPULATION D'ENSEMBLE DE FORMATS ----------------------- */
/* Format d'exécutables enregistré */
typedef struct _registered_format
{
const char *name; /* Désignation du format */
FormatType type; /* Type de format */
format_match_fc match; /* Procédure de reconnaissance */
format_load_fc load; /* Fonction de chargement */
} registered_format;
/* Liste des formats d'exécutables enregistrés */
static registered_format _formats[FID_COUNT];
#define register_format(id, n, t, m, l) \
do \
{ \
_formats[id].name = n; \
_formats[id].type = t; \
_formats[id].match = m; \
_formats[id].load = l; \
} \
while (0)
/* ---------------------------------------------------------------------------------- */
/* TRAITEMENT INDIVIDUEL DE FORMATS */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un format binaire générique. */
G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des formats binaires génériques. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_format_class_init(GBinFormatClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : format = instance à initialiser. *
* *
* Description : Initialise une instance de format binaire générique. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_binary_format_init(GBinFormat *format)
{
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* content = contenu binaire à parcourir. *
* length = taille du contenu fourni. *
* *
* Description : Définit le contenu binaire à analyser. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_binary_format_set_content(GBinFormat *format, bin_t *content, off_t length)
{
format->content = content;
format->length = length;
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* length = taille du contenu à fournir. [OUT] *
* *
* Description : Fournit une référence vers le contenu binaire analysé. *
* *
* Retour : Adresse du tampon contenant le contenu du binaire. *
* *
* Remarques : - *
* *
******************************************************************************/
const bin_t *g_binary_format_get_content(const GBinFormat *format, off_t *length)
{
if (length != NULL) *length = format->length;
return format->content;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à compléter. *
* symbol = symbole à ajouter à la liste. *
* *
* Description : Ajoute un symbole à la collection du format binaire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
{
format->symbols = (GBinSymbol **)realloc(format->symbols,
++format->symbols_count * sizeof(GBinSymbol *));
format->symbols[format->symbols_count - 1] = symbol;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* count = taille du tableau créé. [OUT] *
* *
* Description : Fournit la liste de tous les symboles détectés. *
* *
* Retour : Tableau créé ou NULL si aucun symbole trouvé. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count)
{
*count = format->symbols_count;
return format->symbols;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à compléter. *
* routine = routine à ajouter à la liste. *
* *
* Description : Ajoute une routine à la collection du format binaire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_binary_format_add_routine(GBinFormat *format, GBinRoutine *routine)
{
format->routines = (GBinRoutine **)realloc(format->routines,
++format->routines_count * sizeof(GBinRoutine *));
format->routines[format->routines_count - 1] = routine;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* count = taille du tableau créé. [OUT] *
* *
* Description : Fournit le prototype de toutes les routines détectées. *
* *
* Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinRoutine **g_binary_format_get_routines(const GBinFormat *format, size_t *count)
{
*count = format->routines_count;
return format->routines;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* label = étiquette du symbole si trouvé. [OUT] *
* type = type du symbole trouvé. [OUT] *
* address = adresse à cibler, puis décallage final. [OUT] *
* *
* Description : Recherche le symbole correspondant à une adresse. *
* *
* Retour : true si l'opération a été un succès, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_binary_format_resolve_symbol(const GBinFormat *format, const char **label, SymbolType *type, vmpa_t *address)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
vmpa_t addr; /* Adresse de symbole */
off_t size; /* Taille du symole */
result = false;
for (i = 0; i < format->symbols_count && !result; i++)
{
addr = g_binary_symbol_get_address(format->symbols[i]);
size = g_binary_symbol_get_size(format->symbols[i]);
if (addr <= *address && *address < (addr + size))
{
*label = g_binary_symbol_to_string(format->symbols[i]);
*type = g_binary_symbol_get_target_type(format->symbols[i]);
*address -= addr;
if (*type == STP_STRING)
*label += *address;
result = true;
}
}
return result;
}
/* ---------------------------------------------------------------------------------- */
/* MANIPULATION D'ENSEMBLE DE FORMATS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Procède au chargement des formats binaires reconnus. *
* *
* Retour : true pour indiquer un chargement réussi, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool init_all_formats(void)
{
register_format(FID_ELF, _("ELF"), FMT_EXEC, elf_is_matching, g_elf_format_new);
register_format(FID_DWARF, _("Dwarf"), FMT_DEBUG, dwarf_is_matching, g_dwarf_format_new);
register_format(FID_PE, _("PE"), FMT_EXEC, pe_is_matching, g_pe_format_new);
return true;
}
/******************************************************************************
* *
* Paramètres : type = type de format recherché. *
* content = contenu binaire à parcourir. *
* length = taille du contenu en question. *
* *
* Description : Charge si possible un nouveau format binaire. *
* *
* Retour : Adresse du nouveau gestionnaire de format ou NULL si erreur. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinFormat *load_new_format(FormatType type, const uint8_t *content, off_t length)
{
GBinFormat *result; /* Adresse à retourner */
size_t i; /* Boucle de parcours */
result = NULL;
for (i = 0; i < FID_COUNT && result == NULL; i++)
if (_formats[i].type == type && _formats[i].match(type, content, length))
{
log_variadic_message(LMT_INFO, _("%s is matching..."), _formats[i].name);
result = _formats[i].load(content, length);
}
return result;
}