From 3173b904d5d56a8b5e6bf549c97e3fc49da6c5ba Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 6 Sep 2009 15:47:08 +0000
Subject: Provided some methods to interact with a GDB server.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@110 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                     |  32 ++++
 configure.ac                  |   1 +
 src/Makefile.am               |   1 +
 src/analysis/exporter.h       |   2 +
 src/common/dllist.h           |   9 +
 src/debug/Makefile.am         |   2 +-
 src/debug/remgdb/Makefile.am  |  18 ++
 src/debug/remgdb/gdb.c        | 248 +++++++++++++++++++++++++++
 src/debug/remgdb/gdb.h        |  61 +++++++
 src/debug/remgdb/packet.c     | 383 ++++++++++++++++++++++++++++++++++++++++++
 src/debug/remgdb/packet.h     |  82 +++++++++
 src/debug/remgdb/stream-int.h |  74 ++++++++
 src/debug/remgdb/stream.c     | 357 +++++++++++++++++++++++++++++++++++++++
 src/debug/remgdb/stream.h     |  65 +++++++
 src/debug/remgdb/tcp.c        | 261 ++++++++++++++++++++++++++++
 src/debug/remgdb/tcp.h        |  56 ++++++
 src/main.c                    |  12 +-
 17 files changed, 1662 insertions(+), 2 deletions(-)
 create mode 100644 src/debug/remgdb/Makefile.am
 create mode 100644 src/debug/remgdb/gdb.c
 create mode 100644 src/debug/remgdb/gdb.h
 create mode 100644 src/debug/remgdb/packet.c
 create mode 100644 src/debug/remgdb/packet.h
 create mode 100644 src/debug/remgdb/stream-int.h
 create mode 100644 src/debug/remgdb/stream.c
 create mode 100644 src/debug/remgdb/stream.h
 create mode 100644 src/debug/remgdb/tcp.c
 create mode 100644 src/debug/remgdb/tcp.h

diff --git a/ChangeLog b/ChangeLog
index f09f937..f15e9c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+09-09-06  Cyrille Bagard <nocbos@gmail.com>
+
+	* configure.ac:
+	Add the new Makefile from the 'src/debug/remgdb' directory to AC_CONFIG_FILES.
+
+	* src/analysis/exporter.h:
+	Typo.
+
+	* src/common/dllist.h:
+	Define dl_list_push and dl_list_pop.
+
+	* src/debug/Makefile.am:
+	Add remgdb to SUBDIRS.
+
+	* src/debug/remgdb/gdb.c:
+	* src/debug/remgdb/gdb.h:
+	* src/debug/remgdb/Makefile.am:
+	* src/debug/remgdb/packet.c:
+	* src/debug/remgdb/packet.h:
+	* src/debug/remgdb/stream.c:
+	* src/debug/remgdb/stream.h:
+	* src/debug/remgdb/stream-int.h:
+	* src/debug/remgdb/tcp.c:
+	* src/debug/remgdb/tcp.h:
+	New entries: provide some methods to interact with a GDB server.
+
+	* src/main.c:
+	Keep by commenting debug code for the GDB client.
+
+	* src/Makefile.am:
+	Include debug/remgdb/libdebugremgdb.a in openida_LDADD.
+
 09-08-30  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/configure.ac b/configure.ac
index 81079a7..1050be1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -242,6 +242,7 @@ AC_CONFIG_FILES([Makefile
                  src/common/Makefile
                  src/debug/Makefile
                  src/debug/ptrace/Makefile
+                 src/debug/remgdb/Makefile
                  src/format/Makefile
                  src/format/dwarf/Makefile
                  src/format/elf/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 95eff37..737609f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -99,6 +99,7 @@ openida_LDFLAGS = $(LIBGTK_LIBS) -L/usr/X11R6/lib -ldl -lm $(LIBXML_LIBS) `pkg-c
 
 openida_LDADD = $(LIBINTL) 				\
 	debug/libdebug.a					\
+	debug/remgdb/libdebugremgdb.a		\
 	debug/ptrace/libdebugptrace.a
 
 
diff --git a/src/analysis/exporter.h b/src/analysis/exporter.h
index 6d99463..76725ad 100644
--- a/src/analysis/exporter.h
+++ b/src/analysis/exporter.h
@@ -74,6 +74,7 @@ typedef struct _GContentExporter GContentExporter;
 typedef struct _GContentExporterClass GContentExporterClass;
 
 
+
 /* Indique le type défini pour une exportation de contenu. */
 GType g_content_exporter_get_type(void);
 
@@ -89,4 +90,5 @@ void g_content_exporter_add_to_gtk_buffer(GContentExporter *, MainRendering, Gtk
 void g_content_exporter_add_arch_to_gtk_buffer(const GContentExporter *, const GExeFormat *, AsmSyntax, GtkTextBuffer *, GtkTextIter *);
 
 
+
 #endif  /* _ANALYSIS_EXPORTER_H */
diff --git a/src/common/dllist.h b/src/common/dllist.h
index 5941f64..3feef5c 100644
--- a/src/common/dllist.h
+++ b/src/common/dllist.h
@@ -100,6 +100,15 @@ void __dl_list_splice(dl_list_item *, dl_list_head);
     }                                                                               \
     while(0)
 
+#define dl_list_push dl_list_add_tail
+
+#define dl_list_pop(head, type, member)                                             \
+    ({                                                                              \
+        type *_result = *head;                                                      \
+        dl_list_del(_result, head, type, member);                                   \
+        _result;                                                                    \
+    })
+
 #define dl_list_splice_before(pos, head1, head2, type, member)                      \
     do                                                                              \
     {                                                                               \
diff --git a/src/debug/Makefile.am b/src/debug/Makefile.am
index caea642..3f98a9a 100755
--- a/src/debug/Makefile.am
+++ b/src/debug/Makefile.am
@@ -13,4 +13,4 @@ AM_CPPFLAGS =
 
 AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
 
-SUBDIRS = ptrace
+SUBDIRS = ptrace remgdb
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 */
diff --git a/src/main.c b/src/main.c
index 6466948..a4424cd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -40,7 +40,7 @@
 #include "plugins/pglist.h"
 
 
-
+/////void test_gdb(void);
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : argc = nombre d'arguments dans la ligne de commande.         *
@@ -78,6 +78,16 @@ 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
-- 
cgit v0.11.2-87-g4458