/* 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 "../panel/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); 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; }