From 73605bffb935fc51a52be1936426211e31dd898a Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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 + + * 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 * 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 +#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 +#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 +#include + + + + + + +/* 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 +#include + + + +/* 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 #include @@ -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 +#include @@ -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 . + */ + + +#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 . + */ + + +#ifndef _DEBUG_JDWP_MISC_ID_H +#define _DEBUG_JDWP_MISC_ID_H + + +#include + + +#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 +#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 . + */ + + +#include "thread.h" + + +#include + + +#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 . + */ + + +#ifndef _DEBUG_JDWP_SETS_THREAD_H +#define _DEBUG_JDWP_SETS_THREAD_H + + +#include + + +#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 #include +#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(" 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(" 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