/* Chrysalide - Outil d'analyse de fichiers binaires * break.c - manipulation des points d'arrêt * * Copyright (C) 2010 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 "break.h" #include #include #include "../common/dllist.h" /* --------------------------- GESTION DES POINTS D'ARRET --------------------------- */ /* Propriétés d'un point d'arrêt (instance) */ struct _GBreakPoint { GObject parent; /* A laisser en premier */ DL_LIST_ITEM(link); /* Maillon de liste chaînée */ vmpa_t address; /* Adresse où s'arrêter */ bool is_enabled; /* Statut d'activité */ }; /* Propriétés d'un point d'arrêt (classe) */ struct _GBreakPointClass { GObjectClass parent; /* A laisser en premier */ /* Signaux */ void (* changed) (GBreakPoint *); }; #define bp_list_add_tail(new, head) dl_list_add_tail(new, head, GBreakPoint, link) #define bp_list_del(item, head) dl_list_del(item, head, GBreakPoint, link) #define bp_list_for_each(pos, head) dl_list_for_each(pos, head, GBreakPoint, link) #define bp_list_for_each_safe(pos, head, next) dl_list_for_each_safe(pos, head, next, GBreakPoint, link) /* Initialise la classe des propriétés d'un point d'arrêt. */ static void g_break_point_class_init(GBreakPointClass *); /* Initialise des propriétés d'un point d'arrêt. */ static void g_break_point_init(GBreakPoint *); /* ---------------------------- GROUPE DE POINTS D'ARRET ---------------------------- */ /* Propriétés d'un groupe de points d'arrêt (instance) */ struct _GBreakGroup { GObject parent; /* A laisser en premier */ char *name; /* Désignation humaine */ GBreakPoint *points; /* Liste de points d'arrêt */ }; /* Propriétés d'un groupe de points d'arrêt (classe) */ struct _GBreakGroupClass { GObjectClass parent; /* A laisser en premier */ /* Signaux */ void (* added) (GBreakGroup *, GBreakPoint *); void (* removed) (GBreakGroup *, GBreakPoint *); }; /* Initialise la classe des groupes de points d'arrêt. */ static void g_break_group_class_init(GBreakGroupClass *); /* Initialise un groupe de points d'arrêt. */ static void g_break_group_init(GBreakGroup *); /* ---------------------------------------------------------------------------------- */ /* GESTION DES POINTS D'ARRET */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour des propriétés d'un point d'arrêt. */ G_DEFINE_TYPE(GBreakPoint, g_break_point, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des propriétés d'un point d'arrêt. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_break_point_class_init(GBreakPointClass *klass) { g_signal_new("changed", G_TYPE_BREAK_POINT, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GBreakPointClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } /****************************************************************************** * * * Paramètres : point = instance à initialiser. * * * * Description : Initialise des propriétés d'un point d'arrêt. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_break_point_init(GBreakPoint *point) { DL_LIST_ITEM_INIT(&point->link); } /****************************************************************************** * * * Paramètres : address = adresse à laquelle s'arrêter. * * * * Description : Construit un nouveau point d'arrêt. * * * * Retour : Point d'arrêt mis en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GBreakPoint *g_break_point_new(vmpa_t address) { GBreakPoint *result; /* Adresse à retourner */ result = g_object_new(G_TYPE_BREAK_POINT, NULL); result->address = address; return result; } /****************************************************************************** * * * Paramètres : point = instance à consulter. * * * * Description : Fournit l'adresse associée à un point d'arrêt. * * * * Retour : Adresse associée. * * * * Remarques : - * * * ******************************************************************************/ vmpa_t g_break_point_get_address(const GBreakPoint *point) { return point->address; } /* ---------------------------------------------------------------------------------- */ /* GROUPE DE POINTS D'ARRET */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour les groupes de points d'errêt. */ G_DEFINE_TYPE(GBreakGroup, g_break_group, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des groupes de points d'arrêt. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_break_group_class_init(GBreakGroupClass *klass) { g_signal_new("added", G_TYPE_BREAK_GROUP, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GBreakGroupClass, added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_BREAK_POINT); g_signal_new("removed", G_TYPE_BREAK_GROUP, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GBreakGroupClass, removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_BREAK_POINT); } /****************************************************************************** * * * Paramètres : group = instance à initialiser. * * * * Description : Initialise un groupe de point d'arrêt. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_break_group_init(GBreakGroup *group) { } /****************************************************************************** * * * Paramètres : - * * * * Description : Construit un nouveau groupe de points d'arrêt. * * * * Retour : Groupe de points d'arrêt mis en place ou NULL en cas d'échec.* * * * Remarques : - * * * ******************************************************************************/ GBreakGroup *g_break_group_new(void) { GBreakGroup *result; /* Adresse à retourner */ result = g_object_new(G_TYPE_BREAK_GROUP, NULL); return result; } /****************************************************************************** * * * Paramètres : group = groupe de points d'arrêt à consulter. * * * * Description : Fournit la désignation humaine associée à un groupe. * * * * Retour : Désignation humaine associée, jamais NULL. * * * * Remarques : - * * * ******************************************************************************/ const char *g_break_group_get_name(const GBreakGroup *group) { return group->name; } /****************************************************************************** * * * Paramètres : group = groupe de points d'arrêt à modifier. * * name = nouveau nom de scène. * * * * Description : Définit la désignation humaine à associer à un groupe. * * * * Retour : Désignation humaine associée, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ void g_break_group_set_name(GBreakGroup *group, const char *name) { if (group->name != NULL) free(group->name); if (name == NULL) group->name = NULL; else group->name = strdup(name); } /****************************************************************************** * * * Paramètres : group = groupe de points d'arrêt à consulter. * * addr = adresse recherchée dans les points d'arrêt. * * * * Description : Indique si une adresse donnée est gérée dans un groupe. * * * * Retour : true si l'adresse est gérée ici, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool g_break_group_has_address(const GBreakGroup *group, vmpa_t addr) { GBreakPoint *iter; /* Boucle de parcours */ bp_list_for_each(iter, group->points) if (g_break_point_get_address(iter) == addr) return true; return false; } /****************************************************************************** * * * Paramètres : group = groupe de points d'arrêt à modifier. * * addr = adresse mémoire à faire basculer. * * * * Description : Ajoute ou supprime un point d'arrêt dans un groupe. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_break_group_toggle_breakpoint(GBreakGroup *group, vmpa_t addr) { GBreakPoint *iter; /* Boucle de parcours */ GBreakPoint *next; /* Prochain point de passage */ /* Suppression d'un éventuel existant */ bp_list_for_each_safe(iter, &group->points, next) if (g_break_point_get_address(iter) == addr) { g_signal_emit_by_name(group, "removed", iter); bp_list_del(iter, &group->points); g_object_unref(G_OBJECT(iter)); return; } /* Si non trouvé, ajout du nouveau point */ iter = g_break_point_new(addr); bp_list_add_tail(iter, &group->points); g_signal_emit_by_name(group, "added", iter); } /****************************************************************************** * * * Paramètres : group = groupe de points d'arrêt à parcourir. * * func = fonction à appeler à chaque point trouvé. * * data = éventuelle donnée de l'utilisateur à joindre. * * * * Description : Parcourt l'ensemble des points d'arrêt d'un groupe donné. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_break_group_for_each(GBreakGroup *group, GExtFunc func, gpointer data) { GBreakPoint *iter; /* Boucle de parcours */ /* Suppression d'un éventuel existant */ bp_list_for_each(iter, group->points) func(group, iter, data); }