/* Chrysalide - Outil d'analyse de fichiers binaires * symbol.c - gestion des symboles dans un binaire * * 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 "symbol.h" #include #include #include "symbol-int.h" #include "../glibext/linegen-int.h" /* --------------------- FONCTIONNALITES BASIQUES POUR SYMBOLES --------------------- */ /* Initialise la classe des symboles d'exécutables. */ static void g_binary_symbol_class_init(GBinSymbolClass *); /* Initialise une instance de symbole d'exécutable. */ static void g_binary_symbol_init(GBinSymbol *); /* Procède à l'initialisation de l'interface de génération. */ static void g_binary_symbol_interface_init(GLineGeneratorInterface *); /* Supprime toutes les références externes. */ static void g_binary_symbol_dispose(GBinSymbol *); /* Procède à la libération totale de la mémoire. */ static void g_binary_symbol_finalize(GBinSymbol *); /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ /* Indique le nombre de ligne prêtes à être générées. */ static size_t g_binary_symbol_count_lines(const GBinSymbol *); /* Retrouve l'emplacement correspondant à une position donnée. */ static void g_binary_symbol_compute_addr(const GBinSymbol *, gint, vmpa2t *, size_t, size_t); /* Détermine si le conteneur s'inscrit dans une plage donnée. */ static int g_binary_symbol_contains_addr(const GBinSymbol *, const vmpa2t *, size_t, size_t); /* Renseigne sur les propriétés liées à un générateur. */ static BufferLineFlags g_binary_symbol_get_flags(const GBinSymbol *, size_t, size_t); /* Imprime dans une ligne de rendu le contenu représenté. */ static void g_binary_symbol_print(GBinSymbol *, GBufferLine *, size_t, size_t, const GBinContent *); /* ---------------------------------------------------------------------------------- */ /* FONCTIONNALITES BASIQUES POUR SYMBOLES */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour un symbole d'exécutable. */ G_DEFINE_TYPE_WITH_CODE(GBinSymbol, g_binary_symbol, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_symbol_interface_init)); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des symboles d'exécutables. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_class_init(GBinSymbolClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_symbol_dispose; object->finalize = (GObjectFinalizeFunc)g_binary_symbol_finalize; } /****************************************************************************** * * * Paramètres : symbol = instance à initialiser. * * * * Description : Initialise une instance de symbole d'exécutable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_init(GBinSymbol *symbol) { } /****************************************************************************** * * * Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de génération. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_interface_init(GLineGeneratorInterface *iface) { iface->count = (linegen_count_lines_fc)g_binary_symbol_count_lines; iface->compute = (linegen_compute_fc)g_binary_symbol_compute_addr; iface->contains = (linegen_contains_fc)g_binary_symbol_contains_addr; iface->get_flags = (linegen_get_flags_fc)g_binary_symbol_get_flags; iface->print = (linegen_print_fc)g_binary_symbol_print; } /****************************************************************************** * * * Paramètres : symbol = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_dispose(GBinSymbol *symbol) { /* TODO... */ G_OBJECT_CLASS(g_binary_symbol_parent_class)->dispose(G_OBJECT(symbol)); } /****************************************************************************** * * * Paramètres : symbol = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_finalize(GBinSymbol *symbol) { free(symbol->alt); G_OBJECT_CLASS(g_binary_symbol_parent_class)->finalize(G_OBJECT(symbol)); } /****************************************************************************** * * * Paramètres : type = type de symbole à créer. * * * * Description : Crée un nouveau symbole d'exécutable. * * * * Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GBinSymbol *g_binary_symbol_new(SymbolType type) { GBinSymbol *result; /* Nouveau symbole à renvoyer */ result = g_object_new(G_TYPE_BIN_SYMBOL, NULL); result->type = type; return result; } /****************************************************************************** * * * Paramètres : a = premier symbole à analyser. * * b = second symbole à analyser. * * * * Description : Compare deux symboles d'exécutable selon leurs propriétés. * * * * Retour : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut). * * * * Remarques : - * * * ******************************************************************************/ int g_binary_symbol_cmp(const GBinSymbol * const *a, const GBinSymbol * const *b) { int result; /* Bilan à retourner */ const mrange_t *ra; /* Emplacement du symbole A */ const mrange_t *rb; /* Emplacement du symbole B */ ra = g_binary_symbol_get_range(*a); rb = g_binary_symbol_get_range(*b); if (ra == NULL && rb == NULL) result = 0; else if (ra != NULL && rb == NULL) result = 1; else if (ra == NULL && rb != NULL) result = -1; else result = cmp_mrange(ra, rb); return result; } /****************************************************************************** * * * Paramètres : symbol = symbole à analyser. * * addr = localisation à venir comparer à celle du symbole. * * * * Description : Compare un symbole et une localisation. * * * * Retour : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut). * * * * Remarques : - * * * ******************************************************************************/ int g_binary_symbol_cmp_with_vmpa(const GBinSymbol *symbol, const vmpa2t *addr) { int result; /* Bilan à retourner */ const mrange_t *range; /* Emplacement du symbole */ range = g_binary_symbol_get_range(symbol); if (range == NULL) result = 1; else result = cmp_mrange_with_vmpa(range, addr); return result; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit le type du symbole. * * * * Retour : Type de symbole représenté. * * * * Remarques : - * * * ******************************************************************************/ SymbolType g_binary_symbol_get_target_type(const GBinSymbol *symbol) { return symbol->type; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit un étiquette pour viser un symbole. * * * * Retour : Chaîne de caractères renvoyant au symbole. * * * * Remarques : - * * * ******************************************************************************/ const char *g_binary_symbol_get_label(const GBinSymbol *symbol) { const char *result; /* Etiquette à retourner */ if (symbol->alt != NULL) return symbol->alt; result = NULL; switch (symbol->type) { case STP_ROUTINE: case STP_ENTRY_POINT: case STP_CODE_LABEL: result = g_binary_routine_get_declarator(symbol->extra.routine, false); break; default: result = NULL; break; } return result; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * alt = désignation humaine alternative à favoriser. * * * * Description : Définit un autre nom pour le symbole. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_symbol_set_alt_label(GBinSymbol *symbol, const char *alt) { if (symbol->alt != NULL) free(symbol->alt); if (alt == NULL) symbol->alt = NULL; else symbol->alt = strdup(alt); } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit l'emplacement où se situe un symbole. * * * * Retour : Zone mémoire couverte par le symbole. * * * * Remarques : - * * * ******************************************************************************/ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *symbol) { const mrange_t *result; /* Plage à retourner */ result = NULL; switch (symbol->type) { case STP_DATA: case STP_RO_STRING: result = g_arch_instruction_get_range(symbol->extra.instr); break; case STP_ROUTINE: case STP_ENTRY_POINT: case STP_CODE_LABEL: result = g_binary_routine_get_range(symbol->extra.routine); break; default: /* FIXME : assert(0); */ result = NULL; break; } return result; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * routine = prototype de la fonction représentée. * * type = (nouveau) type du symbole attaché. * * * * Description : Attache la routine associée au symbole. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void _g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine, SymbolType type) { if (symbol->extra.routine != NULL) g_object_unref(G_OBJECT(symbol->extra.routine)); symbol->type = type; symbol->extra.routine = routine; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * routine = prototype de la fonction représentée. * * * * Description : Attache la routine associée au symbole. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine) { _g_binary_symbol_attach_routine(symbol, routine, symbol->type); } /****************************************************************************** * * * Paramètres : symbol = symbole à venir manipuler. * * instr = représentation du symbole associé. * * * * Description : Attache l'instruction associée au symbole. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_symbol_attach_instruction(GBinSymbol *symbol, GArchInstruction *instr) { if (symbol->type != STP_RO_STRING) symbol->type = STP_DATA; symbol->extra.instr = instr; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit l'éventuelle routine associée au symbole. * * * * Retour : Instance GLib en place ou NULL si aucune. * * * * Remarques : Il n'y a pas de transfert de propriété ici ! * * * ******************************************************************************/ GBinRoutine *g_binary_symbol_get_routine(const GBinSymbol *symbol) { /* TODO : rajouter des assert() sur le type de symbole */ /* TODO : ref() */ return symbol->extra.routine; } /****************************************************************************** * * * Paramètres : symbol = symbole à venir consulter. * * * * Description : Fournit l'éventuelle instruction associée au symbole. * * * * Retour : Instance GLib en place ou NULL si aucune. * * * * Remarques : Il n'y a pas de transfert de propriété ici ! * * * ******************************************************************************/ GArchInstruction *g_binary_symbol_get_instruction(const GBinSymbol *symbol) { /* TODO : rajouter des assert() sur le type de symbole */ /* TODO : ref() */ return symbol->extra.instr; } /* ---------------------------------------------------------------------------------- */ /* OFFRE DE CAPACITES DE GENERATION */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : symbol = générateur à consulter pour futur usage. * * * * Description : Détermine si un symbole pour faire office de générateur. * * * * Retour : Instance de générateur si les capacités sont là. * * * * Remarques : - * * * ******************************************************************************/ GLineGenerator *g_binary_symbol_produce_label(GBinSymbol *symbol) { GLineGenerator *result; /* Instance à retourner */ const char *label; /* Etiquette à insérer */ label = g_binary_symbol_get_label(symbol); result = (label != NULL ? G_LINE_GENERATOR(symbol) : NULL); return result; } /****************************************************************************** * * * Paramètres : symbol = générateur à consulter. * * * * Description : Indique le nombre de ligne prêtes à être générées. * * * * Retour : Nombre de lignes devant apparaître au final. * * * * Remarques : - * * * ******************************************************************************/ static size_t g_binary_symbol_count_lines(const GBinSymbol *symbol) { return 1; } /****************************************************************************** * * * Paramètres : symbol = générateur à consulter. * * x = position géographique sur la ligne concernée. * * addr = position en mémoire à analyser. * * index = indice de cette même ligne dans le tampon global. * * repeat = indice d'utilisations successives du générateur. * * * * Description : Retrouve l'emplacement correspondant à une position donnée. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_symbol_compute_addr(const GBinSymbol *symbol, gint x, vmpa2t *addr, size_t index, size_t repeat) { const mrange_t *range; /* Emplacement à manipuler */ range = g_binary_symbol_get_range(symbol); copy_vmpa(addr, get_mrange_addr(range)); } /****************************************************************************** * * * Paramètres : symbol = générateur à consulter. * * addr = position en mémoire à analyser. * * index = indice de cette même ligne dans le tampon global. * * repeat = indice d'utilisations successives du générateur. * * * * Description : Détermine si le conteneur s'inscrit dans une plage donnée. * * * * Retour : Bilan de la détermination, utilisable en comparaisons. * * * * Remarques : - * * * ******************************************************************************/ static int g_binary_symbol_contains_addr(const GBinSymbol *symbol, const vmpa2t *addr, size_t index, size_t repeat) { int result; /* Conclusion à retourner */ const mrange_t *range; /* Emplacement à manipuler */ range = g_binary_symbol_get_range(symbol); result = cmp_mrange_with_vmpa(range, addr); return result; } /****************************************************************************** * * * Paramètres : symbol = générateur à consulter. * * index = indice de cette même ligne dans le tampon global. * * repeat = indice d'utilisations successives du générateur. * * * * Description : Renseigne sur les propriétés liées à un générateur. * * * * Retour : Propriétés particulières associées. * * * * Remarques : - * * * ******************************************************************************/ static BufferLineFlags g_binary_symbol_get_flags(const GBinSymbol *symbol, size_t index, size_t repeat) { return BLF_IS_LABEL; } /****************************************************************************** * * * Paramètres : symbol = générateur à utiliser pour l'impression. * * line = ligne de rendu à compléter. * * index = indice de cette même ligne dans le tampon global. * * repeat = indice d'utilisations successives du générateur. * * content = éventuel contenu binaire brut à imprimer. * * * * Description : Imprime dans une ligne de rendu le contenu représenté. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_symbol_print(GBinSymbol *symbol, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) { const mrange_t *range; /* Emplacement à manipuler */ const char *label; /* Etiquette à insérer */ range = g_binary_symbol_get_range(symbol); g_buffer_line_fill_vmpa(line, get_mrange_addr(range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED); label = g_binary_symbol_get_label(symbol); g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, SL(label), RTT_LABEL, NULL); g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT, NULL); }