/* Chrysalide - Outil d'analyse de fichiers binaires * preload.c - préchargement d'instructions à partir d'un format * * Copyright (C) 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 "preload.h" #include "preload-int.h" /* Initialise la classe des préchargements à partir d'un format. */ static void g_preload_info_class_init(GPreloadInfoClass *); /* Initialise une instance de préchargement à partir de format. */ static void g_preload_info_init(GPreloadInfo *); /* Supprime toutes les références externes. */ static void g_preload_info_dispose(GPreloadInfo *); /* Procède à la libération totale de la mémoire. */ static void g_preload_info_finalize(GPreloadInfo *); /* Indique le type défini pour un préchargement à partir d'un format. */ G_DEFINE_TYPE(GPreloadInfo, g_preload_info, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des préchargements à partir d'un format.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_preload_info_class_init(GPreloadInfoClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_preload_info_dispose; object->finalize = (GObjectFinalizeFunc)g_preload_info_finalize; } /****************************************************************************** * * * Paramètres : info = instance à initialiser. * * * * Description : Initialise une instance de préchargement à partir de format. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_preload_info_init(GPreloadInfo *info) { info->instructions = NULL; info->comments = NULL; } /****************************************************************************** * * * Paramètres : info = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_preload_info_dispose(GPreloadInfo *info) { GArchInstruction *instr; /* Instruction à libérer */ GDbComment *comment; /* Commentaire à libérer */ g_preload_info_lock_instructions(info); while (_g_preload_info_count_instructions(info) > 0) { instr = _g_preload_info_grab_instruction(info, 0); g_object_unref(G_OBJECT(instr)); } _g_preload_info_drain_instructions(info); g_preload_info_unlock_instructions(info); g_preload_info_lock_comments(info); while (_g_preload_info_count_comments(info) > 0) { comment = _g_preload_info_grab_comment(info, 0); g_object_unref(G_OBJECT(comment)); } _g_preload_info_drain_comments(info); g_preload_info_unlock_comments(info); G_OBJECT_CLASS(g_preload_info_parent_class)->dispose(G_OBJECT(info)); } /****************************************************************************** * * * Paramètres : info = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_preload_info_finalize(GPreloadInfo *info) { G_OBJECT_CLASS(g_preload_info_parent_class)->finalize(G_OBJECT(info)); } /****************************************************************************** * * * Paramètres : - * * * * Description : Crée une nouvelle collecte d'informations préchargées. * * * * Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GPreloadInfo *g_preload_info_new(void) { GPreloadInfo *result; /* Nouveau preloade à renvoyer */ result = g_object_new(G_TYPE_PRELOAD_INFO, NULL); return result; } /****************************************************************************** * * * Paramètres : info = préchargements à mettre à jour. * * * * Description : Verrouille les accès à la liste des instructions. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_lock_instructions(GPreloadInfo *info) { lock_flat_array(&info->instructions); } /****************************************************************************** * * * Paramètres : info = préchargements à mettre à jour. * * * * Description : Déverrouille les accès à la liste des instructions. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_unlock_instructions(GPreloadInfo *info) { unlock_flat_array(&info->instructions); } /****************************************************************************** * * * Paramètres : info = instance à mettre à jour. * * instr = instruction à venir associer. * * * * Description : Ajoute une instruction supplémentaire aux préchargements. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr) { int cmp_instr_by_addr(const GArchInstruction **a, const GArchInstruction **b) { const mrange_t *range_a; /* Emplacement pour l'instr. A */ const mrange_t *range_b; /* Emplacement pour l'instr. B */ range_a = g_arch_instruction_get_range(*a); range_b = g_arch_instruction_get_range(*b); return cmp_vmpa(get_mrange_addr(range_a), get_mrange_addr(range_b)); } g_preload_info_lock_instructions(info); insert_item_into_flat_array(&info->instructions, &instr, sizeof(GArchInstruction *), (__compar_fn_t)cmp_instr_by_addr); g_preload_info_unlock_instructions(info); } /****************************************************************************** * * * Paramètres : info = instance à consulter. * * * * Description : Indique la quantité d'instructions préchargées disponibles. * * * * Retour : Nombre d'instructions attachées. * * * * Remarques : - * * * ******************************************************************************/ size_t _g_preload_info_count_instructions(const GPreloadInfo *info) { size_t result; /* Décompte à retourner */ result = count_flat_array_items(info->instructions); return result; } /****************************************************************************** * * * Paramètres : info = instance à consulter. * * index = indice de l'instruction concernée. * * * * Description : Fournit une instruction préchargée donnée. * * * * Retour : Instruction trouvée. * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *_g_preload_info_grab_instruction(const GPreloadInfo *info, size_t index) { GArchInstruction *result; /* Opérande à retourner */ GArchInstruction **ptr; /* Adresse dans le tableau */ ptr = get_flat_array_item(info->instructions, index, sizeof(GArchInstruction *)); result = *ptr; /** * La propriétée de l'élément est transmise à l'appelant. * * Ainsi, pour vider une liste via _g_preload_info_drain_instructions(), * il suffit juste de libérer la mémoire occupée pour le stockage sans * se préoccuper des références contenues ; le gain de temps est important * puisqu'on évite là un parcours et des déplacements. */ return result; } /****************************************************************************** * * * Paramètres : info = instance à manipuler. * * * * Description : Dépile une instruction présente dans les préchargements. * * * * Retour : Instruction retirée ou NULL si aucune. * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *info) { GArchInstruction *result; /* Instruction à retourner */ GArchInstruction **ptr; /* Adresse dans le tableau */ g_preload_info_lock_instructions(info); if (_g_preload_info_count_instructions(info) == 0) result = NULL; else { ptr = get_flat_array_item(info->instructions, 0, sizeof(GArchInstruction *)); result = *ptr; rem_item_from_flat_array(&info->instructions, 0, sizeof(GArchInstruction *)); } g_preload_info_unlock_instructions(info); return result; } /****************************************************************************** * * * Paramètres : info = instance à manipuler. * * * * Description : Retire des préchargements toutes les instructions. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void _g_preload_info_drain_instructions(GPreloadInfo *info) { /** * A utiliser en conjonction avec _g_preload_info_grab_instruction() * uniquement. */ reset_flat_array(&info->instructions); } /****************************************************************************** * * * Paramètres : info = préchargements à mettre à jour. * * * * Description : Verrouille les accès à la liste des commentaires. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_lock_comments(GPreloadInfo *info) { lock_flat_array(&info->comments); } /****************************************************************************** * * * Paramètres : info = préchargements à mettre à jour. * * * * Description : Déverrouille les accès à la liste des commentaires. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_unlock_comments(GPreloadInfo *info) { unlock_flat_array(&info->comments); } /****************************************************************************** * * * Paramètres : info = instance à mettre à jour. * * comment = commentaire à venir associer. * * * * Description : Ajoute un commentaire supplémentaire aux préchargements. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) { int cmp_comment_by_addr(const GDbComment * const *a, const GDbComment * const *b) { const vmpa2t *addr_a; /* Position du commentaire A */ const vmpa2t *addr_b; /* Position du commentaire B */ addr_a = g_db_comment_get_address(*a); addr_b = g_db_comment_get_address(*b); return cmp_vmpa(addr_a, addr_b); } g_preload_info_lock_comments(info); insert_item_into_flat_array(&info->comments, &comment, sizeof(GDbComment *), (__compar_fn_t)cmp_comment_by_addr); g_preload_info_unlock_comments(info); } /****************************************************************************** * * * Paramètres : info = instance à consulter. * * * * Description : Indique la quantité de commentaires préchargés disponibles. * * * * Retour : Nombre de commentaires attachés. * * * * Remarques : - * * * ******************************************************************************/ size_t _g_preload_info_count_comments(const GPreloadInfo *info) { size_t result; /* Décompte à retourner */ result = count_flat_array_items(info->comments); return result; } /****************************************************************************** * * * Paramètres : info = instance à consulter. * * index = indice de l'instruction concernée. * * * * Description : Fournit un commentaire préchargé donné. * * * * Retour : Commentaire trouvé. * * * * Remarques : - * * * ******************************************************************************/ GDbComment *_g_preload_info_grab_comment(const GPreloadInfo *info, size_t index) { GDbComment *result; /* Opérande à retourner */ GDbComment **ptr; /* Adresse dans le tableau */ ptr = get_flat_array_item(info->comments, index, sizeof(GDbComment *)); result = *ptr; /** * La propriétée de l'élément est transmise à l'appelant. * * Ainsi, pour vider une liste via _g_preload_info_drain_comments(), * il suffit juste de libérer la mémoire occupée pour le stockage sans * se préoccuper des références contenues ; le gain de temps est important * puisqu'on évite là un parcours et des déplacements. */ return result; } /****************************************************************************** * * * Paramètres : info = instance à manipuler. * * * * Description : Retire des préchargements tous les commentaires. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void _g_preload_info_drain_comments(GPreloadInfo *info) { /** * A utiliser en conjonction avec _g_preload_info_grab_comment() * uniquement. */ reset_flat_array(&info->comments); }