summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2012-02-18 16:41:31 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2012-02-18 16:41:31 (GMT)
commitdeb012d919ea6c5e79702a39a03a85be2ffcf406 (patch)
treeae9cee108d05e0a6674d8617a08d0ea09165443c /src/debug
parent73605bffb935fc51a52be1936426211e31dd898a (diff)
Retrieved the frames stack from the running process.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@235 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/debugger-int.h4
-rw-r--r--src/debug/debugger.c31
-rw-r--r--src/debug/debugger.h14
-rw-r--r--src/debug/jdwp/debugger.c79
-rw-r--r--src/debug/jdwp/jdwp_def.h42
-rw-r--r--src/debug/jdwp/misc/Makefile.am1
-rw-r--r--src/debug/jdwp/misc/location.c64
-rw-r--r--src/debug/jdwp/misc/location.h40
-rw-r--r--src/debug/jdwp/sets/list.c7
-rw-r--r--src/debug/jdwp/sets/list.h2
-rw-r--r--src/debug/jdwp/sets/thread.c108
-rw-r--r--src/debug/jdwp/sets/thread.h9
12 files changed, 400 insertions, 1 deletions
diff --git a/src/debug/debugger-int.h b/src/debug/debugger-int.h
index 490b35c..f6f51ad 100644
--- a/src/debug/debugger-int.h
+++ b/src/debug/debugger-int.h
@@ -44,6 +44,9 @@ 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 liste des frames courantes d'un thread donné. */
+typedef dbg_frame_t * (* dbg_get_frames_stack_fc) (GBinaryDebugger *, pid_t, size_t *);
+
/* Fournit la valeur des registres de l'architecture. */
typedef register_value * (* get_register_values_fc) (GBinaryDebugger *, size_t *);
@@ -63,6 +66,7 @@ struct _GBinaryDebugger
basic_debugger_fc kill; /* Tue le débogueur */
dbg_list_all_threads_fc all_threads; /* Liste des threads actifs */
+ dbg_get_frames_stack_fc frames_stack; /* Pile des frames courantes */
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 ce62625..73b8719 100644
--- a/src/debug/debugger.c
+++ b/src/debug/debugger.c
@@ -261,6 +261,37 @@ pid_t *g_binary_debugger_list_all_threads(GBinaryDebugger *debugger, char ***nam
/******************************************************************************
* *
+* Paramètres : debugger = instance du module de débogage chargé. *
+* thread = thread concerné par l'analyse. *
+* count = nombre de frames en place. [OUT] *
+* *
+* Description : Fournit la liste des frames courantes d'un thread donné. *
+* *
+* Retour : Liste des frames trouvées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+dbg_frame_t *g_binary_debugger_get_frames_stack(GBinaryDebugger *debugger, pid_t thread, size_t *count)
+{
+ dbg_frame_t *result; /* Liste à retourner */
+
+ if (debugger->frames_stack != NULL)
+ result = debugger->frames_stack(debugger, thread, count);
+ else
+ {
+ *count = 0;
+ 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 362f8a1..7a6459b 100644
--- a/src/debug/debugger.h
+++ b/src/debug/debugger.h
@@ -31,6 +31,7 @@
#include "../analysis/binary.h"
+#include "../arch/archbase.h"
@@ -46,6 +47,16 @@ typedef enum _DebuggerType
} DebuggerType;
+/* Définition d'une frame */
+typedef struct _dbg_frame_t
+{
+
+ vmpa_t addr; /* Position dans le code */
+
+} dbg_frame_t;
+
+
+
/* Transmission des valeurs des registres */
typedef struct _register_value
{
@@ -91,6 +102,9 @@ 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 liste des frames courantes d'un thread donné. */
+dbg_frame_t *g_binary_debugger_get_frames_stack(GBinaryDebugger *, pid_t, 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 51a0db8..b416840 100644
--- a/src/debug/jdwp/debugger.c
+++ b/src/debug/jdwp/debugger.c
@@ -24,7 +24,10 @@
#include "debugger.h"
+#include <malloc.h>
#include <string.h>
+
+
#include <i18n.h>
@@ -70,6 +73,9 @@ 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 *);
+/* Fournit la liste des frames courantes d'un thread donné. */
+static dbg_frame_t *g_java_debugger_get_frames_stack(GJavaDebugger *, pid_t, size_t *);
+
/* Indique le type défini par la GLib pour le débogueur java. */
@@ -116,6 +122,7 @@ 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;
+ parent->frames_stack = (dbg_get_frames_stack_fc)g_java_debugger_get_frames_stack;
#if 0
parent->run = (basic_debugger_fc)g_java_debugger_run;
@@ -364,3 +371,75 @@ static pid_t *g_java_debugger_list_all_threads(GJavaDebugger *debugger, char ***
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = instance du module de débogage chargé. *
+* thread = thread concerné par l'analyse. *
+* count = nombre de frames en place. [OUT] *
+* *
+* Description : Fournit la liste des frames courantes d'un thread donné. *
+* *
+* Retour : Liste des frames trouvées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static dbg_frame_t *g_java_debugger_get_frames_stack(GJavaDebugger *debugger, pid_t thread, size_t *count)
+{
+ dbg_frame_t *result; /* Bilan à retourner */
+ GDebugPacket *req; /* Requête à formuler */
+ jdwp_cmd_thread_frames_request frames; /* Ciblage du thread désiré */
+ GDebugPacket *ret; /* Obtention de la réponse */
+ jdwp_payload *payload; /* Charge utile d'une réponse */
+ size_t i; /* Boucle de parcours */
+
+ 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_THREAD_REFERENCE, JDWP_CMD_THREAD_FRAMES);
+
+ frames.id = thread;
+ frames.start = 0;
+ frames.length = ALL_FRAMES;
+ g_jdwp_packet_set_payload(G_JDWP_PACKET(req), (jdwp_payload *)&frames);
+
+ if (!g_debug_stream_send_packet(debugger->stream, req))
+ goto gjdgsf_req_error;
+
+ ret = g_debug_stream_recv_packet(debugger->stream,
+ (filter_packet_fc)g_jdwp_packet_is_reply, req);
+ if (!ret) goto gjdgsf_req_error;
+
+ if (!g_jdwp_packet_parse_payload(G_JDWP_PACKET(ret),
+ JDWP_CST_THREAD_REFERENCE, JDWP_CMD_THREAD_FRAMES))
+ goto gjdgsf_ret_error;
+
+ payload = g_jdwp_packet_get_payload(G_JDWP_PACKET(ret));
+
+ *count = payload->th_frames.count;
+ result = (dbg_frame_t *)calloc(*count, sizeof(dbg_frame_t));
+
+ for (i = 0; i < *count; i++)
+ {
+ /* TODO */
+ result[i].addr = payload->th_frames.frames[i].location.index;
+
+ }
+
+ gjdgsf_ret_error:
+
+ g_debug_stream_mark_packet_as_free(debugger->stream, ret);
+
+ gjdgsf_req_error:
+
+ 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 7f13f8c..17df081 100644
--- a/src/debug/jdwp/jdwp_def.h
+++ b/src/debug/jdwp/jdwp_def.h
@@ -99,6 +99,17 @@ typedef uint64_t jdwp_dynsized_id;
+/* "location" */
+typedef struct _jdwp_location
+{
+ jdwp_type_tag tag; /* Classe ou interface ? */
+
+ jdwp_dynsized_id class_id; /* Identifiant correspondant */
+ jdwp_dynsized_id method_id; /* Méthode concernée */
+ uint64_t index; /* Position dans le code */
+
+} jdwp_location;
+
/* "string" */
typedef struct _jdwp_string
@@ -111,6 +122,10 @@ typedef struct _jdwp_string
+
+
+
+
/**
* Jeux de commandes.
*/
@@ -137,6 +152,7 @@ typedef struct _jdwp_string
/* ThreadReference Command Set */
#define JDWP_CMD_THREAD_NAME 1
+#define JDWP_CMD_THREAD_FRAMES 6
/**
@@ -190,6 +206,32 @@ typedef struct _jdwp_cmd_thread_name_reply
} jdwp_cmd_thread_name_reply;
+/* JDWP_CMD_THREAD_FRAMES */
+
+typedef struct _jdwp_cmd_thread_frames_request
+{
+ jdwp_dynsized_id id; /* Identifiant du thread visé */
+ uint32_t start; /* Première frame à traiter */
+ uint32_t length; /* Longueur de la liste ou -1 */
+
+} jdwp_cmd_thread_frames_request;
+
+#define ALL_FRAMES 0xffffffff
+
+typedef struct _jdwp_thread_frame
+{
+ jdwp_dynsized_id frame_id; /* Identifiant de la frame */
+ jdwp_location location; /* Localisation de la frame */
+
+} jdwp_thread_frame;
+
+typedef struct _jdwp_cmd_thread_frames_reply
+{
+ uint32_t count; /* Taille de la liste */
+ jdwp_thread_frame *frames; /* Liste de frames */
+
+} jdwp_cmd_thread_frames_reply;
+
#endif /* _DEBUG_JDWP_JDWP_DEF_H */
diff --git a/src/debug/jdwp/misc/Makefile.am b/src/debug/jdwp/misc/Makefile.am
index 44c6224..f955501 100644
--- a/src/debug/jdwp/misc/Makefile.am
+++ b/src/debug/jdwp/misc/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libdebugjdwpmisc.la
libdebugjdwpmisc_la_SOURCES = \
header.h header.c \
id.h id.c \
+ location.h location.c \
types.h types.c
libdebugjdwpmisc_la_LDFLAGS =
diff --git a/src/debug/jdwp/misc/location.c b/src/debug/jdwp/misc/location.c
new file mode 100644
index 0000000..3fd95cb
--- /dev/null
+++ b/src/debug/jdwp/misc/location.c
@@ -0,0 +1,64 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * location.c - constitution des localisations d'instructions courantes
+ *
+ * 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 "location.h"
+
+
+#include "id.h"
+#include "../../../common/endianness.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : blob = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* sizes = référence pour la taille utilisée. *
+* loc = localisation à fournir. [OUT] *
+* *
+* Description : Lit une localisation d'instruction courante dans l'exécution.*
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_jdwp_location(const bin_t *blob, off_t *pos, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_location *loc)
+{
+ if (!read_u8(&loc->tag, blob, pos, len, SRE_BIG))
+ return false;
+
+ if (!get_jdwp_class_id(blob, pos, len, sizes, &loc->class_id))
+ return false;
+
+ if (!get_jdwp_method_id(blob, pos, len, sizes, &loc->method_id))
+ return false;
+
+ if (!read_u64(&loc->index, blob, pos, len, SRE_BIG))
+ return false;
+
+ return true;
+
+}
diff --git a/src/debug/jdwp/misc/location.h b/src/debug/jdwp/misc/location.h
new file mode 100644
index 0000000..a594bac
--- /dev/null
+++ b/src/debug/jdwp/misc/location.h
@@ -0,0 +1,40 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * location.h - prototypes pour la constitution des localisations d'instructions courantes
+ *
+ * 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_LOCATION_H
+#define _DEBUG_JDWP_MISC_LOCATION_H
+
+
+#include <stdbool.h>
+
+
+#include "../jdwp_def.h"
+#include "../../../arch/archbase.h"
+
+
+/* Lit une localisation d'instruction courante dans l'exécution. */
+bool get_jdwp_location(const bin_t *, off_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_location *);
+
+
+
+#endif /* _DEBUG_JDWP_MISC_LOCATION_H */
diff --git a/src/debug/jdwp/sets/list.c b/src/debug/jdwp/sets/list.c
index 84c6ac0..ba96917 100644
--- a/src/debug/jdwp/sets/list.c
+++ b/src/debug/jdwp/sets/list.c
@@ -87,6 +87,13 @@ static jdwp_command _commands[][256] = {
.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
+ },
+
+ [JDWP_CMD_THREAD_FRAMES] = {
+ .set_payload = (set_jdwp_payload_fc)set_jdwp_thread_frames,
+ .free_set_payload = (free_jdwp_payload_fc)NULL,
+ .get_payload = (get_jdwp_payload_fc)get_jdwp_thread_frames,
+ .free_got_payload = (free_jdwp_payload_fc)free_jdwp_thread_frames_reply
}
}
diff --git a/src/debug/jdwp/sets/list.h b/src/debug/jdwp/sets/list.h
index 9880e69..ba66842 100644
--- a/src/debug/jdwp/sets/list.h
+++ b/src/debug/jdwp/sets/list.h
@@ -42,6 +42,8 @@ typedef union _jdwp_payload
jdwp_cmd_thread_name_request th_ident; /* Identification d'un thread */
jdwp_cmd_thread_name_reply th_name; /* Désignation d'un thread */
+ jdwp_cmd_thread_frames_request __nu0; /* Inutilisé */
+ jdwp_cmd_thread_frames_reply th_frames; /* Pile des frames courantes */
bin_t padding[500];
diff --git a/src/debug/jdwp/sets/thread.c b/src/debug/jdwp/sets/thread.c
index 9391ff6..ea60bc6 100644
--- a/src/debug/jdwp/sets/thread.c
+++ b/src/debug/jdwp/sets/thread.c
@@ -24,10 +24,12 @@
#include "thread.h"
+#include <malloc.h>
#include <string.h>
#include "../misc/id.h"
+#include "../misc/location.h"
#include "../misc/types.h"
#include "../../../common/endianness.h"
@@ -87,7 +89,7 @@ bool get_jdwp_thread_name(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_siz
off_t pos; /* Tête de lecture */
pos = 0;
- memset(reply, 0, sizeof(jdwp_cmd_vm_version_reply));
+ memset(reply, 0, sizeof(jdwp_cmd_thread_name_reply));
result = get_jdwp_string(blob, &pos, len, &reply->name);
if (!result) return false;
@@ -114,3 +116,107 @@ void free_jdwp_thread_name_reply(jdwp_cmd_thread_name_reply *reply)
free_jdwp_string(&reply->name);
}
+
+
+/******************************************************************************
+* *
+* 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 les frames d'un thread. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool set_jdwp_thread_frames(const jdwp_cmd_thread_frames_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_frames_request));
+
+ result = set_jdwp_frame_id(&req->id, sizes, blob, &pos, *len);
+ if (!result) return false;
+
+ result = write_u32(&req->start, blob, &pos, *len, SRE_BIG);
+ if (!result) return false;
+
+ result = write_u32(&req->length, blob, &pos, *len, SRE_BIG);
+ 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 les frames d'un thread. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_jdwp_thread_frames(const bin_t *blob, off_t len, const jdwp_cmd_vm_id_sizes_reply *sizes, jdwp_cmd_thread_frames_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_thread_frames_reply));
+
+ result = read_u32(&reply->count, blob, &pos, len, SRE_BIG);
+ if (!result) return false;
+
+ reply->frames = (jdwp_thread_frame *)calloc(reply->count, sizeof(jdwp_thread_frame));
+
+ for (i = 0; i < reply->count && result; i++)
+ {
+ result = get_jdwp_frame_id(blob, &pos, len, sizes, &reply->frames[i].frame_id);
+
+ result &= get_jdwp_location(blob, &pos, len, sizes, &reply->frames[i].location);
+
+ }
+
+ if (!result)
+ free_jdwp_thread_frames_reply(reply);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reply = structure de réponse à supprimer de la mémoire. *
+* *
+* Description : Libère une liste de frames d'un thread. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void free_jdwp_thread_frames_reply(jdwp_cmd_thread_frames_reply *reply)
+{
+ if (reply->frames != NULL)
+ free(reply->frames);
+
+}
diff --git a/src/debug/jdwp/sets/thread.h b/src/debug/jdwp/sets/thread.h
index f8c3abe..a304cc0 100644
--- a/src/debug/jdwp/sets/thread.h
+++ b/src/debug/jdwp/sets/thread.h
@@ -41,6 +41,15 @@ bool get_jdwp_thread_name(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply
/* Libère le nom donné à un thread. */
void free_jdwp_thread_name_reply(jdwp_cmd_thread_name_reply *);
+/* Prépare une requête demandant les frames d'un thread. */
+bool set_jdwp_thread_frames(const jdwp_cmd_thread_frames_request *, const jdwp_cmd_vm_id_sizes_reply *, bin_t *, off_t *);
+
+/* Reconstitue une réponse fournissant les frames d'un thread. */
+bool get_jdwp_thread_frames(const bin_t *, off_t, const jdwp_cmd_vm_id_sizes_reply *, jdwp_cmd_thread_frames_reply *);
+
+/* Libère une liste de frames d'un thread. */
+void free_jdwp_thread_frames_reply(jdwp_cmd_thread_frames_reply *);
+
#endif /* _DEBUG_JDWP_SETS_THREAD_H */