summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog76
-rw-r--r--plugins/pyoida/Makefile.am3
-rw-r--r--plugins/pyoida/debug/debugger.c87
-rw-r--r--plugins/pyoida/debug/module.c6
-rw-r--r--plugins/pyoida/pyoida.c2
-rw-r--r--plugins/pyoida/quirks.c148
-rw-r--r--plugins/pyoida/quirks.h42
-rw-r--r--plugins/python/exectracer/exectracer.py4
-rw-r--r--src/debug/debugger-int.h7
-rw-r--r--src/debug/debugger.c28
-rw-r--r--src/debug/debugger.h3
-rw-r--r--src/debug/jdwp/debugger.c171
-rw-r--r--src/debug/jdwp/jdwp_def.h70
-rw-r--r--src/debug/jdwp/misc/Makefile.am1
-rw-r--r--src/debug/jdwp/misc/header.c26
-rw-r--r--src/debug/jdwp/misc/header.h5
-rw-r--r--src/debug/jdwp/misc/id.c148
-rw-r--r--src/debug/jdwp/misc/id.h131
-rw-r--r--src/debug/jdwp/packet.c90
-rw-r--r--src/debug/jdwp/packet.h10
-rw-r--r--src/debug/jdwp/sets/Makefile.am1
-rw-r--r--src/debug/jdwp/sets/list.c86
-rw-r--r--src/debug/jdwp/sets/list.h14
-rw-r--r--src/debug/jdwp/sets/thread.c116
-rw-r--r--src/debug/jdwp/sets/thread.h46
-rw-r--r--src/debug/jdwp/sets/vm.c109
-rw-r--r--src/debug/jdwp/sets/vm.h13
-rw-r--r--src/debug/jdwp/tcp.c34
-rw-r--r--src/debug/packet.c22
-rw-r--r--src/debug/packet.h5
-rw-r--r--src/debug/stream-int.h8
-rw-r--r--src/debug/stream.c7
32 files changed, 1461 insertions, 58 deletions
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)