summaryrefslogtreecommitdiff
path: root/src/debug/break.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/break.c')
-rw-r--r--src/debug/break.c489
1 files changed, 256 insertions, 233 deletions
diff --git a/src/debug/break.c b/src/debug/break.c
index 19eb787..1d4c2d3 100644
--- a/src/debug/break.c
+++ b/src/debug/break.c
@@ -24,114 +24,20 @@
#include "break.h"
+#include <assert.h>
#include <malloc.h>
-#include <string.h>
-#include "../common/dllist.h"
+#include "break-int.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. *
+* Paramètres : bp = point d'arrêt à initialiser. *
+* addr = adresse d'action du point d'arrêt. *
* *
-* Description : Initialise la classe des propriétés d'un point d'arrêt. *
+* Description : Initialise le coeur d'un point d'arrêt. *
* *
* Retour : - *
* *
@@ -139,24 +45,20 @@ G_DEFINE_TYPE(GBreakPoint, g_break_point, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_break_point_class_init(GBreakPointClass *klass)
+void init_raw_breakpoint(raw_breakpoint *bp, virt_t addr)
{
- 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);
+ bp->addr = addr;
+
+ bp->count = 0;
}
/******************************************************************************
* *
-* Paramètres : point = instance à initialiser. *
+* Paramètres : bp = point d'arrêt à traiter. *
* *
-* Description : Initialise des propriétés d'un point d'arrêt. *
+* Description : Libère le coeur d'un point d'arrêt. *
* *
* Retour : - *
* *
@@ -164,135 +66,133 @@ static void g_break_point_class_init(GBreakPointClass *klass)
* *
******************************************************************************/
-static void g_break_point_init(GBreakPoint *point)
+void fini_raw_breakpoint(raw_breakpoint *bp)
{
- DL_LIST_ITEM_INIT(&point->link);
+ if (bp->count > 1)
+ free(bp->sources);
+
+ free(bp);
}
/******************************************************************************
* *
-* Paramètres : address = adresse à laquelle s'arrêter. *
+* Paramètres : bp = point d'arrêt à consulter. *
* *
-* Description : Construit un nouveau point d'arrêt. *
+* Description : Indique l'adresse du point d'arrêt dans la mémoire ciblée. *
* *
-* Retour : Point d'arrêt mis en place ou NULL en cas d'échec. *
+* Retour : Adresse associée au point d'arrêt. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBreakPoint *g_break_point_new(vmpa_t address)
+virt_t get_raw_breakpoint_addr(const raw_breakpoint *bp)
{
- GBreakPoint *result; /* Adresse à retourner */
-
- result = g_object_new(G_TYPE_BREAK_POINT, NULL);
-
- result->address = address;
-
- return result;
+ return bp->addr;
}
+
/******************************************************************************
* *
-* Paramètres : point = instance à consulter. *
+* Paramètres : bp = point d'arrêt à consulter. *
* *
-* Description : Fournit l'adresse associée à un point d'arrêt. *
+* Description : Fournit l'adresse d'origine d'un point d'arrêt de pas à pas. *
* *
-* Retour : Adresse associée. *
+* Retour : - *
* *
-* Remarques : - *
+* Remarques : Un appel à cette fonction n'est valide que pour un point *
+* d'arrêt de type RBO_STEP. *
* *
******************************************************************************/
-vmpa_t g_break_point_get_address(const GBreakPoint *point)
+virt_t get_raw_breakpoint_prev_addr(const raw_breakpoint *bp)
{
- return point->address;
+ virt_t result; /* Localisation à retourner */
+ bool found; /* Valide une obtention */
+ size_t i; /* Boucle de parcours */
-}
+ switch (bp->count)
+ {
+ case 1:
+ assert(bp->source.origin == RBO_INTERNAL || bp->source.origin == RBO_STEP);
+ result = bp->source.previous;
+ break;
+ default:
+ found = false;
-/* ---------------------------------------------------------------------------------- */
-/* GROUPE DE POINTS D'ARRET */
-/* ---------------------------------------------------------------------------------- */
+ for (i = 0; i < bp->count && !found; i++)
+ if (bp->sources[i].origin == RBO_INTERNAL || bp->sources[i].origin == RBO_STEP)
+ {
+ result = bp->sources[i].previous;
+ found = true;
+ }
+ assert(found);
-/* Indique le type défini pour les groupes de points d'errêt. */
-G_DEFINE_TYPE(GBreakGroup, g_break_group, G_TYPE_OBJECT);
+ break;
+ }
-/******************************************************************************
-* *
-* 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);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : group = instance à initialiser. *
+* Paramètres : addr = adresse à consulter. *
+* bp = point d'arrêt à consulter. *
* *
-* Description : Initialise un groupe de point d'arrêt. *
+* Description : Effectue une comparaison entre adresse et point d'arrêt. *
* *
-* Retour : - *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_break_group_init(GBreakGroup *group)
+int compare_raw_breakpoint_with_addr(const virt_t *addr, const raw_breakpoint **bp)
{
+ int result; /* Bilan à retourner */
+
+ if (*addr < (*bp)->addr)
+ result = -1;
+
+ else if (*addr == (*bp)->addr)
+ result = 0;
+
+ else
+ result = 1;
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : a = premier point d'arrêt à consulter. *
+* b = second point d'arrêt à consulter. *
* *
-* Description : Construit un nouveau groupe de points d'arrêt. *
+* Description : Effectue une comparaison entre deux points d'arrêt. *
* *
-* Retour : Groupe de points d'arrêt mis en place ou NULL en cas d'échec.*
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBreakGroup *g_break_group_new(void)
+int compare_raw_breakpoints(const raw_breakpoint **a, const raw_breakpoint **b)
{
- GBreakGroup *result; /* Adresse à retourner */
+ int result; /* Bilan à retourner */
- result = g_object_new(G_TYPE_BREAK_GROUP, NULL);
+ result = compare_raw_breakpoint_with_addr(&(*a)->addr, b);
return result;
@@ -301,140 +201,263 @@ GBreakGroup *g_break_group_new(void)
/******************************************************************************
* *
-* Paramètres : group = groupe de points d'arrêt à consulter. *
+* Paramètres : bp = point d'arrêt à manipuler. *
+* origin = origine de la création du point d'arrêt. *
+* tid = identifiant du thread concerné. *
+* previous = éventuelle adresse précédent celle du point. *
* *
-* Description : Fournit la désignation humaine associée à un groupe. *
+* Description : Enregistre la source d'un point d'arrêt posé. *
* *
-* Retour : Désignation humaine associée, jamais NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_break_group_get_name(const GBreakGroup *group)
+void set_raw_breakpoint_origin(raw_breakpoint *bp, RawBpOrigin origin, dbg_thread_id_t tid, virt_t previous)
{
- return group->name;
+#ifndef NDEBUG
+ size_t i; /* Boucle de parcours */
+#endif
+ bp_source *src; /* Source à définir */
+ bp_source tmp; /* Copie temporaire */
+
+#ifndef NDEBUG
+
+ if (bp->count == 1)
+ assert(bp->source.tid != tid || (bp->source.origin & origin) == 0);
+
+ else
+ for (i = 0; i < bp->count; i++)
+ if (bp->source.tid == tid)
+ {
+ assert((bp->sources[i].origin & origin) == 0);
+ break;
+ }
+
+#endif
+
+ bp->count++;
+
+ switch (bp->count)
+ {
+ case 1:
+ src = &bp->source;
+ break;
+
+ case 2:
+ tmp = bp->source;
+ bp->sources = (bp_source *)calloc(2, sizeof(bp_source));
+ bp->sources[0] = tmp;
+ src = &bp->sources[1];
+ break;
+
+ default:
+ bp->sources = (bp_source *)realloc(bp->sources, bp->count * sizeof(bp_source));
+ src = &bp->sources[bp->count - 1];
+ break;
+
+ }
+
+ src->origin = origin;
+ src->tid = tid;
+ src->previous = previous;
}
/******************************************************************************
* *
-* Paramètres : group = groupe de points d'arrêt à modifier. *
-* name = nouveau nom de scène. *
+* Paramètres : bp = point d'arrêt à manipuler. *
+* origin = origine de la création du point d'arrêt. *
+* tid = identifiant du thread concerné. *
+* previous = éventuelle adresse précédent celle du point. *
* *
-* Description : Définit la désignation humaine à associer à un groupe. *
+* Description : Oublie la source d'un point d'arrêt posé. *
* *
-* Retour : Désignation humaine associée, voire NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_break_group_set_name(GBreakGroup *group, const char *name)
+void unset_raw_breakpoint_origin(raw_breakpoint *bp, RawBpOrigin origin, dbg_thread_id_t tid)
{
- if (group->name != NULL)
- free(group->name);
+ size_t i; /* Boucle de parcours #1 */
+ bp_source tmp; /* Copie temporaire */
+#ifndef NDEBUG
+ size_t j; /* Boucle de parcours #2 */
+#endif
- if (name == NULL)
- group->name = NULL;
+ bool has_same_origin(bp_source *src)
+ {
+ bool result;
- else
- group->name = strdup(name);
+ result = (src->origin == origin && src->tid == tid);
+
+ return result;
+
+ }
+
+ switch (bp->count)
+ {
+ case 1:
+
+ if (has_same_origin(&bp->source))
+ bp->count = 0;
+
+ break;
+
+ case 2:
+
+ if (has_same_origin(&bp->sources[0]))
+ {
+ assert(!has_same_origin(&bp->sources[1]));
+
+ tmp = bp->sources[1];
+
+ bp->count = 1;
+ free(bp->sources);
+
+ bp->source = tmp;
+
+ }
+
+ else if (has_same_origin(&bp->sources[1]))
+ {
+ assert(!has_same_origin(&bp->sources[0]));
+
+ tmp = bp->sources[0];
+
+ bp->count = 1;
+ free(bp->sources);
+
+ bp->source = tmp;
+
+ }
+
+ break;
+
+ default:
+
+ for (i = 0; i < bp->count; i++)
+ {
+ if (has_same_origin(&bp->sources[i]))
+ {
+ if ((i + 1) < bp->count)
+ memmove(&bp->sources[i], &bp->sources[i + 1], (bp->count - i - 1) * sizeof(bp_source));
+
+ bp->sources = (bp_source *)realloc(bp->sources, --bp->count * sizeof(bp_source));
+
+#ifndef NDEBUG
+ for (j = i; j < bp->count; j++)
+ assert(!has_same_origin(&bp->sources[j]));
+#endif
+
+ break;
+
+ }
+
+ }
+
+ break;
+
+ }
}
/******************************************************************************
* *
-* Paramètres : group = groupe de points d'arrêt à consulter. *
-* addr = adresse recherchée dans les points d'arrêt. *
+* Paramètres : bp = point d'arrêt à manipuler. *
+* origin = origine de la création du point d'arrêt. *
+* tid = identifiant du thread concerné. *
* *
-* Description : Indique si une adresse donnée est gérée dans un groupe. *
+* Description : Indique si le point d'arrêt correspond à une source donnée. *
* *
-* Retour : true si l'adresse est gérée ici, false sinon. *
+* Retour : Bilan de l'analyse. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_break_group_has_address(const GBreakGroup *group, vmpa_t addr)
+bool has_raw_breakpoint_origin(const raw_breakpoint *bp, RawBpOrigin origin, dbg_thread_id_t tid)
{
- GBreakPoint *iter; /* Boucle de parcours */
+ bool result; /* Conclusion à retourner */
+ size_t i; /* Boucle de parcours */
+
+ if (bp->count == 1)
+ result = (bp->source.tid == tid && (bp->source.origin & origin) != 0);
+
+ else
+ {
+ result = false;
+
+ for (i = 0; i < bp->count && !result; i++)
+ result = (bp->sources[i].tid == tid && (bp->sources[i].origin & origin) != 0);
- bp_list_for_each(iter, group->points)
- if (g_break_point_get_address(iter) == addr)
- return true;
+ }
- return false;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : group = groupe de points d'arrêt à modifier. *
-* addr = adresse mémoire à faire basculer. *
+* Paramètres : bp = point d'arrêt à manipuler. *
+* origin = origine de la création du point d'arrêt. *
+* tid = identifiant du thread concerné. *
+* prev = adresse d'instruction qui a conduit à des poses. *
* *
-* Description : Ajoute ou supprime un point d'arrêt dans un groupe. *
+* Description : Indique si le point d'arrêt correspond à une origine donnée. *
* *
-* Retour : - *
+* Retour : Bilan de l'analyse. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_break_group_toggle_breakpoint(GBreakGroup *group, vmpa_t addr)
+bool has_raw_breakpoint_previous_address(const raw_breakpoint *bp, RawBpOrigin origin, dbg_thread_id_t tid, virt_t prev)
{
- GBreakPoint *iter; /* Boucle de parcours */
- GBreakPoint *next; /* Prochain point de passage */
+ bool result; /* Conclusion à retourner */
+ size_t i; /* Boucle de parcours */
- /* Suppression d'un éventuel existant */
+ if (bp->count == 1)
+ result = (bp->source.tid == tid && (bp->source.origin & origin) != 0 && bp->source.previous == prev);
- 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 */
+ else
+ {
+ result = false;
- iter = g_break_point_new(addr);
+ for (i = 0; i < bp->count && !result; i++)
+ result = (bp->sources[i].tid == tid && (bp->sources[i].origin & origin) != 0 && bp->sources[i].previous == prev);
- bp_list_add_tail(iter, &group->points);
+ }
- g_signal_emit_by_name(group, "added", iter);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : group = groupe de points d'arrêt à parcourir. *
-* func = fonction à appeler à chaque point trouvé. *
-* data = éventuelle donnée de l'utilisateur à joindre. *
+* Paramètres : bp = point d'arrêt à consulter. *
* *
-* Description : Parcourt l'ensemble des points d'arrêt d'un groupe donné. *
+* Description : Indique si un point d'arrêt a encore une utilité. *
* *
-* Retour : - *
+* Retour : true si le point peut être retiré, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_break_group_for_each(GBreakGroup *group, GExtFunc func, gpointer data)
+bool is_breakpoint_useless(const raw_breakpoint *bp)
{
- GBreakPoint *iter; /* Boucle de parcours */
+ bool result; /* Conclusion à faire remonter */
- /* Suppression d'un éventuel existant */
+ result = (bp->count == 0);
- bp_list_for_each(iter, group->points)
- func(group, iter, data);
+ return result;
}