diff options
34 files changed, 3006 insertions, 7 deletions
@@ -1,3 +1,60 @@ +10-12-31 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + Add the new Makefiles from the 'src/debug/jdwp{,misc,sets}' directories + to AC_CONFIG_FILES. + + * src/common/endianness.c: + * src/common/endianness.h: + Write values using LE or BE encoding. + + * src/common/Makefile.am: + Add net.[ch] to libcommon_la_SOURCES. + + * src/common/net.c: + * src/common/net.h: + Provide a generic way to connect to a server via TCP. + + * src/debug/debugger.h: + Rename DGT_COUNT into DGT_COUNT2. + + * src/debug/jdwp/debugger.c: + * src/debug/jdwp/debugger.h: + * src/debug/jdwp/jdwp_def.h: + * src/debug/jdwp/Makefile.am: + * src/debug/jdwp/misc/header.c: + * src/debug/jdwp/misc/header.h: + * src/debug/jdwp/misc/Makefile.am: + * src/debug/jdwp/misc/types.c: + * src/debug/jdwp/misc/types.h: + * src/debug/jdwp/packet.c: + * src/debug/jdwp/packet.h: + * src/debug/jdwp/sets/list.c: + * src/debug/jdwp/sets/list.h: + * src/debug/jdwp/sets/Makefile.am: + * src/debug/jdwp/sets/vm.c: + * src/debug/jdwp/sets/vm.h: + * src/debug/jdwp/tcp.c: + * src/debug/jdwp/tcp.h: + New entries: support a first basic packet of the Java Debug Wire Protocol. + + * src/debug/Makefile.am: + Add the packet-int.h, packet.[ch], stream-int.h and stream.[ch] files + to libdebug_la_SOURCES. Add jdwp/libdebugjdwp.la to libdebug_la_LIBADD. + + * src/debug/packet.c: + * src/debug/packet.h: + * src/debug/packet-int.h: + New entries: define a generic packet for debugging communications. + + * src/debug/remgdb/tcp.c: + Update code relative to connect_via_tcp(). + + * src/debug/stream.c: + * src/debug/stream.h: + * src/debug/stream-int.h: + New entries: define a generic handler for debugging communications. + 10-12-21 Cyrille Bagard <nocbos@gmail.com> * configure.ac: diff --git a/configure.ac b/configure.ac index fe2cc9f..da0e825 100644 --- a/configure.ac +++ b/configure.ac @@ -253,6 +253,9 @@ AC_CONFIG_FILES([Makefile src/arch/x86/Makefile src/common/Makefile src/debug/Makefile + src/debug/jdwp/Makefile + src/debug/jdwp/misc/Makefile + src/debug/jdwp/sets/Makefile src/debug/remgdb/Makefile src/decomp/Makefile src/decomp/expr/Makefile diff --git a/src/common/Makefile.am b/src/common/Makefile.am index c883e02..391f35a 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -9,6 +9,7 @@ libcommon_la_SOURCES = \ extstr.h extstr.c \ leb128.h leb128.c \ macros.h \ + net.h net.c \ xml.h xml.c libcommon_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS) diff --git a/src/common/endianness.c b/src/common/endianness.c index 0b7e192..15ca52a 100755 --- a/src/common/endianness.c +++ b/src/common/endianness.c @@ -25,6 +25,7 @@ #include <stdarg.h> +#include <string.h> @@ -323,6 +324,94 @@ bool read_u64(uint64_t *target, const bin_t *data, off_t *pos, off_t len, Source } + + + + + +/****************************************************************************** +* * +* Paramètres : value = source de la valeur à transcrire. * +* size = taille de cette source de données. * +* data = flux de données à modifier. [OUT] * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* endian = ordre des bits dans la source. * +* * +* Description : Ecrit un nombre non signé sur n octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _write_un(const bin_t *value, size_t size, bin_t *data, off_t *pos, off_t len, SourceEndian endian) +{ + size_t i; /* Boucle de parcours */ + + if (*pos < 0) return false; + if ((len - *pos) < size) return false; + + switch (endian) + { + case SRE_LITTLE: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + memcpy(&data[*pos], value, size); + (*pos) += size; + +#elif __BYTE_ORDER == __BIG_ENDIAN + + for (i = 0; i < size; i++, (*pos)++) + *(data + *pos) = *(value + size - i - 1); + +#else + +# error "TODO : PDP !" + +#endif + + break; + + case SRE_MIDDLE: + return false; /* TODO ! */ + break; + + case SRE_BIG: + +#if __BYTE_ORDER == __LITTLE_ENDIAN + + for (i = 0; i < size; i++, (*pos)++) + *(data + *pos) = *(value + size - i - 1); + +#elif __BYTE_ORDER == __BIG_ENDIAN + + memcpy(&data[*pos], value, size); + (*pos) += size; + +#else + +# error "TODO : PDP !" + +#endif + + break; + + } + + return true; + +} + + + + + + + + /****************************************************************************** * * * Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * diff --git a/src/common/endianness.h b/src/common/endianness.h index 0664d6a..e4aca6e 100755 --- a/src/common/endianness.h +++ b/src/common/endianness.h @@ -65,6 +65,33 @@ bool read_u64(uint64_t *, const bin_t *, off_t *, off_t, SourceEndian); #define read_s64(target, data, pos, len, endian) read_u64((uint64_t *)target, data, pos, len, endian) + +/* Ecrit un nombre non signé sur n octets. */ +bool _write_un(const bin_t *, size_t, bin_t *, off_t *, off_t, SourceEndian); + + +#define write_un(value, data, pos, len, endian, type) \ + ({ \ + type __tmp; \ + (void)(value == &__tmp); \ + _write_un((bin_t *)value, sizeof(type), data, pos, len, endian); \ + }) + + +#define write_u8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint8_t) +#define write_u16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint16_t) +#define write_u32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint32_t) +#define write_u64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint64_t) + +#define write_s8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint8_t) +#define write_s16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint16_t) +#define write_s32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint32_t) +#define write_s64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint64_t) + + + + + /* Lit un nombre hexadécimal non signé sur deux octets. */ bool strtou8(uint8_t *, const char *, size_t *, size_t, SourceEndian); diff --git a/src/common/net.c b/src/common/net.c new file mode 100644 index 0000000..79a5883 --- /dev/null +++ b/src/common/net.c @@ -0,0 +1,102 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * net.c - fonctions complémentaires liées au réseau + * + * 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 "net.h" + + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + + + +/****************************************************************************** +* * +* Paramètres : server = nom ou adresse du serveur à contacter. * +* port = port de connexion. * +* addr = éventuelle remontée d'informations. [OUT] * +* * +* Description : Ouvre une connexion TCP à un serveur quelconque. * +* * +* Retour : Flux ouvert en lecture/écriture ou -1 en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int connect_via_tcp(const char *server, const char *port, struct sockaddr_in *addr) +{ + 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 */ + + 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; + + if (addr != NULL) + { + ret = getpeername(result, (struct sockaddr *)addr, + (socklen_t []){ sizeof(struct sockaddr_in) }); + + if (ret == -1) + { + perror("getpeername"); + close(result); + return -1; + } + + } + + return result; + +} diff --git a/src/common/net.h b/src/common/net.h new file mode 100644 index 0000000..fbfe6e0 --- /dev/null +++ b/src/common/net.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * net.h - prototypes pour les fonctions complémentaires liées au réseau + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _COMMON_NET_H +#define _COMMON_NET_H + + +#include <netdb.h> + + + +/* Ouvre une connexion TCP à un serveur quelconque. */ +int connect_via_tcp(const char *, const char *, struct sockaddr_in *); + + + +#endif /* _COMMON_NET_H */ diff --git a/src/debug/Makefile.am b/src/debug/Makefile.am index 4369a69..e2e87b8 100755 --- a/src/debug/Makefile.am +++ b/src/debug/Makefile.am @@ -3,7 +3,14 @@ noinst_LTLIBRARIES = libdebug.la libdebug_la_SOURCES = \ break.h break.c \ - debugger.h debugger.c + debugger.h debugger.c \ + packet-int.h \ + packet.h packet.c \ + stream-int.h \ + stream.h stream.c + +libdebug_la_LIBADD = \ + jdwp/libdebugjdwp.la libdebug_la_CFLAGS = $(AM_CFLAGS) @@ -14,4 +21,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = remgdb +SUBDIRS = jdwp remgdb diff --git a/src/debug/debugger.h b/src/debug/debugger.h index d6163cf..521d346 100644 --- a/src/debug/debugger.h +++ b/src/debug/debugger.h @@ -40,7 +40,7 @@ typedef enum _DebuggerType DGT_REMOTE_GDB, /* Utilisation de GDB */ DGT_PTRACE, /* Utilisation de ptrace() */ - DGT_COUNT + DGT_COUNT2/* FIXME */ } DebuggerType; diff --git a/src/debug/jdwp/Makefile.am b/src/debug/jdwp/Makefile.am new file mode 100644 index 0000000..a9b9c81 --- /dev/null +++ b/src/debug/jdwp/Makefile.am @@ -0,0 +1,23 @@ + +noinst_LTLIBRARIES = libdebugjdwp.la + +libdebugjdwp_la_SOURCES = \ + debugger.h debugger.c \ + jdwp_def.h \ + packet.h packet.c \ + tcp.h tcp.c + +libdebugjdwp_la_LIBADD = \ + misc/libdebugjdwpmisc.la \ + sets/libdebugjdwpsets.la + +libdebugjdwp_la_LDFLAGS = + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = misc sets diff --git a/src/debug/jdwp/debugger.c b/src/debug/jdwp/debugger.c new file mode 100644 index 0000000..a99c6d0 --- /dev/null +++ b/src/debug/jdwp/debugger.c @@ -0,0 +1,204 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * debugger.c - débogage d'une cible en Java. + * + * 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 "debugger.h" + + +#include "packet.h" +#include "tcp.h" + + +#include "../debugger-int.h" +#include "../stream.h" + + + + + +/* Débogueur utilisant un serveur JAVA (instance) */ +struct _GJavaDebugger +{ + GBinaryDebugger parent; /* A laisser en premier */ + + GDebugStream *stream; + +}; + +/* Débogueur utilisant un serveur JAVA (classe) */ +struct _GJavaDebuggerClass +{ + GBinaryDebuggerClass parent; /* A laisser en premier */ + +}; + + + + + +/* Initialise la classe du débogueur utilisant Java. */ +static void g_java_debugger_class_init(GJavaDebuggerClass *); + +/* Procède à l'initialisation du débogueur utilisant Java. */ +static void g_java_debugger_init(GJavaDebugger *); + + + +/* Indique le type défini par la GLib pour le débogueur java. */ +G_DEFINE_TYPE(GJavaDebugger, g_java_debugger, G_TYPE_BINARY_DEBUGGER); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe de débogueur à initialiser. * +* * +* Description : Initialise la classe du débogueur utilisant Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_debugger_class_init(GJavaDebuggerClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : debugger = instance de débogueur à préparer. * +* * +* Description : Procède à l'initialisation du débogueur utilisant Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_debugger_init(GJavaDebugger *debugger) +{ + GBinaryDebugger *parent; /* Instance parente */ + + parent = G_BINARY_DEBUGGER(debugger); +#if 0 + parent->run = (basic_debugger_fc)g_java_debugger_run; + parent->resume = (resume_debugger_fc)g_java_debugger_resume; + parent->kill = (basic_debugger_fc)g_java_debugger_kill; +#endif + + +} + + +/****************************************************************************** +* * +* 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 JAVA distant. * +* * +* Retour : Instance de débogueur mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinaryDebugger *g_java_debugger_new(GOpenidaBinary *binary, void *options) +{ + GBinaryDebugger *result; /* Débogueur à retourner */ + + result = g_object_new(G_TYPE_JAVA_DEBUGGER, NULL); + + + G_JAVA_DEBUGGER(result)->stream = g_jdwp_tcp_client_new("localhost", "9000"); + + return result; + +} + + + + + + + +void test_java(void) +{ + GBinaryDebugger *debugger; + GDebugPacket *packet; + GDebugPacket *packet2; + jdwp_payload *payload; + + printf("JDWP-start !!!!\n"); + + printf("size == %d\n", sizeof(jdwp_header)); + + + debugger = g_java_debugger_new(NULL, NULL); + + + g_debug_stream_connect(G_JAVA_DEBUGGER(debugger)->stream); + + + packet = g_debug_stream_get_free_packet(G_JAVA_DEBUGGER(debugger)->stream); + + + g_jdwp_packet_set_request_header(G_JDWP_PACKET(packet), JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION); + + if (!g_debug_stream_send_packet(G_JAVA_DEBUGGER(debugger)->stream, packet)) + printf("erreur envoi\n"); + + packet2 = g_debug_stream_recv_packet(G_JAVA_DEBUGGER(debugger)->stream, (filter_packet_fc)g_jdwp_packet_is_reply, packet); + + if (!packet2) + printf("erreur réception\n"); + + if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(packet2), JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION)) + printf("erreur de décodage\n"); + + payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(packet2)); + + + + printf("-----------\n"); + + printf("desc :: '%s'\n", payload->vs_reply.description.value); + + printf("version :: %d.%d\n", payload->vs_reply.jdwp_major, payload->vs_reply.jdwp_minor); + + printf("version :: '%s'\n", payload->vs_reply.vm_version.value); + printf("name :: '%s'\n", payload->vs_reply.vm_name.value); + + printf("-----------\n"); + + + + g_jdwp_packet_free_payload(G_JDWP_PACKET(packet2), JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION); + + + printf("JDWP-end !!!!\n"); + +} diff --git a/src/debug/jdwp/debugger.h b/src/debug/jdwp/debugger.h new file mode 100644 index 0000000..c19a415 --- /dev/null +++ b/src/debug/jdwp/debugger.h @@ -0,0 +1,61 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * debugger.h - prototypes pour le débogage d'une cible en Java. + * + * 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_JDWP_DEBUGGER_H +#define _DEBUG_JDWP_DEBUGGER_H + + +#include <glib-object.h> + + +#include "../debugger.h" + + + +#define G_TYPE_JAVA_DEBUGGER (g_java_debugger_get_type()) +#define G_JAVA_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_JAVA_DEBUGGER, GJavaDebugger)) +#define G_IS_JAVA_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_JAVA_DEBUGGER)) +#define G_JAVA_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JAVA_DEBUGGER, GJavaDebuggerClass)) +#define G_IS_JAVA_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JAVA_DEBUGGER)) +#define G_JAVA_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JAVA_DEBUGGER, GJavaDebuggerClass)) + + +/* Débogueur utilisant un serveur Java (instance) */ +typedef struct _GJavaDebugger GJavaDebugger; + +/* Débogueur utilisant un serveur Java (classe) */ +typedef struct _GJavaDebuggerClass GJavaDebuggerClass; + + +/* Indique le type défini par la GLib pour le débogueur Java. */ +GType g_java_debugger_get_type(void); + +/* Crée un débogueur utilisant un serveur Java distant. */ +GBinaryDebugger *g_java_debugger_new(GOpenidaBinary *, void *); + + +void test_java(void); + + + +#endif /* _DEBUG_JDWP_DEBUGGER_H */ diff --git a/src/debug/jdwp/jdwp_def.h b/src/debug/jdwp/jdwp_def.h new file mode 100644 index 0000000..fc5a8fe --- /dev/null +++ b/src/debug/jdwp/jdwp_def.h @@ -0,0 +1,131 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * jdwp_def.h - transcription du protocole Java Debug Wire Protocol + * + * 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_JDWP_JDWP_DEF_H +#define _DEBUG_JDWP_JDWP_DEF_H + + +#include <stdint.h> + + + +/** + * Les définitions ci-dessous sont issues des pages Web suivantes : + * - http://download.oracle.com/javase/1.4.2/docs/guide/jpda/jdwp-spec.html + * - http://download.oracle.com/javase/1.4.2/docs/guide/jpda/jdwp/jdwp-protocol.html + */ + + + +/* ---------------------------------------------------------------------------------- */ +/* EN-TETES DE PAQUETS JDWP */ +/* ---------------------------------------------------------------------------------- */ + + +/* En-tête générique */ +typedef struct __attribute__((__packed__)) _jdwp_header +{ + uint32_t length; /* Taille totale du paquet */ + uint32_t id; /* Numéro de séquence */ + uint8_t flags; /* Options diverses */ + + union + { + /* Requête */ + struct + { + uint8_t set; /* Jeu de commandes */ + uint8_t command; /* Identifiant de commande */ + }; + + /* Réponse */ + uint16_t error; /* Numéro d'erreur */ + + }; + +} jdwp_header; + + +#define JDWP_FLAGS_NONE 0x00 +#define JDWP_FLAGS_REPLY 0x80 + + + +/* ---------------------------------------------------------------------------------- */ +/* TYPES DE BASE DIVERS POUR JDWP */ +/* ---------------------------------------------------------------------------------- */ + + + + +/* "string" */ +typedef struct _jdwp_string +{ + uint32_t length; /* Taille de la chaîne */ + char *value; /* Chaîne encodée en UTF-8 */ + +} jdwp_string; + + + + + + +/** + * Jeux de commandes. + */ + +#define JDWP_CST_VIRTUAL_MACHINE 1 + + +/** + * Sous-commandes d'un jeu. + */ + +/* VirtualMachine Command Set */ + +#define JDWP_CMD_VM_VERSION 1 + + +/** + * Charges utiles des paquets. + */ + +/* JDWP_CMD_VM_VERSION */ + +typedef struct _jdwp_cmd_vm_version_reply +{ + jdwp_string description; /* Infos sur la VM */ + uint32_t jdwp_major; /* Numéro majeur de JDWP */ + uint32_t jdwp_minor; /* Numéro mineur de JDWP */ + jdwp_string vm_version; /* Version JRE de la VM ciblée */ + jdwp_string vm_name; /* Nom de la VM */ + +} jdwp_cmd_vm_version_reply; + + + + + + +#endif /* _DEBUG_JDWP_JDWP_DEF_H */ diff --git a/src/debug/jdwp/misc/Makefile.am b/src/debug/jdwp/misc/Makefile.am new file mode 100644 index 0000000..cfb4a06 --- /dev/null +++ b/src/debug/jdwp/misc/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libdebugjdwpmisc.la + +libdebugjdwpmisc_la_SOURCES = \ + header.h header.c \ + types.h types.c + +libdebugjdwpmisc_la_LDFLAGS = + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/debug/jdwp/misc/header.c b/src/debug/jdwp/misc/header.c new file mode 100644 index 0000000..ad41c90 --- /dev/null +++ b/src/debug/jdwp/misc/header.c @@ -0,0 +1,172 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * header.c - constitution des deux types d'en-têtes JDWP + * + * 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 "header.h" + + +#include <string.h> + + +#include "../../../common/endianness.h" + + + +/****************************************************************************** +* * +* Paramètres : header = en-tête logicielle au format local à constituer. * +* blob = en-tête en gros boutiste du paquet à constituer. * +* length = taille totale du paquet. * +* set = jeu de commandes de la requête. * +* command = commande proprement dite. * +* * +* Description : Définit une en-tête de requête au format JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_jdwp_request_header(jdwp_header *header, bin_t *blob, uint32_t length, uint8_t set, uint8_t command) +{ + off_t pos; /* Tête d'écriture */ + + pos = 0; + + length += sizeof(jdwp_header); + + /* Encodage local */ + + header->length = length; + header->id = 1; + header->flags = JDWP_FLAGS_NONE; + + header->set = set; + header->command = command; + + /* Encodage gros boutiste */ + + write_u32(&length, blob, &pos, sizeof(jdwp_header), SRE_BIG); + write_u32((uint32_t []) { 1 }, blob, &pos, sizeof(jdwp_header), SRE_BIG); + write_u8((uint8_t []) { JDWP_FLAGS_NONE }, blob, &pos, sizeof(jdwp_header), SRE_BIG); + + write_u8(&set, blob, &pos, sizeof(jdwp_header), SRE_BIG); + write_u8(&command, blob, &pos, sizeof(jdwp_header), SRE_BIG); + +} + + +/****************************************************************************** +* * +* Paramètres : header = en-tête logicielle au format local à constituer. * +* blob = en-tête en gros boutiste du paquet à constituer. * +* length = taille totale du paquet. * +* lastid = jeton du paquet à l'origine du besoin de réponse. * +* error = éventuelle indication d'erreur. * +* * +* Description : Définit une en-tête de réponse au format JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_jdwp_reply_header(jdwp_header *header, bin_t *blob, uint32_t length, uint32_t lastid, uint16_t error) +{ + off_t pos; /* Tête d'écriture */ + + pos = 0; + + length += sizeof(jdwp_header); + + /* Encodage local */ + + header->length = length; + header->id = 1; + header->flags = JDWP_FLAGS_REPLY; + + header->error = error; + + /* Encodage gros boutiste */ + + write_u32(&length, blob, &pos, sizeof(jdwp_header), SRE_BIG); + write_u32((uint32_t []) { 1 }, blob, &pos, sizeof(jdwp_header), SRE_BIG); + write_u8((uint8_t []) { JDWP_FLAGS_REPLY }, blob, &pos, sizeof(jdwp_header), SRE_BIG); + + write_u16(&error, blob, &pos, sizeof(jdwp_header), SRE_BIG); + +} + + +/****************************************************************************** +* * +* Paramètres : blob = flux de données à analyser. * +* header = en-tête de paquet JDWP reconstituée. [OUT] * +* * +* Description : Lit une en-tête de paquet au format JDWP. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_jdwp_header(const bin_t *blob, jdwp_header *header) +{ + off_t pos; /* Tête de lecture */ + off_t len; /* Taille standard d'en-tête */ + + pos = 0; + len = sizeof(jdwp_header); + + if (!read_u32(&header->length, blob, &pos, len, SRE_BIG)) + return false; + + if (!read_u32(&header->id, blob, &pos, len, SRE_BIG)) + return false; + + if (!read_u8(&header->flags, blob, &pos, len, SRE_BIG)) + return false; + + /* Réponse ? */ + if (header->flags & JDWP_FLAGS_REPLY) + { + if (!read_u16(&header->error, blob, &pos, len, SRE_BIG)) + return false; + } + + /* Requête ! */ + else + { + if (!read_u8(&header->set, blob, &pos, len, SRE_BIG)) + return false; + + if (!read_u8(&header->command, blob, &pos, len, SRE_BIG)) + return false; + + } + + return true; + +} diff --git a/src/debug/jdwp/misc/header.h b/src/debug/jdwp/misc/header.h new file mode 100644 index 0000000..d8fa845 --- /dev/null +++ b/src/debug/jdwp/misc/header.h @@ -0,0 +1,47 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * header.h - prototypes pour la constitution des deux types d'en-têtes JDWP + * + * 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_JDWP_MISC_HEADER_H +#define _DEBUG_JDWP_MISC_HEADER_H + + +#include <stdbool.h> + + +#include "../jdwp_def.h" +#include "../../../arch/archbase.h" + + + +/* Définit une en-tête de requête au format JDWP. */ +void set_jdwp_request_header(jdwp_header *, bin_t *, uint32_t, uint8_t, uint8_t); + +/* Définit une en-tête de réponse au format JDWP. */ +void set_jdwp_reply_header(jdwp_header *, bin_t *, uint32_t, uint32_t, uint16_t); + +/* Lit une en-tête de paquet au format JDWP. */ +bool get_jdwp_header(const bin_t *, jdwp_header *); + + + +#endif /* _DEBUG_JDWP_MISC_HEADER_H */ diff --git a/src/debug/jdwp/misc/types.c b/src/debug/jdwp/misc/types.c new file mode 100644 index 0000000..4eca44c --- /dev/null +++ b/src/debug/jdwp/misc/types.c @@ -0,0 +1,85 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * types.c - constitution des types communs de JDWP + * + * 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 "types.h" + + +#include <malloc.h> +#include <string.h> + + +#include "../../../common/endianness.h" + + + +/****************************************************************************** +* * +* Paramètres : blob = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* str = chaîne de caractères à la sauce JDWP. [OUT] * +* * +* Description : Lit une chaîne de caractères UTF-8 au format JDWP. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_jdwp_string(const bin_t *blob, off_t *pos, off_t len, jdwp_string *str) +{ + if (!read_u32(&str->length, blob, pos, len, SRE_BIG)) + return false; + + if ((*pos + str->length) > len) + return false; + + str->value = (char *)calloc(str->length + 1, sizeof(char)); + memcpy(str->value, &blob[*pos], str->length); + + *pos += str->length; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : str = chaîne de caractères à la sauce JDWP. * +* * +* Description : Libère de la mémoire une chaîne de caractères UTF-8 JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_jdwp_string(jdwp_string *str) +{ + if (str->value != NULL) + free(str->value); + +} diff --git a/src/debug/jdwp/misc/types.h b/src/debug/jdwp/misc/types.h new file mode 100644 index 0000000..1c285ff --- /dev/null +++ b/src/debug/jdwp/misc/types.h @@ -0,0 +1,44 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * types.h - prototypes pour la constitution des types communs de JDWP + * + * 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_JDWP_MISC_TYPES_H +#define _DEBUG_JDWP_MISC_TYPES_H + + +#include <stdbool.h> + + +#include "../jdwp_def.h" +#include "../../../arch/archbase.h" + + + +/* Lit une chaîne de caractères UTF-8 au format JDWP. */ +bool get_jdwp_string(const bin_t *, off_t *, off_t, jdwp_string *); + +/* Libère de la mémoire une chaîne de caractères UTF-8 JDWP. */ +void free_jdwp_string(jdwp_string *); + + + +#endif /* _DEBUG_JDWP_MISC_TYPES_H */ diff --git a/src/debug/jdwp/packet.c b/src/debug/jdwp/packet.c new file mode 100644 index 0000000..8afaeb4 --- /dev/null +++ b/src/debug/jdwp/packet.c @@ -0,0 +1,348 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.c - définition des paquets destiné au protocole JDWP + * + * 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 "packet.h" + + +#include "misc/header.h" +#include "../packet-int.h" +#include "../../arch/archbase.h" +#include "../../common/endianness.h" + + + +/* Répresentation d'un paquet de débogage JDWP (instance) */ +struct _GJdwpPacket +{ + GDebugPacket parent; /* A laisser en premier */ + + jdwp_header header; /* En-tête du paquet JDWP */ + bin_t hblob[sizeof(jdwp_header)]; /* Contenu encodé en B.E. */ + + jdwp_payload payload; /* Charge utile du paquet */ + bin_t pblob[sizeof(jdwp_payload)]; /* Contenu encodé en B.E. */ + +}; + + +/* Répresentation d'un paquet de débogage JDWP (classe) */ +struct _GJdwpPacketClass +{ + GDebugPacketClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des paquets de débogage JDWP. */ +static void g_jdwp_packet_class_init(GJdwpPacketClass *); + +/* Initialise une instance de paquet de débogage JDWP. */ +static void g_jdwp_packet_init(GJdwpPacket *); + +/* Précise les zones mémoires correspondant au contenu. */ +static void g_jdwp_packet_vectorize(GJdwpPacket *, struct iovec [UIO_MAXIOV], int *); + + + +/* Indique le type défini pour un paquet de débogage JDWP. */ +G_DEFINE_TYPE(GJdwpPacket, g_jdwp_packet, G_TYPE_DEBUG_PACKET); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des paquets de débogage JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_packet_class_init(GJdwpPacketClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à initialiser. * +* * +* Description : Initialise une instance de paquet de débogage JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_packet_init(GJdwpPacket *packet) +{ + GDebugPacket *dpkt; /* Version parente */ + + dpkt = G_DEBUG_PACKET(packet); + + dpkt->vectorize = (debug_vectorize_fc)g_jdwp_packet_vectorize; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à convertir. * +* iov = table de vecteurs. [OUT] * +* iovcnt = quantité de champs renseignés. [OUT] * +* * +* Description : Précise les zones mémoires correspondant au contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_packet_vectorize(GJdwpPacket *packet, struct iovec iov[UIO_MAXIOV], int *iovcnt) +{ + uint32_t length; /* Quantité de données */ + bool empty; /* Présence d'une charge utile */ + + read_u32(&length, packet->hblob, (off_t []) { 0 }, sizeof(jdwp_header), SRE_BIG); + + iov[0].iov_base = packet->hblob; + iov[0].iov_len = sizeof(jdwp_header); + + empty = (length == sizeof(jdwp_header)); + + if (!empty) + { + iov[1].iov_base = packet->pblob; + iov[1].iov_len = length - sizeof(jdwp_header); + } + + *iovcnt = (empty ? 1 : 2); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à consulter. * +* * +* Description : Fournit l'adresse des données de l'en-tête d'un paquet JDWP. * +* * +* Retour : Adresse des données de l'en-tête (à priori de requête). * +* * +* Remarques : - * +* * +******************************************************************************/ + +jdwp_header *g_jdwp_packet_get_header(GJdwpPacket *packet) +{ + return &packet->header; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à consulter. * +* * +* Description : Fournit l'adresse des données de l'en-tête d'un paquet JDWP. * +* * +* Retour : Adresse des données de l'en-tête (à priori de requête). * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_t *g_jdwp_packet_get_hblob(GJdwpPacket *packet) +{ + return packet->hblob; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à mettre à jour. * +* * +* Description : Recompose l'en-tête d'un paquet à partir de données brutes. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_jdwp_packet_parse_header(GJdwpPacket *packet) +{ + return get_jdwp_header(packet->hblob, &packet->header); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à mettre à jour. * +* set = jeu de commandes de la requête. * +* command = commande proprement dite. * +* * +* Description : Définit l'en-tête du paquet pour une requête au format JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_jdwp_packet_set_request_header(GJdwpPacket *packet, uint8_t set, uint8_t command) +{ + set_jdwp_request_header(&packet->header, packet->hblob, + 0 /* FIXME */, set, command); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = paquet à mettre à jour. * +* lastid = jeton du paquet à l'origine du besoin de réponse. * +* error = éventuelle indication d'erreur. * +* * +* Description : Définit l'en-tête du paquet pour une réponse au format JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_jdwp_packet_set_reply_header(GJdwpPacket *packet, uint32_t lastid, uint16_t error) +{ + set_jdwp_reply_header(&packet->header, packet->hblob, + 0 /* FIXME */, lastid, error); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à consulter. * +* * +* Description : Fournit l'adresse des charges utiles d'un paquet JDWP. * +* * +* Retour : Adresse des données d'une charge utile. * +* * +* Remarques : - * +* * +******************************************************************************/ + +jdwp_payload *g_jdwp_packet_get_payload(GJdwpPacket *packet) +{ + return &packet->payload; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à consulter. * +* * +* Description : Fournit l'adresse des charges utiles d'un paquet JDWP. * +* * +* Retour : Adresse des données d'une charge utile. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_t *g_jdwp_packet_get_pblob(GJdwpPacket *packet) +{ + return packet->pblob; + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à mettre à jour. * +* set = jeu de commandes concerné. * +* cmd = identifiant d'une commande donnée. * +* * +* Description : Recompose une charge utile à partir de ses données brutes. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_jdwp_packet_parse_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd) +{ + return get_jdwp_payload(packet->pblob, packet->header.length - sizeof(jdwp_header)/* FIXME */, set, cmd, &packet->payload); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à mettre à jour. * +* set = jeu de commandes concerné. * +* cmd = identifiant d'une commande donnée. * +* * +* Description : Libère la mémoire occupée par une charge utile de paquet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_jdwp_packet_free_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd) +{ + free_jdwp_payload(&packet->payload, set, cmd); + +} + + +/****************************************************************************** +* * +* Paramètres : reply = instance de paquet à analyser. * +* packet = instance de paquet de référence. * +* * +* Description : Détermine si un paquet est une réponse à un premier paquet. * +* * +* Retour : true si le paquet correspond à la réponse attendue. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_jdwp_packet_is_reply(const GJdwpPacket *reply, const GJdwpPacket *packet) +{ + return (reply->header.id == packet->header.id + && reply->header.flags & JDWP_FLAGS_REPLY); + +} diff --git a/src/debug/jdwp/packet.h b/src/debug/jdwp/packet.h new file mode 100644 index 0000000..fda9faf --- /dev/null +++ b/src/debug/jdwp/packet.h @@ -0,0 +1,87 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.h - prototypes pour la définition des paquets destiné au protocole JDWP + * + * 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_JDWP_PACKET_H +#define _DEBUG_JDWP_PACKET_H + + +#include <glib-object.h> + + +#include "jdwp_def.h" +#include "sets/list.h" + + + +#define G_TYPE_JDWP_PACKET g_jdwp_packet_get_type() +#define G_JDWP_PACKET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_jdwp_packet_get_type(), GJdwpPacket)) +#define G_IS_JDWP_PACKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_jdwp_packet_get_type())) +#define G_JDWP_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JDWP_PACKET, GJdwpPacketClass)) +#define G_IS_JDWP_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JDWP_PACKET)) +#define G_JDWP_PACKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JDWP_PACKET, GJdwpPacketClass)) + + +/* Répresentation d'un paquet de débogage JDWP (instance) */ +typedef struct _GJdwpPacket GJdwpPacket; + +/* Répresentation d'un paquet de débogage JDWP (classe) */ +typedef struct _GJdwpPacketClass GJdwpPacketClass; + + + +/* Indique le type défini pour un paquet de débogage JDWP. */ +GType g_jdwp_packet_get_type(void); + +/* Fournit l'adresse des données de l'en-tête d'un paquet JDWP. */ +jdwp_header *g_jdwp_packet_get_header(GJdwpPacket *); + +/* Fournit l'adresse des données de l'en-tête d'un paquet JDWP. */ +bin_t *g_jdwp_packet_get_hblob(GJdwpPacket *); + +/* Recompose l'en-tête d'un paquet à partir de données brutes. */ +bool g_jdwp_packet_parse_header(GJdwpPacket *); + +/* Définit l'en-tête du paquet pour une requête au format JDWP. */ +void g_jdwp_packet_set_request_header(GJdwpPacket *, uint8_t, uint8_t); + +/* Définit l'en-tête du paquet pour une réponse au format JDWP. */ +void g_jdwp_packet_set_reply_header(GJdwpPacket *, uint32_t, uint16_t); + +/* Fournit l'adresse des charges utiles d'un paquet JDWP. */ +jdwp_payload *g_jdwp_packet_get_payload(GJdwpPacket *); + +/* Fournit l'adresse des charges utiles d'un paquet JDWP. */ +bin_t *g_jdwp_packet_get_pblob(GJdwpPacket *); + +/* Recompose une charge utile à partir de ses données brutes. */ +bool g_jdwp_packet_parse_payload(GJdwpPacket *, uint8_t, uint8_t); + +/* Libère la mémoire occupée par une charge utile de paquet. */ +void g_jdwp_packet_free_payload(GJdwpPacket *, uint8_t, uint8_t); + +/* Détermine si un paquet est une réponse à un premier paquet. */ +bool g_jdwp_packet_is_reply(const GJdwpPacket *, const GJdwpPacket *); + + + +#endif /* _DEBUG_JDWP_PACKET_H */ diff --git a/src/debug/jdwp/sets/Makefile.am b/src/debug/jdwp/sets/Makefile.am new file mode 100644 index 0000000..98a76b4 --- /dev/null +++ b/src/debug/jdwp/sets/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libdebugjdwpsets.la + +libdebugjdwpsets_la_SOURCES = \ + list.h list.c \ + vm.h vm.c + +libdebugjdwpsets_la_LDFLAGS = + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/debug/jdwp/sets/list.c b/src/debug/jdwp/sets/list.c new file mode 100644 index 0000000..0dad1e8 --- /dev/null +++ b/src/debug/jdwp/sets/list.c @@ -0,0 +1,118 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * list.c - ensemble des jeux de commandes de JDWP + * + * 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 "list.h" + + +#include <stddef.h> + + +#include "vm.h" + + + +/* Reconstitue une charge utile à partir d'un contenu binaire. */ +typedef bool (* get_jdwp_payload_fc) (const bin_t *, off_t, jdwp_payload *); + +/* Libère le contenu d'une charge utile. */ +typedef void (* free_jdwp_payload_fc) (jdwp_payload *); + + +/* Commandes JDWP */ +typedef struct _jdwp_command +{ + get_jdwp_payload_fc get_payload; /* Constitution de la charge */ + free_jdwp_payload_fc free_payload; /* Libération de la mémoire */ + +} jdwp_command; + + +/* Energistrement des différents jeux */ +static jdwp_command _commands[][256] = { + + [JDWP_CST_VIRTUAL_MACHINE] = { + + [JDWP_CMD_VM_VERSION] = { + .get_payload = (get_jdwp_payload_fc)get_jdwp_vm_version, + .free_payload = (free_jdwp_payload_fc)free_jdwp_vm_version + }, + + + + + }, + + + +}; + + + +/****************************************************************************** +* * +* Paramètres : blob = ensemble de données binaires brutes. * +* len = quantité de données valides. * +* set = jeu de commandes concerné. * +* cmd = identifiant d'une commande donnée. * +* payload = charge utile à reconstituer. [OUT] * +* * +* Description : Reconstitue une charge utile à partir d'un contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_jdwp_payload(const bin_t *blob, off_t len, uint8_t set, uint8_t cmd, jdwp_payload *payload) +{ + bool result; /* Bilan à retourner */ + + if (_commands[set][cmd].get_payload == NULL) result = false; + else result = _commands[set][cmd].get_payload(blob, len, payload); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : payload = charge utile à supprimer de la mémoire. * +* set = jeu de commandes concerné. * +* cmd = identifiant d'une commande donnée. * +* * +* Description : Libère le contenu d'une charge utile. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_jdwp_payload(jdwp_payload *payload, uint8_t set, uint8_t cmd) +{ + if (_commands[set][cmd].free_payload != NULL) + _commands[set][cmd].free_payload(payload); + +} diff --git a/src/debug/jdwp/sets/list.h b/src/debug/jdwp/sets/list.h new file mode 100644 index 0000000..2fb135e --- /dev/null +++ b/src/debug/jdwp/sets/list.h @@ -0,0 +1,54 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * list.h - prototypes pour l'ensemble des jeux de commandes de JDWP + * + * 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_JDWP_SETS_LIST_H +#define _DEBUG_JDWP_SETS_LIST_H + + +#include <stdbool.h> + + +#include "../jdwp_def.h" +#include "../../../arch/archbase.h" + + + +/* Ensemble des contenus pris en compte */ +typedef union _jdwp_payload +{ + jdwp_cmd_vm_version_reply vs_reply; /* Infos. sur la version */ + + bin_t padding[500]; + +} jdwp_payload; + + +/* Reconstitue une charge utile à partir d'un contenu binaire. */ +bool get_jdwp_payload(const bin_t *, off_t, uint8_t, uint8_t, jdwp_payload *); + +/* Libère le contenu d'une charge utile. */ +void free_jdwp_payload(jdwp_payload *, uint8_t, uint8_t); + + + +#endif /* _DEBUG_JDWP_SETS_LIST_H */ diff --git a/src/debug/jdwp/sets/vm.c b/src/debug/jdwp/sets/vm.c new file mode 100644 index 0000000..fdb1ec0 --- /dev/null +++ b/src/debug/jdwp/sets/vm.c @@ -0,0 +1,97 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * vm.c - constitution des charges utiles liées à la VM + * + * 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 "vm.h" + + +#include <string.h> + + +#include "../misc/types.h" +#include "../../../common/endianness.h" + + + +/****************************************************************************** +* * +* Paramètres : blob = ensemble de données binaires brutes. * +* len = quantité de données valides. * +* reply = structure de réponse à constituer. [OUT] * +* * +* Description : Reconstitue une réponse quant à une version de serveur. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_jdwp_vm_version(const bin_t *blob, off_t len, jdwp_cmd_vm_version_reply *reply) +{ + bool result; /* Bilan à retourner */ + off_t pos; /* Tête de lecture */ + + pos = 0; + memset(reply, 0, sizeof(jdwp_cmd_vm_version_reply)); + + result = get_jdwp_string(blob, &pos, len, &reply->description); + if (!result) return false; + + result = read_u32(&reply->jdwp_major, blob, &pos, len, SRE_BIG); + if (!result) return false; + + result = read_u32(&reply->jdwp_minor, blob, &pos, len, SRE_BIG); + if (!result) return false; + + result = get_jdwp_string(blob, &pos, len, &reply->vm_version); + if (!result) return false; + + result = get_jdwp_string(blob, &pos, len, &reply->vm_name); + if (!result) return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : reply = structure de réponse à supprimer de la mémoire. * +* * +* Description : Libère le contenu d'une réponse quant à une version. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_jdwp_vm_version(jdwp_cmd_vm_version_reply *reply) +{ + free_jdwp_string(&reply->description); + + free_jdwp_string(&reply->vm_version); + + free_jdwp_string(&reply->vm_name); + +} diff --git a/src/debug/jdwp/sets/vm.h b/src/debug/jdwp/sets/vm.h new file mode 100644 index 0000000..de2c7db --- /dev/null +++ b/src/debug/jdwp/sets/vm.h @@ -0,0 +1,44 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * vm.h - prototypes pour la constitution des charges utiles liées à la VM + * + * 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_JDWP_SETS_VM_H +#define _DEBUG_JDWP_SETS_VM_H + + +#include <stdbool.h> + + +#include "../jdwp_def.h" +#include "../../../arch/archbase.h" + + + +/* Reconstitue une réponse quant à une version de serveur. */ +bool get_jdwp_vm_version(const bin_t *, off_t, jdwp_cmd_vm_version_reply *); + +/* Libère le contenu d'une réponse quant à une version. */ +void free_jdwp_vm_version(jdwp_cmd_vm_version_reply *); + + + +#endif /* _DEBUG_JDWP_SETS_VM_H */ diff --git a/src/debug/jdwp/tcp.c b/src/debug/jdwp/tcp.c new file mode 100644 index 0000000..38acd29 --- /dev/null +++ b/src/debug/jdwp/tcp.c @@ -0,0 +1,328 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * tcp.c - gestion des connexions TCP aux serveurs JDWP. + * + * 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 "tcp.h" + + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/types.h> + + +#include "packet.h" +#include "misc/header.h" +#include "sets/list.h" +#include "../stream-int.h" +#include "../../common/net.h" + + + +/* Flux de communication TCP avec un serveur JDWP (instance) */ +struct _GJdwpTcpClient +{ + GDebugStream parent; /* A laisser en premier */ + + char *server; /* Serveur à contacter */ + char *port; /* Port de connexion */ + int fd; /* Flux ouvert en L./E. */ + +}; + + +/* Flux de communication TCP avec un serveur JDWP (classe) */ +struct _GJdwpTcpClientClass +{ + GDebugStreamClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des flux de communication JDWP over TCP. */ +static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *); + +/* Initialise une instance de flux de communication avec JDWP. */ +static void g_jdwp_tcp_client_init(GJdwpTcpClient *); + +/* Etablit de façon effective une connexion à la cible. */ +static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *); + +/* Attend le signalement de données à traiter. */ +static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *); + +/* Envoie un paquet de données à un serveur de débogage. */ +static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *, const GJdwpPacket *); + +/* Réceptionne un paquet de données d'un serveur de débogage. */ +static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *, GJdwpPacket *); + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur JDWP. */ +G_DEFINE_TYPE(GJdwpTcpClient, g_jdwp_tcp_client, G_TYPE_DEBUG_STREAM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des flux de communication JVDP over TCP.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : client = instance à initialiser. * +* * +* Description : Initialise une instance de flux de communication avec JDWP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_jdwp_tcp_client_init(GJdwpTcpClient *client) +{ + GDebugStream *stream; /* Version parente */ + + stream = G_DEBUG_STREAM(client); + + stream->connect = (debug_connect_fc)g_jdwp_tcp_client_connect; + + stream->poll = (debug_poll_fc)g_jdwp_tcp_client_poll; + stream->send_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_send_packet; + stream->recv_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_recv_packet; + + stream->pkt_type = G_TYPE_JDWP_PACKET; + +} + + +/****************************************************************************** +* * +* Paramètres : server = nom ou adresse du serveur à contacter. * +* port = port de connexion. * +* * +* Description : Crée une nouvelle connexion TCP à un serveur JDWP. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDebugStream *g_jdwp_tcp_client_new(const char *server, const char *port) +{ + GJdwpTcpClient *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_JDWP_TCP_CLIENT, NULL); + + result->server = strdup(server); + result->port = strdup(port); + result->fd = -1; + + return G_DEBUG_STREAM(result); + +} + + +/****************************************************************************** +* * +* Paramètres : client = paramètres de connexion au serveur JDWP. * +* * +* Description : Etablit de façon effective une connexion à la cible. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *client) +{ + struct sockaddr_in addr; /* Infos de connexion distante */ + int sock; /* Flux ouvert à construire */ + char handshake[15]; /* Poignée de main chaleureuse */ + + sock = connect_via_tcp(client->server, client->port, &addr); + if (sock == -1) + { + printf("Echec de connexion au serveur JDWP sur %s:%s\n", + client->server, client->port); + return false; + } + + printf("Connecté à %s:%hd\n", client->server, ntohs(addr.sin_port)); + + if (send(sock, "JDWP-Handshake", 14, 0) != 14) + goto gjtcc_error; + + if (recv(sock, handshake, 14, 0) != 14) + goto gjtcc_error; + + if (strncmp(handshake, "JDWP-Handshake", 14) != 0) + goto gjtcc_error; + + client->fd = sock; + + return true; + + gjtcc_error: + + printf("Echec des premiers échanges !\n"); + + close(sock); + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : client = paramètres de connexion au serveur JDWP. * +* * +* Description : Attend le signalement de données à traiter. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *client) +{ + bool result; /* Statut à faire remonter */ + fd_set rfds; /* Liste des flux à surveiller */ + int ret; /* Bilan d'un appel */ + + result = false; + + FD_ZERO(&rfds); + FD_SET(client->fd, &rfds); + + ret = select(client->fd + 1, &rfds, NULL, NULL, NULL); + + switch (ret) + { + case -1: + perror("select()"); + break; + + case 0: + /* ?! */ + break; + + default: + result = true; + break; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en écriture à utiliser. * +* packet = zone mémoire à parcourir. * +* * +* Description : Envoie un paquet de données à un serveur de débogage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *client, const GJdwpPacket *packet) +{ + struct iovec iov[UIO_MAXIOV]; /* Table de vecteurs à écrire */ + int iovcnt; /* Quantité de champs valides */ + int i; /* Boucle de parcours */ + + g_debug_packet_vectorize(G_DEBUG_PACKET(packet), iov, &iovcnt); + + for (i = 0; i < iovcnt; i++) + if (send(client->fd, iov[i].iov_base, iov[i].iov_len, 0) != iov[i].iov_len) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : client = flux ouvert en lecture à utiliser. * +* packet = zone mémoire à remplir. [OUT] * +* * +* Description : Réceptionne un paquet de données d'un serveur de débogage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *client, GJdwpPacket *packet) +{ + bin_t *hblob; /* Contenu encodé en B.E. */ + jdwp_header *header; /* En-tête à reconstituer */ + uint32_t length; /* Taille de la charge utile */ + bin_t *pblob; /* Contenu encodé en B.E. */ + + hblob = g_jdwp_packet_get_hblob(packet); + + if (recv(client->fd, hblob, sizeof(jdwp_header), 0) != sizeof(jdwp_header)) + return false; + + if (!g_jdwp_packet_parse_header(packet)) + return false; + + header = g_jdwp_packet_get_header(packet); + length = header->length - sizeof(jdwp_header); + + pblob = g_jdwp_packet_get_pblob(packet); + + if (recv(client->fd, pblob, length, 0) != length) + return false; + + return true; + +} diff --git a/src/debug/jdwp/tcp.h b/src/debug/jdwp/tcp.h new file mode 100644 index 0000000..74487d6 --- /dev/null +++ b/src/debug/jdwp/tcp.h @@ -0,0 +1,56 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * tcp.h - prototypes pour la gestion des connexions TCP aux serveurs JDWP. + * + * 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_JDWP_TCP_H +#define _DEBUG_JDWP_TCP_H + + +#include "../stream.h" + + + +#define G_TYPE_JDWP_TCP_CLIENT g_jdwp_tcp_client_get_type() +#define G_JDWP_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_jdwp_tcp_client_get_type(), GJdwpTcpClient)) +#define G_IS_JDWP_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_jdwp_tcp_client_get_type())) +#define G_JDWP_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_JDWP_TCP_CLIENT, GJdwpTcpClientClass)) +#define G_IS_JDWP_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_JDWP_TCP_CLIENT)) +#define G_JDWP_TCP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JDWP_TCP_CLIENT, GJdwpTcpClientClass)) + + +/* Flux de communication TCP avec un serveur JDWP (instance) */ +typedef struct _GJdwpTcpClient GJdwpTcpClient; + +/* Flux de communication TCP avec un serveur JDWP (classe) */ +typedef struct _GJdwpTcpClientClass GJdwpTcpClientClass; + + + +/* Indique le type défini pour un flux de communication TCP avec un serveur JDWP. */ +GType g_jdwp_tcp_client_get_type(void); + +/* Crée une nouvelle connexion TCP à un serveur JDWP. */ +GDebugStream *g_jdwp_tcp_client_new(const char *, const char *); + + + +#endif /* _DEBUG_JDWP_TCP_H */ diff --git a/src/debug/packet-int.h b/src/debug/packet-int.h new file mode 100644 index 0000000..016b5d3 --- /dev/null +++ b/src/debug/packet-int.h @@ -0,0 +1,60 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.h - prototypes pour la définition interne des paquets utiles au débogage + * + * 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_PACKET_INT_H +#define _DEBUG_PACKET_INT_H + + +#include "packet.h" + + +#include "../common/dllist.h" + + + +/* Précise les zones mémoires correspondant au contenu. */ +typedef void (* debug_vectorize_fc) (GDebugPacket *, struct iovec [UIO_MAXIOV], int *); + + +/* Répresentation d'un paquet de débogage (instance) */ +struct _GDebugPacket +{ + GObject parent; /* A laisser en premier */ + + DL_LIST_ITEM(link); /* Lien vers les autres */ + + debug_vectorize_fc vectorize; /* Découpage des données */ + +}; + + +/* Répresentation d'un paquet de débogage (classe) */ +struct _GDebugPacketClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _DEBUG_PACKET_INT_H */ diff --git a/src/debug/packet.c b/src/debug/packet.c new file mode 100644 index 0000000..9a7df58 --- /dev/null +++ b/src/debug/packet.c @@ -0,0 +1,161 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.c - définition des paquets issus des protocoles de débogage + * + * 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 "packet.h" + + +#include "packet-int.h" + + + +/* Initialise la classe des paquets de débogage. */ +static void g_debug_packet_class_init(GDebugPacketClass *); + +/* Initialise une instance de paquet de débogage. */ +static void g_debug_packet_init(GDebugPacket *); + + + +/* Indique le type défini pour un paquet de débogage. */ +G_DEFINE_TYPE(GDebugPacket, g_debug_packet, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des paquets de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_debug_packet_class_init(GDebugPacketClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à initialiser. * +* * +* Description : Initialise une instance de paquet de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_debug_packet_init(GDebugPacket *packet) +{ + DL_LIST_ITEM_INIT(&packet->link); + +} + + +/****************************************************************************** +* * +* Paramètres : packet = instance à convertir. * +* iov = table de vecteurs. [OUT] * +* iovcnt = quantité de champs renseignés. [OUT] * +* * +* Description : Précise les zones mémoires correspondant au contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_debug_packet_vectorize(GDebugPacket *packet, struct iovec iov[UIO_MAXIOV], int *iovcnt) +{ + packet->vectorize(packet, iov, iovcnt); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de paquets à consulter. * +* : iter = position actuelle dans la liste. * +* * +* Description : Fournit l'élement suivant un autre pour un parcours. * +* * +* Retour : Elément suivant ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDebugPacket *g_debug_packet_get_next_iter(const GDebugPacket *list, const GDebugPacket *iter) +{ + GDebugPacket *result; /* Elément suivant à renvoyer */ + + result = dl_list_next_iter(iter, list, GDebugPacket, link); + + return result; + +} + + +/****************************************************************************** +* * +* 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_debug_packet_push(GDebugPacket **list, GDebugPacket *item) +{ + dl_list_push(item, list, GDebugPacket, 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 : - * +* * +******************************************************************************/ + +GDebugPacket *g_debug_packet_pop(GDebugPacket **list) +{ + return dl_list_pop(list, GDebugPacket, link); + +} diff --git a/src/debug/packet.h b/src/debug/packet.h new file mode 100644 index 0000000..c3d45a5 --- /dev/null +++ b/src/debug/packet.h @@ -0,0 +1,66 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * packet.h - prototypes pour la définition des paquets issus des protocoles de débogage + * + * 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_PACKET_H +#define _DEBUG_PACKET_H + + +#include <glib-object.h> +#include <sys/uio.h> + + + +#define G_TYPE_DEBUG_PACKET g_debug_packet_get_type() +#define G_DEBUG_PACKET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_debug_packet_get_type(), GDebugPacket)) +#define G_IS_DEBUG_PACKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_debug_packet_get_type())) +#define G_DEBUG_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEBUG_PACKET, GDebugPacketClass)) +#define G_IS_DEBUG_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEBUG_PACKET)) +#define G_DEBUG_PACKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEBUG_PACKET, GDebugPacketClass)) + + +/* Répresentation d'un paquet de débogage (instance) */ +typedef struct _GDebugPacket GDebugPacket; + +/* Répresentation d'un paquet de débogage (classe) */ +typedef struct _GDebugPacketClass GDebugPacketClass; + + + +/* Indique le type défini pour un paquet de débogage. */ +GType g_debug_packet_get_type(void); + +/* Précise les zones mémoires correspondant au contenu. */ +void g_debug_packet_vectorize(GDebugPacket *, struct iovec [UIO_MAXIOV], int *); + +/* Fournit l'élement suivant un autre pour un parcours. */ +GDebugPacket *g_debug_packet_get_next_iter(const GDebugPacket *, const GDebugPacket *); + +/* Ajoute un paquet à une liste de paquets. */ +void g_debug_packet_push(GDebugPacket **, GDebugPacket *); + +/* Retire et fournit le premier élément d'une liste de paquets. */ +GDebugPacket *g_debug_packet_pop(GDebugPacket **); + + + +#endif /* _DEBUG_PACKET_H */ diff --git a/src/debug/remgdb/tcp.c b/src/debug/remgdb/tcp.c index fa97f8c..6c6b78b 100644 --- a/src/debug/remgdb/tcp.c +++ b/src/debug/remgdb/tcp.c @@ -35,6 +35,8 @@ #include "stream-int.h" +#include "../../common/net.h" + /* Flux de communication TCP avec un serveur GDB (instance) */ struct _GGdbTcpClient @@ -59,7 +61,7 @@ static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *); static void g_gdb_tcp_client_init(GGdbTcpClient *); /* Ouvre une connexion TCP à un serveur GDB. */ -static int connect_via_tcp(const char *, const char *); +//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); @@ -127,7 +129,7 @@ static void g_gdb_tcp_client_init(GGdbTcpClient *client) * Remarques : - * * * ******************************************************************************/ - +#if 0 static int connect_via_tcp(const char *server, const char *port) { int result; /* Bilan à retourner */ @@ -181,7 +183,7 @@ static int connect_via_tcp(const char *server, const char *port) return result; } - +#endif /****************************************************************************** * * @@ -201,7 +203,7 @@ 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); + sock = connect_via_tcp(server, port, NULL); if (sock == -1) return NULL; result = g_object_new(G_TYPE_GDB_TCP_CLIENT, NULL); diff --git a/src/debug/stream-int.h b/src/debug/stream-int.h new file mode 100644 index 0000000..6250522 --- /dev/null +++ b/src/debug/stream-int.h @@ -0,0 +1,86 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream-int.h - prototypes internes pour la gestion des connexions liées aux débogages. + * + * 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_STREAM_INT_H +#define _DEBUG_STREAM_INT_H + + +#include "stream.h" + + + +/* Etablit de façon effective une connexion à la cible. */ +typedef bool (* debug_connect_fc) (GDebugStream *); + + + +/* Attend le signalement de données à traiter. */ +typedef bool (* debug_poll_fc) (GDebugStream *); + +/* Réceptionne un paquet de données d'un serveur de débogage. */ +typedef bool (* debug_pkt_op_fc) (GDebugStream *, GDebugPacket *); + + + + +/* Envoie des données à un serveur de débogage. */ +typedef bool (* send_debug_data_fc) (GDebugStream *, const char *, size_t); + +/* Réceptionne un octet de donnée d'un serveur de débogage. */ +typedef bool (* recv_debug_byte_fc) (GDebugStream *, char *); + + +/* Flux de communication avec un serveur de débogage (instance) */ +struct _GDebugStream +{ + GObject parent; /* A laisser en premier */ + + debug_connect_fc connect; /* Connexion distante */ + + debug_poll_fc poll; /* Attente de traitements */ + debug_pkt_op_fc send_packet; /* Emission d'un paquet */ + debug_pkt_op_fc recv_packet; /* Réception d'un paquet */ + + GThread *listening; /* Thread pour les réceptions */ + + GType pkt_type; /* Type des paquets traités */ + GDebugPacket *free_packets; /* Liste des disponibles */ + GMutex *free_mutex; /* Accès à la liste */ + + GDebugPacket *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 de débogage (classe) */ +struct _GDebugStreamClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _DEBUG_STREAM_INT_H */ diff --git a/src/debug/stream.c b/src/debug/stream.c new file mode 100644 index 0000000..4c4767a --- /dev/null +++ b/src/debug/stream.c @@ -0,0 +1,298 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream.c - gestion des connexions aux serveurs de débogage. + * + * 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 "stream.h" + + +#include <stdio.h> +#include <stdlib.h> +#include <glib/gthread.h> + + +#include "stream-int.h" +#include "../common/dllist.h" /* FIXME : remme ! */ + + + +/* Initialise la classe des flux de communication de débogage. */ +static void g_debug_stream_class_init(GDebugStreamClass *); + +/* Initialise une instance de flux de communication de débogage. */ +static void g_debug_stream_init(GDebugStream *); + +/* Ecoute une connexion à un serveur de débogage. */ +static void *debug_stream_thread(GDebugStream *); + +/* Réceptionne un paquet d'un serveur de débogage. */ +static bool g_debug_stream_read_packet(GDebugStream *, GDebugPacket *); + + + +/* Indique le type défini pour un flux de communication avec un serveur de débogage. */ +G_DEFINE_TYPE(GDebugStream, g_debug_stream, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des flux de communication de débogage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_debug_stream_class_init(GDebugStreamClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : stream = instance à initialiser. * +* * +* Description : Initialise une instance de flux de communication de débogage.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_debug_stream_init(GDebugStream *stream) +{ + stream->free_mutex = g_mutex_new(); + + stream->recv_cond = g_cond_new(); + stream->recv_mutex = g_mutex_new(); + +} + + +/****************************************************************************** +* * +* Paramètres : stream = paramètres de connexion distante. * +* * +* Description : Etablit de façon effective une connexion à la cible. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_debug_stream_connect(GDebugStream *stream) +{ + GError *error; /* Bilan de création de thread */ + + if (stream->connect == NULL || !stream->connect(stream)) + return false; + + if (!g_thread_create((GThreadFunc)debug_stream_thread, stream, FALSE, &error)) + { + /* TODO : disconnect ! */ + return false; + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = encadrement associée à l'opération. * +* * +* Description : Ecoute une connexion à un serveur de débogage. * +* * +* Retour : ??? * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *debug_stream_thread(GDebugStream *stream) +{ + bool status; /* Bilan d'évolution */ + GDebugPacket *packet; /* Nouveau paquet reçu */ + + while (1) + { + status = stream->poll(stream); + if (!status) break; + + packet = g_debug_stream_get_free_packet(stream); + + if (stream->recv_packet(stream, packet)) + { + g_mutex_lock(stream->recv_mutex); + g_debug_packet_push(&stream->recv_packets, packet); + g_mutex_unlock(stream->recv_mutex); + + g_cond_signal(stream->recv_cond); + + } + else g_debug_stream_mark_packet_as_free(stream, packet); + + } + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication de débogage à consulter. * +* * +* Description : Fournit un paquet prêt à emploi. * +* * +* Retour : Paquet prêt à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDebugPacket *g_debug_stream_get_free_packet(GDebugStream *stream) +{ + GDebugPacket *result; /* Paquet à retourner */ + + g_mutex_lock(stream->free_mutex); + + if (dl_list_empty(stream->free_packets)) + result = g_object_new(stream->pkt_type, NULL); + + else + result = g_debug_packet_pop(&stream->free_packets); + + g_mutex_unlock(stream->free_mutex); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication de débogage à mettre à jour. * +* packet = paquet à considérer comme disponible. * +* * +* Description : Place un paquet en attente d'une future utilisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_debug_stream_mark_packet_as_free(GDebugStream *stream, GDebugPacket *packet) +{ + g_mutex_lock(stream->free_mutex); + + g_debug_packet_push(&stream->free_packets, packet); + + g_mutex_unlock(stream->free_mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux ouvert en écriture à mettre à jour. * +* packet = données à transmettre. * +* * +* Description : Envoie un paquet à un serveur de débogage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_debug_stream_send_packet(GDebugStream *stream, GDebugPacket *packet) +{ + bool result; /* Bilan à retourner */ + + result = stream->send_packet(stream, packet); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stream = flux de communication de débogage à consulter. * +* filter = éventuelle fonction de sélection du paquet. * +* data = éventuelle donnée à associer au filtrage. * +* * +* Description : Fournit un paquet reçu d'un serveur de débogage. * +* * +* Retour : Paquet de débogage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDebugPacket *g_debug_stream_recv_packet(GDebugStream *stream, filter_packet_fc filter, void *data) +{ + GDebugPacket *result; /* Paquet à retourner */ + + g_mutex_lock(stream->recv_mutex); + + if (filter != NULL) + { + gdsrp_try_again: + + for (result = stream->recv_packets; + result != NULL; + result = g_debug_packet_get_next_iter(stream->recv_packets, result)) + { + if (filter(result, data)) + break; + } + + if (result == NULL) + { + g_cond_wait(stream->recv_cond, stream->recv_mutex); + goto gdsrp_try_again; + } + + } + else + { + if (dl_list_empty(stream->recv_packets)) + g_cond_wait(stream->recv_cond, stream->recv_mutex); + + result = g_debug_packet_pop(&stream->recv_packets); + + } + + g_mutex_unlock(stream->recv_mutex); + + return result; + +} diff --git a/src/debug/stream.h b/src/debug/stream.h new file mode 100644 index 0000000..c0d342d --- /dev/null +++ b/src/debug/stream.h @@ -0,0 +1,74 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * stream.h - prototypes pour la gestion des connexions aux serveurs de débogage. + * + * 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_STREAM_H +#define _DEBUG_STREAM_H + + +#include <stdbool.h> + + +#include "packet.h" + + + +#define G_TYPE_DEBUG_STREAM g_debug_stream_get_type() +#define G_DEBUG_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_debug_stream_get_type(), GDebugStream)) +#define G_IS_DEBUG_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_debug_stream_get_type())) +#define G_DEBUG_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEBUG_STREAM, GDebugStreamClass)) +#define G_IS_DEBUG_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEBUG_STREAM)) +#define G_DEBUG_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEBUG_STREAM, GDebugStreamClass)) + + +/* Flux de communication avec un serveur de débogage (instance) */ +typedef struct _GDebugStream GDebugStream; + +/* Flux de communication avec un serveur de débogage (classe) */ +typedef struct _GDebugStreamClass GDebugStreamClass; + + +/* Filtre la récupération de paquet */ +typedef bool (* filter_packet_fc) (const GDebugPacket *, void *); + + +/* Indique le type défini pour un flux de communication avec un serveur de débogage. */ +GType g_debug_stream_get_type(void); + +/* Etablit de façon effective une connexion à la cible. */ +bool g_debug_stream_connect(GDebugStream *); + +/* Fournit un paquet prêt à emploi. */ +GDebugPacket *g_debug_stream_get_free_packet(GDebugStream *); + +/* Place un paquet en attente d'une future utilisation. */ +void g_debug_stream_mark_packet_as_free(GDebugStream *, GDebugPacket *); + +/* Envoie un paquet à un serveur de débogage. */ +bool g_debug_stream_send_packet(GDebugStream *, GDebugPacket *); + +/* Fournit un paquet reçu d'un serveur de débogage. */ +GDebugPacket *g_debug_stream_recv_packet(GDebugStream *, filter_packet_fc, void *); + + + +#endif /* _DEBUG_STREAM_H */ |