From 73605bffb935fc51a52be1936426211e31dd898a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 17 Feb 2012 17:51:06 +0000
Subject: Listed all running threads using Python.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@234 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                               |  76 ++++++++++++++
 plugins/pyoida/Makefile.am              |   3 +-
 plugins/pyoida/debug/debugger.c         |  87 ++++++++++++++--
 plugins/pyoida/debug/module.c           |   6 +-
 plugins/pyoida/pyoida.c                 |   2 +
 plugins/pyoida/quirks.c                 | 148 +++++++++++++++++++++++++++
 plugins/pyoida/quirks.h                 |  42 ++++++++
 plugins/python/exectracer/exectracer.py |   4 +
 src/debug/debugger-int.h                |   7 +-
 src/debug/debugger.c                    |  28 ++++++
 src/debug/debugger.h                    |   3 +
 src/debug/jdwp/debugger.c               | 171 ++++++++++++++++++++++++++++++--
 src/debug/jdwp/jdwp_def.h               |  70 ++++++++++++-
 src/debug/jdwp/misc/Makefile.am         |   1 +
 src/debug/jdwp/misc/header.c            |  26 ++++-
 src/debug/jdwp/misc/header.h            |   5 +-
 src/debug/jdwp/misc/id.c                | 148 +++++++++++++++++++++++++++
 src/debug/jdwp/misc/id.h                | 131 ++++++++++++++++++++++++
 src/debug/jdwp/packet.c                 |  90 +++++++++++++++--
 src/debug/jdwp/packet.h                 |  10 +-
 src/debug/jdwp/sets/Makefile.am         |   1 +
 src/debug/jdwp/sets/list.c              |  86 ++++++++++++++--
 src/debug/jdwp/sets/list.h              |  14 ++-
 src/debug/jdwp/sets/thread.c            | 116 ++++++++++++++++++++++
 src/debug/jdwp/sets/thread.h            |  46 +++++++++
 src/debug/jdwp/sets/vm.c                | 109 +++++++++++++++++++-
 src/debug/jdwp/sets/vm.h                |  13 ++-
 src/debug/jdwp/tcp.c                    |  34 +++++++
 src/debug/packet.c                      |  22 +++-
 src/debug/packet.h                      |   5 +-
 src/debug/stream-int.h                  |   8 +-
 src/debug/stream.c                      |   7 +-
 32 files changed, 1461 insertions(+), 58 deletions(-)
 create mode 100644 plugins/pyoida/quirks.c
 create mode 100644 plugins/pyoida/quirks.h
 create mode 100644 src/debug/jdwp/misc/id.c
 create mode 100644 src/debug/jdwp/misc/id.h
 create mode 100644 src/debug/jdwp/sets/thread.c
 create mode 100644 src/debug/jdwp/sets/thread.h

diff --git a/ChangeLog b/ChangeLog
index e09997e..4db2e5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,79 @@
+12-02-17  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pyoida/debug/debugger.c:
+	Write a wrapper for listing all running threads.
+
+	* plugins/pyoida/debug/module.c:
+	Properly register the Python debug module.
+
+	* plugins/pyoida/Makefile.am:
+	Add the quirks.[ch] files to pyoida_la_SOURCES.
+
+	* plugins/pyoida/pyoida.c:
+	Init PyGObjects quirks.
+
+	* plugins/pyoida/quirks.c:
+	* plugins/pyoida/quirks.h:
+	New entries: setup extra glue between the GLib et PyGObject.
+
+	* plugins/python/exectracer/exectracer.py:
+	Print all running threads.
+
+	* src/debug/debugger.c:
+	* src/debug/debugger.h:
+	* src/debug/debugger-int.h:
+	List all running threads.
+
+	* src/debug/jdwp/debugger.c:
+	List all running threads, properly free packets and get
+	used VM memory sizes.
+
+	* src/debug/jdwp/jdwp_def.h:
+	Allow to get threads name and WM memory sizes.
+
+	* src/debug/jdwp/misc/header.c:
+	* src/debug/jdwp/misc/header.h:
+	Update packet length when needed.
+
+	* src/debug/jdwp/misc/id.c:
+	* src/debug/jdwp/misc/id.h:
+	New entries: handle common identifiers.
+
+	* src/debug/jdwp/misc/Makefile.am:
+	Add the id.[ch] files to libdebugjdwpmisc_la_SOURCES.
+
+	* src/debug/jdwp/packet.c:
+	* src/debug/jdwp/packet.h:
+	Free all packets and define payload for requests.
+
+	* src/debug/jdwp/sets/list.c:
+	* src/debug/jdwp/sets/list.h:
+	Setup a binary payload for requests.
+
+	* src/debug/jdwp/sets/Makefile.am:
+	Add the thread.[ch] files to libdebugjdwpsets_la_SOURCES.
+
+	* src/debug/jdwp/sets/thread.c:
+	* src/debug/jdwp/sets/thread.h:
+	New entries: get thread names.
+
+	* src/debug/jdwp/sets/vm.c:
+	* src/debug/jdwp/sets/vm.h:
+	Deal with VM memory sizes and threads.
+
+	* src/debug/jdwp/tcp.c:
+	Disable debug code and free packets.
+
+	* src/debug/packet.c:
+	* src/debug/packet.h:
+	Extract a packet from a packets list.
+
+	* src/debug/stream.c:
+	Extract the selected packet for processing.
+
+	* src/debug/stream-int.h:
+	Free packets.
+
 12-02-01  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/plugins/pyoida/Makefile.am b/plugins/pyoida/Makefile.am
