/* Chrysalide - Outil d'analyse de fichiers binaires * executable.c - support des formats d'exécutables * * Copyright (C) 2009-2017 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide 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. * * Chrysalide 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 #include #include #include "executable-int.h" #include "format.h" /* 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 *); /* Supprime toutes les références externes. */ static void g_executable_format_dispose(GExeFormat *); /* Procède à la libération totale de la mémoire. */ static void g_executable_format_finalize(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) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_executable_format_dispose; object->finalize = (GObjectFinalizeFunc)g_executable_format_finalize; } /****************************************************************************** * * * 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) { g_mutex_init(&format->mutex); } /****************************************************************************** * * * Paramètres : format = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_executable_format_dispose(GExeFormat *format) { size_t i; /* Boucle de parcours */ for (i = 0; i < format->debugs_count; i++) g_object_unref(G_OBJECT(format->debugs[i])); if (format->portions != NULL) g_object_unref(G_OBJECT(format->portions)); g_mutex_clear(&format->mutex); G_OBJECT_CLASS(g_executable_format_parent_class)->dispose(G_OBJECT(format)); } /****************************************************************************** * * * Paramètres : format = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_executable_format_finalize(GExeFormat *format) { G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format)); } /****************************************************************************** * * * Paramètres : format = informations chargées à compléter. * * info = informations de débogage à lier. * * * * Description : Rajoute des informations de débogage à un exécutable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_exe_format_add_debug_info(GExeFormat *format, GDbgFormat *info) { /* Ajout dans la liste */ format->debugs = (GDbgFormat **)realloc(format->debugs, ++format->debugs_count * sizeof(GDbgFormat *)); format->debugs[format->debugs_count - 1] = info; /* Intégration des symboles */ /* TODO */ } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * * * Description : Compte le nombre de formats de débogage liés à l'exécutable. * * * * Retour : Nombre de formats de débogage attachés. * * * * Remarques : - * * * ******************************************************************************/ size_t g_exe_format_count_debug_info(const GExeFormat *format) { return format->debugs_count; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * index = indice des informations à transmettre. * * * * Description : Fournit un format de débogage attaché à l'exécutable. * * * * Retour : Informations de débogage attachées. * * * * Remarques : - * * * ******************************************************************************/ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) { GDbgFormat *result; /* Format à retourner */ if (index >= format->debugs_count) result = NULL; else { result = format->debugs[index]; g_object_ref(G_OBJECT(result)); } return result; } /****************************************************************************** * * * 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 : - * * * ******************************************************************************/ const char *g_exe_format_get_target_machine(const GExeFormat *format) { return G_EXE_FORMAT_GET_CLASS(format)->get_machine(format); } /****************************************************************************** * * * Paramètres : format = instance à traiter. * * status = barre de statut à tenir informée. * * * * Description : Effectue les ultimes opérations de chargement d'un binaire. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *status) { bool result; /* Bilan à faire remonter */ GBinFormat *base; /* Version basique du format */ vmpa2t addr; /* Emplacement vide de sens */ phys_t length; /* Taille de portion globale */ base = G_BIN_FORMAT(format); result = g_binary_format_complete_loading(base, status); if (result) { result = g_exe_format_translate_offset_into_vmpa(format, 0, &addr); assert(result); length = g_binary_content_compute_size(base->content); format->portions = g_binary_portion_new(BPC_RAW, &addr, length); G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format); } return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à modifier. * * portion = portion à inclure dans les définitions du format. * * * * Description : Procède à l'enregistrement d'une portion dans un format. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion) { g_mutex_lock(&format->mutex); g_binary_portion_include(format->portions, portion); g_mutex_unlock(&format->mutex); } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * * * Description : Fournit la première couche des portions composent le binaire.* * * * Retour : Arborescence des différentes portions binaires. * * * * Remarques : Le compteur de références de l'instance renvoyée doit être * * décrémenté après usage. * * * ******************************************************************************/ GBinPortion *g_exe_format_get_portions(GExeFormat *format) { GBinPortion *result; /* Instance à retourner */ g_mutex_lock(&format->mutex); result = format->portions; if (result != NULL) g_object_ref(G_OBJECT(result)); g_mutex_unlock(&format->mutex); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * off = position physique à retrouver. * * pos = position correspondante. [OUT] * * * * Description : Fournit l'emplacement correspondant à une position physique. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_exe_format_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos) { bool result; /* Bilan à retourner */ result = G_EXE_FORMAT_GET_CLASS(format)->translate_phys(format, off, pos); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * addr = adresse virtuelle à retrouver. * * pos = position correspondante. [OUT] * * * * Description : Fournit l'emplacement correspondant à une adresse virtuelle. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_exe_format_translate_address_into_vmpa(const GExeFormat *format, virt_t addr, vmpa2t *pos) { bool result; /* Bilan à retourner */ result = G_EXE_FORMAT_GET_CLASS(format)->translate_virt(format, addr, pos); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * name = nom de la section recherchée. * * range = emplacement en mémoire à renseigner. [OUT] * * * * Description : Fournit l'emplacement d'une section donnée. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_exe_format_get_section_range_by_name(const GExeFormat *format, const char *name, mrange_t *range) { bool result; /* Bilan à retourner */ result = G_EXE_FORMAT_GET_CLASS(format)->get_range_by_name(format, name, range); return result; }