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