summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2012-02-17 17:51:06 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2012-02-17 17:51:06 (GMT)
commit73605bffb935fc51a52be1936426211e31dd898a (patch)
tree094d72321011baae0d5054e06906e9d006249c3b /src/debug
parent98a3c749a15349b874dcef0ce3a43ebff651d95a (diff)
Listed all running threads using Python.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@234 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/debugger-int.h7
-rw-r--r--src/debug/debugger.c28
-rw-r--r--src/debug/debugger.h3
-rw-r--r--src/debug/jdwp/debugger.c171
-rw-r--r--src/debug/jdwp/jdwp_def.h70
-rw-r--r--src/debug/jdwp/misc/Makefile.am1
-rw-r--r--src/debug/jdwp/misc/header.c26
-rw-r--r--src/debug/jdwp/misc/header.h5
-rw-r--r--src/debug/jdwp/misc/id.c148
-rw-r--r--src/debug/jdwp/misc/id.h131
-rw-r--r--src/debug/jdwp/packet.c90
-rw-r--r--src/debug/jdwp/packet.h10
-rw-r--r--src/debug/jdwp/sets/Makefile.am1
-rw-r--r--src/debug/jdwp/sets/list.c86
-rw-r--r--src/debug/jdwp/sets/list.h14
-rw-r--r--src/debug/jdwp/sets/thread.c116
-rw-r--r--src/debug/jdwp/sets/thread.h46
-rw-r--r--src/debug/jdwp/sets/vm.c109
-rw-r--r--src/debug/jdwp/sets/vm.h13
-rw-r--r--src/debug/jdwp/tcp.c34
-rw-r--r--src/debug/packet.c22
-rw-r--r--src/debug/packet.h5
-rw-r--r--src/debug/stream-int.h8
-rw-r--r--src/debug/stream.c7
24 files changed, 1105 insertions, 46 deletions
diff --git a/src/debug/debugger-int.h b/src/debug/debugger-int.h
index 6f85a84..490b35c 100644
--- a/src/debug/debugger-int.h
+++ b/src/debug/debugger-int.h
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* debugger-int.h - prototypes pour l'interface des débogueurs
*
- * Copyright (C) 2009-2011 Cyrille Bagard
+ * Copyright (C) 2009-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -41,6 +41,9 @@ typedef bool (* basic_debugger_fc) (GBinaryDebugger *);
/* Reprend une procédure de débogage. */
typedef bool (* resume_debugger_fc) (GBinaryDebugger *);
+/* Fournit les identifiants de tous les threads actifs. */
+typedef pid_t * (* dbg_list_all_threads_fc) (GBinaryDebugger *, char ***, size_t *);
+
/* Fournit la valeur des registres de l'architecture. */
typedef register_value * (* get_register_values_fc) (GBinaryDebugger *, size_t *);
@@ -59,6 +62,8 @@ struct _GBinaryDebugger
resume_debugger_fc resume; /* Relance le débogueur */
basic_debugger_fc kill; /* Tue le débogueur */
+ dbg_list_all_threads_fc all_threads; /* Liste des threads actifs */
+
get_register_values_fc get_reg_values; /* Obtient les valeurs de reg. */
};
diff --git a/src/debug/debugger.c b/src/debug/debugger.c
index d08bd26..ce62625 100644
--- a/src/debug/debugger.c
+++ b/src/debug/debugger.c
@@ -233,6 +233,34 @@ void g_binary_debugger_kill(GBinaryDebugger *debugger)
/******************************************************************************
* *
+* Paramètres : debugger = instance du module de débogage chargé. *
+* names = désignations de tous les threads ou NULL. [OUT] *
+* count = nombre de threads actifs. [OUT] *
+* *
+* Description : Fournit les identifiants de tous les threads actifs. *
+* *
+* Retour : Liste des threads décomptés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+pid_t *g_binary_debugger_list_all_threads(GBinaryDebugger *debugger, char ***names, size_t *count)
+{
+ pid_t *result; /* Liste à retourner */
+
+ if (debugger->all_threads != NULL)
+ result = debugger->all_threads(debugger, names, count);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : debugger = débogueur à manipuler ici. *
* count = nombre de transmissions effetuées. *
* *
diff --git a/src/debug/debugger.h b/src/debug/debugger.h
index f57a9f0..362f8a1 100644
--- a/src/debug/debugger.h
+++ b/src/debug/debugger.h
@@ -88,6 +88,9 @@ void g_binary_debugger_resume(GBinaryDebugger *);
/* Tue une procédure de débogage. */
void g_binary_debugger_kill(GBinaryDebugger *);
+/* Fournit les identifiants de tous les threads actifs. */
+pid_t *g_binary_debugger_list_all_threads(GBinaryDebugger *, char ***, size_t *);
+
/* Fournit la valeur des registres de l'architecture. */
register_value *g_binary_debugger_get_registers(GBinaryDebugger *, size_t *);
diff --git a/src/debug/jdwp/debugger.c b/src/debug/jdwp/debugger.c
index ada09bb..51a0db8 100644
--- a/src/debug/jdwp/debugger.c
+++ b/src/debug/jdwp/debugger.c
@@ -24,6 +24,7 @@
#include "debugger.h"
+#include <string.h>
#include <i18n.h>
@@ -66,6 +67,10 @@ static void g_java_debugger_init(GJavaDebugger *);
/* Procède au démarrage effectif de la session de débogage. */
static bool g_java_debugger_attach(GJavaDebugger *);
+/* Fournit les identifiants de tous les threads actifs. */
+static pid_t *g_java_debugger_list_all_threads(GJavaDebugger *, char ***, size_t *);
+
+
/* Indique le type défini par la GLib pour le débogueur java. */
G_DEFINE_TYPE(GJavaDebugger, g_java_debugger, G_TYPE_BINARY_DEBUGGER);
@@ -110,6 +115,8 @@ static void g_java_debugger_init(GJavaDebugger *debugger)
parent->attach = (attach_debugger_fc)g_java_debugger_attach;
+ parent->all_threads = (dbg_list_all_threads_fc)g_java_debugger_list_all_threads;
+
#if 0
parent->run = (basic_debugger_fc)g_java_debugger_run;
parent->resume = (resume_debugger_fc)g_java_debugger_resume;
@@ -174,6 +181,8 @@ static bool g_java_debugger_attach(GJavaDebugger *debugger)
result = g_debug_stream_connect(debugger->stream);
if (!result) goto gjda_error;
+ result = false;
+
/* Demande de version */
req = g_debug_stream_get_free_packet(debugger->stream);
@@ -182,14 +191,15 @@ static bool g_java_debugger_attach(GJavaDebugger *debugger)
JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION);
if (!g_debug_stream_send_packet(debugger->stream, req))
- goto gjda_error;
+ goto gjda_req_error;
ret = g_debug_stream_recv_packet(debugger->stream,
(filter_packet_fc)g_jdwp_packet_is_reply, req);
- if (!ret) goto gjda_error;
+ if (!ret) goto gjda_req_error;
- if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(ret), JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION))
- goto gjda_error;
+ if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(ret),
+ JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION))
+ goto gjda_ret_error;
payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(ret));
@@ -198,15 +208,158 @@ static bool g_java_debugger_attach(GJavaDebugger *debugger)
payload->vs_reply.jdwp_major, payload->vs_reply.jdwp_minor,
payload->vs_reply.vm_version.value);
- g_jdwp_packet_free_payload(G_JDWP_PACKET(ret), JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_VERSION);
+ g_debug_stream_mark_packet_as_free(debugger->stream, req);
+ g_debug_stream_mark_packet_as_free(debugger->stream, ret);
+
+ /* Récupération des tailles d'identifiants */
+
+ req = g_debug_stream_get_free_packet(debugger->stream);
+
+ g_jdwp_packet_set_request_header(G_JDWP_PACKET(req),
+ JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_ID_SIZES);
+
+ if (!g_debug_stream_send_packet(debugger->stream, req))
+ goto gjda_req_error;
+
+ ret = g_debug_stream_recv_packet(debugger->stream,
+ (filter_packet_fc)g_jdwp_packet_is_reply, req);
+ if (!ret) goto gjda_req_error;
+
+ if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(ret),
+ JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_ID_SIZES))
+ goto gjda_ret_error;
+
+ payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(ret));
+
+ g_jdwp_packet_set_sizes(G_JDWP_PACKET(ret), &payload->sz_reply);
+
+ result = true;
+
+ gjda_ret_error:
+
+ g_debug_stream_mark_packet_as_free(debugger->stream, ret);
+
+ gjda_req_error:
+
+ g_debug_stream_mark_packet_as_free(debugger->stream, req);
gjda_error:
- if (req != NULL)
- g_debug_stream_mark_packet_as_free(debugger->stream, req);
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = instance du module de débogage chargé. *
+* names = désignations de tous les threads ou NULL. [OUT] *
+* count = nombre de threads actifs. [OUT] *
+* *
+* Description : Fournit les identifiants de tous les threads actifs. *
+* *
+* Retour : Liste des threads décomptés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static pid_t *g_java_debugger_list_all_threads(GJavaDebugger *debugger, char ***names, size_t *count)
+{
+ pid_t *result; /* Bilan à retourner */
+ GDebugPacket *req; /* Requête à formuler */
+ GDebugPacket *ret; /* Obtention de la réponse */
+ jdwp_payload *payload; /* Charge utile d'une réponse */
+ size_t i; /* Boucle de parcours */
+ GDebugPacket *sub_req; /* Requête à formuler */
+ jdwp_cmd_thread_name_request ident; /* Indentification d'un thread */
+ GDebugPacket *sub_ret; /* Obtention de la réponse */
+ jdwp_payload *sub_payload; /* Charge utile d'une réponse */
+
+ result = NULL;
+ *count = 0;
+
+ req = g_debug_stream_get_free_packet(debugger->stream);
+
+ g_jdwp_packet_set_request_header(G_JDWP_PACKET(req),
+ JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_ALL_THREADS);
+
+ if (!g_debug_stream_send_packet(debugger->stream, req))
+ goto gjdlat_req_error;
+
+ ret = g_debug_stream_recv_packet(debugger->stream,
+ (filter_packet_fc)g_jdwp_packet_is_reply, req);
+ if (!ret) goto gjdlat_req_error;
+
+ if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(ret),
+ JDWP_CST_VIRTUAL_MACHINE, JDWP_CMD_VM_ALL_THREADS))
+ goto gjdlat_ret_error;
+
+ payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(ret));
+
+ *count = payload->th_reply.count;
+ result = (pid_t *)calloc(*count, sizeof(pid_t));
+
+ if (names != NULL)
+ *names = (char **)calloc(*count, sizeof(char *));
+
+ for (i = 0; i < *count; i++)
+ {
+ result[i] = (pid_t)payload->th_reply.threads[i];
+
+ if (names != NULL)
+ {
+ sub_req = g_debug_stream_get_free_packet(debugger->stream);
+
+ g_jdwp_packet_set_request_header(G_JDWP_PACKET(sub_req),
+ JDWP_CST_THREAD_REFERENCE, JDWP_CMD_THREAD_NAME);
+
+ ident.id = result[i];
+ g_jdwp_packet_set_payload(G_JDWP_PACKET(sub_req), (jdwp_payload *)&ident);
+
+ if (!g_debug_stream_send_packet(debugger->stream, sub_req))
+ {
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_req);
+ (*names)[i] = strdup("???");
+ continue;
+ }
+
+ sub_ret = g_debug_stream_recv_packet(debugger->stream,
+ (filter_packet_fc)g_jdwp_packet_is_reply, sub_req);
+ if (!sub_ret)
+ {
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_req);
+ (*names)[i] = strdup("???");
+ continue;
+ }
+
+ if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(sub_ret),
+ JDWP_CST_THREAD_REFERENCE, JDWP_CMD_THREAD_NAME))
+ {
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_req);
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_ret);
+ (*names)[i] = strdup("???");
+ continue;
+ }
+
+ sub_payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(sub_ret));
+
+ (*names)[i] = strdup(sub_payload->th_name.name.value);
+
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_req);
+ g_debug_stream_mark_packet_as_free(debugger->stream, sub_ret);
+
+ }
+
+ }
+
+ gjdlat_ret_error:
+
+ g_debug_stream_mark_packet_as_free(debugger->stream, ret);
+
+ gjdlat_req_error:
- if (ret != NULL)
- g_debug_stream_mark_packet_as_free(debugger->stream, ret);
+ g_debug_stream_mark_packet_as_free(debugger->stream, req);
return result;
diff --git a/src/debug/jdwp/jdwp_def.h b/src/debug/jdwp/jdwp_def.h
index fc5a8fe..7f13f8c 100644
--- a/src/debug/jdwp/jdwp_def.h
+++ b/src/debug/jdwp/jdwp_def.h
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* jdwp_def.h - transcription du protocole Java Debug Wire Protocol
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -26,6 +26,7 @@
#include <stdint.h>
+#include <sys/types.h>
@@ -72,10 +73,31 @@ typedef struct __attribute__((__packed__)) _jdwp_header
/* ---------------------------------------------------------------------------------- */
+/* CONSTANTES UTILISEES DANS JDWP */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Constantes TypeTag */
+typedef uint8_t jdwp_type_tag;
+
+#define JDWP_TYPE_TAG_CLASS 1 /* Le type est une classe */
+#define JDWP_TYPE_TAG_INTERFACE 2 /* Le type est une interface */
+#define JDWP_TYPE_TAG_ARRAY 3 /* Le type est un tableau */
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* TYPES DE BASE DIVERS POUR JDWP */
/* ---------------------------------------------------------------------------------- */
+/* Identifiant de taille dynamique */
+typedef uint64_t jdwp_dynsized_id;
+
+
/* "string" */
@@ -89,22 +111,32 @@ typedef struct _jdwp_string
-
-
/**
* Jeux de commandes.
*/
+#define JDWP_CST_NONE 0 /* Organisation interne */
#define JDWP_CST_VIRTUAL_MACHINE 1
+#define JDWP_CST_THREAD_REFERENCE 11
/**
* Sous-commandes d'un jeu.
*/
+/* Organisation interne */
+
+#define JDWP_CMD_NONE 0
+
/* VirtualMachine Command Set */
#define JDWP_CMD_VM_VERSION 1
+#define JDWP_CMD_VM_ALL_THREADS 4
+#define JDWP_CMD_VM_ID_SIZES 7
+
+/* ThreadReference Command Set */
+
+#define JDWP_CMD_THREAD_NAME 1
/**
@@ -123,8 +155,40 @@ typedef struct _jdwp_cmd_vm_version_reply
} jdwp_cmd_vm_version_reply;
+/* JDWP_CMD_VM_ALL_THREADS */
+
+typedef struct _jdwp_cmd_vm_allthreads_reply
+{
+ uint32_t count; /* Taille de la liste */
+ jdwp_dynsized_id *threads; /* Identifiant des threads */
+
+} jdwp_cmd_vm_allthreads_reply;
+/* JDWP_CMD_VM_ID_SIZES */
+
+typedef struct _jdwp_cmd_vm_id_sizes_reply
+{
+ uint32_t field_id_size; /* taille pour un 'fieldID' */
+ uint32_t method_id_size; /* taille pour un 'methodID' */
+ uint32_t object_id_size; /* taille pour un 'objectID' */
+ uint32_t reference_type_id_size; /* taille pour un '...TypeID' */
+ uint32_t frame_id_size; /* taille pour un 'frameID' */
+
+} jdwp_cmd_vm_id_sizes_reply;
+
+/* JDWP_CMD_THREAD_NAME */
+
+typedef struct _jdwp_cmd_thread_name_request
+{
+ jdwp_dynsized_id id; /* Identifiant du thread visé */
+
+} jdwp_cmd_thread_name_request;
+
+typedef struct _jdwp_cmd_thread_name_reply
+{
+ jdwp_string name; /* Désignation humaine */
+} jdwp_cmd_thread_name_reply;
diff --git a/src/debug/jdwp/misc/Makefile.am b/src/debug/jdwp/misc/Makefile.am
index cfb4a06..44c6224 100644
--- a/src/debug/jdwp/misc/Makefile.am
+++ b/src/debug/jdwp/misc/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdebugjdwpmisc.la
libdebugjdwpmisc_la_SOURCES = \
header.h header.c \
+ id.h id.c \
types.h types.c
libdebugjdwpmisc_la_LDFLAGS =
diff --git a/src/debug/jdwp/misc/header.c b/src/debug/jdwp/misc/header.c
index ad41c90..8e381a1 100644
--- a/src/debug/jdwp/misc/header.c
+++ b/src/debug/jdwp/misc/header.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* header.c - constitution des deux types d'en-têtes JDWP
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -121,6 +121,30 @@ void set_jdwp_reply_header(jdwp_header *header, bin_t *blob, uint32_t length, ui
/******************************************************************************
* *
+* Paramètres : header = en-tête logicielle au format local à constituer. *
+* blob = en-tête en gros boutiste du paquet à constituer. *
+* *
+* Description : Enregistre au format binaire la valeur actuelle de la taille.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void update_jdwp_header_length(const jdwp_header *header, bin_t *blob)
+{
+ off_t pos; /* Tête d'écriture */
+
+ pos = 0;
+
+ write_u32(&header->length, 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] *
* *
diff --git a/src/debug/jdwp/misc/header.h b/src/debug/jdwp/misc/header.h
index d8fa845..f76a852 100644
--- a/src/debug/jdwp/misc/header.h
+++ b/src/debug/jdwp/misc/header.h
@@ -2,7 +2,7 @@
/* 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
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -39,6 +39,9 @@ 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);
+/* Enregistre au format binaire la valeur actuelle de la taille. */
+void update_jdwp_header_length(const jdwp_header *, bin_t *);
+
/* Lit une en-tête de paquet au format JDWP. */
bool get_jdwp_header(const bin_t *, jdwp_header *);
diff --git a/src/debug/jdwp/misc/id.c b/src/debug/jdwp/misc/id.c
new file mode 100644
index 0000000..bf49ede
--- /dev/null
+++ b/src/debug/jdwp/misc/id.c
@@ -0,0 +1,148 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * id.c - constitution des identifiants de taille dynamique
+ *
+ * Copyright (C) 2012 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 "id.h"
+
+
+#include "../../../common/endianness.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : id = identifiant à fournir. *
+* size = référence pour la taille utilisée. *
+* blob = flux de données à analyser. [OUT] *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* *
+* Description : Ecrit un identifiant enregistré dans une taille dynamique. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _set_jdwp_dynsized_id(const jdwp_dynsized_id *id, uint32_t size, bin_t *blob, off_t *pos, off_t len)
+{
+ uint8_t id8; /* Valeur sur 1 octets */
+ uint16_t id16; /* Valeur sur 2 octets */
+ uint32_t id32; /* Valeur sur 4 octets */
+ uint64_t id64; /* Valeur sur 8 octets */
+
+ switch (size)
+ {
+ case 1:
+ id8 = (uint8_t)*id;
+ if (!write_u8(&id8, blob, pos, len, SRE_BIG))
+ return false;
+ break;
+
+ case 2:
+ id16 = (uint16_t)*id;
+ if (!write_u16(&id16, blob, pos, len, SRE_BIG))
+ return false;
+ break;
+
+ case 4:
+ id32 = (uint32_t)*id;
+ if (!write_u32(&id32, blob, pos, len, SRE_BIG))
+ return false;
+ break;
+
+ case 8:
+ id64 = (uint64_t)*id;
+ if (!write_u64(&id64, blob, pos, len, SRE_BIG))
+ return false;
+ break;
+
+ default:
+ return false;
+ break;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : blob = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* size = référence pour la taille utilisée. *
+* id = identifiant à fournir. [OUT] *
+* *
+* Description : Lit un identifiant enregistré dans une taille dynamique. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _get_jdwp_dynsized_id(const bin_t *blob, off_t *pos, off_t len, uint32_t size, jdwp_dynsized_id *id)
+{
+ uint8_t id8; /* Valeur sur 1 octets */
+ uint16_t id16; /* Valeur sur 2 octets */
+ uint32_t id32; /* Valeur sur 4 octets */
+ uint64_t id64; /* Valeur sur 8 octets */
+
+ switch (size)
+ {
+ case 1:
+ if (!read_u8(&id8, blob, pos, len, SRE_BIG))
+ return false;
+ *id = (jdwp_dynsized_id)id8;
+ break;
+
+ case 2:
+ if (!read_u16(&id16, blob, pos, len, SRE_BIG))
+ return false;
+ *id = (jdwp_dynsized_id)id16;
+ break;
+
+ case 4:
+ if (!read_u32(&id32, blob, pos, len, SRE_BIG))
+ return false;
+ *id = (jdwp_dynsized_id)id32;
+ break;
+
+ case 8:
+ if (!read_u64(&id64, blob, pos, len, SRE_BIG))
+ return false;
+ *id = (jdwp_dynsized_id)id64;
+ break;
+
+ default:
+ return false;
+ break;
+
+ }
+
+ return true;
+
+}
diff --git a/src/debug/jdwp/misc/id.h b/src/debug/jdwp/misc/id.h
new file mode 100644
index 0000000..49a103b
--- /dev/null
+++ b/src/debug/jdwp/misc/id.h
@@ -0,0 +1,131 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * id.h - prototypes pour la constitution des identifiants de taille dynamique
+ *
+ * Copyright (C) 2012 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_ID_H
+#define _DEBUG_JDWP_MISC_ID_H
+
+
+#include <stdbool.h>
+
+
+#include "../jdwp_def.h"
+#include "../../../arch/archbase.h"
+
+
+
+/* Ecrit un identifiant enregistré dans une taille dynamique. */
+bool _set_jdwp_dynsized_id(const jdwp_dynsized_id *, uint32_t, bin_t *, off_t *, off_t);
+
+
+#define set_jdwp_object_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_thread_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_thread_group_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_string_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_class_loader_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_class_object_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_array_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_reference_type_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->object_id_size, blob, pos, len)
+
+#define set_jdwp_class_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->reference_type_id_size, blob, pos, len)
+
+#define set_jdwp_interface_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->reference_type_id_size, blob, pos, len)
+
+#define set_jdwp_array_type_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->reference_type_id_size, blob, pos, len)
+
+#define set_jdwp_method_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->method_id_size, blob, pos, len)
+
+#define set_jdwp_field_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->field_id_size, blob, pos, len)
+
+#define set_jdwp_frame_id(id, sizes, blob, pos, len) \
+ _set_jdwp_dynsized_id(id, sizes->frame_id_size, blob, pos, len)
+
+
+/* Lit un identifiant enregistré dans une taille dynamique. */
+bool _get_jdwp_dynsized_id(const bin_t *, off_t *, off_t, uint32_t, jdwp_dynsized_id *);
+
+
+#define get_jdwp_object_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_thread_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_thread_group_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_string_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_class_loader_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_class_object_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_array_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_reference_type_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->object_id_size, id)
+
+#define get_jdwp_class_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->reference_type_id_size, id)
+
+#define get_jdwp_interface_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->reference_type_id_size, id)
+
+#define get_jdwp_array_type_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->reference_type_id_size, id)
+
+#define get_jdwp_method_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->method_id_size, id)
+
+#define get_jdwp_field_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->field_id_size, id)
+
+#define get_jdwp_frame_id(blob, pos, len, sizes, id) \
+ _get_jdwp_dynsized_id(blob, pos, len, sizes->frame_id_size, id)
+
+
+
+#endif /* _DEBUG_JDWP_MISC_ID_H */
diff --git a/src/debug/jdwp/packet.c b/src/debug/jdwp/packet.c
index 8afaeb4..5b496f7 100644
--- a/src/debug/jdwp/packet.c
+++ b/src/debug/jdwp/packet.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* packet.c - définition des paquets destiné au protocole JDWP
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -41,6 +41,7 @@ struct _GJdwpPacket
jdwp_payload payload; /* Charge utile du paquet */
bin_t pblob[sizeof(jdwp_payload)]; /* Contenu encodé en B.E. */
+ bool got; /* Précise le type de charge */
};
@@ -50,6 +51,8 @@ struct _GJdwpPacketClass
{
GDebugPacketClass parent; /* A laisser en premier */
+ jdwp_cmd_vm_id_sizes_reply sizes; /* Réf. des tailles dynamiques */
+
};
@@ -111,6 +114,26 @@ static void g_jdwp_packet_init(GJdwpPacket *packet)
/******************************************************************************
* *
+* Paramètres : packet = instance à utiliser comme intermédiaire. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* *
+* Description : Enregistre les différentes tailles dynamiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_jdwp_packet_set_sizes(GJdwpPacket *packet, const jdwp_cmd_vm_id_sizes_reply *sizes)
+{
+ G_JDWP_PACKET_GET_CLASS(packet)->sizes = *sizes;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : packet = instance à convertir. *
* iov = table de vecteurs. [OUT] *
* iovcnt = quantité de champs renseignés. [OUT] *
@@ -220,7 +243,9 @@ bool g_jdwp_packet_parse_header(GJdwpPacket *packet)
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);
+ 0, set, command);
+
+ packet->got = false;
}
@@ -242,7 +267,41 @@ void g_jdwp_packet_set_request_header(GJdwpPacket *packet, uint8_t set, uint8_t
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);
+ 0, lastid, error);
+
+ packet->got = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : packet = instance à consulter. *
+* payload = modèle de charge à copier. *
+* *
+* Description : Fournit l'adresse des charges utiles d'un paquet JDWP. *
+* *
+* Retour : Adresse des données d'une charge utile. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_jdwp_packet_set_payload(GJdwpPacket *packet, const jdwp_payload *payload)
+{
+ off_t len; /* Quantité max puis effective */
+
+ len = sizeof(jdwp_payload);
+
+ set_jdwp_payload(payload, packet->header.set, packet->header.command,
+ &G_JDWP_PACKET_GET_CLASS(packet)->sizes,
+ packet->pblob, &len);
+
+ packet->header.length += len;
+
+ update_jdwp_header_length(&packet->header, packet->hblob);
+
+ packet->got = false;
}
@@ -301,7 +360,20 @@ bin_t *g_jdwp_packet_get_pblob(GJdwpPacket *packet)
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);
+ bool result; /* Bilan à retourner */
+
+ result = get_jdwp_payload(packet->pblob, packet->header.length - sizeof(jdwp_header)/* FIXME */,
+ set, cmd, &G_JDWP_PACKET_GET_CLASS(packet)->sizes, &packet->payload);
+
+ if (result)
+ {
+ packet->header.set = set;
+ packet->header.command = cmd;
+ }
+
+ packet->got = true;
+
+ return result;
}
@@ -309,8 +381,6 @@ bool g_jdwp_packet_parse_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd)
/******************************************************************************
* *
* 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. *
* *
@@ -320,9 +390,13 @@ bool g_jdwp_packet_parse_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd)
* *
******************************************************************************/
-void g_jdwp_packet_free_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd)
+void g_jdwp_packet_free_payload(GJdwpPacket *packet)
{
- free_jdwp_payload(&packet->payload, set, cmd);
+ if (packet->header.set == JDWP_CST_NONE || packet->header.command == JDWP_CMD_NONE)
+ return;
+
+ free_jdwp_payload(&packet->payload, packet->got,
+ packet->header.set, packet->header.command);
}
diff --git a/src/debug/jdwp/packet.h b/src/debug/jdwp/packet.h
index fda9faf..f27130d 100644
--- a/src/debug/jdwp/packet.h
+++ b/src/debug/jdwp/packet.h
@@ -2,7 +2,7 @@
/* 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
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -52,6 +52,9 @@ typedef struct _GJdwpPacketClass GJdwpPacketClass;
/* Indique le type défini pour un paquet de débogage JDWP. */
GType g_jdwp_packet_get_type(void);
+/* Enregistre les différentes tailles dynamiques. */
+void g_jdwp_packet_set_sizes(GJdwpPacket *, const jdwp_cmd_vm_id_sizes_reply *);
+
/* Fournit l'adresse des données de l'en-tête d'un paquet JDWP. */
jdwp_header *g_jdwp_packet_get_header(GJdwpPacket *);
@@ -68,6 +71,9 @@ void g_jdwp_packet_set_request_header(GJdwpPacket *, uint8_t, uint8_t);
void g_jdwp_packet_set_reply_header(GJdwpPacket *, uint32_t, uint16_t);
/* Fournit l'adresse des charges utiles d'un paquet JDWP. */
+void g_jdwp_packet_set_payload(GJdwpPacket *, const jdwp_payload *);
+
+/* 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. */
@@ -77,7 +83,7 @@ bin_t *g_jdwp_packet_get_pblob(GJdwpPacket *);
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);
+void g_jdwp_packet_free_payload(GJdwpPacket *);
/* Détermine si un paquet est une réponse à un premier paquet. */
bool g_jdwp_packet_is_reply(const GJdwpPacket *, const GJdwpPacket *);
diff --git a/src/debug/jdwp/sets/Makefile.am b/src/debug/jdwp/sets/Makefile.am
index 98a76b4..55277bf 100644
--- a/src/debug/jdwp/sets/Makefile.am
+++ b/src/debug/jdwp/sets/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdebugjdwpsets.la
libdebugjdwpsets_la_SOURCES = \
list.h list.c \
+ thread.h thread.c \
vm.h vm.c
libdebugjdwpsets_la_LDFLAGS =
diff --git a/src/debug/jdwp/sets/list.c b/src/debug/jdwp/sets/list.c
index 0dad1e8..84c6ac0 100644
--- a/src/debug/jdwp/sets/list.c
+++ b/src/debug/jdwp/sets/list.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* list.c - ensemble des jeux de commandes de JDWP
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -27,12 +27,15 @@
#include <stddef.h>
+#include "thread.h"
#include "vm.h"
+/* Consitue un contenu binaire à partir d'une charge utile. */
+typedef bool (* set_jdwp_payload_fc) (const jdwp_payload *, const jdwp_cmd_vm_id_sizes_reply *, bin_t *, off_t *);
/* Reconstitue une charge utile à partir d'un contenu binaire. */
-typedef bool (* get_jdwp_payload_fc) (const bin_t *, off_t, jdwp_payload *);
+typedef bool (* get_jdwp_payload_fc) (const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_payload *);
/* Libère le contenu d'une charge utile. */
typedef void (* free_jdwp_payload_fc) (jdwp_payload *);
@@ -41,8 +44,10 @@ typedef void (* free_jdwp_payload_fc) (jdwp_payload *);
/* Commandes JDWP */
typedef struct _jdwp_command
{
+ set_jdwp_payload_fc set_payload; /* Constitution du binaire */
+ free_jdwp_payload_fc free_set_payload; /* Libération de la mémoire */
get_jdwp_payload_fc get_payload; /* Constitution de la charge */
- free_jdwp_payload_fc free_payload; /* Libération de la mémoire */
+ free_jdwp_payload_fc free_got_payload; /* Libération de la mémoire */
} jdwp_command;
@@ -53,16 +58,38 @@ static jdwp_command _commands[][256] = {
[JDWP_CST_VIRTUAL_MACHINE] = {
[JDWP_CMD_VM_VERSION] = {
+ .set_payload = (set_jdwp_payload_fc)NULL,
+ .free_set_payload = (free_jdwp_payload_fc)NULL,
.get_payload = (get_jdwp_payload_fc)get_jdwp_vm_version,
- .free_payload = (free_jdwp_payload_fc)free_jdwp_vm_version
+ .free_got_payload = (free_jdwp_payload_fc)free_jdwp_vm_version
},
+ [JDWP_CMD_VM_ALL_THREADS] = {
+ .set_payload = (set_jdwp_payload_fc)NULL,
+ .free_set_payload = (free_jdwp_payload_fc)NULL,
+ .get_payload = (get_jdwp_payload_fc)get_jdwp_vm_all_threads,
+ .free_got_payload = (free_jdwp_payload_fc)free_jdwp_all_threads
+ },
-
+ [JDWP_CMD_VM_ID_SIZES] = {
+ .set_payload = (set_jdwp_payload_fc)NULL,
+ .free_set_payload = (free_jdwp_payload_fc)NULL,
+ .get_payload = (get_jdwp_payload_fc)get_jdwp_vm_id_sizes,
+ .free_got_payload = (free_jdwp_payload_fc)NULL
+ }
},
+ [JDWP_CST_THREAD_REFERENCE] = {
+
+ [JDWP_CMD_THREAD_NAME] = {
+ .set_payload = (set_jdwp_payload_fc)set_jdwp_thread_name,
+ .free_set_payload = (free_jdwp_payload_fc)NULL,
+ .get_payload = (get_jdwp_payload_fc)get_jdwp_thread_name,
+ .free_got_payload = (free_jdwp_payload_fc)free_jdwp_thread_name_reply
+ }
+ }
};
@@ -70,10 +97,40 @@ static jdwp_command _commands[][256] = {
/******************************************************************************
* *
+* Paramètres : payload = charge utile à transcrire. *
+* set = jeu de commandes concerné. *
+* cmd = identifiant d'une commande donnée. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* blob = futures données binaires brutes. [OUT] *
+* len = quantité de données valides. [OUT] *
+* *
+* Description : Reconstitue un contenu binaire à partir d'une charge utile. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool set_jdwp_payload(const jdwp_payload *payload, uint8_t set, uint8_t cmd, const jdwp_cmd_vm_id_sizes_reply *sizes, bin_t *blob, off_t *len)
+{
+ bool result; /* Bilan à retourner */
+
+ if (_commands[set][cmd].set_payload == NULL) result = false;
+ else result = _commands[set][cmd].set_payload(payload, sizes, blob, len);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* 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. *
+* sizes = références pour la valeur des tailles dynamiques. *
* payload = charge utile à reconstituer. [OUT] *
* *
* Description : Reconstitue une charge utile à partir d'un contenu binaire. *
@@ -84,12 +141,12 @@ static jdwp_command _commands[][256] = {
* *
******************************************************************************/
-bool get_jdwp_payload(const bin_t *blob, off_t len, uint8_t set, uint8_t cmd, jdwp_payload *payload)
+bool get_jdwp_payload(const bin_t *blob, off_t len, uint8_t set, uint8_t cmd, const jdwp_cmd_vm_id_sizes_reply *sizes, 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);
+ else result = _commands[set][cmd].get_payload(blob, len, sizes, payload);
return result;
@@ -99,6 +156,7 @@ bool get_jdwp_payload(const bin_t *blob, off_t len, uint8_t set, uint8_t cmd, jd
/******************************************************************************
* *
* Paramètres : payload = charge utile à supprimer de la mémoire. *
+* got = type de charge utile à traiter. *
* set = jeu de commandes concerné. *
* cmd = identifiant d'une commande donnée. *
* *
@@ -110,9 +168,17 @@ bool get_jdwp_payload(const bin_t *blob, off_t len, uint8_t set, uint8_t cmd, jd
* *
******************************************************************************/
-void free_jdwp_payload(jdwp_payload *payload, uint8_t set, uint8_t cmd)
+void free_jdwp_payload(jdwp_payload *payload, bool got, uint8_t set, uint8_t cmd)
{
- if (_commands[set][cmd].free_payload != NULL)
- _commands[set][cmd].free_payload(payload);
+ if (got)
+ {
+ if (_commands[set][cmd].free_got_payload != NULL)
+ _commands[set][cmd].free_got_payload(payload);
+ }
+ else
+ {
+ if (_commands[set][cmd].free_set_payload != NULL)
+ _commands[set][cmd].free_set_payload(payload);
+ }
}
diff --git a/src/debug/jdwp/sets/list.h b/src/debug/jdwp/sets/list.h
index 2fb135e..9880e69 100644
--- a/src/debug/jdwp/sets/list.h
+++ b/src/debug/jdwp/sets/list.h
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* list.h - prototypes pour l'ensemble des jeux de commandes de JDWP
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -37,17 +37,25 @@
typedef union _jdwp_payload
{
jdwp_cmd_vm_version_reply vs_reply; /* Infos. sur la version */
+ jdwp_cmd_vm_allthreads_reply th_reply; /* Liste des threads */
+ jdwp_cmd_vm_id_sizes_reply sz_reply; /* Tailles dynamiques */
+
+ jdwp_cmd_thread_name_request th_ident; /* Identification d'un thread */
+ jdwp_cmd_thread_name_reply th_name; /* Désignation d'un thread */
bin_t padding[500];
} jdwp_payload;
+/* Reconstitue un contenu binaire à partir d'une charge utile. */
+bool set_jdwp_payload(const jdwp_payload *, uint8_t, uint8_t, const jdwp_cmd_vm_id_sizes_reply *, bin_t *, off_t *);
+
/* Reconstitue une charge utile à partir d'un contenu binaire. */
-bool get_jdwp_payload(const bin_t *, off_t, uint8_t, uint8_t, jdwp_payload *);
+bool get_jdwp_payload(const bin_t *, off_t, uint8_t, uint8_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_payload *);
/* Libère le contenu d'une charge utile. */
-void free_jdwp_payload(jdwp_payload *, uint8_t, uint8_t);
+void free_jdwp_payload(jdwp_payload *, bool, uint8_t, uint8_t);
diff --git a/src/debug/jdwp/sets/thread.c b/src/debug/jdwp/sets/thread.c
new file mode 100644
index 0000000..9391ff6
--- /dev/null
+++ b/src/debug/jdwp/sets/thread.c
@@ -0,0 +1,116 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * thread.c - interactions avec les différents threads
+ *
+ * Copyright (C) 2012 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 "thread.h"
+
+
+#include <string.h>
+
+
+#include "../misc/id.h"
+#include "../misc/types.h"
+#include "../../../common/endianness.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : req = structure de réponse à constituer. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* blob = ensemble de données binaires brutes. [OUT] *
+* len = quantité de données disponibles, puis écrites. [OUT] *
+* *
+* Description : Prépare une requête demandant le nom d'un thread. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool set_jdwp_thread_name(const jdwp_cmd_thread_name_request *req, const jdwp_cmd_vm_id_sizes_reply *sizes, bin_t *blob, off_t *len)
+{
+ bool result; /* Bilan à retourner */
+ off_t pos; /* Tête de lecture */
+
+ pos = 0;
+ memset(blob, 0, sizeof(jdwp_cmd_thread_name_request));
+
+ result = set_jdwp_thread_id(&req->id, sizes, blob, &pos, *len);
+ if (!result) return false;
+
+ *len = pos;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : blob = ensemble de données binaires brutes. *
+* len = quantité de données valides. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* reply = structure de réponse à constituer. [OUT] *
+* *
+* Description : Reconstitue une réponse fournissant le nom d'un thread. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_jdwp_thread_name(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_cmd_thread_name_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->name);
+ if (!result) return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reply = structure de réponse à supprimer de la mémoire. *
+* *
+* Description : Libère le nom donné à un thread. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void free_jdwp_thread_name_reply(jdwp_cmd_thread_name_reply *reply)
+{
+ free_jdwp_string(&reply->name);
+
+}
diff --git a/src/debug/jdwp/sets/thread.h b/src/debug/jdwp/sets/thread.h
new file mode 100644
index 0000000..f8c3abe
--- /dev/null
+++ b/src/debug/jdwp/sets/thread.h
@@ -0,0 +1,46 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * thread.h - prototypes pour les interactions avec les différents threads
+ *
+ * Copyright (C) 2012 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_THREAD_H
+#define _DEBUG_JDWP_SETS_THREAD_H
+
+
+#include <stdbool.h>
+
+
+#include "../jdwp_def.h"
+#include "../../../arch/archbase.h"
+
+
+/* Prépare une requête demandant le nom d'un thread. */
+bool set_jdwp_thread_name(const jdwp_cmd_thread_name_request *, const jdwp_cmd_vm_id_sizes_reply *, bin_t *, off_t *);
+
+/* Reconstitue une réponse fournissant le nom d'un thread. */
+bool get_jdwp_thread_name(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_cmd_thread_name_reply *);
+
+/* Libère le nom donné à un thread. */
+void free_jdwp_thread_name_reply(jdwp_cmd_thread_name_reply *);
+
+
+
+#endif /* _DEBUG_JDWP_SETS_THREAD_H */
diff --git a/src/debug/jdwp/sets/vm.c b/src/debug/jdwp/sets/vm.c
index fdb1ec0..d8e3255 100644
--- a/src/debug/jdwp/sets/vm.c
+++ b/src/debug/jdwp/sets/vm.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* vm.c - constitution des charges utiles liées à la VM
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -24,9 +24,11 @@
#include "vm.h"
+#include <malloc.h>
#include <string.h>
+#include "../misc/id.h"
#include "../misc/types.h"
#include "../../../common/endianness.h"
@@ -36,6 +38,7 @@
* *
* Paramètres : blob = ensemble de données binaires brutes. *
* len = quantité de données valides. *
+* sizes = références pour la valeur des tailles dynamiques. *
* reply = structure de réponse à constituer. [OUT] *
* *
* Description : Reconstitue une réponse quant à une version de serveur. *
@@ -46,7 +49,7 @@
* *
******************************************************************************/
-bool get_jdwp_vm_version(const bin_t *blob, off_t len, jdwp_cmd_vm_version_reply *reply)
+bool get_jdwp_vm_version(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_cmd_vm_version_reply *reply)
{
bool result; /* Bilan à retourner */
off_t pos; /* Tête de lecture */
@@ -95,3 +98,105 @@ void free_jdwp_vm_version(jdwp_cmd_vm_version_reply *reply)
free_jdwp_string(&reply->vm_name);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : blob = ensemble de données binaires brutes. *
+* len = quantité de données valides. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* reply = structure de réponse à constituer. [OUT] *
+* *
+* Description : Reconstitue une réponse fournissant la liste des threads. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_jdwp_vm_all_threads(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_cmd_vm_allthreads_reply *reply)
+{
+ bool result; /* Bilan à retourner */
+ off_t pos; /* Tête de lecture */
+ uint32_t i; /* Boucle de parcours */
+
+ pos = 0;
+ memset(reply, 0, sizeof(jdwp_cmd_vm_id_sizes_reply));
+
+ result = read_u32(&reply->count, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ reply->threads = (jdwp_dynsized_id *)calloc(reply->count, sizeof(jdwp_dynsized_id));
+
+ for (i = 0; i < reply->count && result; i++)
+ result = get_jdwp_thread_id(blob, &pos, len, sizes, &reply->threads[i]);
+
+ if (!result)
+ free_jdwp_all_threads(reply);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reply = structure de réponse à supprimer de la mémoire. *
+* *
+* Description : Libère le contenu d'une réponse offrant une liste de threads.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void free_jdwp_all_threads(jdwp_cmd_vm_allthreads_reply *reply)
+{
+ free(reply->threads);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : blob = ensemble de données binaires brutes. *
+* len = quantité de données valides. *
+* sizes = références pour la valeur des tailles dynamiques. *
+* reply = structure de réponse à constituer. [OUT] *
+* *
+* Description : Reconstitue une réponse quant aux tailles spécifiques. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_jdwp_vm_id_sizes(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_cmd_vm_id_sizes_reply *reply)
+{
+ bool result; /* Bilan à retourner */
+ off_t pos; /* Tête de lecture */
+
+ pos = 0;
+ memset(reply, 0, sizeof(jdwp_cmd_vm_id_sizes_reply));
+
+ result = read_u32(&reply->field_id_size, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ result = read_u32(&reply->method_id_size, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ result = read_u32(&reply->object_id_size, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ result = read_u32(&reply->reference_type_id_size, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ result = read_u32(&reply->frame_id_size, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ return true;
+
+}
diff --git a/src/debug/jdwp/sets/vm.h b/src/debug/jdwp/sets/vm.h
index de2c7db..996001f 100644
--- a/src/debug/jdwp/sets/vm.h
+++ b/src/debug/jdwp/sets/vm.h
@@ -2,7 +2,7 @@
/* 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
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -34,11 +34,20 @@
/* Reconstitue une réponse quant à une version de serveur. */
-bool get_jdwp_vm_version(const bin_t *, off_t, jdwp_cmd_vm_version_reply *);
+bool get_jdwp_vm_version(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, 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 *);
+/* Reconstitue une réponse fournissant la liste des threads. */
+bool get_jdwp_vm_all_threads(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_cmd_vm_allthreads_reply *);
+
+/* Libère le contenu d'une réponse offrant une liste de threads. */
+void free_jdwp_all_threads(jdwp_cmd_vm_allthreads_reply *);
+
+/* Reconstitue une réponse quant aux tailles spécifiques. */
+bool get_jdwp_vm_id_sizes(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_cmd_vm_id_sizes_reply *);
+
#endif /* _DEBUG_JDWP_SETS_VM_H */
diff --git a/src/debug/jdwp/tcp.c b/src/debug/jdwp/tcp.c
index 554d5b6..4f56351 100644
--- a/src/debug/jdwp/tcp.c
+++ b/src/debug/jdwp/tcp.c
@@ -82,6 +82,9 @@ 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 *);
+/* Libère le contenu alloué d'un paquet de débogage. */
+static void g_jdwp_tcp_client_free_packet(GJdwpTcpClient *, GJdwpPacket *);
+
/* Indique le type défini pour un flux de communication TCP avec un serveur JDWP. */
@@ -129,6 +132,7 @@ static void g_jdwp_tcp_client_init(GJdwpTcpClient *client)
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->free_packet = (debug_free_pkt_fc)g_jdwp_tcp_client_free_packet;
stream->pkt_type = G_TYPE_JDWP_PACKET;
@@ -282,6 +286,14 @@ static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *client, const GJdwpPac
int iovcnt; /* Quantité de champs valides */
int i; /* Boucle de parcours */
+#if 0
+ jdwp_header *header; /* En-tête à reconstituer */
+
+ header = g_jdwp_packet_get_header(packet);
+ printf(" <JDWP> send %p :: %u / %hhu.%hhu (%u)\n", packet, header->id, header->set,
+ header->command, header->length);
+#endif
+
g_debug_packet_vectorize(G_DEBUG_PACKET(packet), iov, &iovcnt);
for (i = 0; i < iovcnt; i++)
@@ -324,6 +336,8 @@ static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *client, GJdwpPacket *p
header = g_jdwp_packet_get_header(packet);
length = header->length - sizeof(jdwp_header);
+ //printf(" <JDWP> recv %p :: %u / %hu (%u)\n", packet, header->id, header->error, header->length);
+
pblob = g_jdwp_packet_get_pblob(packet);
if (recv(client->fd, pblob, length, 0) != length)
@@ -332,3 +346,23 @@ static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *client, GJdwpPacket *p
return true;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = flux ouvert inutile. *
+* packet = zone mémoire à libérer. *
+* *
+* Description : Libère le contenu alloué d'un paquet de débogage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_jdwp_tcp_client_free_packet(GJdwpTcpClient *client, GJdwpPacket *packet)
+{
+ g_jdwp_packet_free_payload(packet);
+
+}
diff --git a/src/debug/packet.c b/src/debug/packet.c
index 9a7df58..344e625 100644
--- a/src/debug/packet.c
+++ b/src/debug/packet.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* packet.c - définition des paquets issus des protocoles de débogage
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -159,3 +159,23 @@ GDebugPacket *g_debug_packet_pop(GDebugPacket **list)
return dl_list_pop(list, GDebugPacket, link);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de paquets à consulter. *
+* packet = paquet à sortir de la liste. *
+* *
+* Description : Retire et fournit un élément d'une liste de paquets. *
+* *
+* Retour : Elément dépilé de la liste de paquets. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_debug_packet_extract(GDebugPacket **list, GDebugPacket *packet)
+{
+ dl_list_del(packet, list, GDebugPacket, link);
+
+}
diff --git a/src/debug/packet.h b/src/debug/packet.h
index c3d45a5..db6a313 100644
--- a/src/debug/packet.h
+++ b/src/debug/packet.h
@@ -2,7 +2,7 @@
/* 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
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -61,6 +61,9 @@ 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 **);
+/* Retire et fournit un élément d'une liste de paquets. */
+void g_debug_packet_extract(GDebugPacket **, GDebugPacket *);
+
#endif /* _DEBUG_PACKET_H */
diff --git a/src/debug/stream-int.h b/src/debug/stream-int.h
index 6250522..05b6c42 100644
--- a/src/debug/stream-int.h
+++ b/src/debug/stream-int.h
@@ -2,7 +2,7 @@
/* 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
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -40,6 +40,11 @@ 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 *);
+/* Libère le contenu alloué d'un paquet de débogage. */
+typedef void (* debug_free_pkt_fc) (GDebugStream *, GDebugPacket *);
+
+
+
@@ -60,6 +65,7 @@ struct _GDebugStream
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 */
+ debug_free_pkt_fc free_packet; /* Libération d'un paquet */
GThread *listening; /* Thread pour les réceptions */
diff --git a/src/debug/stream.c b/src/debug/stream.c
index 4c4767a..5d91aa8 100644
--- a/src/debug/stream.c
+++ b/src/debug/stream.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* stream.c - gestion des connexions aux serveurs de débogage.
*
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -210,6 +210,8 @@ GDebugPacket *g_debug_stream_get_free_packet(GDebugStream *stream)
void g_debug_stream_mark_packet_as_free(GDebugStream *stream, GDebugPacket *packet)
{
+ stream->free_packet(stream, packet);
+
g_mutex_lock(stream->free_mutex);
g_debug_packet_push(&stream->free_packets, packet);
@@ -272,7 +274,10 @@ GDebugPacket *g_debug_stream_recv_packet(GDebugStream *stream, filter_packet_fc
result = g_debug_packet_get_next_iter(stream->recv_packets, result))
{
if (filter(result, data))
+ {
+ g_debug_packet_extract(&stream->recv_packets, result);
break;
+ }
}
if (result == NULL)