summaryrefslogtreecommitdiff
path: root/src/debug/remgdb
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2010-07-29 00:02:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2010-07-29 00:02:49 (GMT)
commit73af1bd66e5d1a2e30d56151532710f2b28d12df (patch)
tree88f98194359accd8349193f4cbe3c4cabee24d23 /src/debug/remgdb
parentf150f36ee0297b4499a41bbbfc06699cd2f72db5 (diff)
Improved the GDB client.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@175 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/debug/remgdb')
-rw-r--r--src/debug/remgdb/Makefile.am1
-rw-r--r--src/debug/remgdb/gdb.c179
-rw-r--r--src/debug/remgdb/gdb.h12
-rw-r--r--src/debug/remgdb/helpers.c139
-rw-r--r--src/debug/remgdb/helpers.h61
-rw-r--r--src/debug/remgdb/packet.c2
-rw-r--r--src/debug/remgdb/packet.h2
-rw-r--r--src/debug/remgdb/stream.c48
8 files changed, 403 insertions, 41 deletions
diff --git a/src/debug/remgdb/Makefile.am b/src/debug/remgdb/Makefile.am
index b2829c9..7ed26b0 100644
--- a/src/debug/remgdb/Makefile.am
+++ b/src/debug/remgdb/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdebugremgdb.la
libdebugremgdb_la_SOURCES = \
gdb.h gdb.c \
+ helpers.h helpers.c \
packet.h packet.c \
stream-int.h \
stream.h stream.c \
diff --git a/src/debug/remgdb/gdb.c b/src/debug/remgdb/gdb.c
index 068cf26..ea8e48e 100644
--- a/src/debug/remgdb/gdb.c
+++ b/src/debug/remgdb/gdb.c
@@ -23,7 +23,46 @@
#include "gdb.h"
+
+#include "../debugger-int.h"
+
+
+
+#include "helpers.h"
+#include "tcp.h"
+
+
+
+
+/* Débogueur utilisant un serveur GDB (instance) */
+struct _GGdbDebugger
+{
+ GBinaryDebugger parent; /* A laisser en premier */
+
+ GGdbStream *stream; /* Flux de communication */
+
+
#if 0
+ GCond *cond; /* Poursuite du déroulement */
+ GMutex *mutex; /* Accès à la condition */
+
+ ptrace_options *options; /* Configuration du débogage */
+
+ pid_t child; /* Processus suivi lancé */
+
+ gboolean run_again; /* Reprise du débogage */
+#endif
+};
+
+/* Débogueur utilisant un serveur GDB (classe) */
+struct _GGdbDebuggerClass
+{
+ GBinaryDebuggerClass parent; /* A laisser en premier */
+
+};
+
+
+
/* Initialise la classe du débogueur utilisant gdb. */
@@ -33,6 +72,16 @@ static void g_gdb_debugger_class_init(GGdbDebuggerClass *);
static void g_gdb_debugger_init(GGdbDebugger *);
+/* Met en marche le débogueur utilisant un serveur GDB. */
+static bool g_gdb_debugger_run(GGdbDebugger *);
+
+/* Remet en marche le débogueur utilisant un serveur GDB. */
+static bool g_gdb_debugger_resume(GGdbDebugger *);
+
+/* Tue le débogueur utilisant un serveur GDB. */
+static bool g_gdb_debugger_kill(GGdbDebugger *);
+
+
/* Indique le type défini par la GLib pour le débogueur gdb. */
G_DEFINE_TYPE(GGdbDebugger, g_gdb_debugger, G_TYPE_BINARY_DEBUGGER);
@@ -79,19 +128,49 @@ static void g_gdb_debugger_init(GGdbDebugger *debugger)
parent->resume = (resume_debugger_fc)g_gdb_debugger_resume;
parent->kill = (basic_debugger_fc)g_gdb_debugger_kill;
- parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger;
+ //parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger;
- debugger->cond = g_cond_new();
- debugger->mutex = g_mutex_new();
+ //debugger->cond = g_cond_new();
+ //debugger->mutex = g_mutex_new();
}
/******************************************************************************
* *
+* Paramètres : binary = binaire représenter à déboguer. *
+* options = paramètres destinés au débogage. *
+* *
+* Description : Crée un débogueur utilisant un serveur GDB distant. *
+* *
+* Retour : Instance de débogueur mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinaryDebugger *g_gdb_debugger_new(GOpenidaBinary *binary, void *options)
+{
+ GBinaryDebugger *result; /* Débogueur à retourner */
+
+ result = g_object_new(G_TYPE_GDB_DEBUGGER, NULL);
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
* Paramètres : debugger = débogueur à lancer. *
* *
-* Description : Met en marche le débogueur utilisant gdb. *
+* Description : Met en marche le débogueur utilisant un serveur GDB. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -99,30 +178,68 @@ static void g_gdb_debugger_init(GGdbDebugger *debugger)
* *
******************************************************************************/
-bool g_gdb_debugger_run(GGdbDebugger *debugger)
+static bool g_gdb_debugger_run(GGdbDebugger *debugger)
{
- GError *error; /* Bilan de création de thread */
- if (debugger->options == NULL)
- debugger->options = create_gdb_options_from_binary(G_BINARY_DEBUGGER(debugger)->binary);
- if (debugger->options == NULL)
- return false;
+ GGdbPacket *packet;
+ bool test;
+
+ const char *data;
+ size_t len;
+
+
+ int sig;
+ vmpa_t addr;
+ pid_t thread;
+
+
+ debugger->stream = g_gdb_tcp_client_new("127.0.0.1", "6666");
+ if (debugger->stream == NULL) return false;
+
+
+ printf("Connection done !\n");
+
+
+
+ packet = g_gdb_stream_get_free_packet(debugger->stream);
+
+ g_gdb_packet_start_new_command(packet);
+ g_gdb_packet_append(packet, "?");
+
+
+ test = g_gdb_stream_send_packet(debugger->stream, packet);
+
+
+
+ printf(" >> Paquet '%s' bien envoyé ? %s\n", "?", test ? "oui" : "non");
+
+
+
+ g_gdb_stream_mark_packet_as_free(debugger->stream, packet);
+
+ packet = g_gdb_stream_recv_packet(debugger->stream);
+
+ g_gdb_packet_get_data(packet, &data, &len, NULL);
+
+ printf(" << Réception de '%s'\n", data);
+
+
+
+
+
+ get_stop_reply_sig_info(packet, &sig, &addr, &thread, SRE_LITTLE);
+
+ g_signal_emit_by_name(debugger, "halted", sig, addr, thread);
+
+
- if (!g_thread_create((GThreadFunc)gdb_thread, debugger, FALSE, &error))
- {
- printf ("Failed to create the thread: %s\n", error->message);
- }
- /*
- printf("Start Debugger with bin :: %p\n", G_BINARY_DEBUGGER_GET_IFACE(debugger)->binary);
- g_signal_emit_by_name(debugger, "debugger-stopped", (uint64_t)0xdeadbeaf);
- */
return true;
}
@@ -132,7 +249,7 @@ bool g_gdb_debugger_run(GGdbDebugger *debugger)
* *
* Paramètres : debugger = débogueur à relancer. *
* *
-* Description : Remet en marche le débogueur utilisant gdb(). *
+* Description : Remet en marche le débogueur utilisant un serveur GDB. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -140,13 +257,16 @@ bool g_gdb_debugger_run(GGdbDebugger *debugger)
* *
******************************************************************************/
-bool g_gdb_debugger_resume(GGdbDebugger *debugger)
+static bool g_gdb_debugger_resume(GGdbDebugger *debugger)
{
+
+
+ /*
g_mutex_lock(debugger->mutex);
debugger->run_again = TRUE;
g_cond_signal(debugger->cond);
g_mutex_unlock(debugger->mutex);
-
+ */
return true;
}
@@ -156,7 +276,7 @@ bool g_gdb_debugger_resume(GGdbDebugger *debugger)
* *
* Paramètres : debugger = débogueur à relancer. *
* *
-* Description : Tue le débogueur utilisant gdb(). *
+* Description : Tue le débogueur utilisant un serveur GDB. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -164,8 +284,11 @@ bool g_gdb_debugger_resume(GGdbDebugger *debugger)
* *
******************************************************************************/
-bool g_gdb_debugger_kill(GGdbDebugger *debugger)
+static bool g_gdb_debugger_kill(GGdbDebugger *debugger)
{
+
+
+#if 0
int ret; /* Bilan de l'appel système */
ret = kill(debugger->child, SIGKILL);
@@ -177,19 +300,11 @@ bool g_gdb_debugger_kill(GGdbDebugger *debugger)
debugger->run_again = TRUE;
g_cond_signal(debugger->cond);
g_mutex_unlock(debugger->mutex);
-
+#endif
return true;
}
-#endif
-
-
-
-
-
-
-#include "tcp.h"
diff --git a/src/debug/remgdb/gdb.h b/src/debug/remgdb/gdb.h
index 2812afd..dfd2f69 100644
--- a/src/debug/remgdb/gdb.h
+++ b/src/debug/remgdb/gdb.h
@@ -28,9 +28,9 @@
#include <glib-object.h>
-#include "../debuggers.h"
+#include "../debugger.h"
+
-#if 0
#define G_TYPE_GDB_DEBUGGER (g_gdb_debugger_get_type())
#define G_GDB_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_DEBUGGER, GGdbDebugger))
@@ -40,18 +40,18 @@
#define G_GDB_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass))
-/* Débogueur utilisant gdb (instance) */
+/* Débogueur utilisant un serveur GDB (instance) */
typedef struct _GGdbDebugger GGdbDebugger;
-/* Débogueur utilisant gdb (classe) */
+/* Débogueur utilisant un serveur GDB (classe) */
typedef struct _GGdbDebuggerClass GGdbDebuggerClass;
/* Indique le type défini par la GLib pour le débogueur gdb. */
GType g_gdb_debugger_get_type(void);
-#endif
-
+/* Crée un débogueur utilisant un serveur GDB distant. */
+GBinaryDebugger *g_gdb_debugger_new(GOpenidaBinary *, void *);
void test_gdb(void);
diff --git a/src/debug/remgdb/helpers.c b/src/debug/remgdb/helpers.c
new file mode 100644
index 0000000..9451b08
--- /dev/null
+++ b/src/debug/remgdb/helpers.c
@@ -0,0 +1,139 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * helpers.c - assistanat dans la manipulation des paquets GDB
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "helpers.h"
+
+
+#include <regex.h>
+#include <string.h>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : packet = paquet de deonnées à interpréter. *
+* sig = identifiant du signal source. [OUT] *
+* addr = adresse de l'instruction courante. [OUT] *
+* thread = identifiant du thread concerné. [OUT] *
+* endian = boutisme de la plateforme ciblée. *
+* *
+* Description : Récupère les informations liées à un arrêt suite à signal. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : Les données sont la forme : *
+* T0505:00000000;04:a08de6bf;08:505878b7;thread:50dc; *
+* *
+******************************************************************************/
+
+bool get_stop_reply_sig_info(const GGdbPacket *packet, int *sig, vmpa_t *addr, pid_t *thread, SourceEndian endian)
+{
+ const char *data; /* Données brutes du paquet */
+ size_t length; /* Quantité de ces données */
+ uint8_t index; /* Indice de 8 bits quelconque */
+ size_t pos; /* Tête de lecture courante */
+ regex_t preg; /* Expression régulière */
+ int ret; /* Bilan d'un appel */
+ regmatch_t pmatch[3]; /* Zones remarquées */
+ size_t key_len; /* Taille de l'indicatif */
+
+ *addr = 0ull;
+
+ g_gdb_packet_get_data(packet, &data, &length, NULL);
+
+ pos = 1;
+
+ /* Lecture du numéro du signal */
+
+ if (!strtou8(&index, data, &pos, length, SRE_LITTLE))
+ return false;
+
+ *sig = index;
+
+ /* Reste des informations */
+
+ ret = regcomp(&preg, "([^:]+):([^;]+);", REG_EXTENDED | REG_ICASE);
+ if (ret != 0) return false;
+
+ for (ret = regexec(&preg, &data[pos], 3, pmatch, 0);
+ ret != REG_NOMATCH;
+ ret = regexec(&preg, &data[pos], 3, pmatch, 0))
+ {
+ key_len = pmatch[1].rm_eo - pmatch[1].rm_so;
+
+ /* Indication sur le thread */
+ if (key_len == strlen("thread")
+ && strncmp(&data[pos + pmatch[1].rm_so], "thread", key_len) == 0)
+ {
+
+ /* TODO printf("Thread found !\n"); */
+
+ }
+
+ /* Valeur de registre ? */
+ else if (key_len == 2)
+ {
+ if (!strtou8(&index, data, (size_t []) { pos + pmatch[1].rm_so }, length, SRE_LITTLE))
+ return false;
+
+ if (index != 8 /* FIXME */)
+ goto next_field;
+
+ if (!strtou32(addr, data, (size_t []) { pos + pmatch[2].rm_so }, length, SRE_LITTLE/* FIXME */))
+ return false;
+
+ }
+
+ next_field:
+ pos += pmatch[0].rm_eo;
+
+ }
+
+ regfree(&preg);
+
+ return (*addr != 0ull);
+
+}
+
+
+
diff --git a/src/debug/remgdb/helpers.h b/src/debug/remgdb/helpers.h
new file mode 100644
index 0000000..d6888d0
--- /dev/null
+++ b/src/debug/remgdb/helpers.h
@@ -0,0 +1,61 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * helpers.h - prototypes pour un assistanat dans la manipulation des paquets GDB
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _DEBUG_REMGDB_HELPERS_H
+#define _DEBUG_REMGDB_HELPERS_H
+
+
+#include "packet.h"
+
+
+#include "../../arch/archbase.h"
+#include "../../common/endianness.h"
+
+
+
+
+
+
+
+/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */
+
+
+/* Récupère les informations liées à un arrêt suite à signal. */
+bool get_stop_reply_sig_info(const GGdbPacket *, int *, vmpa_t *, pid_t *, SourceEndian);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PAQUETS DES REPONSES D'ARRET */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
+
+
+
+
+
+
+#endif /* _DEBUG_REMGDB_HELPERS_H */
diff --git a/src/debug/remgdb/packet.c b/src/debug/remgdb/packet.c
index 3fd3cba..acdec1d 100644
--- a/src/debug/remgdb/packet.c
+++ b/src/debug/remgdb/packet.c
@@ -333,7 +333,7 @@ bool g_gdb_packet_decode(GGdbPacket *packet)
* *
******************************************************************************/
-void g_gdb_packet_get_data(GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum)
+void g_gdb_packet_get_data(const GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum)
{
*data = packet->buffer;
*len = packet->len;
diff --git a/src/debug/remgdb/packet.h b/src/debug/remgdb/packet.h
index 30be43e..9276e62 100644
--- a/src/debug/remgdb/packet.h
+++ b/src/debug/remgdb/packet.h
@@ -69,7 +69,7 @@ bool g_gdb_packet_verify_checksum(GGdbPacket *, uint8_t);
bool g_gdb_packet_decode(GGdbPacket *);
/* Fournit le contenu du paquet. */
-void g_gdb_packet_get_data(GGdbPacket *, const char **, size_t *, uint8_t *);
+void g_gdb_packet_get_data(const GGdbPacket *, const char **, size_t *, uint8_t *);
/* Ajoute un paquet à une liste de paquets. */
void g_gdb_packet_push(GGdbPacket **, GGdbPacket *);
diff --git a/src/debug/remgdb/stream.c b/src/debug/remgdb/stream.c
index 2b487ad..0f17930 100644
--- a/src/debug/remgdb/stream.c
+++ b/src/debug/remgdb/stream.c
@@ -41,6 +41,9 @@ static void g_gdb_stream_class_init(GGdbStreamClass *);
/* Initialise une instance de flux de communication avec GDB. */
static void g_gdb_stream_init(GGdbStream *);
+/* Envoie un acquittement pour la dernière réception. */
+static bool gdb_stream_ack(GGdbStream *);
+
/* Ecoute une connexion à un serveur GDB. */
static void *gdb_stream_thread(GGdbStream *);
@@ -124,6 +127,37 @@ bool g_gdb_stream_listen(GGdbStream *stream)
* *
* Paramètres : stream = encadrement associée à l'opération. *
* *
+* Description : Envoie un acquittement pour la dernière réception. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool gdb_stream_ack(GGdbStream *stream)
+{
+ bool result; /* Bilan à retourner */
+ GGdbPacket *packet; /* Paquet à envoyer */
+
+ packet = g_gdb_stream_get_free_packet(stream);
+
+ g_gdb_packet_start_new_command(packet);
+ g_gdb_packet_append(packet, "+");
+
+ result = g_gdb_stream_send_packet(stream, packet);
+
+ g_gdb_stream_mark_packet_as_free(stream, packet);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = encadrement associée à l'opération. *
+* *
* Description : Ecoute une connexion à un serveur GDB. *
* *
* Retour : ??? *
@@ -145,6 +179,8 @@ static void *gdb_stream_thread(GGdbStream *stream)
ret = select(stream->fd + 1, &rfds, NULL, NULL, NULL);
+ printf("ret :: %d\n", ret);
+
switch (ret)
{
case -1:
@@ -162,6 +198,11 @@ static void *gdb_stream_thread(GGdbStream *stream)
if (g_gdb_stream_read_packet(stream, packet))
{
+ /* Acquittement */
+ if (!gdb_stream_ack(stream)) goto bad_recv;
+
+ /* On conserve le résultat */
+
g_mutex_lock(stream->recv_mutex);
g_gdb_packet_push(&stream->recv_packets, packet);
g_mutex_unlock(stream->recv_mutex);
@@ -169,7 +210,12 @@ static void *gdb_stream_thread(GGdbStream *stream)
g_cond_signal(stream->recv_cond);
}
- else g_gdb_stream_mark_packet_as_free(stream, packet);
+
+ bad_recv:
+
+ printf("bad things happend...\n");
+
+ g_gdb_stream_mark_packet_as_free(stream, packet);
break;