diff options
Diffstat (limited to 'src/debug/remgdb')
-rw-r--r-- | src/debug/remgdb/Makefile.am | 18 | ||||
-rw-r--r-- | src/debug/remgdb/gdb.c | 248 | ||||
-rw-r--r-- | src/debug/remgdb/gdb.h | 61 | ||||
-rw-r--r-- | src/debug/remgdb/packet.c | 383 | ||||
-rw-r--r-- | src/debug/remgdb/packet.h | 82 | ||||
-rw-r--r-- | src/debug/remgdb/stream-int.h | 74 | ||||
-rw-r--r-- | src/debug/remgdb/stream.c | 357 | ||||
-rw-r--r-- | src/debug/remgdb/stream.h | 65 | ||||
-rw-r--r-- | src/debug/remgdb/tcp.c | 261 | ||||
-rw-r--r-- | src/debug/remgdb/tcp.h | 56 |
10 files changed, 1605 insertions, 0 deletions
diff --git a/src/debug/remgdb/Makefile.am b/src/debug/remgdb/Makefile.am new file mode 100644 index 0000000..ab6715d --- /dev/null +++ b/src/debug/remgdb/Makefile.am @@ -0,0 +1,18 @@ + +lib_LIBRARIES = libdebugremgdb.a + +libdebugremgdb_a_SOURCES = \ + gdb.h gdb.c \ + packet.h packet.c \ + stream-int.h \ + stream.h stream.c \ + tcp.h tcp.c + +libdebugremgdb_a_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/debug/remgdb/gdb.c b/src/debug/remgdb/gdb.c new file mode 100644 index 0000000..068cf26 --- /dev/null +++ b/src/debug/remgdb/gdb.c @@ -0,0 +1,248 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gdb.c - débogage à l'aide de gdb. + * + * Copyright (C) 2009 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 "gdb.h" + +#if 0 + + +/* Initialise la classe du débogueur utilisant gdb. */ +static void g_gdb_debugger_class_init(GGdbDebuggerClass *); + +/* Procède à l'initialisation du débogueur utilisant gdb. */ +static void g_gdb_debugger_init(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); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe de débogueur à initialiser. * +* * +* Description : Initialise la classe du débogueur utilisant gdb. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_debugger_class_init(GGdbDebuggerClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = instance de débogueur à préparer. * +* * +* Description : Procède à l'initialisation du débogueur utilisant gdb. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_debugger_init(GGdbDebugger *debugger) +{ + GBinaryDebugger *parent; /* Instance parente */ + + parent = G_BINARY_DEBUGGER(debugger); + + parent->run = (basic_debugger_fc)g_gdb_debugger_run; + 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; + + debugger->cond = g_cond_new(); + debugger->mutex = g_mutex_new(); + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à lancer. * +* * +* Description : Met en marche le débogueur utilisant gdb. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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; + + + + + 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; + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à relancer. * +* * +* Description : Remet en marche le débogueur utilisant gdb(). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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; + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = débogueur à relancer. * +* * +* Description : Tue le débogueur utilisant gdb(). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_gdb_debugger_kill(GGdbDebugger *debugger) +{ + int ret; /* Bilan de l'appel système */ + + ret = kill(debugger->child, SIGKILL); + if (ret != 0) perror("kill"); + + debugger->child = 0; + + g_mutex_lock(debugger->mutex); + debugger->run_again = TRUE; + g_cond_signal(debugger->cond); + g_mutex_unlock(debugger->mutex); + + return true; + +} + +#endif + + + + + + +#include "tcp.h" + + + + + + + + + + + +void test_gdb(void) +{ + + GGdbStream *stream; + + GGdbPacket *packet; + + bool test; + + const char *data; + size_t len; + + printf("GDB !!!!\n"); + + + stream = g_gdb_tcp_client_new("192.168.100.141", "6666"); + + + + packet = g_gdb_stream_get_free_packet(stream); + + g_gdb_packet_start_new_command(packet); + g_gdb_packet_append(packet, "g"); + + + test = g_gdb_stream_send_packet(stream, packet); + + + + printf(" >> Paquet '%s' bien envoyé ? %s\n", "g", test ? "oui" : "non"); + + + + g_gdb_stream_mark_packet_as_free(stream, packet); + + packet = g_gdb_stream_recv_packet(stream); + + g_gdb_packet_get_data(packet, &data, &len, NULL); + + printf(" << Réception de '%s'\n", data); + + + + +} diff --git a/src/debug/remgdb/gdb.h b/src/debug/remgdb/gdb.h new file mode 100644 index 0000000..2812afd --- /dev/null +++ b/src/debug/remgdb/gdb.h @@ -0,0 +1,61 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gdb.h - prototypes pour le débogage à l'aide de gdb. + * + * Copyright (C) 2009 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_GDB_H +#define _DEBUG_REMGDB_GDB_H + + +#include <glib-object.h> + + +#include "../debuggers.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)) +#define G_IS_GDB_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_DEBUGGER)) +#define G_GDB_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) +#define G_IS_GDB_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_DEBUGGER)) +#define G_GDB_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) + + +/* Débogueur utilisant gdb (instance) */ +typedef struct _GGdbDebugger GGdbDebugger; + +/* Débogueur utilisant 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 + + + +void test_gdb(void); + + + +#endif /* _DEBUG_REMGDB_GDB_H */ diff --git a/src/debug/remgdb/packet.c b/src/debug/remgdb/packet.c new file mode 100644 index 0000000..3fd3cba --- /dev/null +++ b/src/debug/remgdb/packet.c @@ -0,0 +1,383 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.c - manipulation des paquets de données GDB. + * + * Copyright (C) 2009 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 "packet.h" + + +#include <malloc.h> +#include <string.h> + + +#include "../../common/dllist.h" + + + +/* Répresentation d'un paquet GDB (instance) */ +struct _GGdbPacket +{ + GObject parent; /* A laisser en premier */ + + DL_LIST_ITEM(link); /* Lien vers les autres */ + + char *buffer; /* Données à traiter */ + size_t len; /* Quantité de ces données */ + size_t allocated; /* Taille du tampon */ + + uint8_t checksum; /* Empreinte de contrôle */ + +}; + + +/* Répresentation d'un paquet GDB (classe) */ +struct _GGdbPacketClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des représentations des paquets GDB. */ +static void g_gdb_packet_class_init(GGdbPacketClass *); + +/* Initialise une instance de représentation de paquet GDB. */ +static void g_gdb_packet_init(GGdbPacket *); + + + +/* Indique le type défini pour une répresentation de paquet GDB. */ +G_DEFINE_TYPE(GGdbPacket, g_gdb_packet, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des représentations des paquets GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_packet_class_init(GGdbPacketClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à initialiser. * +* * +* Description : Initialise une instance de représentation de paquet GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_packet_init(GGdbPacket *packet) +{ + DL_LIST_ITEM_INIT(&packet->link); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une représentation de paquet GDB. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGdbPacket *g_gdb_packet_new(void) +{ + GGdbPacket *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_GDB_PACKET, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à préparer pour une émission. * +* * +* Description : Prépare un paquet pour un envoi prochain. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_packet_start_new_command(GGdbPacket *packet) +{ + if (packet->allocated == 0) + { + packet->allocated = 1; + packet->buffer = (char *)calloc(packet->allocated, sizeof(char)); + } + + packet->buffer[0] = '\0'; + packet->len = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à préparer pour une émission. * +* string = chaîne à inclure dans le paquet. * +* * +* Description : Complète un paquet pour un envoi prochain. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_packet_append(GGdbPacket *packet, const char *string) +{ + size_t len; /* Taille de la chaîne donnée */ + + len = strlen(string); + + /* Si la place n'est pas assez grande */ + if ((packet->len + len + 1) >= packet->allocated) + { + packet->buffer = (char *)realloc(packet->buffer, (packet->len + len + 1) * sizeof(char)); + packet->allocated = packet->len + len + 1; + } + + strcat(packet->buffer, string); + + packet->len += len; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à analyser. * +* * +* Description : Détermine l'empreinte des données d'un paquet GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_packet_compute_checksum(GGdbPacket *packet) +{ + int sum; /* Valeur cumulée des données */ + size_t i; /* Boucle de parcours */ + + sum = 0; + + for (i = 0; i < packet->len; i++) + sum += packet->buffer[i]; + + packet->checksum = sum % 256; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à analyser. * +* checksum = contrôle d'intégrité à retrouver. * +* * +* Description : Contrôle l'intégrité des données d'un paquet GDB. * +* * +* Retour : Bilan de la vérification. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_gdb_packet_verify_checksum(GGdbPacket *packet, uint8_t checksum) +{ + g_gdb_packet_compute_checksum(packet); + + return checksum == packet->checksum; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à décoder et/ou décompresser. * +* * +* Description : Décode et/ou décompresse un paquet GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_gdb_packet_decode(GGdbPacket *packet) +{ + bool result; /* Bilan à retourner */ + char *buffer; /* Données transcrites */ + size_t allocated; /* Quantité de données gérées */ + size_t i; /* Boucle de parcours */ + size_t k; /* Point d'insertion */ + size_t repeat; /* Nombre de répétitions */ + + result = true; + + allocated = packet->len + 1; + buffer = (char *)calloc(allocated, sizeof(char)); + + for (i = 0, k = 0; i < packet->len && result; i++) + switch (packet->buffer[i]) + { + case '#': + case '$': + result = false; + break; + + case '*': + + if (++i == packet->len || k == 0) + { + result = false; + break; + } + + repeat = packet->buffer[i] - ' ' + 3; + + allocated += repeat; + buffer = (char *)realloc(buffer, allocated * sizeof(char)); + + memset(&buffer[k], buffer[k - 1], repeat); + k += repeat; + + break; + + case '}': + + if (++i == packet->len) + { + result = false; + break; + } + + buffer[k++] = packet->buffer[i] ^ 0x20; + + break; + + default: + buffer[k++] = packet->buffer[i]; + break; + + } + + if (packet->buffer != NULL) + free(packet->buffer); + + packet->buffer = buffer; + packet->len = k; + packet->allocated = allocated; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à analyser. * +* data = données contenues dans le paquet. [OUT] * +* len = quantité de ces données. [OUT] * +* checksum = contrôle d'intégrité des données ou NULL. [OUT] * +* * +* Description : Fournit le contenu du paquet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_packet_get_data(GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum) +{ + *data = packet->buffer; + *len = packet->len; + + if (checksum != NULL) + *checksum = packet->checksum; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de paquets à compléter. * +* item = paquet à ajouter à la liste. * +* * +* Description : Ajoute un paquet à une liste de paquets. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_packet_push(GGdbPacket **list, GGdbPacket *item) +{ + dl_list_push(item, list, GGdbPacket, link); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de paquets à consulter. * +* * +* Description : Retire et fournit le premier élément d'une liste de paquets. * +* * +* Retour : Elément dépilé de la liste de paquets. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGdbPacket *g_gdb_packet_pop(GGdbPacket **list) +{ + return dl_list_pop(list, GGdbPacket, link); + +} diff --git a/src/debug/remgdb/packet.h b/src/debug/remgdb/packet.h new file mode 100644 index 0000000..30be43e --- /dev/null +++ b/src/debug/remgdb/packet.h @@ -0,0 +1,82 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.h - prototypes pour la manipulation des paquets de données GDB. + * + * Copyright (C) 2009 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_PACKET_H +#define _DEBUG_REMGDB_PACKET_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <stdint.h> + + + +#define G_TYPE_GDB_PACKET g_gdb_packet_get_type() +#define G_GDB_PACKET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_packet_get_type(), GGdbPacket)) +#define G_IS_GDB_PACKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_packet_get_type())) +#define G_GDB_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_PACKET, GGdbPacketClass)) +#define G_IS_GDB_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_PACKET)) +#define G_GDB_PACKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_PACKET, GGdbPacketClass)) + + +/* Répresentation d'un paquet GDB (instance) */ +typedef struct _GGdbPacket GGdbPacket; + +/* Répresentation d'un paquet GDB (classe) */ +typedef struct _GGdbPacketClass GGdbPacketClass; + + + +/* Indique le type défini pour une répresentation de paquet GDB. */ +GType g_gdb_packet_get_type(void); + +/* Crée une représentation de paquet GDB. */ +GGdbPacket *g_gdb_packet_new(void); + +/* Prépare un paquet pour un envoi prochain. */ +void g_gdb_packet_start_new_command(GGdbPacket *); + +/* Complète un paquet pour un envoi prochain. */ +void g_gdb_packet_append(GGdbPacket *, const char *); + +/* Détermine l'empreinte des données d'un paquet GDB. */ +void g_gdb_packet_compute_checksum(GGdbPacket *); + +/* Contrôle l'intégrité des données d'un paquet GDB. */ +bool g_gdb_packet_verify_checksum(GGdbPacket *, uint8_t); + +/* Décode et/ou décompresse un paquet GDB. */ +bool g_gdb_packet_decode(GGdbPacket *); + +/* Fournit le contenu du paquet. */ +void g_gdb_packet_get_data(GGdbPacket *, const char **, size_t *, uint8_t *); + +/* Ajoute un paquet à une liste de paquets. */ +void g_gdb_packet_push(GGdbPacket **, GGdbPacket *); + +/* Retire et fournit le premier élément d'une liste de paquets. */ +GGdbPacket *g_gdb_packet_pop(GGdbPacket **); + + + +#endif /* _DEBUG_REMGDB_PACKET_H */ diff --git a/src/debug/remgdb/stream-int.h b/src/debug/remgdb/stream-int.h new file mode 100644 index 0000000..bdfe11a --- /dev/null +++ b/src/debug/remgdb/stream-int.h @@ -0,0 +1,74 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream-int.h - prototypes internes pour la gestion des connexions aux serveurs GDB. + * + * Copyright (C) 2009 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_STREAM_INT_H +#define _DEBUG_REMGDB_STREAM_INT_H + + +#include "stream.h" + + + +/* Envoie des données à un serveur GDB. */ +typedef bool (* send_gdb_data_fc) (GGdbStream *, const char *, size_t); + +/* Réceptionne un octet de donnée d'un serveur GDB. */ +typedef bool (* recv_gdb_byte_fc) (GGdbStream *, char *); + + +/* Flux de communication avec un serveur GDB (instance) */ +struct _GGdbStream +{ + GObject parent; /* A laisser en premier */ + + int fd; /* Flux ouvert en L./E. */ + + send_gdb_data_fc send_data; /* Envoi d'un paquet GDB */ + recv_gdb_byte_fc recv_byte; /* Réception d'un paquet GDB */ + + GThread *listening; /* Thread pour les réceptions */ + + GGdbPacket *free_packets; /* Liste des disponibles */ + GMutex *free_mutex; /* Accès à la liste */ + + GGdbPacket *recv_packets; /* Liste des paquets reçus */ + GCond *recv_cond; /* Attente de disponibilité */ + GMutex *recv_mutex; /* Accès à la liste */ + +}; + + +/* Flux de communication avec un serveur GDB (classe) */ +struct _GGdbStreamClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Lance l'écoute d'un flux de communication avec GDB. */ +bool g_gdb_stream_listen(GGdbStream *); + + + +#endif /* _DEBUG_REMGDB_STREAM_INT_H */ diff --git a/src/debug/remgdb/stream.c b/src/debug/remgdb/stream.c new file mode 100644 index 0000000..2b487ad --- /dev/null +++ b/src/debug/remgdb/stream.c @@ -0,0 +1,357 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream.c - gestion des connexions aux serveurs GDB. + * + * Copyright (C) 2009 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 "stream.h" + + +#include <stdio.h> +#include <stdlib.h> +#include <glib/gthread.h> +#include <sys/select.h> + + +#include "stream-int.h" +#include "../../common/dllist.h" + + + +/* Initialise la classe des flux de communication avec GDB. */ +static void g_gdb_stream_class_init(GGdbStreamClass *); + +/* Initialise une instance de flux de communication avec GDB. */ +static void g_gdb_stream_init(GGdbStream *); + +/* Ecoute une connexion à un serveur GDB. */ +static void *gdb_stream_thread(GGdbStream *); + +/* Réceptionne un paquet d'un serveur GDB. */ +static bool g_gdb_stream_read_packet(GGdbStream *, GGdbPacket *); + + + +/* Indique le type défini pour un flux de communication avec un serveur GDB. */ +G_DEFINE_TYPE(GGdbStream, g_gdb_stream, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des flux de communication avec GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_stream_class_init(GGdbStreamClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : stream = instance à initialiser. * +* * +* Description : Initialise une instance de flux de communication avec GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_stream_init(GGdbStream *stream) +{ + stream->free_mutex = g_mutex_new(); + + stream->recv_cond = g_cond_new(); + stream->recv_mutex = g_mutex_new(); + +} + + +/****************************************************************************** +* * +* Paramètres : stream = instance à réellement lancer. * +* * +* Description : Lance l'écoute d'un flux de communication avec GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_gdb_stream_listen(GGdbStream *stream) +{ + bool result; /* Bilan final à retourner */ + GError *error; /* Bilan de création de thread */ + + result = true; + + if (!g_thread_create((GThreadFunc)gdb_stream_thread, stream, FALSE, &error)) + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = encadrement associée à l'opération. * +* * +* Description : Ecoute une connexion à un serveur GDB. * +* * +* Retour : ??? * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *gdb_stream_thread(GGdbStream *stream) +{ + fd_set rfds; /* Liste des flux à surveiller */ + int ret; /* Bilan d'un appel */ + GGdbPacket *packet; /* Nouveau paquet reçu */ + + while (1) + { + FD_ZERO(&rfds); + FD_SET(stream->fd, &rfds); + + ret = select(stream->fd + 1, &rfds, NULL, NULL, NULL); + + switch (ret) + { + case -1: + perror("select()"); + break; + + case 0: + break; + + default: + + packet = g_gdb_stream_get_free_packet(stream); + + g_gdb_packet_start_new_command(packet); + + if (g_gdb_stream_read_packet(stream, packet)) + { + g_mutex_lock(stream->recv_mutex); + g_gdb_packet_push(&stream->recv_packets, packet); + g_mutex_unlock(stream->recv_mutex); + + g_cond_signal(stream->recv_cond); + + } + else g_gdb_stream_mark_packet_as_free(stream, packet); + + break; + + } + + } + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication avec GDB à consulter. * +* * +* Description : Fournit un paquet prêt à emploi. * +* * +* Retour : Paquet prêt à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *stream) +{ + GGdbPacket *result; /* Paquet à retourner */ + + g_mutex_lock(stream->free_mutex); + + if (dl_list_empty(stream->free_packets)) + result = g_gdb_packet_new(); + + else + result = g_gdb_packet_pop(&stream->free_packets); + + g_mutex_unlock(stream->free_mutex); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication avec GDB à mettre à jour. * +* packet = paquet à considérer comme disponible. * +* * +* Description : Place un paquet en attente d'une future utilisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_gdb_stream_mark_packet_as_free(GGdbStream *stream, GGdbPacket *packet) +{ + g_mutex_lock(stream->free_mutex); + + g_gdb_packet_push(&stream->free_packets, packet); + + g_mutex_unlock(stream->free_mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux ouvert en lecture à utiliser. * +* packet = données à recevoir. * +* * +* Description : Réceptionne un paquet d'un serveur GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_gdb_stream_read_packet(GGdbStream *stream, GGdbPacket *packet) +{ + bool result; /* Bilan à renvoyer */ + char tmp[3]; /* Tampon de réception */ + uint8_t checksum; /* Contrôle d'intégrité */ + + result = stream->recv_byte(stream, tmp); + + if (tmp[0] != '$') return false; + + tmp[1] = '\0'; + + while ((result = stream->recv_byte(stream, tmp))) + { + if (tmp[0] == '#') break; + else g_gdb_packet_append(packet, tmp); + } + + if (result) + { + result = stream->recv_byte(stream, &tmp[0]); + result &= stream->recv_byte(stream, &tmp[1]); + + tmp[2] = 0; + checksum = strtol(tmp, NULL, 16); + + } + + if (result) + result = g_gdb_packet_verify_checksum(packet, checksum); + + if (result) + result = g_gdb_packet_decode(packet); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux ouvert en écriture à mettre à jour. * +* packet = données à transmettre. * +* * +* Description : Envoie un paquet à un serveur GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_gdb_stream_send_packet(GGdbStream *stream, GGdbPacket *packet) +{ + bool result; /* Bilan à renvoyer */ + const char *data; /* Données à envoyer */ + size_t len; /* Quantité de ces données */ + uint8_t checksum; /* Contrôle d'intégrité */ + char tmp[3]; /* Impression du checksum */ + + result = stream->send_data(stream, "$", 1); + + g_gdb_packet_compute_checksum(packet); + g_gdb_packet_get_data(packet, &data, &len, &checksum); + + result &= stream->send_data(stream, data, len); + + result = stream->send_data(stream, "#", 1); + + snprintf(tmp, 3, "%hhx", checksum); + result &= stream->send_data(stream, tmp, 2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication avec GDB à consulter. * +* * +* Description : Fournit un paquet reçu d'un serveur GDB. * +* * +* Retour : Paquet GDB. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *stream) +{ + GGdbPacket *result; /* Paquet à retourner */ + + g_mutex_lock(stream->recv_mutex); + + if (dl_list_empty(stream->recv_packets)) + g_cond_wait(stream->recv_cond, stream->recv_mutex); + + result = g_gdb_packet_pop(&stream->recv_packets); + + g_mutex_unlock(stream->recv_mutex); + + return result; + +} diff --git a/src/debug/remgdb/stream.h b/src/debug/remgdb/stream.h new file mode 100644 index 0000000..7373f39 --- /dev/null +++ b/src/debug/remgdb/stream.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream.h - prototypes pour la gestion des connexions aux serveurs GDB. + * + * Copyright (C) 2009 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_STREAM_H +#define _DEBUG_REMGDB_STREAM_H + + +#include "packet.h" + + + +#define G_TYPE_GDB_STREAM g_gdb_stream_get_type() +#define G_GDB_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_stream_get_type(), GGdbStream)) +#define G_IS_GDB_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_stream_get_type())) +#define G_GDB_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_STREAM, GGdbStreamClass)) +#define G_IS_GDB_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_STREAM)) +#define G_GDB_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_STREAM, GGdbStreamClass)) + + +/* Flux de communication avec un serveur GDB (instance) */ +typedef struct _GGdbStream GGdbStream; + +/* Flux de communication avec un serveur GDB (classe) */ +typedef struct _GGdbStreamClass GGdbStreamClass; + + + +/* Indique le type défini pour un flux de communication avec un serveur GDB. */ +GType g_gdb_stream_get_type(void); + +/* Fournit un paquet prêt à emploi. */ +GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *); + +/* Place un paquet en attente d'une future utilisation. */ +void g_gdb_stream_mark_packet_as_free(GGdbStream *, GGdbPacket *); + +/* Envoie un paquet à un serveur GDB. */ +bool g_gdb_stream_send_packet(GGdbStream *, GGdbPacket *); + +/* Fournit un paquet reçu d'un serveur GDB. */ +GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *); + + + +#endif /* _DEBUG_REMGDB_STREAM_H */ diff --git a/src/debug/remgdb/tcp.c b/src/debug/remgdb/tcp.c new file mode 100644 index 0000000..fa97f8c --- /dev/null +++ b/src/debug/remgdb/tcp.c @@ -0,0 +1,261 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * tcp.c - gestion des connexions TCP aux serveurs GDB. + * + * Copyright (C) 2009 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 "tcp.h" + + +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/types.h> + + +#include "stream-int.h" + + + +/* Flux de communication TCP avec un serveur GDB (instance) */ +struct _GGdbTcpClient +{ + GGdbStream parent; /* A laisser en premier */ + +}; + + +/* Flux de communication TCP avec un serveur GDB (classe) */ +struct _GGdbTcpClientClass +{ + GGdbStreamClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des flux de communication TCP avec GDB. */ +static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *); + +/* Initialise une instance de flux de communication avec GDB. */ +static void g_gdb_tcp_client_init(GGdbTcpClient *); + +/* Ouvre une connexion TCP à un serveur GDB. */ +static int connect_via_tcp(const char *, const char *); + +/* Envoie des données à un serveur GDB. */ +static bool g_gdb_tcp_client_send_data(GGdbTcpClient *, const char *, size_t); + +/* Réceptionne un octet de donnée d'un serveur GDB. */ +static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *, char *); + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ +G_DEFINE_TYPE(GGdbTcpClient, g_gdb_tcp_client, G_TYPE_GDB_STREAM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des flux de communication TCP avec GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : client = instance à initialiser. * +* * +* Description : Initialise une instance de flux de communication avec GDB. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_gdb_tcp_client_init(GGdbTcpClient *client) +{ + GGdbStream *stream; /* Version parente */ + + stream = G_GDB_STREAM(client); + + stream->send_data = (send_gdb_data_fc)g_gdb_tcp_client_send_data; + stream->recv_byte = (recv_gdb_byte_fc)g_gdb_tcp_client_recv_byte; + +} + + +/****************************************************************************** +* * +* Paramètres : server = nom ou adresse du serveur à contacter. * +* port = port de connexion. * +* * +* Description : Ouvre une connexion TCP à un serveur GDB. * +* * +* Retour : Flux ouvert en lecture/écriture ou -1 en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int connect_via_tcp(const char *server, const char *port) +{ + int result; /* Bilan à retourner */ + struct addrinfo hints; /* Type de connexion souhaitée */ + struct addrinfo *infos; /* Informations disponibles */ + int ret; /* Bilan d'un appel */ + struct addrinfo *iter; /* Boucle de parcours */ + struct sockaddr_in addr; /* Infos de connexion distante */ + + memset(&hints, 0, sizeof(struct addrinfo)); + + hints.ai_family = AF_UNSPEC; /* IPv4 ou IPv6 */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + hints.ai_protocol = 0; /* N'importe quel protocole */ + + ret = getaddrinfo(server, port, &hints, &infos); + if (ret != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); + return -1; + } + + for (iter = infos; iter != NULL; iter = iter->ai_next) + { + result = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol); + if (result == -1) continue; + + ret = connect(result, iter->ai_addr, iter->ai_addrlen); + if (ret == 0) break; + + perror("connect"); + close(result); + + } + + freeaddrinfo(infos); + + if (iter == NULL) return -1; + + ret = getpeername(result, (struct sockaddr *)&addr, (socklen_t []){ sizeof(struct sockaddr_in) }); + if (ret == -1) + { + perror("getpeername"); + close(result); + return -1; + } + + printf("Connecté à %s:%hd\n", server, ntohs(addr.sin_port)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : server = nom ou adresse du serveur à contacter. * +* port = port de connexion. * +* * +* Description : Crée une nouvelle connexion TCP à un serveur GDB. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGdbStream *g_gdb_tcp_client_new(const char *server, const char *port) +{ + GGdbTcpClient *result; /* Structure à retourner */ + int sock; /* Flux ouvert à construire */ + + sock = connect_via_tcp(server, port); + if (sock == -1) return NULL; + + result = g_object_new(G_TYPE_GDB_TCP_CLIENT, NULL); + + G_GDB_STREAM(result)->fd = sock; + + if (!g_gdb_stream_listen(G_GDB_STREAM(result))) + goto ggtcn_error; + + return G_GDB_STREAM(result); + + ggtcn_error: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en écriture à utiliser. * +* data = données à envoyer. * +* len = quantité de ces données. * +* * +* Description : Envoie des données à un serveur GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_gdb_tcp_client_send_data(GGdbTcpClient *client, const char *data, size_t len) +{ + return (send(G_GDB_STREAM(client)->fd, data, len, 0) == len); + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en lecture à utiliser. * +* data = donnée à recevoir. * +* * +* Description : Réceptionne un octet de donnée d'un serveur GDB. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *client, char *data) +{ + return (recv(G_GDB_STREAM(client)->fd, data, 1, 0) == 1); + +} diff --git a/src/debug/remgdb/tcp.h b/src/debug/remgdb/tcp.h new file mode 100644 index 0000000..2536b64 --- /dev/null +++ b/src/debug/remgdb/tcp.h @@ -0,0 +1,56 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * tcp.h - prototypes pour la gestion des connexions TCP aux serveurs GDB. + * + * Copyright (C) 2009 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_TCP_H +#define _DEBUG_REMGDB_TCP_H + + +#include "stream.h" + + + +#define G_TYPE_GDB_TCP_CLIENT g_gdb_tcp_client_get_type() +#define G_GDB_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_tcp_client_get_type(), GGdbTcpClient)) +#define G_IS_GDB_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_tcp_client_get_type())) +#define G_GDB_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) +#define G_IS_GDB_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_TCP_CLIENT)) +#define G_GDB_TCP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) + + +/* Flux de communication TCP avec un serveur GDB (instance) */ +typedef struct _GGdbTcpClient GGdbTcpClient; + +/* Flux de communication TCP avec un serveur GDB (classe) */ +typedef struct _GGdbTcpClientClass GGdbTcpClientClass; + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ +GType g_gdb_tcp_client_get_type(void); + +/* Crée une nouvelle connexion TCP à un serveur GDB. */ +GGdbStream *g_gdb_tcp_client_new(const char *, const char *); + + + +#endif /* _DEBUG_REMGDB_TCP_H */ |