This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
multithreaded watchpoints for i386 gdb
- From: "Hoffmann, Christian" <Christian-Hoffmann at siemens dot com>
- To: <gdb-patches at sourceware dot org>
- Date: Wed, 20 Feb 2008 15:07:00 +0100
- Subject: multithreaded watchpoints for i386 gdb
Hi,
this implements multithreaded watchpoints for I386 gdb.
i tested it on a heavily multithreaded application on
SUSE10.1/kernel 2.6.16.21.
best regards
Christian
ChangeLog:
* thread.c (prune_threads): declare non-static
to be callable by i386-linux-nat.c.
* i386-linux-nat.c (iterate_thread_callback): New function
serves as callback for iterate_over_threads.
(i386_linux_dr_set ): if multithreaded set DR reg in every thread's
process descriptor.
diff -up ../originalModules/thread.c ./thread.c
--- ../originalModules/thread.c 2005-12-17 23:34:04.000000000 +0100
+++ ./thread.c 2008-02-20 13:21:52.000000000 +0100
@@ -64,7 +64,7 @@ static void info_threads_command (char *
static void thread_apply_command (char *, int);
static void restore_current_thread (ptid_t);
static void switch_to_thread (ptid_t ptid);
-static void prune_threads (void);
+void prune_threads (void);
void
delete_step_resume_breakpoint (void *arg)
@@ -382,7 +382,7 @@ thread_alive (struct thread_info *tp)
return 1;
}
-static void
+void
prune_threads (void)
{
struct thread_info *tp, *next;
diff -up ../originalModules/i386-linux-nat.c ./i386-linux-nat.c
--- ../originalModules/i386-linux-nat.c 2006-08-09 00:32:38.000000000 +0200
+++ ./i386-linux-nat.c 2008-02-20 14:32:40.000000000 +0100
@@ -33,6 +33,8 @@
#include <sys/user.h>
#include <sys/procfs.h>
+#include "gdbthread.h"
+
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
@@ -642,6 +644,35 @@ i386_linux_dr_get (int regnum)
return value;
}
+
+/* christian hoffmann (hc002821@arcor.de <mailto:hc002821@arcor.de> ) multithreaded watchpoints */
+
+#define MAX_THREADS_PER_PROCESS 100
+
+static struct thread_info *pThreadInfoArray[MAX_THREADS_PER_PROCESS];
+static int threadArrayIndex;
+
+/* callback function for iterate_over_threads called from within i386_linux_dr_set.
+ since we return 0 we will be called for every thread of the debugee.
+ store every pThreadInfo and the number of threads for use in i386_linux_dr_set. */
+
+static int
+iterate_thread_callback(struct thread_info *pThreadInfo, void *pData)
+{
+ pThreadInfoArray[threadArrayIndex] = pThreadInfo;
+ threadArrayIndex++;
+ if (threadArrayIndex >= MAX_THREADS_PER_PROCESS)
+ {
+ return 1; /* stop the loop. iterate_over_threads will return != NULL so nothing be done */
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
static void
i386_linux_dr_set (int regnum, unsigned long value)
{
@@ -650,13 +681,53 @@ i386_linux_dr_set (int regnum, unsigned
/* FIXME: kettenis/2001-01-29: It's not clear what we should do with
multi-threaded processes here. For now, pretend there is just
one thread. */
- tid = PIDGET (inferior_ptid);
-
- errno = 0;
- ptrace (PTRACE_POKEUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
- if (errno != 0)
- perror_with_name (_("Couldn't write debug register"));
+
+ /* christian hoffmann (hc002821@arcor.de <mailto:hc002821@arcor.de> ) multithreaded watchpoints */
+
+ int i;
+ struct thread_info *rc;
+
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ {
+ /* single threaded application */
+ tid = PIDGET (inferior_ptid);
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, tid,
+ offsetof (struct user, u_debugreg[regnum]), value);
+ if (errno != 0)
+ perror_with_name (_("Couldn't write debug register"));
+ }
+ else
+ {
+ /* multi threaded application. update DR in every threads process descriptor */
+ memset (pThreadInfoArray, 0, sizeof(pThreadInfoArray));
+ threadArrayIndex = 0;
+ /* the following 2 calls are necessary to update our thread list */
+ prune_threads ();
+ target_find_new_threads ();
+
+ rc = iterate_over_threads (iterate_thread_callback, NULL);
+ if(rc != NULL)
+ {
+ printf("i386_linux_dr_set multi-threaded iterate_over_threads failed\n");
+ }
+ else
+ {
+ for (i=0; i<MAX_THREADS_PER_PROCESS; i++) /* avoid endless loop */
+ {
+ errno = 0;
+ if( (pThreadInfoArray[i] == NULL)||(i == threadArrayIndex) )
+ {
+ break;
+ }
+ ptrace (PTRACE_POKEUSER, TIDGET(pThreadInfoArray[i]->ptid),
+ offsetof (struct user, u_debugreg[regnum]), value);
+ if (errno != 0)
+ perror_with_name (_("Couldn't write debug register"));
+ }
+ }
+ }
}
void
Mit freundlichen Grüßen/ kind regards
Christian Hoffmann
Siemens Enterprise Communications GmbH & Co. KG
Small Medium Enterprice Software Development Platform
SEN ESY SME MP532
Brauckstr.14
D-58449 Witten
Phone: +49 2302 667 2821
Fax: +49 2302 667 2121
Email : Christian-Hoffmann@siemens.com
Communication for the open minded
www.siemens.de/open <http://www.siemens.de/open>
www.siemens.com/open <http://www.siemens.com/open>
Siemens Enterprise Communications GmbH & Co. KG
Managing Directors: Andreas Bernhardt, Reinhard Benditte,
Gerhard Otterbach, Thomas Zimmermann
Registered offices: Munich
Commercial registry Munich, HRA 88546
WEEE-Reg.-No. DE 27980375
General Partner:
Siemens Enterprise Communications Management GmbH
Registered offices: Munich
Commercial registry: Munich, HRB 163415