diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2010-07-29 00:02:49 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2010-07-29 00:02:49 (GMT) |
commit | 73af1bd66e5d1a2e30d56151532710f2b28d12df (patch) | |
tree | 88f98194359accd8349193f4cbe3c4cabee24d23 /src/debug/remgdb | |
parent | f150f36ee0297b4499a41bbbfc06699cd2f72db5 (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.am | 1 | ||||
-rw-r--r-- | src/debug/remgdb/gdb.c | 179 | ||||
-rw-r--r-- | src/debug/remgdb/gdb.h | 12 | ||||
-rw-r--r-- | src/debug/remgdb/helpers.c | 139 | ||||
-rw-r--r-- | src/debug/remgdb/helpers.h | 61 | ||||
-rw-r--r-- | src/debug/remgdb/packet.c | 2 | ||||
-rw-r--r-- | src/debug/remgdb/packet.h | 2 | ||||
-rw-r--r-- | src/debug/remgdb/stream.c | 48 |
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; |