/* Chrysalide - Outil d'analyse de fichiers binaires
* executable.c - support des formats d'exécutables
*
* Copyright (C) 2009-2013 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 "executable.h"
#include "executable-int.h"
#include "format.h"
#include
/* Initialise la classe des formats d'exécutables génériques. */
static void g_executable_format_class_init(GExeFormatClass *);
/* Initialise une instance de format d'exécutable générique. */
static void g_executable_format_init(GExeFormat *);
/* Indique le type défini pour un format d'exécutable générique. */
G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des formats d'exécutables génériques. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_executable_format_class_init(GExeFormatClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : format = instance à initialiser. *
* *
* Description : Initialise une instance de format d'exécutable générique. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_executable_format_init(GExeFormat *format)
{
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* *
* Description : Indique le type d'architecture visée par le format. *
* *
* Retour : Identifiant de l'architecture ciblée par le format. *
* *
* Remarques : - *
* *
******************************************************************************/
FormatTargetMachine g_exe_format_get_target_machine(const GExeFormat *format)
{
return format->get_machine(format);
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* *
* Description : Fournit l'adresse mémoire du point d'entrée du programme. *
* *
* Retour : Adresse de mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
vmpa_t g_exe_format_get_entry_point(const GExeFormat *format)
{
return format->get_entry_point(format);
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* *
* Description : Décrit les différentes portions qui composent le binaire. *
* *
* Retour : Défintions de zones. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinPortion *g_exe_format_get_portions(GExeFormat *format)
{
vmpa2t addr; /* Emplacement vide de sens */
if (format->portions == NULL)
{
format->portions = g_binary_portion_new(BPC_RAW);
init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
g_binary_portion_set_values(format->portions, &addr, G_BIN_FORMAT(format)->length);
if (format->refine_portions != NULL)
format->refine_portions(format, format->portions);
}
return format->portions;
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* level = étage des portions à considérer ou -1 pour tous. *
* count = nombre de portions trouvées et renvoyées. [OUT] *
* *
* Description : Fournit une liste choisie de portions d'un binaire. *
* *
* Retour : Liste de définitins de zones à libérer après usage. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinPortion **g_exe_format_get_portions_at_level(GExeFormat *format, unsigned int level, size_t *count)
{
GBinPortion **result; /* Liste à retourner */
typedef struct _portions_list
{
unsigned int required;
GBinPortion **portions;
size_t length;
} portions_list;
portions_list list; /* Sauvegarde de la liste */
bool visit_for_level(GBinPortion *portion, portions_list *list)
{
if (list->required == -1 || g_binary_portion_get_level(portion) == list->required)
{
list->portions = (GBinPortion **)realloc(list->portions, ++list->length * sizeof(GBinPortion *));
list->portions[list->length - 1] = portion;
}
return true;
}
list.required = level;
list.portions = NULL;
list.length = 0;
g_binary_portion_visit(g_exe_format_get_portions(format), (visit_portion_fc)visit_for_level, &list);
result = list.portions;
*count = list.length;
qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare);
return result;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* count = quantité de zones listées. [OUT] *
* *
* Description : Fournit les espaces mémoires des portions exécutables. *
* *
* Retour : Liste de zones binaires exécutables à libérer après usage. *
* *
* Remarques : - *
* *
******************************************************************************/
mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count)
{
mrange_t *result; /* Liste à retourner */
typedef struct _x_ranges
{
mrange_t *list;
size_t length;
} x_ranges;
x_ranges tmp; /* Sauvegarde de la liste */
bool visit_for_x(GBinPortion *portion, x_ranges *ranges)
{
const mrange_t *range;
if (g_binary_portion_get_rights(portion) & PAC_EXEC)
{
range = g_binary_portion_get_range(portion);
ranges->list = (mrange_t *)realloc(ranges->list, ++ranges->length * sizeof(mrange_t));
copy_mrange(&ranges->list[ranges->length - 1], range);
}
return true;
}
tmp.list = NULL;
tmp.length = 0;
g_binary_portion_visit(g_exe_format_get_portions(format), (visit_portion_fc)visit_for_x, &tmp);
result = tmp.list;
*count = tmp.length;
return result;
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* count = quantité de zones listées. [OUT] *
* *
* Description : Fournit les références aux zones binaires à analyser. *
* *
* Retour : Zones binaires à analyser. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinPart **g_exe_format_get_parts(const GExeFormat *format, size_t *count)
{
return format->get_parts(format, count);
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* addr = adresse virtuelle à retrouver. *
* pos = position correspondante. [OUT] *
* *
* Description : Fournit la position correspondant à une adresse virtuelle. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_exe_format_translate_address_into_offset(const GExeFormat *format, vmpa_t addr, off_t *pos)
{
return format->translate_addr(format, addr, pos);
}
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* pos = position dans le flux binaire à retrouver. *
* addr = adresse virtuelle correspondante. [OUT] *
* *
* Description : Fournit l'adresse virtuelle correspondant à une position. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_exe_format_translate_offset_into_address(const GExeFormat *format, off_t pos, vmpa_t *addr)
{
return format->translate_off(format, pos, addr);
}