diff options
Diffstat (limited to 'src')
36 files changed, 2396 insertions, 351 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c index d8199c0..f6f56c7 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -39,7 +39,9 @@ #include "line_comment.h" /* TODO : supprimer ? */ #include "line_prologue.h" #include "routine.h" +#include "../common/cpp.h" #include "../common/extstr.h" +#include "../debug/break.h" #include "../glibext/delayed-int.h" #include "../format/format.h" #include "../panels/log.h" @@ -143,6 +145,10 @@ struct _GOpenidaBinary GRenderingLine *lines; /* Lignes de rendu en place */ GRenderingOptions *options; /* Options de désassemblage */ + GBreakGroup **brk_groups; /* Groupes de points d'arrêt */ + size_t brk_count; /* Taille de cette liste */ + GBreakGroup *brk_default; /* Groupe par défaut */ + }; /* Description de fichier binaire (classe) */ @@ -176,6 +182,16 @@ void ack_completed_disassembly(GDelayedDisassembly *, GOpenidaBinary *); +/* ------------------------------ ELEMENTS DE DEBOGAGE ------------------------------ */ + + +/* Réagit à une nouvelle création de point d'arrêt. */ +static void g_openida_binary_breakpoint_added(GBreakGroup *, GBreakPoint *, GOpenidaBinary *); + +/* Réagit à une suppression de point d'arrêt. */ +static void g_openida_binary_breakpoint_removed(GBreakGroup *, GBreakPoint *, GOpenidaBinary *); + + /* ---------------------------------------------------------------------------------- */ /* DESASSEMBLAGE DE BINAIRE DIFFERE */ @@ -707,6 +723,8 @@ static void g_openida_binary_class_init(GOpenidaBinaryClass *klass) static void g_openida_binary_init(GOpenidaBinary *binary) { + /* FIXME : à replacer ailleurs */ + g_openida_binary_add_break_group(binary, _("default")); } @@ -1473,3 +1491,196 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GOpenidaBinary *bina g_signal_emit_by_name(binary, "disassembly-done"); } + + + +/* ---------------------------------------------------------------------------------- */ +/* ELEMENTS DE DEBOGAGE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : binary = représentation de binaire à modifier. * +* name = éventuel nom à associer au groupe. * +* * +* Description : Ajoute un nouveau groupe de points d'arrêt au binaire. * +* * +* Retour : true si l'opération s'est bien effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_openida_binary_add_break_group(GOpenidaBinary *binary, const char *name) +{ + bool result; /* Bilan à faire remonter */ + const char *used; /* Désignation à utiliser */ + size_t tmp_len; /* Longeur maximale à gérer */ + char *tmp; /* Construction temporaire */ + size_t i; /* Boucle de parcours */ + const char *test; /* Nom existant à tester */ + + result = true; + + /* Préparation du nom de scène */ + + if (name != NULL) used = name; + else + { + tmp_len = strlen(_("Group")) + 1 + SIZE_T_MAXLEN + 1; + tmp = (char *)calloc(tmp_len, sizeof(char)); + + snprintf(tmp, tmp_len, "%s %lu", _("Group"), binary->brk_count); + + used = tmp; + + } + + /* Vérification d'unicité */ + + for (i = 0; i < binary->brk_count && result; i++) + { + test = g_break_group_get_name(binary->brk_groups[i]); + + if (test != NULL) + result = (strcmp(used, test) != 0); + + } + + /* Mise en place finale */ + + if (result) + { + binary->brk_count++; + binary->brk_groups = (GBreakGroup **)realloc(binary->brk_groups, + binary->brk_count * sizeof(GBreakGroup *)); + + binary->brk_groups[i] = g_break_group_new(); + + g_break_group_set_name(binary->brk_groups[i], used); + + if (binary->brk_default == NULL) + binary->brk_default = binary->brk_groups[i]; + + g_signal_connect(binary->brk_groups[i], "added", + G_CALLBACK(g_openida_binary_breakpoint_added), binary); + + g_signal_connect(binary->brk_groups[i], "removed", + G_CALLBACK(g_openida_binary_breakpoint_removed), binary); + + } + + if (name == NULL) free(tmp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : group = ensemble de points d'arrêt intervenant. * +* point = point d'arrêt à l'origine de la procédure. * +* binary = représentation de binaire à modifier. * +* * +* Description : Réagit à une nouvelle création de point d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_openida_binary_breakpoint_added(GBreakGroup *group, GBreakPoint *point, GOpenidaBinary *binary) +{ + GRenderingLine *line; /* Ligne à retrouver */ + + line = g_rendering_line_find_by_address(binary->lines, NULL, + g_break_point_get_address(point)); + + if (line != NULL) + g_rendering_line_toggle_flag(line, RLF_BREAK_POINT); + +} + + +/****************************************************************************** +* * +* Paramètres : group = ensemble de points d'arrêt intervenant. * +* point = point d'arrêt à l'origine de la procédure. * +* binary = représentation de binaire à modifier. * +* * +* Description : Réagit à une suppression de point d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_openida_binary_breakpoint_removed(GBreakGroup *group, GBreakPoint *point, GOpenidaBinary *binary) +{ + GRenderingLine *line; /* Ligne à retrouver */ + + line = g_rendering_line_find_by_address(binary->lines, NULL, + g_break_point_get_address(point)); + + if (line != NULL) + g_rendering_line_toggle_flag(line, RLF_BREAK_POINT); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = représentation de binaire à mettre à jour. * +* addr = adresse mémoire à faire basculer. * +* * +* Description : Ajoute ou supprime un point d'arrêt dans un binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_openida_binary_toggle_breakpoint(GOpenidaBinary *binary, vmpa_t addr) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < binary->brk_count; i++) + if (g_break_group_has_address(binary->brk_groups[i], addr)) + { + g_break_group_toggle_breakpoint(binary->brk_groups[i], addr); + break; + } + + if (i == binary->brk_count) + g_break_group_toggle_breakpoint(binary->brk_default, addr); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = représentation de binaire à parcourir. * +* func = fonction à appeler à chaque point trouvé. * +* data = éventuelle donnée de l'utilisateur à joindre. * +* * +* Description : Parcourt l'ensemble des groupes de points d'arrêt du binaire.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_openida_binary_for_each_bp_group(GOpenidaBinary *binary, GExtFunc func, gpointer data) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < binary->brk_count; i++) + func(binary, binary->brk_groups[i], data); + +} diff --git a/src/analysis/binary.h b/src/analysis/binary.h index f556c4a..3869cae 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -31,6 +31,7 @@ #include "line.h" #include "../arch/processor.h" +#include "../debug/break.h" #include "../format/executable.h" #include "../common/xml.h" @@ -106,4 +107,18 @@ GRenderingLine *g_openida_binary_get_lines(const GOpenidaBinary *); +/* ------------------------------ ELEMENTS DE DEBOGAGE ------------------------------ */ + + +/* Ajoute un nouveau groupe de points d'arrêt au binaire. */ +bool g_openida_binary_add_break_group(GOpenidaBinary *, const char *); + +/* Ajoute ou supprime un point d'arrêt dans un binaire. */ +void g_openida_binary_toggle_breakpoint(GOpenidaBinary *, vmpa_t); + +/* Parcourt l'ensemble des groupes de points d'arrêt du binaire. */ +void g_openida_binary_for_each_bp_group(GOpenidaBinary *, GExtFunc, gpointer); + + + #endif /* _ANALYSIS_BINARY_H */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index f8e4f20..c883e02 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -2,6 +2,7 @@ lib_LTLIBRARIES = libcommon.la libcommon_la_SOURCES = \ + cpp.h \ dllist.h dllist.c \ endianness.h endianness.c \ environment.h environment.c \ diff --git a/src/common/cpp.h b/src/common/cpp.h new file mode 100644 index 0000000..b5e09c0 --- /dev/null +++ b/src/common/cpp.h @@ -0,0 +1,45 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * cpp.h - prototypes pour avoir à disposition un langage C plus plus mieux + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _COMMON_CPP_H +#define _COMMON_CPP_H + + +#include <limits.h> +#include <string.h> + + + +/** + * Détermine la taille de la plus longue chaîne de caractères + * correspondant à un type donné. + */ + +#define XSTR(e) STR(e) +#define STR(e) #e + +#define SIZE_T_MAXLEN strlen(XSTR(LONG_MAX)) + + + +#endif /* _COMMON_CPP_H */ diff --git a/src/common/endianness.c b/src/common/endianness.c index 5a14e1c..0b7e192 100755 --- a/src/common/endianness.c +++ b/src/common/endianness.c @@ -24,6 +24,9 @@ #include "endianness.h" +#include <stdarg.h> + + /****************************************************************************** * * @@ -318,3 +321,197 @@ bool read_u64(uint64_t *target, const bin_t *data, off_t *pos, off_t len, Source return true; } + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* Description : Lit un nombre hexadécimal non signé sur deux octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool strtou8(uint8_t *target, const char *data, size_t *pos, size_t len, SourceEndian endian) +{ + size_t i; /* Boucle de parcours */ + + if (*pos < 0) return false; + if ((len - *pos) < 2) return false; + + *target = 0; + + for (i = 0; i < 2; i++) + switch (data[*pos + i]) + { + case '0' ... '9': + *target |= ((data[*pos + i] - '0') << (4 * (1 - i))); + break; + + case 'A' ... 'F': + *target |= ((data[*pos + i] + 10 - 'A') << (4 * (1 - i))); + break; + + case 'a' ... 'f': + *target |= ((data[*pos + i] + 10 - 'a') << (4 * (1 - i))); + break; + + } + + *pos += 2; + + return true; + +} + + + +/****************************************************************************** +* * +* Paramètres : n = nombre d'octets constituant le nombre à lire. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* endian = ordre des bits dans la source. * +* ... = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre hexadécimal non signé sur n octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _strtoun(uint8_t n, const char *data, size_t *pos, size_t len, SourceEndian endian, ...) +{ + bool result; /* Bilan à renvoyer */ + va_list ap; /* Arguments variables */ + uint8_t *target8; /* Enregistrement sur 8 bits */ + uint16_t *target16; /* Enregistrement sur 16 bits */ + uint32_t *target32; /* Enregistrement sur 32 bits */ + uint64_t *target64; /* Enregistrement sur 64 bits */ + uint8_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + uint8_t tmp; /* Valeur temporaire de 8 bits */ + + if (*pos < 0) return false; + if ((len - *pos) < (n * 2)) return false; + + /* Récupération de la destination */ + + va_start(ap, endian); + + switch (n) + { + case 1: + target8 = va_arg(ap, uint8_t *); + *target8 = 0; + target64 = (uint64_t *)target8; + break; + case 2: + target16 = va_arg(ap, uint16_t *); + *target16 = 0; + target64 = (uint64_t *)target16; + break; + case 4: + target32 = va_arg(ap, uint32_t *); + *target32 = 0; + target64 = (uint64_t *)target32; + break; + case 8: + target64 = va_arg(ap, uint64_t *); + *target64 = 0ull; + break; + default: + va_end(ap); + return false; + break; + } + + va_end(ap); + + /* Lecture des données */ + + result = true; + + for (i = 0; i < n && result; i++) + { + tmp = 0; + + for (j = 0; j < 2 && result; j++) + switch (data[*pos + j]) + { + case '0' ... '9': + tmp |= ((data[*pos + j] - '0') << (4 * (1 - j))); + break; + + case 'A' ... 'F': + tmp |= ((data[*pos + j] + 10 - 'A') << (4 * (1 - j))); + break; + + case 'a' ... 'f': + tmp |= ((data[*pos + j] + 10 - 'a') << (4 * (1 - j))); + break; + + default: + printf(" string :: '%s'\n", &data[*pos + j]); + result = false; + break; + + } + + *pos += 2; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * i); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); + +#else + +# error "TODO : PDP !" + +#endif + + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i)); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + *target64 |= ((uint64_t)tmp) << (8 * i); + +#else + +# error "TODO : PDP !" + +#endif + + break; + + } + + } + + return result; + +} diff --git a/src/common/endianness.h b/src/common/endianness.h index f729ac5..0664d6a 100755 --- a/src/common/endianness.h +++ b/src/common/endianness.h @@ -65,5 +65,17 @@ bool read_u64(uint64_t *, const bin_t *, off_t *, off_t, SourceEndian); #define read_s64(target, data, pos, len, endian) read_u64((uint64_t *)target, data, pos, len, endian) +/* Lit un nombre hexadécimal non signé sur deux octets. */ +bool strtou8(uint8_t *, const char *, size_t *, size_t, SourceEndian); + + + +/* Lit un nombre hexadécimal non signé sur n octets. */ +bool _strtoun(uint8_t, const char *, size_t *, size_t, SourceEndian, ...); + + +#define strtou32(target, data, pos, len, endian) _strtoun(4, data, pos, len, endian, target) + + #endif /* _COMMON_ENDIANNESS_H */ diff --git a/src/debug/Makefile.am b/src/debug/Makefile.am index 7a19221..ec3dde7 100755 --- a/src/debug/Makefile.am +++ b/src/debug/Makefile.am @@ -2,7 +2,8 @@ noinst_LTLIBRARIES = libdebug.la libdebug_la_SOURCES = \ - debuggers.h debuggers.c + break.h break.c \ + debugger.h debugger.c libdebug_la_CFLAGS = $(AM_CFLAGS) diff --git a/src/debug/break.c b/src/debug/break.c new file mode 100644 index 0000000..4a19f25 --- /dev/null +++ b/src/debug/break.c @@ -0,0 +1,440 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * break.c - manipulation des points d'arrêt + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "break.h" + + +#include <malloc.h> +#include <string.h> + + +#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); + +} diff --git a/src/debug/break.h b/src/debug/break.h new file mode 100644 index 0000000..76b537a --- /dev/null +++ b/src/debug/break.h @@ -0,0 +1,105 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * break.h - prototypes pour la manipulation des points d'arrêt + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DEBUG_BREAK_H +#define _DEBUG_BREAK_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "../arch/archbase.h" +#include "../glibext/proto.h" + + + +/* --------------------------- GESTION DES POINTS D'ARRET --------------------------- */ + + +#define G_TYPE_BREAK_POINT g_break_point_get_type() +#define G_BREAK_POINT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_break_point_get_type(), GBreakPoint)) +#define G_IS_BREAK_POINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_break_point_get_type())) +#define G_BREAK_POINT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_break_point_get_type(), GBreakPointIface)) +#define G_BREAK_POINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BREAK_POINT, GBreakPointClass)) + + +/* Propriétés d'un point d'arrêt (instance) */ +typedef struct _GBreakPoint GBreakPoint; + +/* Propriétés d'un point d'arrêt (classe) */ +typedef struct _GBreakPointClass GBreakPointClass; + + +/* Indique le type défini pour des propriétés d'un point d'arrêt. */ +GType g_break_point_get_type(void); + +/* Construit un nouveau point d'arrêt. */ +GBreakPoint *g_break_point_new(vmpa_t); + +/* Fournit l'adresse associée à un point d'arrêt. */ +vmpa_t g_break_point_get_address(const GBreakPoint *); + + + +/* ---------------------------- GROUPE DE POINTS D'ARRET ---------------------------- */ + + +#define G_TYPE_BREAK_GROUP g_break_group_get_type() +#define G_BREAK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_break_group_get_type(), GBreakGroup)) +#define G_IS_BREAK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_break_group_get_type())) +#define G_BREAK_GROUP_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_break_group_get_type(), GBreakGroupIface)) +#define G_BREAK_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BREAK_GROUP, GBreakGroupClass)) + + +/* Propriétés d'un groupe de points d'arrêt (instance) */ +typedef struct _GBreakGroup GBreakGroup; + +/* Propriétés d'un groupe de points d'arrêt (classe) */ +typedef struct _GBreakGroupClass GBreakGroupClass; + + +/* Indique le type défini pour les groupes de points d'errêt. */ +GType g_break_group_get_type(void); + +/* Construit un nouveau groupe de points d'arrêt. */ +GBreakGroup *g_break_group_new(void); + +/* Fournit la désignation humaine associée à un groupe. */ +const char *g_break_group_get_name(const GBreakGroup *); + +/* Définit la désignation humaine à associer à un groupe. */ +void g_break_group_set_name(GBreakGroup *, const char *); + +/* Indique si une adresse donnée est gérée dans un groupe. */ +bool g_break_group_has_address(const GBreakGroup *, vmpa_t); + +/* Ajoute ou supprime un point d'arrêt dans un groupe. */ +void g_break_group_toggle_breakpoint(GBreakGroup *, vmpa_t); + +/* Parcourt l'ensemble des points d'arrêt d'un groupe donné. */ +void g_break_group_for_each(GBreakGroup *, GExtFunc, gpointer); + + + +#endif /* _DEBUG_BREAK_H */ diff --git a/src/debug/debugger-int.h b/src/debug/debugger-int.h index 3ba594a..642efd7 100644 --- a/src/debug/debugger-int.h +++ b/src/debug/debugger-int.h @@ -25,7 +25,7 @@ #define _DEBUG_DEBUGGER_INT_H -#include "debuggers.h" +#include "debugger.h" #include <gtk/gtk.h> @@ -68,6 +68,8 @@ struct _GBinaryDebuggerClass void (* debugger_stopped) (GBinaryDebugger *, uint64_t, uint64_t); + void (* debugger_halted) (GBinaryDebugger *, int, vmpa_t, pid_t); + }; diff --git a/src/debug/debugger.c b/src/debug/debugger.c new file mode 100644 index 0000000..a7d7470 --- /dev/null +++ b/src/debug/debugger.c @@ -0,0 +1,212 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * debugger.c - gestion des différents débogueurs + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "debugger.h" + +#include "debugger-int.h" +#include "remgdb/gdb.h" +#include "ptrace/ptrace.h" +#include "../gtkext/iodamarshal.h" + + + +/* Initialise la classe de base des débogueurs. */ +static void g_binary_debugger_class_init(GBinaryDebuggerClass *); + +/* Initialise une instance de base d'un débogueur. */ +static void g_binary_debugger_init(GBinaryDebugger *); + + + +/* Indique le type définit pour une ligne de représentation. */ +G_DEFINE_TYPE(GBinaryDebugger, g_binary_debugger, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe de base des débogueurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_debugger_class_init(GBinaryDebuggerClass *klass) +{ + g_signal_new("debugger-stopped", + G_TYPE_BINARY_DEBUGGER, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBinaryDebuggerClass, debugger_stopped), + NULL, NULL, + g_cclosure_user_marshal_VOID__UINT64_UINT64, + G_TYPE_NONE, 2, G_TYPE_UINT64, G_TYPE_UINT64); + + g_signal_new("halted", + G_TYPE_BINARY_DEBUGGER, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GBinaryDebuggerClass, debugger_halted), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_UINT64_INT, + G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT64, G_TYPE_INT); + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = instance à initialiser. * +* * +* Description : Initialise une instance de base d'un débogueur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_debugger_init(GBinaryDebugger *debugger) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de débigueur choisi pour l'opération. * +* binary = binaire devant être débogué. * +* * +* Description : Crée un nouveau débogueur. * +* * +* Retour : Composant GObject mis en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinaryDebugger *g_new_binary_debugger(DebuggerType type, GOpenidaBinary *binary) +{ + GBinaryDebugger *result; + + switch (type) + { + case DGT_REMOTE_GDB: + result = g_gdb_debugger_new(binary, NULL); + break; + + case DGT_PTRACE: + result = g_object_new(G_TYPE_PTRACE_DEBUGGER, NULL); + break; + + default: + result = NULL; + break; + + } + + if (result != NULL) + result->binary = binary; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à manipuler ici. * +* * +* Description : Démarre une procédure de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_debugger_run(GBinaryDebugger *debugger) +{ + debugger->run(debugger); + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à manipuler ici. * +* * +* Description : Reprend une procédure de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_debugger_resume(GBinaryDebugger *debugger) +{ + debugger->resume(debugger); + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à manipuler ici. * +* * +* Description : Tue une procédure de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_debugger_kill(GBinaryDebugger *debugger) +{ + debugger->kill(debugger); + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à manipuler ici. * +* count = nombre de transmissions effetuées. * +* * +* Description : Fournit la valeur des registres de l'architecture. * +* * +* Retour : Tableau de valeurs transmises à libérer de la mémoire / NULL.* +* * +* Remarques : - * +* * +******************************************************************************/ + +register_value *g_binary_debugger_get_registers(GBinaryDebugger *debugger, size_t *count) +{ + return debugger->get_reg_values(debugger, count); + +} diff --git a/src/debug/debugger.h b/src/debug/debugger.h new file mode 100644 index 0000000..d6163cf --- /dev/null +++ b/src/debug/debugger.h @@ -0,0 +1,92 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * debugger.h - prototypes pour la gestion des différents débogueurs + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DEBUG_DEBUGGER_H +#define _DEBUG_DEBUGGER_H + + +#include <glib-object.h> +#include <stdint.h> +#include <sys/types.h> + + +#include "../analysis/binary.h" + + + +/* Liste de tous les débogueurs */ +typedef enum _DebuggerType +{ + DGT_REMOTE_GDB, /* Utilisation de GDB */ + DGT_PTRACE, /* Utilisation de ptrace() */ + + DGT_COUNT + +} DebuggerType; + + +/* Transmission des valeurs des registres */ +typedef struct _register_value +{ + const char *name; /* Nom à ne pas libérer */ + uint64_t value; /* Valeur (taille maximale) */ + +} register_value; + + +#define G_TYPE_BINARY_DEBUGGER g_binary_debugger_get_type() +#define G_BINARY_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_debugger_get_type(), GBinaryDebugger)) +#define G_IS_BINARY_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_debugger_get_type())) +#define G_BINARY_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_DEBUGGER, GGBinaryDebuggerClass)) +#define G_IS_BINARY_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_DEBUGGER)) +#define G_BINARY_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_DEBUGGER, GGBinaryDebuggerClass)) + + +/* Définition des fonctionnalités d'un débogueur (instance) */ +typedef struct _GBinaryDebugger GBinaryDebugger; + +/* Définition des fonctionnalités d'un débogueur (classe) */ +typedef struct _GBinaryDebuggerClass GBinaryDebuggerClass; + + +/* Indique le type définit par la GLib pour le débogueur ptrace(). */ +GType g_binary_debugger_get_type(void); + +/* Crée un nouveau débogueur. */ +GBinaryDebugger *g_new_binary_debugger(DebuggerType, GOpenidaBinary *); + +/* Démarre une procédure de débogage. */ +void g_binary_debugger_run(GBinaryDebugger *); + +/* Reprend une procédure de débogage. */ +void g_binary_debugger_resume(GBinaryDebugger *); + +/* Tue une procédure de débogage. */ +void g_binary_debugger_kill(GBinaryDebugger *); + +/* Fournit la valeur des registres de l'architecture. */ +register_value *g_binary_debugger_get_registers(GBinaryDebugger *, size_t *); + + + +#endif /* _DEBUG_DEBUGGER_H */ diff --git a/src/debug/debuggers.c b/src/debug/debuggers.c index c9af67a..e69de29 100644 --- a/src/debug/debuggers.c +++ b/src/debug/debuggers.c @@ -1,197 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * debugger.sc - gestion des différents débogueurs - * - * Copyright (C) 2008 Cyrille Bagard - * - * This file is part of OpenIDA. - * - * 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 <http://www.gnu.org/licenses/>. - */ - - -#include "debuggers.h" - -#include "debugger-int.h" -#include "ptrace/ptrace.h" -#include "../gtkext/iodamarshal.h" - - - -/* Initialise la classe de base des débogueurs. */ -static void g_binary_debugger_class_init(GBinaryDebuggerClass *); - -/* Initialise une instance de base d'un débogueur. */ -static void g_binary_debugger_init(GBinaryDebugger *); - - - -/* Indique le type définit pour une ligne de représentation. */ -G_DEFINE_TYPE(GBinaryDebugger, g_binary_debugger, G_TYPE_OBJECT); - - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe de base des débogueurs. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_debugger_class_init(GBinaryDebuggerClass *klass) -{ - g_signal_new("debugger-stopped", - G_TYPE_BINARY_DEBUGGER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GBinaryDebuggerClass, debugger_stopped), - NULL, NULL, - g_cclosure_user_marshal_VOID__UINT64_UINT64, - G_TYPE_NONE, 2, G_TYPE_UINT64, G_TYPE_UINT64); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = instance à initialiser. * -* * -* Description : Initialise une instance de base d'un débogueur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_debugger_init(GBinaryDebugger *debugger) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : type = type de débigueur choisi pour l'opération. * -* binary = binaire devant être débogué. * -* * -* Description : Crée un nouveau débogueur. * -* * -* Retour : Composant GObject mis en place ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinaryDebugger *g_new_binary_debugger(DebuggerType type, GOpenidaBinary *binary) -{ - GBinaryDebugger *result; - - switch (type) - { - case DGT_PTRACE: - result = g_object_new(G_TYPE_PTRACE_DEBUGGER, NULL); - break; - default: - result = NULL; - break; - } - - if (result != NULL) - result->binary = binary; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* * -* Description : Démarre une procédure de débogage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_debugger_run(GBinaryDebugger *debugger) -{ - debugger->run(debugger); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* * -* Description : Reprend une procédure de débogage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_debugger_resume(GBinaryDebugger *debugger) -{ - debugger->resume(debugger); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* * -* Description : Tue une procédure de débogage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_debugger_kill(GBinaryDebugger *debugger) -{ - debugger->kill(debugger); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* count = nombre de transmissions effetuées. * -* * -* Description : Fournit la valeur des registres de l'architecture. * -* * -* Retour : Tableau de valeurs transmises à libérer de la mémoire / NULL.* -* * -* Remarques : - * -* * -******************************************************************************/ - -register_value *g_binary_debugger_get_registers(GBinaryDebugger *debugger, size_t *count) -{ - return debugger->get_reg_values(debugger, count); - -} diff --git a/src/debug/debuggers.h b/src/debug/debuggers.h index 90db12f..e69de29 100644 --- a/src/debug/debuggers.h +++ b/src/debug/debuggers.h @@ -1,91 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * debuggers.h - prototypes pour la gestion des différents débogueurs - * - * Copyright (C) 2008 Cyrille Bagard - * - * This file is part of OpenIDA. - * - * 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_DEBUGGER_H -#define _DEBUG_DEBUGGER_H - - -#include <glib-object.h> -#include <stdint.h> -#include <sys/types.h> - - -#include "../analysis/binary.h" - - - -/* Liste de tous les débogueurs */ -typedef enum _DebuggerType -{ - DGT_PTRACE, /* Utilisation de ptrace() */ - - DGT_COUNT - -} DebuggerType; - - -/* Transmission des valeurs des registres */ -typedef struct _register_value -{ - const char *name; /* Nom à ne pas libérer */ - uint64_t value; /* Valeur (taille maximale) */ - -} register_value; - - -#define G_TYPE_BINARY_DEBUGGER g_binary_debugger_get_type() -#define G_BINARY_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_debugger_get_type(), GBinaryDebugger)) -#define G_IS_BINARY_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_debugger_get_type())) -#define G_BINARY_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_DEBUGGER, GGBinaryDebuggerClass)) -#define G_IS_BINARY_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_DEBUGGER)) -#define G_BINARY_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_DEBUGGER, GGBinaryDebuggerClass)) - - -/* Définition des fonctionnalités d'un débogueur (instance) */ -typedef struct _GBinaryDebugger GBinaryDebugger; - -/* Définition des fonctionnalités d'un débogueur (classe) */ -typedef struct _GBinaryDebuggerClass GBinaryDebuggerClass; - - -/* Indique le type définit par la GLib pour le débogueur ptrace(). */ -GType g_binary_debugger_get_type(void); - -/* Crée un nouveau débogueur. */ -GBinaryDebugger *g_new_binary_debugger(DebuggerType, GOpenidaBinary *); - -/* Démarre une procédure de débogage. */ -void g_binary_debugger_run(GBinaryDebugger *); - -/* Reprend une procédure de débogage. */ -void g_binary_debugger_resume(GBinaryDebugger *); - -/* Tue une procédure de débogage. */ -void g_binary_debugger_kill(GBinaryDebugger *); - -/* Fournit la valeur des registres de l'architecture. */ -register_value *g_binary_debugger_get_registers(GBinaryDebugger *, size_t *); - - - -#endif /* _DEBUG_DEBUGGER_H */ diff --git a/src/debug/ptrace/ptrace.h b/src/debug/ptrace/ptrace.h index f0e2c2b..e309fb2 100644 --- a/src/debug/ptrace/ptrace.h +++ b/src/debug/ptrace/ptrace.h @@ -28,7 +28,7 @@ #include <glib-object.h> -#include "../debuggers.h" +#include "../debugger.h" diff --git a/src/debug/remgdb/Makefile.am b/src/debug/remgdb/Makefile.am index b2829c9..7ed26b0 100644 --- a/src/debug/remgdb/Makefile.am +++ b/src/debug/remgdb/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdebugremgdb.la libdebugremgdb_la_SOURCES = \ gdb.h gdb.c \ + helpers.h helpers.c \ packet.h packet.c \ stream-int.h \ stream.h stream.c \ diff --git a/src/debug/remgdb/gdb.c b/src/debug/remgdb/gdb.c index 068cf26..ea8e48e 100644 --- a/src/debug/remgdb/gdb.c +++ b/src/debug/remgdb/gdb.c @@ -23,7 +23,46 @@ #include "gdb.h" + +#include "../debugger-int.h" + + + +#include "helpers.h" +#include "tcp.h" + + + + +/* Débogueur utilisant un serveur GDB (instance) */ +struct _GGdbDebugger +{ + GBinaryDebugger parent; /* A laisser en premier */ + + GGdbStream *stream; /* Flux de communication */ + + #if 0 + GCond *cond; /* Poursuite du déroulement */ + GMutex *mutex; /* Accès à la condition */ + + ptrace_options *options; /* Configuration du débogage */ + + pid_t child; /* Processus suivi lancé */ + + gboolean run_again; /* Reprise du débogage */ +#endif +}; + +/* Débogueur utilisant un serveur GDB (classe) */ +struct _GGdbDebuggerClass +{ + GBinaryDebuggerClass parent; /* A laisser en premier */ + +}; + + + /* Initialise la classe du débogueur utilisant gdb. */ @@ -33,6 +72,16 @@ static void g_gdb_debugger_class_init(GGdbDebuggerClass *); static void g_gdb_debugger_init(GGdbDebugger *); +/* Met en marche le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_run(GGdbDebugger *); + +/* Remet en marche le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_resume(GGdbDebugger *); + +/* Tue le débogueur utilisant un serveur GDB. */ +static bool g_gdb_debugger_kill(GGdbDebugger *); + + /* Indique le type défini par la GLib pour le débogueur gdb. */ G_DEFINE_TYPE(GGdbDebugger, g_gdb_debugger, G_TYPE_BINARY_DEBUGGER); @@ -79,19 +128,49 @@ static void g_gdb_debugger_init(GGdbDebugger *debugger) parent->resume = (resume_debugger_fc)g_gdb_debugger_resume; parent->kill = (basic_debugger_fc)g_gdb_debugger_kill; - parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger; + //parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger; - debugger->cond = g_cond_new(); - debugger->mutex = g_mutex_new(); + //debugger->cond = g_cond_new(); + //debugger->mutex = g_mutex_new(); } /****************************************************************************** * * +* Paramètres : binary = binaire représenter à déboguer. * +* options = paramètres destinés au débogage. * +* * +* Description : Crée un débogueur utilisant un serveur GDB distant. * +* * +* Retour : Instance de débogueur mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinaryDebugger *g_gdb_debugger_new(GOpenidaBinary *binary, void *options) +{ + GBinaryDebugger *result; /* Débogueur à retourner */ + + result = g_object_new(G_TYPE_GDB_DEBUGGER, NULL); + + return result; + +} + + + + + + + + +/****************************************************************************** +* * * Paramètres : debugger = débogueur à lancer. * * * -* Description : Met en marche le débogueur utilisant gdb. * +* Description : Met en marche le débogueur utilisant un serveur GDB. * * * * Retour : Bilan de l'opération. * * * @@ -99,30 +178,68 @@ static void g_gdb_debugger_init(GGdbDebugger *debugger) * * ******************************************************************************/ -bool g_gdb_debugger_run(GGdbDebugger *debugger) +static bool g_gdb_debugger_run(GGdbDebugger *debugger) { - GError *error; /* Bilan de création de thread */ - if (debugger->options == NULL) - debugger->options = create_gdb_options_from_binary(G_BINARY_DEBUGGER(debugger)->binary); - if (debugger->options == NULL) - return false; + GGdbPacket *packet; + bool test; + + const char *data; + size_t len; + + + int sig; + vmpa_t addr; + pid_t thread; + + + debugger->stream = g_gdb_tcp_client_new("127.0.0.1", "6666"); + if (debugger->stream == NULL) return false; + + + printf("Connection done !\n"); + + + + packet = g_gdb_stream_get_free_packet(debugger->stream); + + g_gdb_packet_start_new_command(packet); + g_gdb_packet_append(packet, "?"); + + + test = g_gdb_stream_send_packet(debugger->stream, packet); + + + + printf(" >> Paquet '%s' bien envoyé ? %s\n", "?", test ? "oui" : "non"); + + + + g_gdb_stream_mark_packet_as_free(debugger->stream, packet); + + packet = g_gdb_stream_recv_packet(debugger->stream); + + g_gdb_packet_get_data(packet, &data, &len, NULL); + + printf(" << Réception de '%s'\n", data); + + + + + + get_stop_reply_sig_info(packet, &sig, &addr, &thread, SRE_LITTLE); + + g_signal_emit_by_name(debugger, "halted", sig, addr, thread); + + - if (!g_thread_create((GThreadFunc)gdb_thread, debugger, FALSE, &error)) - { - printf ("Failed to create the thread: %s\n", error->message); - } - /* - printf("Start Debugger with bin :: %p\n", G_BINARY_DEBUGGER_GET_IFACE(debugger)->binary); - g_signal_emit_by_name(debugger, "debugger-stopped", (uint64_t)0xdeadbeaf); - */ return true; } @@ -132,7 +249,7 @@ bool g_gdb_debugger_run(GGdbDebugger *debugger) * * * Paramètres : debugger = débogueur à relancer. * * * -* Description : Remet en marche le débogueur utilisant gdb(). * +* Description : Remet en marche le débogueur utilisant un serveur GDB. * * * * Retour : Bilan de l'opération. * * * @@ -140,13 +257,16 @@ bool g_gdb_debugger_run(GGdbDebugger *debugger) * * ******************************************************************************/ -bool g_gdb_debugger_resume(GGdbDebugger *debugger) +static bool g_gdb_debugger_resume(GGdbDebugger *debugger) { + + + /* g_mutex_lock(debugger->mutex); debugger->run_again = TRUE; g_cond_signal(debugger->cond); g_mutex_unlock(debugger->mutex); - + */ return true; } @@ -156,7 +276,7 @@ bool g_gdb_debugger_resume(GGdbDebugger *debugger) * * * Paramètres : debugger = débogueur à relancer. * * * -* Description : Tue le débogueur utilisant gdb(). * +* Description : Tue le débogueur utilisant un serveur GDB. * * * * Retour : Bilan de l'opération. * * * @@ -164,8 +284,11 @@ bool g_gdb_debugger_resume(GGdbDebugger *debugger) * * ******************************************************************************/ -bool g_gdb_debugger_kill(GGdbDebugger *debugger) +static bool g_gdb_debugger_kill(GGdbDebugger *debugger) { + + +#if 0 int ret; /* Bilan de l'appel système */ ret = kill(debugger->child, SIGKILL); @@ -177,19 +300,11 @@ bool g_gdb_debugger_kill(GGdbDebugger *debugger) debugger->run_again = TRUE; g_cond_signal(debugger->cond); g_mutex_unlock(debugger->mutex); - +#endif return true; } -#endif - - - - - - -#include "tcp.h" diff --git a/src/debug/remgdb/gdb.h b/src/debug/remgdb/gdb.h index 2812afd..dfd2f69 100644 --- a/src/debug/remgdb/gdb.h +++ b/src/debug/remgdb/gdb.h @@ -28,9 +28,9 @@ #include <glib-object.h> -#include "../debuggers.h" +#include "../debugger.h" + -#if 0 #define G_TYPE_GDB_DEBUGGER (g_gdb_debugger_get_type()) #define G_GDB_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_DEBUGGER, GGdbDebugger)) @@ -40,18 +40,18 @@ #define G_GDB_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) -/* Débogueur utilisant gdb (instance) */ +/* Débogueur utilisant un serveur GDB (instance) */ typedef struct _GGdbDebugger GGdbDebugger; -/* Débogueur utilisant gdb (classe) */ +/* Débogueur utilisant un serveur GDB (classe) */ typedef struct _GGdbDebuggerClass GGdbDebuggerClass; /* Indique le type défini par la GLib pour le débogueur gdb. */ GType g_gdb_debugger_get_type(void); -#endif - +/* Crée un débogueur utilisant un serveur GDB distant. */ +GBinaryDebugger *g_gdb_debugger_new(GOpenidaBinary *, void *); void test_gdb(void); diff --git a/src/debug/remgdb/helpers.c b/src/debug/remgdb/helpers.c new file mode 100644 index 0000000..9451b08 --- /dev/null +++ b/src/debug/remgdb/helpers.c @@ -0,0 +1,139 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * helpers.c - assistanat dans la manipulation des paquets GDB + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "helpers.h" + + +#include <regex.h> +#include <string.h> + + + + + + + + + + + + + + + + +/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */ + + + + + + +/****************************************************************************** +* * +* Paramètres : packet = paquet de deonnées à interpréter. * +* sig = identifiant du signal source. [OUT] * +* addr = adresse de l'instruction courante. [OUT] * +* thread = identifiant du thread concerné. [OUT] * +* endian = boutisme de la plateforme ciblée. * +* * +* Description : Récupère les informations liées à un arrêt suite à signal. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : Les données sont la forme : * +* T0505:00000000;04:a08de6bf;08:505878b7;thread:50dc; * +* * +******************************************************************************/ + +bool get_stop_reply_sig_info(const GGdbPacket *packet, int *sig, vmpa_t *addr, pid_t *thread, SourceEndian endian) +{ + const char *data; /* Données brutes du paquet */ + size_t length; /* Quantité de ces données */ + uint8_t index; /* Indice de 8 bits quelconque */ + size_t pos; /* Tête de lecture courante */ + regex_t preg; /* Expression régulière */ + int ret; /* Bilan d'un appel */ + regmatch_t pmatch[3]; /* Zones remarquées */ + size_t key_len; /* Taille de l'indicatif */ + + *addr = 0ull; + + g_gdb_packet_get_data(packet, &data, &length, NULL); + + pos = 1; + + /* Lecture du numéro du signal */ + + if (!strtou8(&index, data, &pos, length, SRE_LITTLE)) + return false; + + *sig = index; + + /* Reste des informations */ + + ret = regcomp(&preg, "([^:]+):([^;]+);", REG_EXTENDED | REG_ICASE); + if (ret != 0) return false; + + for (ret = regexec(&preg, &data[pos], 3, pmatch, 0); + ret != REG_NOMATCH; + ret = regexec(&preg, &data[pos], 3, pmatch, 0)) + { + key_len = pmatch[1].rm_eo - pmatch[1].rm_so; + + /* Indication sur le thread */ + if (key_len == strlen("thread") + && strncmp(&data[pos + pmatch[1].rm_so], "thread", key_len) == 0) + { + + /* TODO printf("Thread found !\n"); */ + + } + + /* Valeur de registre ? */ + else if (key_len == 2) + { + if (!strtou8(&index, data, (size_t []) { pos + pmatch[1].rm_so }, length, SRE_LITTLE)) + return false; + + if (index != 8 /* FIXME */) + goto next_field; + + if (!strtou32(addr, data, (size_t []) { pos + pmatch[2].rm_so }, length, SRE_LITTLE/* FIXME */)) + return false; + + } + + next_field: + pos += pmatch[0].rm_eo; + + } + + regfree(&preg); + + return (*addr != 0ull); + +} + + + diff --git a/src/debug/remgdb/helpers.h b/src/debug/remgdb/helpers.h new file mode 100644 index 0000000..d6888d0 --- /dev/null +++ b/src/debug/remgdb/helpers.h @@ -0,0 +1,61 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * helpers.h - prototypes pour un assistanat dans la manipulation des paquets GDB + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DEBUG_REMGDB_HELPERS_H +#define _DEBUG_REMGDB_HELPERS_H + + +#include "packet.h" + + +#include "../../arch/archbase.h" +#include "../../common/endianness.h" + + + + + + + +/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */ + + +/* Récupère les informations liées à un arrêt suite à signal. */ +bool get_stop_reply_sig_info(const GGdbPacket *, int *, vmpa_t *, pid_t *, SourceEndian); + + + +/* ---------------------------------------------------------------------------------- */ +/* PAQUETS DES REPONSES D'ARRET */ +/* ---------------------------------------------------------------------------------- */ + + + + + + + + + + +#endif /* _DEBUG_REMGDB_HELPERS_H */ diff --git a/src/debug/remgdb/packet.c b/src/debug/remgdb/packet.c index 3fd3cba..acdec1d 100644 --- a/src/debug/remgdb/packet.c +++ b/src/debug/remgdb/packet.c @@ -333,7 +333,7 @@ bool g_gdb_packet_decode(GGdbPacket *packet) * * ******************************************************************************/ -void g_gdb_packet_get_data(GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum) +void g_gdb_packet_get_data(const GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum) { *data = packet->buffer; *len = packet->len; diff --git a/src/debug/remgdb/packet.h b/src/debug/remgdb/packet.h index 30be43e..9276e62 100644 --- a/src/debug/remgdb/packet.h +++ b/src/debug/remgdb/packet.h @@ -69,7 +69,7 @@ bool g_gdb_packet_verify_checksum(GGdbPacket *, uint8_t); bool g_gdb_packet_decode(GGdbPacket *); /* Fournit le contenu du paquet. */ -void g_gdb_packet_get_data(GGdbPacket *, const char **, size_t *, uint8_t *); +void g_gdb_packet_get_data(const GGdbPacket *, const char **, size_t *, uint8_t *); /* Ajoute un paquet à une liste de paquets. */ void g_gdb_packet_push(GGdbPacket **, GGdbPacket *); diff --git a/src/debug/remgdb/stream.c b/src/debug/remgdb/stream.c index 2b487ad..0f17930 100644 --- a/src/debug/remgdb/stream.c +++ b/src/debug/remgdb/stream.c @@ -41,6 +41,9 @@ static void g_gdb_stream_class_init(GGdbStreamClass *); /* Initialise une instance de flux de communication avec GDB. */ static void g_gdb_stream_init(GGdbStream *); +/* Envoie un acquittement pour la dernière réception. */ +static bool gdb_stream_ack(GGdbStream *); + /* Ecoute une connexion à un serveur GDB. */ static void *gdb_stream_thread(GGdbStream *); @@ -124,6 +127,37 @@ bool g_gdb_stream_listen(GGdbStream *stream) * * * Paramètres : stream = encadrement associée à l'opération. * * * +* Description : Envoie un acquittement pour la dernière réception. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool gdb_stream_ack(GGdbStream *stream) +{ + bool result; /* Bilan à retourner */ + GGdbPacket *packet; /* Paquet à envoyer */ + + packet = g_gdb_stream_get_free_packet(stream); + + g_gdb_packet_start_new_command(packet); + g_gdb_packet_append(packet, "+"); + + result = g_gdb_stream_send_packet(stream, packet); + + g_gdb_stream_mark_packet_as_free(stream, packet); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = encadrement associée à l'opération. * +* * * Description : Ecoute une connexion à un serveur GDB. * * * * Retour : ??? * @@ -145,6 +179,8 @@ static void *gdb_stream_thread(GGdbStream *stream) ret = select(stream->fd + 1, &rfds, NULL, NULL, NULL); + printf("ret :: %d\n", ret); + switch (ret) { case -1: @@ -162,6 +198,11 @@ static void *gdb_stream_thread(GGdbStream *stream) if (g_gdb_stream_read_packet(stream, packet)) { + /* Acquittement */ + if (!gdb_stream_ack(stream)) goto bad_recv; + + /* On conserve le résultat */ + g_mutex_lock(stream->recv_mutex); g_gdb_packet_push(&stream->recv_packets, packet); g_mutex_unlock(stream->recv_mutex); @@ -169,7 +210,12 @@ static void *gdb_stream_thread(GGdbStream *stream) g_cond_signal(stream->recv_cond); } - else g_gdb_stream_mark_packet_as_free(stream, packet); + + bad_recv: + + printf("bad things happend...\n"); + + g_gdb_stream_mark_packet_as_free(stream, packet); break; diff --git a/src/editor.c b/src/editor.c index f038de6..c446234 100644 --- a/src/editor.c +++ b/src/editor.c @@ -48,7 +48,7 @@ #include "gtkext/gtkblockview.h" #include "gtkext/gtkdockpanel.h" -#include "debug/debuggers.h" +#include "debug/debugger.h" #include "dialogs/about.h" #include "dialogs/binparts.h" #include "dialogs/export.h" @@ -126,7 +126,7 @@ static void mcb_binary_select_plugins(GtkMenuItem *, GObject *); static void mcb_binary_export(GtkMenuItem *, GObject *); -/*Réagit avec le menu "Débogage -> Démarrer". */ +/* Réagit avec le menu "Débogage -> Démarrer". */ void mcb_debug_start(GtkCheckMenuItem *, gpointer); /* Réagit avec le menu "Débogage -> Mettre en pause". */ @@ -162,6 +162,12 @@ static void refresh_editor_menus(GObject *, GOpenidaBinary *, GtkBinView *); +/* ------------------------- PARTIE DEDIEE AU MODE DEBOGAGE ------------------------- */ + + +/* Prend note d'une pause dans le débogage. */ +static void on_debugger_halted(GBinaryDebugger *, int, vmpa_t, pid_t, GObject *); + @@ -1271,12 +1277,14 @@ void mcb_debug_start(GtkCheckMenuItem *menuitem, gpointer data) - debugger = g_new_binary_debugger(DGT_PTRACE, binary); + debugger = g_new_binary_debugger(DGT_REMOTE_GDB, binary); g_object_set_data(G_OBJECT(data), "current_debugger", debugger); g_signal_connect(debugger, "debugger-stopped", G_CALLBACK(debugger_stopped_cb), data); + g_signal_connect(debugger, "halted", G_CALLBACK(on_debugger_halted), data); + g_binary_debugger_run(debugger); @@ -1450,6 +1458,7 @@ static void mcb_help_about(GtkMenuItem *menuitem, GObject *ref) static void on_dock_item_switch(GtkDockPanel *panel, GDockItem *item, GObject *ref) { GtkWidget *widget; /* Support réel à traiter */ + GOpenidaBinary *old_binary; /* Ancien binaire édité */ GOpenidaBinary *binary; /* Binaire en cours d'édition */ widget = g_dock_item_get_panel(item); @@ -1462,9 +1471,17 @@ static void on_dock_item_switch(GtkDockPanel *panel, GDockItem *item, GObject *r if (GTK_IS_BIN_VIEW(widget)) { + /* Changement de binaire ? */ + + old_binary = G_OPENIDA_BINARY(g_object_get_data(ref, "current_binary")); binary = gtk_bin_view_get_binary(GTK_BIN_VIEW(widget)); - g_object_set_data(ref, "current_binary", binary); + if (old_binary != binary) + { + g_object_set_data(ref, "current_binary", binary); + notify_panels_of_binary_change(binary); + } + g_object_set_data(ref, "binview", widget); refresh_editor_menus(ref, binary, GTK_BIN_VIEW(widget)); @@ -1520,3 +1537,43 @@ static void refresh_editor_menus(GObject *ref, GOpenidaBinary *binary, GtkBinVie g_signal_connect(menuitem, "toggled", G_CALLBACK(mcb_view_change_support), ref); } + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE DEDIEE AU MODE DEBOGAGE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur intervenant dans l'action. * +* sig = identifiant du signal source (nul si indéterminé).* +* addr = adresse de l'instruction courante. * +* thread = identifiant du thread concerné. * +* ref = espace de référencement global. * +* * +* Description : Prend note d'une pause dans le débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_debugger_halted(GBinaryDebugger *debugger, int sig, vmpa_t addr, pid_t thread, GObject *ref) +{ + + printf("HALT (sig=%d) at 0x%016llx\n", sig, addr); + + + + +} diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 7712965..1e21b58 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -6,7 +6,8 @@ libglibext_la_SOURCES = \ delayed.h delayed.c \ gbufferline.h gbufferline.c \ gbuffersegment.h gbuffersegment.c \ - gcodebuffer.h gcodebuffer.c + gcodebuffer.h gcodebuffer.c \ + proto.h libglibext_la_LDFLAGS = diff --git a/src/glibext/proto.h b/src/glibext/proto.h new file mode 100644 index 0000000..5831e11 --- /dev/null +++ b/src/glibext/proto.h @@ -0,0 +1,42 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * proto.h - prototypes supplémentaires pour les fonctions GLib + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GLIBEXT_PROTO_H +#define _GLIBEXT_PROTO_H + + +#include <glib-object.h> + + + +/** + * Boucle de parcours avec plusieurs arguments : + * - #1 : conteneur. + * - #2 : élément parcouru. + * - #3 : éventuelle donnée de l'utilisateur. + */ +typedef void (* GExtFunc) (gpointer container, gpointer item, gpointer data); + + + +#endif /* _GLIBEXT_PROTO_H */ diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c index 5c5d0f6..a19c17a 100644 --- a/src/gtkext/gtkblockview.c +++ b/src/gtkext/gtkblockview.c @@ -663,8 +663,10 @@ static gboolean gtk_block_view_button_press(GtkWidget *widget, GdkEventButton *e { line = G_RENDERING_LINE(g_object_get_data(G_OBJECT(bline), "line")); + g_openida_binary_toggle_breakpoint(GTK_BIN_VIEW(view)->binary, + get_rendering_line_address(line)); + result = TRUE; - g_rendering_line_toggle_flag(line, RLF_BREAK_POINT); } @@ -38,7 +38,6 @@ #include "plugins/pglist.h" -/////void test_gdb(void); //extern test_itanium_demangling(name_demangler *); @@ -80,16 +79,6 @@ int main(int argc, char **argv) gtk_set_locale(); gtk_init(&argc, &argv); - - /* - test_gdb(); - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - */ - - - /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared diff --git a/src/panels/Makefile.am b/src/panels/Makefile.am index 2ab4bad..0db863a 100755 --- a/src/panels/Makefile.am +++ b/src/panels/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libpanels.la libpanels_la_SOURCES = \ + breaks.h breaks.c \ glimpse.h glimpse.c \ log.h log.c \ panel-int.h \ diff --git a/src/panels/breaks.c b/src/panels/breaks.c new file mode 100644 index 0000000..5455aed --- /dev/null +++ b/src/panels/breaks.c @@ -0,0 +1,454 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * breaks.c - panneau d'affichage des points d'arrêt + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "breaks.h" + + +#include "panel-int.h" +#include "../gtkext/easygtk.h" +#include "../gtkext/support.h" + + + +#define _(str) str + + +/* Panneau d'affichage des points d'arrêt (instance) */ +struct _GBreaksPanel +{ + GEditorPanel parent; /* A laisser en premier */ + + GtkTreeView *treeview; /* Composant d'affichage */ + GtkTreeStore *store; /* Modèle de gestion */ + + GOpenidaBinary *binary; /* Binaire en cours d'étude */ + +}; + + +/* Panneau d'affichage des points d'arrêt (classe) */ +struct _GBreaksPanelClass +{ + GEditorPanelClass parent; /* A laisser en premier */ + +}; + + +/* Colonnes de la liste des symboles */ +typedef enum _BreaksColumn +{ + BKC_POINT, /* Point d'arrêt de référence */ + BKC_ICON, /* Statut du point d'arrêt */ + BKC_ADDRESS, /* Adresse mémoire du symbole */ + BKC_STRING, /* Désignation humaine */ + + BKC_COUNT /* Nombre de colonnes */ + +} BreaksColumn; + + +/* Initialise la classe des panneaux de points d'arrêt. */ +static void g_breaks_panel_class_init(GBreaksPanelClass *); + +/* Initialise une instance de panneau de points d'arrêt. */ +static void g_breaks_panel_init(GBreaksPanel *); + +/* Réagit à un changement du binaire courant. */ +static void reload_breaks_for_new_binary(GBreaksPanel *, GOpenidaBinary *); + + + + +/* Intègre à l'affichage un groupe de points d'arrêt. */ +static void add_bp_group_to_breaks_panel(GOpenidaBinary *, GBreakGroup *, GBreaksPanel *); + +/* Réagit à une nouvelle création de point d'arrêt. */ +static void refresh_breaks_panel_on_bp_added(GBreakGroup *, GBreakPoint *, GBreaksPanel *); + +/* Réagit à une suppression de point d'arrêt. */ +static void refresh_breaks_panel_on_bp_removed(GBreakGroup *, GBreakPoint *, GBreaksPanel *); + +/* Réagit à une modification de point d'arrêt. */ +static void refresh_breaks_panel_on_bp_changed(GBreakGroup *, GBreakPoint *, GBreaksPanel *); + + + + +/* Retrouve un point d'arrêt dans la liste affichée. */ +static bool find_breakpoint_in_breaks_panel(GBreaksPanel *, GBreakPoint *, GtkTreeIter *); + + + +/* Indique le type définit pour un panneau d'affichage des points d'arrêt. */ +G_DEFINE_TYPE(GBreaksPanel, g_breaks_panel, G_TYPE_EDITOR_PANEL); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des panneaux de points d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_breaks_panel_class_init(GBreaksPanelClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : panel = instance à initialiser. * +* * +* Description : Initialise une instance de panneau de points d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_breaks_panel_init(GBreaksPanel *panel) +{ + GEditorPanel *base; /* Version basique d'instance */ + GObject *ref; /* Espace de référencement */ + GtkTooltips *tooltips; /* Affichage des bulles d'aide */ + GtkWidget *toolbar; /* Barre d'outils */ + GtkWidget *button; /* Bouton de cette même barre */ + GtkWidget *separator; /* Barre de séparation vert. */ + GtkWidget *scrollwnd; /* Support défilant */ + GtkWidget *treeview; /* Affichage de la liste */ + GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ + GtkTreeViewColumn *column; /* Colonne de la liste */ + GtkTreeSelection *select; /* Sélection dans la liste */ + + + + + base = G_EDITOR_PANEL(panel); + + base->name = _("Breakpoints"); + base->reload_binary = (reload_for_new_binary_fc)reload_breaks_for_new_binary; + + base->widget = gtk_vbox_new(FALSE, 0); + gtk_widget_show(base->widget); + + ref = G_OBJECT(base->widget); + g_object_set_data(ref, "panel", panel); + + scrollwnd = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrollwnd); + gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); + + panel->store = gtk_tree_store_new(BKC_COUNT, G_TYPE_OBJECT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); + + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(panel->store)); + gtk_widget_show(treeview); + gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); + + panel->treeview = GTK_TREE_VIEW(treeview); + + g_object_unref(G_OBJECT(panel->store)); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column); + + + + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(column, _("Address")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(column, renderer, FALSE); + gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", BKC_ICON); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, "text", BKC_ADDRESS); + + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + + + + //renderer = gtk_cell_renderer_text_new(); + //column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer, "text", BKC_ADDRESS, NULL); + //gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("String"), renderer, "text", BKC_STRING, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + + + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un panneau d'aperçu de graphiques. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GEditorPanel *g_breaks_panel_new(void) +{ + GEditorPanel *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BREAKS_PANEL, NULL); + + return G_EDITOR_PANEL(result); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau à mettre à jour. * +* binary = nouvelle instance de binaire analysé. * +* * +* Description : Réagit à un changement du binaire courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reload_breaks_for_new_binary(GBreaksPanel *panel, GOpenidaBinary *binary) +{ + + printf("CHNAGE BINARY !\n"); + + panel->binary = binary; + + g_openida_binary_for_each_bp_group(binary, (GExtFunc)add_bp_group_to_breaks_panel, panel); + + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : binary = instance active du binaire analysé. * +* group = groupe de points d'arrêt présent dans le binaire. * +* panel = panneau à mettre à jour. * +* * +* Description : Intègre à l'affichage un groupe de points d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void add_bp_group_to_breaks_panel(GOpenidaBinary *binary, GBreakGroup *group, GBreaksPanel *panel) +{ + /* FIXME : bloquer toute émission de signal tant que les ajouts ne sont pas terminés. */ + + g_signal_connect(group, "added", + G_CALLBACK(refresh_breaks_panel_on_bp_added), panel); + + g_signal_connect(group, "removed", + G_CALLBACK(refresh_breaks_panel_on_bp_removed), panel); + + g_break_group_for_each(group, (GExtFunc)refresh_breaks_panel_on_bp_added, panel); + +} + + +/****************************************************************************** +* * +* Paramètres : group = ensemble de points d'arrêt intervenant. * +* point = point d'arrêt à l'origine de la procédure. * +* panel = panneau à mettre à jour. * +* * +* Description : Réagit à une nouvelle création de point d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void refresh_breaks_panel_on_bp_added(GBreakGroup *group, GBreakPoint *point, GBreaksPanel *panel) +{ + GExeFormat *format; /* Format associé au binaire */ + GArchProcessor *proc; /* Architecture utilisée */ + char address[VMPA_MAX_SIZE]; /* Conversion de l'adresse */ + GtkTreeIter iter; /* Point d'insertion */ + + format = g_openida_binary_get_format(panel->binary); + proc = get_arch_processor_from_format(format); + + vmpa_to_string(g_break_point_get_address(point), + g_arch_processor_get_memory_size(proc), + address); + + gtk_tree_store_append(panel->store, &iter, NULL); + gtk_tree_store_set(panel->store, &iter, + BKC_POINT, point, + BKC_ADDRESS, address, + BKC_STRING, "???", + -1); + + /* Pour le reste... */ + refresh_breaks_panel_on_bp_changed(group, point, panel); + +} + + +/****************************************************************************** +* * +* Paramètres : group = ensemble de points d'arrêt intervenant. * +* point = point d'arrêt à l'origine de la procédure. * +* panel = panneau à mettre à jour. * +* * +* Description : Réagit à une suppression de point d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void refresh_breaks_panel_on_bp_removed(GBreakGroup *group, GBreakPoint *point, GBreaksPanel *panel) +{ + GtkTreeIter iter; /* Point de modification */ + + if (!find_breakpoint_in_breaks_panel(panel, point, &iter)) + return; + + gtk_tree_store_remove(panel->store, &iter); + +} + + +/****************************************************************************** +* * +* Paramètres : group = ensemble de points d'arrêt intervenant. * +* point = point d'arrêt à l'origine de la procédure. * +* panel = panneau à mettre à jour. * +* * +* Description : Réagit à une modification de point d'arrêt. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void refresh_breaks_panel_on_bp_changed(GBreakGroup *group, GBreakPoint *point, GBreaksPanel *panel) +{ + GtkTreeIter iter; /* Point de modification */ + GdkPixbuf *pixbuf; /* Tampon d'image chargé */ + + if (!find_breakpoint_in_breaks_panel(panel, point, &iter)) + return; + + pixbuf = get_pixbuf_from_file("breakpoint_normal.png"); + if (pixbuf == NULL) return; + + gtk_tree_store_set(panel->store, &iter, + BKC_ICON, pixbuf, + -1); + +} + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : panel = panneau d'affichage à consulter. * +* point = point d'arrêt lié à la procédure. * +* * +* Description : Retrouve un point d'arrêt dans la liste affichée. * +* * +* Retour : Bilan de la recherche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool find_breakpoint_in_breaks_panel(GBreaksPanel *panel, GBreakPoint *point, GtkTreeIter *iter) +{ + bool result; /* Bilan à retourner */ + GtkTreeIter tmp; /* Sauvegarde temporaire */ + bool test; /* Valide la poursuite */ + GBreakPoint *bp; /* Adresse à comparer */ + + result = false; + + for (test = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(panel->store), &tmp); + test && !result; + test = gtk_tree_model_iter_next(GTK_TREE_MODEL(panel->store), &tmp)) + { + gtk_tree_model_get(GTK_TREE_MODEL(panel->store), + &tmp, BKC_POINT, &bp, -1); + + if (bp == point) + { + *iter = tmp; + result = true; + } + + } + + return result; + +} diff --git a/src/panels/breaks.h b/src/panels/breaks.h new file mode 100644 index 0000000..7a32e31 --- /dev/null +++ b/src/panels/breaks.h @@ -0,0 +1,59 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * breaks.h - prototypes pour le panneau d'affichage des points d'arrêt + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PANELS_BREAKS_H +#define _PANELS_BREAKS_H + + +#include <glib-object.h> + + +#include "panel.h" + + + +#define G_TYPE_BREAKS_PANEL g_breaks_panel_get_type() +#define G_BREAKS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_breaks_panel_get_type(), GBreaksPanel)) +#define G_IS_BREAKS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_breaks_panel_get_type())) +#define G_BREAKS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BREAKS_PANEL, GBreaksPanelClass)) +#define G_IS_BREAKS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BREAKS_PANEL)) +#define G_BREAKS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BREAKS_PANEL, GBreaksPanelClass)) + + +/* Panneau d'affichage des points d'arrêt (instance) */ +typedef struct _GBreaksPanel GBreaksPanel; + +/* Panneau d'affichage des points d'arrêt (classe) */ +typedef struct _GBreaksPanelClass GBreaksPanelClass; + + +/* Indique le type définit pour un panneau d'affichage des points d'arrêt. */ +GType g_breaks_panel_get_type(void); + +/* Crée un panneau d'affichage des points d'arrêt. */ +GEditorPanel *g_breaks_panel_new(void); + + + +#endif /* _PANELS_BREAKS_H */ diff --git a/src/panels/panel-int.h b/src/panels/panel-int.h index 417665f..0048d19 100644 --- a/src/panels/panel-int.h +++ b/src/panels/panel-int.h @@ -34,6 +34,9 @@ +/* Réagit à un changement du binaire courant. */ +typedef void (* reload_for_new_binary_fc) (GEditorPanel *, GOpenidaBinary *); + /* Réagit à un changement d'affichage principal de contenu. */ typedef void (* reload_for_new_view_fc) (GEditorPanel *, GtkBinView *, bool); @@ -47,6 +50,7 @@ struct _GEditorPanel const char *name; /* Nom du panneau */ + reload_for_new_binary_fc reload_binary; /* Changement de binaire */ reload_for_new_view_fc reload_view; /* Rechargement dû à une vue */ GtkWidget *widget; /* Composant GTK d'affichage */ diff --git a/src/panels/panel.c b/src/panels/panel.c index 9cf3f98..c9acac9 100644 --- a/src/panels/panel.c +++ b/src/panels/panel.c @@ -25,6 +25,7 @@ #include "panel.h" +#include "breaks.h" #include "glimpse.h" #include "panel-int.h" #include "symbols.h" @@ -143,6 +144,9 @@ void init_internal_panels(void) { GEditorPanel *panel; /* Nouveau panneau chargé */ + panel = g_breaks_panel_new(); + panels_list_add_tail(panel, &panels_list); + panel = g_symbols_panel_new(); panels_list_add_tail(panel, &panels_list); @@ -180,6 +184,29 @@ void place_all_panels_in_editor(GtkWidget *top) /****************************************************************************** * * +* Paramètres : binary = nouvelle instance de binaire analysé. * +* * +* Description : Lance une actualisation du fait d'un changement de binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void notify_panels_of_binary_change(GOpenidaBinary *binary) +{ + GEditorPanel *iter; /* Boucle de parcours */ + + panels_list_for_each(iter, panels_list) + if (iter->reload_binary != NULL) + iter->reload_binary(iter, binary); + +} + + +/****************************************************************************** +* * * Paramètres : view = nouvelle visualisation de désassemblage. * * same = changement de binaire ou de vue ? * * * diff --git a/src/panels/panel.h b/src/panels/panel.h index 1a94ebc..38eeb79 100644 --- a/src/panels/panel.h +++ b/src/panels/panel.h @@ -76,6 +76,9 @@ void init_internal_panels(void); /* Incruste tous les panneaux dans la fenêtre de l'éditeur. */ void place_all_panels_in_editor(GtkWidget *); +/* Lance une actualisation du fait d'un changement de binaire. */ +void notify_panels_of_binary_change(GOpenidaBinary *); + /* Lance une actualisation du fait d'un changement de vue. */ void notify_panels_of_view_change(GtkBinView *, bool); diff --git a/src/panels/registers.h b/src/panels/registers.h index 7110414..0abf849 100644 --- a/src/panels/registers.h +++ b/src/panels/registers.h @@ -29,7 +29,7 @@ #include <gtk/gtk.h> -#include "../debug/debuggers.h" +#include "../debug/debugger.h" diff --git a/src/panels/symbols.c b/src/panels/symbols.c index d24bedf..e3c9bd4 100644 --- a/src/panels/symbols.c +++ b/src/panels/symbols.c @@ -26,7 +26,6 @@ #include <string.h> -#include <gtk/gtk.h> #include "panel-int.h" |