index a343e6f..42a2fc2 100644
--- a/plugins/pyoida/Makefile.am
+++ b/plugins/pyoida/Makefile.am
@@ -4,7 +4,8 @@ pkglib_LTLIBRARIES = pyoida.la
 pyoida_la_SOURCES =						\
 	plugin.h plugin.c					\
 	py_log.h py_log.c					\
-	pyoida.h pyoida.c
+	pyoida.h pyoida.c					\
+	quirks.h quirks.c
 
 pyoida_la_LIBADD =						\
 	analysis/libpyoidaanalysis.la		\
diff --git a/plugins/pyoida/debug/debugger.c b/plugins/pyoida/debug/debugger.c
index 380f579..75de6d8 100644
--- a/plugins/pyoida/debug/debugger.c
+++ b/plugins/pyoida/debug/debugger.c
@@ -28,9 +28,12 @@
 #include <pygobject.h>
 
 
+#include "../quirks.h"
 
 
 
+/*  Fournit les identifiants de tous les threads actifs. */
+static PyObject *py_binary_debugger_list_all_threads(PyObject *, PyObject *);
 
 /* Fournit la pile d'exécution courante via un débogueur. */
 static PyObject *py_binary_debugger_get_current_stack(PyObject *, PyObject *);
@@ -38,9 +41,6 @@ static PyObject *py_binary_debugger_get_current_stack(PyObject *, PyObject *);
 
 
 
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : type = type de l'objet à instancier.                         *
@@ -89,6 +89,15 @@ static PyObject *py_binary_debugger_new(PyTypeObject *type, PyObject *args, PyOb
 
 PyObject *py_binary_debugger_from_c(GBinaryDebugger *debugger)
 {
+    PyObject *module;                       /* Module d'appartenance       */
+    PyTypeObject *type;                     /* Type Python correspondant   */
+
+    module = PyImport_ImportModule("pyoida.debug");
+    type = (PyTypeObject*)PyObject_GetAttrString(module, "BinaryDebugger");
+    Py_DECREF(module);
+
+    pychrysalide_set_instance_data(G_OBJECT(debugger), type);
+
     return pygobject_new(G_OBJECT(debugger));
 
 }
@@ -96,25 +105,75 @@ PyObject *py_binary_debugger_from_c(GBinaryDebugger *debugger)
 
 
 
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : self = classe représentant un débogueur.                     *
 *                args = arguments fournis à l'appel.                          *
 *                                                                             *
-*  Description : Fournit la pile d'exécution courante via un débogueur.       *
+*  Description : Fournit les identifiants de tous les threads actifs.         *
 *                                                                             *
-*  Retour      : Valeur booléenne indiquant le statut d'une option.           *
+*  Retour      : Object Python représentant le résultat de l'opération.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_binary_debugger_get_current_stack(PyObject *self, PyObject *args)
+static PyObject *py_binary_debugger_list_all_threads(PyObject *self, PyObject *args)
 {
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GBinaryDebugger *debugger;              /* Version native              */
+    char **names;                           /* Noms associés aux threads   */
+    size_t count;                           /* Taille de cette liste       */
+    pid_t *threads;                         /* Liste des threads actifs    */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *thread;                       /* Détails sur un thread donné */
+
+    debugger = G_BINARY_DEBUGGER(pygobject_get(self));
+
+    threads = g_binary_debugger_list_all_threads(debugger, &names, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        thread = PyTuple_New(2);
+        PyTuple_SetItem(result, i, thread);
+
+        PyTuple_SetItem(thread, 0, PyLong_FromLong(threads[i]));
+        PyTuple_SetItem(thread, 1, PyString_FromString(names[i]));
+
+        free(names[i]);
+
+    }
+
+    if (names != NULL)
+        free(names);
+
+    if (threads != NULL)
+        free(threads);
+
+    return result;
+
+}
+
 
-    printf(" -->> get stack\n");
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un débogueur.                     *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Fournit la pile d'exécution courante via un débogueur.       *
+*                                                                             *
+*  Retour      : Object Python représentant le résultat de l'opération.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    return Py_BuildValue("i", true);
+static PyObject *py_binary_debugger_get_current_stack(PyObject *self, PyObject *args)
+{
+    return PyLong_FromLong(23);
 
 }
 
@@ -136,10 +195,16 @@ static PyObject *py_binary_debugger_get_current_stack(PyObject *self, PyObject *
 
 bool register_python_binary_debugger(PyObject *module)
 {
+    PyObject *pygobj_mod;                   /* Module Python-GObject       */
     int ret;                                /* Bilan d'un appel            */
 
     static PyMethodDef py_binary_debugger_methods[] = {
         {
+            "list_all_threads", (PyCFunction)py_binary_debugger_list_all_threads,
+            METH_NOARGS,
+            "List all current active threads."
+        },
+        {
             "get_current_stack", (PyCFunction)py_binary_debugger_get_current_stack,
             METH_NOARGS,
             "Provide the current callstack using a debugger."
@@ -163,6 +228,12 @@ bool register_python_binary_debugger(PyObject *module)
 
     };
 
+    pygobj_mod = PyImport_ImportModule("gobject");
+    if (pygobj_mod == NULL) return false;
+
+    py_binary_debugger_type.tp_base = (PyTypeObject *)PyObject_GetAttrString(pygobj_mod, "GObject");
+    Py_DECREF(pygobj_mod);
+
     if (PyType_Ready(&py_binary_debugger_type) < 0)
         return false;
 
diff --git a/plugins/pyoida/debug/module.c b/plugins/pyoida/debug/module.c
index fe59595..7537dc7 100644
--- a/plugins/pyoida/debug/module.c
+++ b/plugins/pyoida/debug/module.c
@@ -47,15 +47,15 @@ bool add_debug_module_to_python_module(PyObject *super)
     PyObject *module;
     int ret;                                /* Bilan d'un appel            */
 
-    static PyMethodDef py_analysis_methods[] = {
+    static PyMethodDef py_debug_methods[] = {
         { NULL }
     };
 
-    module = Py_InitModule("pychrysalide.debug", py_analysis_methods);
+    module = Py_InitModule("pyoida.debug", py_debug_methods);
     if (module == NULL) return false;
 
     Py_INCREF(module);
-    ret = PyModule_AddObject(super, "pychrysalide.debug", module);
+    ret = PyModule_AddObject(super, "pyoida.debug", module);
 
     result = (ret != 0);
 
diff --git a/plugins/pyoida/pyoida.c b/plugins/pyoida/pyoida.c
index d3b37e5..f3051cc 100644
--- a/plugins/pyoida/pyoida.c
+++ b/plugins/pyoida/pyoida.c
@@ -32,6 +32,7 @@
 #include <pygobject.h>
 
 
+#include "quirks.h"
 #include "analysis/module.h"
 #include "arch/module.h"
 #include "debug/module.h"
@@ -253,6 +254,7 @@ initpyoida(void)
     PyObject *module;
 
     pygobject_init(-1, -1, -1);
+    pychrysalide_init_quirks();
 
     printf("Passage 2\n");
     module = Py_InitModule("pyoida", SpamMethods);
diff --git a/plugins/pyoida/quirks.c b/plugins/pyoida/quirks.c
new file mode 100644
index 0000000..4dcae2c
--- /dev/null
+++ b/plugins/pyoida/quirks.c
@@ -0,0 +1,148 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * quirks.c - transmission du type Python exact aux instances de PyObject
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "quirks.h"
+
+
+
+#include <pyglib.h>
+#include <pygobject.h>
+
+
+
+
+
+
+/* Coordonnées insérées manuellement */
+typedef struct _PyGObjectData_fake
+{
+    PyTypeObject *type;                     /* Type précis pour Python     */
+    GSList *closures;                       /* Supports d'appel            */
+
+} PyGObjectData_fake;
+
+
+/* Clef d'accès réservée */
+static GQuark pygobject_instance_data_key_fake = 0;
+
+
+
+
+
+static void pygobject_data_free_fake(PyGObjectData_fake *data)
+{
+    PyGILState_STATE state;                 /* Etat interne de Python      */
+    GSList *iter;                           /* Boucle de parcours          */
+
+    state = pyglib_gil_state_ensure();
+
+    Py_DECREF(data->type);
+
+    pyg_begin_allow_threads;
+
+    for (iter = data->closures; iter; )
+    {
+        /**
+         * On obtient le lien avant la libération via
+         * pygobject_unwatch_closure()...
+         */
+        iter = iter->next;
+
+        g_closure_invalidate((GClosure *)iter->data);
+
+    }
+
+    pyg_end_allow_threads;
+
+    g_free(data);
+
+    pyglib_gil_state_release(state);
+
+}
+
+
+
+static PyGObjectData_fake *pygobject_data_new_fake(void)
+{
+    PyGObjectData_fake *result;             /* Instance à retourner        */
+
+    result = g_new0(PyGObjectData_fake, 1);
+
+    return result;
+
+}
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Définit les éléments immuables pour toute association.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void pychrysalide_init_quirks(void)
+{
+    pygobject_instance_data_key_fake = g_quark_from_static_string("PyGObject::instance-data");
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : obj  = instance GLib crée en C.                              *
+*                type = type de l'objet Python correspond.                    *
+*                                                                             *
+*  Description : Crée l'association précise attendue par Python-GObject.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void pychrysalide_set_instance_data(GObject *obj, PyTypeObject *type)
+{
+    PyGObjectData_fake *data;
+
+    data = g_object_get_qdata(obj, pygobject_instance_data_key_fake);
+
+    if (data == NULL)
+    {
+        data = pygobject_data_new_fake();
+
+        data->type = type;
+        Py_INCREF(type);
+
+        g_object_set_qdata_full(obj, pygobject_instance_data_key_fake,
+                                data, (GDestroyNotify)pygobject_data_free_fake);
+
+    }
+
+}
diff --git a/plugins/pyoida/quirks.h b/plugins/pyoida/quirks.h
new file mode 100644
index 0000000..70e036e
--- /dev/null
+++ b/plugins/pyoida/quirks.h
@@ -0,0 +1,42 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * quirks.h - prototypes pour la transmission du type Python exact aux instances de PyObject
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYOIDA_QUIRKS_H
+#define _PLUGINS_PYOIDA_QUIRKS_H
+
+
+#include <Python.h>
+#include <glib-object.h>
+
+
+
+/* Définit les éléments immuables pour toute association. */
+void pychrysalide_init_quirks(void);
+
+/* Crée l'association précise attendue par Python-GObject. */
+void pychrysalide_set_instance_data(GObject *, PyTypeObject *);
+
+
+
+#endif  /* _PLUGINS_PYOIDA_QUIRKS_H */
diff --git a/plugins/python/exectracer/exectracer.py b/plugins/python/exectracer/exectracer.py
index ddeff75..898f0be 100644
--- a/plugins/python/exectracer/exectracer.py
+++ b/plugins/python/exectracer/exectracer.py
@@ -17,3 +17,7 @@ class ExecTracer(Plugin):
 
         print "Python Hello !"
         print debugger
+
+        for i in debugger.list_all_threads():
+
+            print "Thread %d '%s'" % (i[0], i[1])
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)
-- 
cgit v0.11.2-87-g4458