2008-01-12 16:16:46 +00:00
|
|
|
|
http://sourceware.org/ml/gdb-patches/2008-01/msg00042.html
|
2007-10-14 20:11:42 +00:00
|
|
|
|
[ Backported for GDB-6.6 (only removed the new file inclusion). ]
|
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
|
2008-01-07 15:10:23 +00:00
|
|
|
|
2007-09-16 Daniel Jacobowitz <dan@codesourcery.com>
|
|
|
|
|
Jeff Johnston <jjohnstn@redhat.com>
|
|
|
|
|
|
|
|
|
|
* gdb.texinfo (Setting Watchpoints): Adjust warning text about
|
|
|
|
|
multi-threaded watchpoints.
|
|
|
|
|
|
|
|
|
|
2007-12-15 Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
|
|
|
|
|
|
|
* gdb.texinfo (Setting Watchpoints): New paragraph on the software
|
|
|
|
|
watchpoints safety wrt `set scheduler-locking'.
|
|
|
|
|
|
2008-03-03 16:13:47 +00:00
|
|
|
|
2008-03-01 Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
|
|
|
|
|
|
|
Port to GDB-6.8pre.
|
|
|
|
|
|
2008-03-30 22:15:14 +00:00
|
|
|
|
2008-03-31 Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
|
|
|
|
|
|
|
* gdb.threads/watchpoint-fork-forkoff.c (forkoff): New delay after the
|
|
|
|
|
parent/child messages to fix a race.
|
|
|
|
|
|
2008-06-01 13:14:20 +00:00
|
|
|
|
2008-05-28 Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
|
|
|
|
|
|
|
* s390-nat.c (s390_fix_watch_points): Fix its compilation failure
|
|
|
|
|
- rename it to S390_FIX_WATCH_POINTS_LIST.
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/amd64-linux-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/amd64-linux-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/amd64-linux-nat.c 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -411,25 +411,43 @@ amd64_linux_dr_set (ptid_t ptid, int reg
|
|
|
|
|
static void
|
2008-03-03 16:13:47 +00:00
|
|
|
|
amd64_linux_dr_set_control (unsigned long control)
|
|
|
|
|
{
|
|
|
|
|
- struct lwp_info *lp;
|
|
|
|
|
- ptid_t ptid;
|
|
|
|
|
-
|
|
|
|
|
amd64_linux_dr[DR_CONTROL] = control;
|
|
|
|
|
- ALL_LWPS (lp, ptid)
|
|
|
|
|
- amd64_linux_dr_set (ptid, DR_CONTROL, control);
|
|
|
|
|
+
|
|
|
|
|
+ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process
|
|
|
|
|
+ not listed for ALL_LWPS. */
|
|
|
|
|
+
|
|
|
|
|
+ if (ptid_get_lwp (inferior_ptid) == 0)
|
|
|
|
|
+ amd64_linux_dr_set (inferior_ptid, DR_CONTROL, control);
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ struct lwp_info *lp;
|
|
|
|
|
+ ptid_t ptid;
|
|
|
|
|
+
|
|
|
|
|
+ ALL_LWPS (lp, ptid)
|
|
|
|
|
+ amd64_linux_dr_set (ptid, DR_CONTROL, control);
|
|
|
|
|
+ }
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
static void
|
2008-03-03 16:13:47 +00:00
|
|
|
|
amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
- struct lwp_info *lp;
|
|
|
|
|
- ptid_t ptid;
|
|
|
|
|
-
|
|
|
|
|
gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
|
|
|
|
|
|
|
|
|
|
amd64_linux_dr[DR_FIRSTADDR + regnum] = addr;
|
|
|
|
|
- ALL_LWPS (lp, ptid)
|
|
|
|
|
- amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+
|
|
|
|
|
+ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process
|
|
|
|
|
+ not listed for ALL_LWPS. */
|
|
|
|
|
+
|
|
|
|
|
+ if (ptid_get_lwp (inferior_ptid) == 0)
|
|
|
|
|
+ amd64_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ struct lwp_info *lp;
|
|
|
|
|
+ ptid_t ptid;
|
|
|
|
|
+
|
|
|
|
|
+ ALL_LWPS (lp, ptid)
|
|
|
|
|
+ amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
static void
|
|
|
|
|
@@ -454,6 +472,42 @@ amd64_linux_new_thread (ptid_t ptid)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
|
|
|
|
|
amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
|
|
|
|
|
}
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child
|
|
|
|
|
+ process of traced FORK. We must clear such watchpoints only once during
|
|
|
|
|
+ DETACH_BREAKPOINTS. */
|
|
|
|
|
+
|
|
|
|
|
+static int amd64_linux_detach_breakpoints_pid;
|
|
|
|
|
+
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+/* Remove a watchpoint that watched the memory region which starts at
|
|
|
|
|
+ address ADDR, whose length is LEN bytes, and for accesses of the
|
|
|
|
|
+ type TYPE. Return 0 on success, -1 on failure. */
|
|
|
|
|
+int
|
|
|
|
|
+amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
|
|
|
|
|
+{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ if (ptid_get_pid (inferior_ptid) == amd64_linux_detach_breakpoints_pid)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */
|
|
|
|
|
+ amd64_linux_detach_breakpoints_pid = 0;
|
|
|
|
|
+
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ return target_remove_watchpoint (addr, len, type);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+static void
|
|
|
|
|
+amd64_linux_detach_breakpoints (int detached_pid)
|
|
|
|
|
+{
|
|
|
|
|
+ struct cleanup *old_chain = save_inferior_ptid ();
|
|
|
|
|
+ int i;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ extern void i386_detach_breakpoints (int detached_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ amd64_linux_detach_breakpoints_pid = detached_pid;
|
|
|
|
|
+ /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */
|
|
|
|
|
+ inferior_ptid = pid_to_ptid (detached_pid);
|
|
|
|
|
+
|
|
|
|
|
+ i386_detach_breakpoints (detached_pid);
|
|
|
|
|
+
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+}
|
2008-03-03 16:13:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This function is called by libthread_db as part of its handling of
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -767,6 +821,42 @@ amd64_linux_siginfo_fixup (struct siginf
|
2009-02-11 00:04:48 +00:00
|
|
|
|
return 0;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
2009-02-11 00:04:48 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+static int (*amd64_linux_super_follow_fork) (struct target_ops *ops,
|
|
|
|
|
+ int follow_child);
|
|
|
|
|
+
|
|
|
|
|
+/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its
|
|
|
|
|
+ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+amd64_linux_follow_fork (struct target_ops *ops, int follow_child)
|
|
|
|
|
+{
|
|
|
|
|
+ ptid_t last_ptid;
|
|
|
|
|
+ struct target_waitstatus last_status;
|
|
|
|
|
+ int has_vforked;
|
|
|
|
|
+ int parent_pid, child_pid;
|
|
|
|
|
+
|
|
|
|
|
+ get_last_target_status (&last_ptid, &last_status);
|
|
|
|
|
+ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
|
|
|
|
|
+ parent_pid = ptid_get_lwp (last_ptid);
|
|
|
|
|
+ if (parent_pid == 0)
|
|
|
|
|
+ parent_pid = ptid_get_pid (last_ptid);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+ child_pid = ptid_get_lwp (last_status.value.related_pid);
|
|
|
|
|
+ if (child_pid == 0)
|
|
|
|
|
+ child_pid = ptid_get_pid (last_status.value.related_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ if (! follow_child)
|
|
|
|
|
+ {
|
|
|
|
|
+ amd64_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if (! has_vforked)
|
|
|
|
|
+ amd64_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (*amd64_linux_super_follow_fork) (ops, follow_child);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
2009-02-11 00:04:48 +00:00
|
|
|
|
void _initialize_amd64_linux_nat (void);
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -809,6 +899,9 @@ _initialize_amd64_linux_nat (void)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
linux_elfcore_write_prstatus = amd64_linux_elfcore_write_prstatus;
|
|
|
|
|
linux_elfcore_write_prfpreg = amd64_linux_elfcore_write_prfpreg;
|
|
|
|
|
|
|
|
|
|
+ amd64_linux_super_follow_fork = t->to_follow_fork;
|
|
|
|
|
+ t->to_follow_fork = amd64_linux_follow_fork;
|
|
|
|
|
+
|
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
linux_nat_set_new_thread (t, amd64_linux_new_thread);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/i386-linux-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/i386-linux-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/i386-linux-nat.c 2009-08-04 07:26:43.000000000 +0200
|
|
|
|
|
@@ -637,21 +637,42 @@ i386_linux_dr_set_control (unsigned long
|
2008-03-03 16:13:47 +00:00
|
|
|
|
ptid_t ptid;
|
|
|
|
|
|
|
|
|
|
i386_linux_dr[DR_CONTROL] = control;
|
|
|
|
|
- ALL_LWPS (lp, ptid)
|
|
|
|
|
- i386_linux_dr_set (ptid, DR_CONTROL, control);
|
|
|
|
|
+
|
|
|
|
|
+ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process
|
|
|
|
|
+ not listed for ALL_LWPS. */
|
|
|
|
|
+
|
|
|
|
|
+ if (ptid_get_lwp (inferior_ptid) == 0)
|
|
|
|
|
+ i386_linux_dr_set (inferior_ptid, DR_CONTROL, control);
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ struct lwp_info *lp;
|
|
|
|
|
+ ptid_t ptid;
|
|
|
|
|
+
|
|
|
|
|
+ ALL_LWPS (lp, ptid)
|
|
|
|
|
+ i386_linux_dr_set (ptid, DR_CONTROL, control);
|
|
|
|
|
+ }
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
static void
|
2008-03-03 16:13:47 +00:00
|
|
|
|
i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
- struct lwp_info *lp;
|
|
|
|
|
- ptid_t ptid;
|
|
|
|
|
-
|
|
|
|
|
gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
|
|
|
|
|
|
|
|
|
|
i386_linux_dr[DR_FIRSTADDR + regnum] = addr;
|
|
|
|
|
- ALL_LWPS (lp, ptid)
|
|
|
|
|
- i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+
|
|
|
|
|
+ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process
|
|
|
|
|
+ not listed for ALL_LWPS. */
|
|
|
|
|
+
|
|
|
|
|
+ if (ptid_get_lwp (inferior_ptid) == 0)
|
|
|
|
|
+ i386_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ struct lwp_info *lp;
|
|
|
|
|
+ ptid_t ptid;
|
|
|
|
|
+
|
|
|
|
|
+ ALL_LWPS (lp, ptid)
|
|
|
|
|
+ i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
static void
|
|
|
|
|
@@ -676,6 +697,42 @@ i386_linux_new_thread (ptid_t ptid)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
|
|
|
|
|
i386_linux_dr_set (ptid, DR_CONTROL, i386_linux_dr[DR_CONTROL]);
|
|
|
|
|
}
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child
|
|
|
|
|
+ process of traced FORK. We must clear such watchpoints only once during
|
|
|
|
|
+ DETACH_BREAKPOINTS. */
|
|
|
|
|
+
|
|
|
|
|
+static int i386_linux_detach_breakpoints_pid;
|
|
|
|
|
+
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+/* Remove a watchpoint that watched the memory region which starts at
|
|
|
|
|
+ address ADDR, whose length is LEN bytes, and for accesses of the
|
|
|
|
|
+ type TYPE. Return 0 on success, -1 on failure. */
|
|
|
|
|
+int
|
|
|
|
|
+i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
|
|
|
|
|
+{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ if (ptid_get_pid (inferior_ptid) == i386_linux_detach_breakpoints_pid)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */
|
|
|
|
|
+ i386_linux_detach_breakpoints_pid = 0;
|
|
|
|
|
+
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ return target_remove_watchpoint (addr, len, type);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+static void
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+i386_linux_detach_breakpoints (int detached_pid)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ struct cleanup *old_chain = save_inferior_ptid ();
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ int i;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ extern void i386_detach_breakpoints (int detached_pid);
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ i386_linux_detach_breakpoints_pid = detached_pid;
|
|
|
|
|
+ /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */
|
|
|
|
|
+ inferior_ptid = pid_to_ptid (detached_pid);
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ i386_detach_breakpoints (detached_pid);
|
|
|
|
|
+
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+}
|
2008-03-03 16:13:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Called by libthread_db. Returns a pointer to the thread local
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -818,6 +875,40 @@ i386_linux_child_post_startup_inferior (
|
2008-01-12 16:16:46 +00:00
|
|
|
|
super_post_startup_inferior (ptid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int (*i386_linux_super_follow_fork) (struct target_ops *ops,
|
|
|
|
|
+ int follow_child);
|
|
|
|
|
+
|
|
|
|
|
+/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its
|
|
|
|
|
+ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+i386_linux_follow_fork (struct target_ops *ops, int follow_child)
|
|
|
|
|
+{
|
|
|
|
|
+ ptid_t last_ptid;
|
|
|
|
|
+ struct target_waitstatus last_status;
|
|
|
|
|
+ int has_vforked;
|
|
|
|
|
+ int parent_pid, child_pid;
|
|
|
|
|
+
|
|
|
|
|
+ get_last_target_status (&last_ptid, &last_status);
|
|
|
|
|
+ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
|
|
|
|
|
+ parent_pid = ptid_get_lwp (last_ptid);
|
|
|
|
|
+ if (parent_pid == 0)
|
|
|
|
|
+ parent_pid = ptid_get_pid (last_ptid);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+ child_pid = ptid_get_pid (last_status.value.related_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ if (! follow_child)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ {
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ i386_linux_detach_breakpoints (child_pid);
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ if (! has_vforked)
|
|
|
|
|
+ i386_linux_detach_breakpoints (child_pid);
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ return (*i386_linux_super_follow_fork) (ops, follow_child);
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
void
|
|
|
|
|
_initialize_i386_linux_nat (void)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -845,6 +936,9 @@ _initialize_i386_linux_nat (void)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
t->to_fetch_registers = i386_linux_fetch_inferior_registers;
|
|
|
|
|
t->to_store_registers = i386_linux_store_inferior_registers;
|
|
|
|
|
|
|
|
|
|
+ i386_linux_super_follow_fork = t->to_follow_fork;
|
|
|
|
|
+ t->to_follow_fork = i386_linux_follow_fork;
|
|
|
|
|
+
|
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
linux_nat_set_new_thread (t, i386_linux_new_thread);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/i386-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/i386-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/i386-nat.c 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -520,6 +520,18 @@ i386_remove_watchpoint (CORE_ADDR addr,
|
2008-01-12 16:16:46 +00:00
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+void
|
|
|
|
|
+i386_detach_breakpoints (int detached_pid)
|
|
|
|
|
+{
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ /* Do not touch any DR_MIRROR or DR_CONTROL_MIRROR mirrors here. */
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ i386_dr_low.set_control (0);
|
|
|
|
|
+ if (i386_dr_low.reset_addr)
|
|
|
|
|
+ ALL_DEBUG_REGISTERS(i)
|
|
|
|
|
+ i386_dr_low.reset_addr (i);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
/* Return non-zero if we can watch a memory region that starts at
|
|
|
|
|
address ADDR and whose length is LEN bytes. */
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/ia64-linux-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/ia64-linux-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/ia64-linux-nat.c 2009-08-04 07:17:58.000000000 +0200
|
2008-03-03 16:13:47 +00:00
|
|
|
|
@@ -583,6 +583,12 @@ ia64_linux_insert_watchpoint (CORE_ADDR
|
|
|
|
|
return 0;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child
|
|
|
|
|
+ process of traced FORK. We must clear such watchpoints only once during
|
|
|
|
|
+ DETACH_BREAKPOINTS. */
|
|
|
|
|
+
|
|
|
|
|
+static int ia64_linux_detach_breakpoints_pid;
|
|
|
|
|
+
|
2008-01-12 16:28:31 +00:00
|
|
|
|
static int
|
2008-03-03 16:13:47 +00:00
|
|
|
|
ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
{
|
2008-03-03 16:13:47 +00:00
|
|
|
|
@@ -590,6 +596,11 @@ ia64_linux_remove_watchpoint (CORE_ADDR
|
|
|
|
|
long dbr_addr, dbr_mask;
|
|
|
|
|
int max_watchpoints = 4;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
|
|
|
|
|
+ if (ptid_get_pid (inferior_ptid) == ia64_linux_detach_breakpoints_pid)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */
|
|
|
|
|
+ ia64_linux_detach_breakpoints_pid = 0;
|
|
|
|
|
+
|
2008-03-03 16:13:47 +00:00
|
|
|
|
if (len <= 0 || !is_power_of_2 (len))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
@@ -617,6 +628,22 @@ ia64_linux_remove_watchpoint (CORE_ADDR
|
|
|
|
|
}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
static void
|
|
|
|
|
+ia64_linux_detach_breakpoints (int detached_pid)
|
|
|
|
|
+{
|
|
|
|
|
+ int idx, i;
|
|
|
|
|
+ long dbr_addr, dbr_mask;
|
|
|
|
|
+ int max_watchpoints = 4;
|
|
|
|
|
+
|
|
|
|
|
+ ia64_linux_detach_breakpoints_pid = detached_pid;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ /* Do not touch any DEBUG_REGISTERS mirrors here. */
|
|
|
|
|
+ dbr_addr = 0;
|
|
|
|
|
+ dbr_mask = 0;
|
|
|
|
|
+ for (idx = 0; idx < max_watchpoints; idx++)
|
|
|
|
|
+ store_debug_register_pair (ptid_build (detached_pid, 0, 0), idx, &dbr_addr, &dbr_mask);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
|
|
|
|
ia64_linux_new_thread (ptid_t ptid)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
{
|
2008-03-03 16:13:47 +00:00
|
|
|
|
int i, any;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -807,6 +834,40 @@ ia64_linux_xfer_partial (struct target_o
|
2008-03-03 16:13:47 +00:00
|
|
|
|
offset, len);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+static int (*ia64_linux_super_follow_fork) (struct target_ops *ops,
|
|
|
|
|
+ int follow_child);
|
|
|
|
|
+
|
|
|
|
|
+/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its
|
|
|
|
|
+ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+int
|
|
|
|
|
+ia64_linux_follow_fork (struct target_ops *ops, int follow_child)
|
|
|
|
|
+{
|
|
|
|
|
+ ptid_t last_ptid;
|
|
|
|
|
+ struct target_waitstatus last_status;
|
|
|
|
|
+ int has_vforked;
|
|
|
|
|
+ int parent_pid, child_pid;
|
|
|
|
|
+
|
|
|
|
|
+ get_last_target_status (&last_ptid, &last_status);
|
|
|
|
|
+ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
|
|
|
|
|
+ parent_pid = ptid_get_lwp (last_ptid);
|
|
|
|
|
+ if (parent_pid == 0)
|
|
|
|
|
+ parent_pid = ptid_get_pid (last_ptid);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+ child_pid = ptid_get_pid (last_status.value.related_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ if (! follow_child)
|
|
|
|
|
+ {
|
|
|
|
|
+ ia64_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if (! has_vforked)
|
|
|
|
|
+ ia64_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (*ia64_linux_super_follow_fork) (ops, follow_child);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void _initialize_ia64_linux_nat (void);
|
|
|
|
|
|
|
|
|
|
/*
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -901,6 +962,9 @@ _initialize_ia64_linux_nat (void)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
t->to_insert_watchpoint = ia64_linux_insert_watchpoint;
|
|
|
|
|
t->to_remove_watchpoint = ia64_linux_remove_watchpoint;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
|
|
|
|
|
+ ia64_linux_super_follow_fork = t->to_follow_fork;
|
|
|
|
|
+ t->to_follow_fork = ia64_linux_follow_fork;
|
|
|
|
|
+
|
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
linux_nat_set_new_thread (t, ia64_linux_new_thread);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/ppc-linux-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/ppc-linux-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/ppc-linux-nat.c 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -1377,6 +1377,12 @@ ppc_linux_insert_watchpoint (CORE_ADDR a
|
2008-03-03 16:13:47 +00:00
|
|
|
|
return 0;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child
|
|
|
|
|
+ process of traced FORK. We must clear such watchpoints only once during
|
|
|
|
|
+ DETACH_BREAKPOINTS. */
|
|
|
|
|
+
|
|
|
|
|
+static int ppc_linux_detach_breakpoints_pid;
|
|
|
|
|
+
|
|
|
|
|
static int
|
|
|
|
|
ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
|
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -1384,6 +1390,11 @@ ppc_linux_remove_watchpoint (CORE_ADDR a
|
2008-03-03 16:13:47 +00:00
|
|
|
|
ptid_t ptid;
|
|
|
|
|
long dabr_value = 0;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
|
|
|
|
|
+ if (ptid_get_pid (inferior_ptid) == ppc_linux_detach_breakpoints_pid)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */
|
|
|
|
|
+ ppc_linux_detach_breakpoints_pid = 0;
|
|
|
|
|
+
|
2008-03-03 16:13:47 +00:00
|
|
|
|
saved_dabr_value = 0;
|
|
|
|
|
ALL_LWPS (lp, ptid)
|
|
|
|
|
if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0)
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -1397,6 +1408,15 @@ ppc_linux_new_thread (ptid_t ptid)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void
|
|
|
|
|
+ppc_linux_detach_breakpoints (int detached_pid)
|
|
|
|
|
+{
|
|
|
|
|
+ ppc_linux_detach_breakpoints_pid = detached_pid;
|
|
|
|
|
+
|
|
|
|
|
+ /* Do not touch the SAVED_DABR_VALUE mirror here. */
|
|
|
|
|
+ ptrace (PTRACE_SET_DEBUGREG, detached_pid, 0, 0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static int
|
|
|
|
|
ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
|
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -1629,6 +1649,40 @@ ppc_linux_read_description (struct targe
|
2008-12-14 14:05:20 +00:00
|
|
|
|
return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int (*ppc_linux_super_follow_fork) (struct target_ops *ops,
|
|
|
|
|
+ int follow_child);
|
|
|
|
|
+
|
|
|
|
|
+/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its
|
|
|
|
|
+ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+ppc_linux_follow_fork (struct target_ops *ops, int follow_child)
|
|
|
|
|
+{
|
|
|
|
|
+ ptid_t last_ptid;
|
|
|
|
|
+ struct target_waitstatus last_status;
|
|
|
|
|
+ int has_vforked;
|
|
|
|
|
+ int parent_pid, child_pid;
|
|
|
|
|
+
|
|
|
|
|
+ get_last_target_status (&last_ptid, &last_status);
|
|
|
|
|
+ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
|
|
|
|
|
+ parent_pid = ptid_get_lwp (last_ptid);
|
|
|
|
|
+ if (parent_pid == 0)
|
|
|
|
|
+ parent_pid = ptid_get_pid (last_ptid);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+ child_pid = ptid_get_pid (last_status.value.related_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ if (! follow_child)
|
|
|
|
|
+ {
|
|
|
|
|
+ ppc_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if (! has_vforked)
|
|
|
|
|
+ ppc_linux_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (*ppc_linux_super_follow_fork) (ops, follow_child);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void _initialize_ppc_linux_nat (void);
|
|
|
|
|
|
|
|
|
|
void
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -1655,6 +1709,9 @@ _initialize_ppc_linux_nat (void)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
t->to_read_description = ppc_linux_read_description;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
t->to_auxv_parse = ppc_linux_auxv_parse;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
|
|
|
|
|
+ ppc_linux_super_follow_fork = t->to_follow_fork;
|
|
|
|
|
+ t->to_follow_fork = ppc_linux_follow_fork;
|
|
|
|
|
+
|
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
linux_nat_set_new_thread (t, ppc_linux_new_thread);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/s390-nat.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/s390-nat.c 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/s390-nat.c 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -285,21 +285,15 @@ s390_stopped_by_watchpoint (void)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-s390_fix_watch_points (ptid_t ptid)
|
2008-06-01 13:14:20 +00:00
|
|
|
|
+s390_fix_watch_points_list (int tid, struct watch_area *area_list)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
{
|
2008-03-03 16:13:47 +00:00
|
|
|
|
- int tid;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
-
|
|
|
|
|
per_struct per_info;
|
|
|
|
|
ptrace_area parea;
|
|
|
|
|
|
|
|
|
|
CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
|
|
|
|
|
struct watch_area *area;
|
|
|
|
|
|
2008-03-03 16:13:47 +00:00
|
|
|
|
- tid = TIDGET (ptid);
|
|
|
|
|
- if (tid == 0)
|
|
|
|
|
- tid = PIDGET (ptid);
|
|
|
|
|
-
|
2008-01-12 16:16:46 +00:00
|
|
|
|
- for (area = watch_base; area; area = area->next)
|
|
|
|
|
+ for (area = area_list; area; area = area->next)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
watch_lo_addr = min (watch_lo_addr, area->lo_addr);
|
|
|
|
|
watch_hi_addr = max (watch_hi_addr, area->hi_addr);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -311,7 +305,7 @@ s390_fix_watch_points (ptid_t ptid)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
|
|
|
|
|
perror_with_name (_("Couldn't retrieve watchpoint status"));
|
|
|
|
|
|
|
|
|
|
- if (watch_base)
|
|
|
|
|
+ if (area_list)
|
|
|
|
|
{
|
|
|
|
|
per_info.control_regs.bits.em_storage_alteration = 1;
|
|
|
|
|
per_info.control_regs.bits.storage_alt_space_ctl = 1;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -328,6 +322,18 @@ s390_fix_watch_points (ptid_t ptid)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
perror_with_name (_("Couldn't modify watchpoint status"));
|
|
|
|
|
}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+static void
|
|
|
|
|
+s390_fix_watch_points (ptid_t ptid)
|
|
|
|
|
+{
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+ int tid;
|
|
|
|
|
+
|
|
|
|
|
+ tid = TIDGET (ptid);
|
|
|
|
|
+ if (tid == 0)
|
|
|
|
|
+ tid = PIDGET (ptid);
|
|
|
|
|
+
|
|
|
|
|
+ s390_fix_watch_points_list (tid, watch_base);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
static int
|
2008-03-03 16:13:47 +00:00
|
|
|
|
s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
|
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -349,6 +355,12 @@ s390_insert_watchpoint (CORE_ADDR addr,
|
2008-01-12 16:16:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child
|
|
|
|
|
+ process of traced FORK. We must clear such watchpoints only once during
|
|
|
|
|
+ DETACH_BREAKPOINTS. */
|
|
|
|
|
+
|
|
|
|
|
+static int s390_detach_breakpoints_pid;
|
|
|
|
|
+
|
|
|
|
|
static int
|
|
|
|
|
s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -356,6 +368,11 @@ s390_remove_watchpoint (CORE_ADDR addr,
|
2008-03-03 16:13:47 +00:00
|
|
|
|
ptid_t ptid;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
struct watch_area *area, **parea;
|
|
|
|
|
|
|
|
|
|
+ if (ptid_get_pid (inferior_ptid) == s390_detach_breakpoints_pid)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */
|
|
|
|
|
+ s390_detach_breakpoints_pid = 0;
|
|
|
|
|
+
|
|
|
|
|
for (parea = &watch_base; *parea; parea = &(*parea)->next)
|
|
|
|
|
if ((*parea)->lo_addr == addr
|
|
|
|
|
&& (*parea)->hi_addr == addr + len - 1)
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -363,8 +380,10 @@ s390_remove_watchpoint (CORE_ADDR addr,
|
2008-08-28 18:48:34 +00:00
|
|
|
|
|
|
|
|
|
if (!*parea)
|
|
|
|
|
{
|
|
|
|
|
+#if 0 /* Red Hat fork/threads watchpoints changes may trigger it. */
|
|
|
|
|
fprintf_unfiltered (gdb_stderr,
|
|
|
|
|
"Attempt to remove nonexistent watchpoint.\n");
|
|
|
|
|
+#endif
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -377,6 +396,15 @@ s390_remove_watchpoint (CORE_ADDR addr,
|
2008-01-12 16:16:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void
|
|
|
|
|
+s390_detach_breakpoints (int detached_pid)
|
|
|
|
|
+{
|
|
|
|
|
+ s390_detach_breakpoints_pid = detached_pid;
|
|
|
|
|
+
|
|
|
|
|
+ /* Do not touch the WATCH_BASE here. */
|
|
|
|
|
+ s390_fix_watch_points_list (detached_pid, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static int
|
|
|
|
|
s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
|
|
|
|
|
{
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -389,6 +417,39 @@ s390_region_ok_for_hw_watchpoint (CORE_A
|
2008-03-03 16:13:47 +00:00
|
|
|
|
return 1;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int (*s390_super_follow_fork) (struct target_ops *ops, int follow_child);
|
|
|
|
|
+
|
|
|
|
|
+/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its
|
|
|
|
|
+ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+s390_follow_fork (struct target_ops *ops, int follow_child)
|
|
|
|
|
+{
|
|
|
|
|
+ ptid_t last_ptid;
|
|
|
|
|
+ struct target_waitstatus last_status;
|
|
|
|
|
+ int has_vforked;
|
|
|
|
|
+ int parent_pid, child_pid;
|
|
|
|
|
+
|
|
|
|
|
+ get_last_target_status (&last_ptid, &last_status);
|
|
|
|
|
+ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
|
|
|
|
|
+ parent_pid = ptid_get_lwp (last_ptid);
|
|
|
|
|
+ if (parent_pid == 0)
|
|
|
|
|
+ parent_pid = ptid_get_pid (last_ptid);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+ child_pid = ptid_get_pid (last_status.value.related_pid);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ if (! follow_child)
|
|
|
|
|
+ {
|
|
|
|
|
+ s390_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if (! has_vforked)
|
|
|
|
|
+ s390_detach_breakpoints (child_pid);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (*s390_super_follow_fork) (ops, follow_child);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
void _initialize_s390_nat (void);
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -412,6 +473,9 @@ _initialize_s390_nat (void)
|
2008-01-12 16:16:46 +00:00
|
|
|
|
t->to_insert_watchpoint = s390_insert_watchpoint;
|
|
|
|
|
t->to_remove_watchpoint = s390_remove_watchpoint;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ s390_super_follow_fork = t->to_follow_fork;
|
|
|
|
|
+ t->to_follow_fork = s390_follow_fork;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-03-03 16:13:47 +00:00
|
|
|
|
linux_nat_set_new_thread (t, s390_fix_watch_points);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
|
|
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c 2009-08-04 07:17:58.000000000 +0200
|
2008-03-30 22:15:14 +00:00
|
|
|
|
@@ -0,0 +1,172 @@
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ Copyright 2008
|
|
|
|
|
+ Free Software Foundation, Inc.
|
|
|
|
|
+
|
|
|
|
|
+ This file is part of GDB.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 2 of the License, or
|
|
|
|
|
+ (at your option) any later version.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 <string.h>
|
|
|
|
|
+#include <errno.h>
|
|
|
|
|
+
|
|
|
|
|
+static void delay (void)
|
|
|
|
|
+{
|
|
|
|
|
+ int i = usleep (1000000 / 100);
|
|
|
|
|
+ assert (i == 0 || errno == EINTR);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#if defined FOLLOW_PARENT
|
|
|
|
|
+
|
|
|
|
|
+static void forkoff (int nr)
|
|
|
|
|
+{
|
|
|
|
|
+ pid_t child, pid_got;
|
|
|
|
|
+ int exit_code = 42 + nr;
|
2008-03-30 22:15:14 +00:00
|
|
|
|
+ int status, i;
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ child = fork ();
|
|
|
|
|
+ switch (child)
|
|
|
|
|
+ {
|
|
|
|
|
+ case -1:
|
|
|
|
|
+ assert (0);
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ printf ("child%d: %d\n", nr, (int) getpid ());
|
2008-03-30 22:15:14 +00:00
|
|
|
|
+ /* Delay to get both the "child%d" and "parent%d" message printed without
|
|
|
|
|
+ a race breaking expect by its endless wait on `$gdb_prompt$':
|
|
|
|
|
+ Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33
|
|
|
|
|
+ 33 }
|
|
|
|
|
+ (gdb) parent2: 14223 */
|
|
|
|
|
+ i = sleep (1);
|
|
|
|
|
+ assert (i == 0);
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+ /* We must not get caught here (against a forgotten breakpoint). */
|
|
|
|
|
+ var++;
|
|
|
|
|
+ breakpoint ();
|
|
|
|
|
+
|
|
|
|
|
+ _exit (exit_code);
|
|
|
|
|
+ default:
|
|
|
|
|
+ printf ("parent%d: %d\n", nr, (int) child);
|
2008-03-30 22:15:14 +00:00
|
|
|
|
+ /* Delay to get both the "child%d" and "parent%d" message printed, see
|
|
|
|
|
+ above. */
|
|
|
|
|
+ i = sleep (1);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ pid_got = wait (&status);
|
|
|
|
|
+ assert (pid_got == child);
|
|
|
|
|
+ assert (WIFEXITED (status));
|
|
|
|
|
+ assert (WEXITSTATUS (status) == exit_code);
|
|
|
|
|
+
|
|
|
|
|
+ /* We must get caught here (against a false watchpoint removal). */
|
|
|
|
|
+ breakpoint ();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#elif defined FOLLOW_CHILD
|
|
|
|
|
+
|
|
|
|
|
+static volatile int usr1_got;
|
|
|
|
|
+
|
|
|
|
|
+static void handler_usr1 (int signo)
|
|
|
|
|
+{
|
|
|
|
|
+ usr1_got++;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void forkoff (int nr)
|
|
|
|
|
+{
|
|
|
|
|
+ pid_t child;
|
|
|
|
|
+ int i, loop;
|
|
|
|
|
+ struct sigaction act, oldact;
|
|
|
|
|
+#ifdef THREAD
|
|
|
|
|
+ void *thread_result;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ memset (&act, 0, sizeof act);
|
|
|
|
|
+ act.sa_flags = SA_RESTART;
|
|
|
|
|
+ act.sa_handler = handler_usr1;
|
|
|
|
|
+ sigemptyset (&act.sa_mask);
|
|
|
|
|
+ i = sigaction (SIGUSR1, &act, &oldact);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
|
|
|
|
+ child = fork ();
|
|
|
|
|
+ switch (child)
|
|
|
|
|
+ {
|
|
|
|
|
+ case -1:
|
|
|
|
|
+ assert (0);
|
|
|
|
|
+ default:
|
|
|
|
|
+ printf ("parent%d: %d\n", nr, (int) child);
|
|
|
|
|
+
|
|
|
|
|
+ /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB
|
|
|
|
|
+ tracing the child fork with no longer valid thread/lwp entries of the
|
|
|
|
|
+ parent. */
|
|
|
|
|
+
|
|
|
|
|
+ i = sleep (2);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
|
|
|
|
+ /* We must not get caught here (against a forgotten breakpoint). */
|
|
|
|
|
+
|
|
|
|
|
+ var++;
|
|
|
|
|
+ breakpoint ();
|
|
|
|
|
+
|
|
|
|
|
+#ifdef THREAD
|
|
|
|
|
+ /* And neither got caught our thread. */
|
|
|
|
|
+
|
|
|
|
|
+ step = 99;
|
|
|
|
|
+ i = pthread_join (thread, &thread_result);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+ assert (thread_result == (void *) 99UL);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ /* Be sure our child knows we did not get caught above. */
|
|
|
|
|
+
|
|
|
|
|
+ i = kill (child, SIGUSR1);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
|
|
|
|
+ /* Sleep for a while to check GDB's `info threads' no longer tracks us in
|
|
|
|
|
+ the child fork. */
|
|
|
|
|
+
|
|
|
|
|
+ i = sleep (2);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
|
|
|
|
+ _exit (0);
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ printf ("child%d: %d\n", nr, (int) getpid ());
|
|
|
|
|
+
|
|
|
|
|
+ /* Let the parent signal us about its success. Be careful of races. */
|
|
|
|
|
+
|
|
|
|
|
+ for (loop = 0; loop < 1000; loop++)
|
|
|
|
|
+ {
|
|
|
|
|
+ /* Parent either died (and USR1_GOT is zero) or it succeeded. */
|
|
|
|
|
+ if (kill (getppid (), 0) != 0)
|
|
|
|
|
+ break;
|
|
|
|
|
+ /* Parent succeeded? */
|
|
|
|
|
+ if (usr1_got)
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ delay ();
|
|
|
|
|
+ }
|
|
|
|
|
+ assert (usr1_got);
|
|
|
|
|
+
|
|
|
|
|
+ /* We must get caught here (against a false watchpoint removal). */
|
|
|
|
|
+
|
|
|
|
|
+ breakpoint ();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ i = sigaction (SIGUSR1, &oldact, NULL);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#else
|
|
|
|
|
+# error "!FOLLOW_PARENT && !FOLLOW_CHILD"
|
|
|
|
|
+#endif
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
|
|
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c 2009-08-04 07:17:58.000000000 +0200
|
2008-01-12 16:16:46 +00:00
|
|
|
|
@@ -0,0 +1,154 @@
|
|
|
|
|
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
|
|
|
|
|
+
|
|
|
|
|
+ Copyright 2008
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ Free Software Foundation, Inc.
|
|
|
|
|
+
|
|
|
|
|
+ This file is part of GDB.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 2 of the License, or
|
|
|
|
|
+ (at your option) any later version.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 <assert.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+#include <sys/wait.h>
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <stdlib.h>
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+#include <pthread.h>
|
|
|
|
|
+
|
|
|
|
|
+#include <asm/unistd.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+#define gettid() syscall (__NR_gettid)
|
|
|
|
|
+
|
|
|
|
|
+/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
|
|
|
|
|
+ variable. Hit-comments need to be duplicite there to catch both at-stops
|
|
|
|
|
+ and behind-stops, depending on the target. */
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
|
|
|
|
+static volatile int var;
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+static void dummy (void)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+static void breakpoint (void)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+/* Include here the functions:
|
|
|
|
|
+ static void forkoff (int nr);
|
|
|
|
|
+ static void delay (void); */
|
|
|
|
|
+
|
|
|
|
|
+static pthread_t thread;
|
|
|
|
|
+static volatile int step;
|
|
|
|
|
+#define THREAD
|
|
|
|
|
+
|
|
|
|
|
+#include "watchpoint-fork-forkoff.c"
|
|
|
|
|
+
|
|
|
|
|
+static void *start (void *arg)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ if (step >= 3)
|
|
|
|
|
+ goto step_3;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ while (step != 1)
|
|
|
|
|
+ delay ();
|
|
|
|
|
+
|
|
|
|
|
+ var++; /* validity-thread-B */
|
|
|
|
|
+ dummy (); /* validity-thread-B */
|
|
|
|
|
+ step = 2;
|
|
|
|
|
+ while (step != 3)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ {
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ if (step == 99)
|
|
|
|
|
+ goto step_99;
|
|
|
|
|
+ delay ();
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ }
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+
|
|
|
|
|
+step_3:
|
|
|
|
|
+ if (step >= 5)
|
|
|
|
|
+ goto step_5;
|
|
|
|
|
+
|
|
|
|
|
+ var++; /* after-fork1-B */
|
|
|
|
|
+ dummy (); /* after-fork1-B */
|
|
|
|
|
+ step = 4;
|
|
|
|
|
+ while (step != 5)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (step == 99)
|
|
|
|
|
+ goto step_99;
|
|
|
|
|
+ delay ();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+step_5:
|
|
|
|
|
+ var++; /* after-fork2-B */
|
|
|
|
|
+ dummy (); /* after-fork2-B */
|
|
|
|
|
+ return (void *) 5UL;
|
|
|
|
|
+
|
|
|
|
|
+step_99:
|
|
|
|
|
+ /* We must not get caught here (against a forgotten breakpoint). */
|
|
|
|
|
+ var++;
|
|
|
|
|
+ breakpoint ();
|
|
|
|
|
+ return (void *) 99UL;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int main (void)
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+{
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ int i;
|
|
|
|
|
+ void *thread_result;
|
|
|
|
|
+
|
|
|
|
|
+ setbuf (stdout, NULL);
|
|
|
|
|
+ printf ("main: %d\n", (int) gettid ());
|
|
|
|
|
+
|
|
|
|
|
+ /* General watchpoints validity. */
|
|
|
|
|
+ var++; /* validity-first */
|
|
|
|
|
+ dummy (); /* validity-first */
|
|
|
|
|
+
|
|
|
|
|
+ i = pthread_create (&thread, NULL, start, NULL);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+
|
|
|
|
|
+ var++; /* validity-thread-A */
|
|
|
|
|
+ dummy (); /* validity-thread-A */
|
|
|
|
|
+ step = 1;
|
|
|
|
|
+ while (step != 2)
|
|
|
|
|
+ delay ();
|
|
|
|
|
+
|
|
|
|
|
+ /* Hardware watchpoints got disarmed here. */
|
|
|
|
|
+ forkoff (1);
|
|
|
|
|
+
|
|
|
|
|
+ var++; /* after-fork1-A */
|
|
|
|
|
+ dummy (); /* after-fork1-A */
|
|
|
|
|
+ step = 3;
|
|
|
|
|
+#ifdef FOLLOW_CHILD
|
|
|
|
|
+ /* Spawn new thread as it was deleted in the child of FORK. */
|
|
|
|
|
+ i = pthread_create (&thread, NULL, start, NULL);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+#endif
|
|
|
|
|
+ while (step != 4)
|
|
|
|
|
+ delay ();
|
|
|
|
|
+
|
|
|
|
|
+ /* A sanity check for double hardware watchpoints removal. */
|
|
|
|
|
+ forkoff (2);
|
|
|
|
|
+
|
|
|
|
|
+ var++; /* after-fork2-A */
|
|
|
|
|
+ dummy (); /* after-fork2-A */
|
|
|
|
|
+ step = 5;
|
|
|
|
|
+#ifdef FOLLOW_CHILD
|
|
|
|
|
+ /* Spawn new thread as it was deleted in the child of FORK. */
|
|
|
|
|
+ i = pthread_create (&thread, NULL, start, NULL);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ i = pthread_join (thread, &thread_result);
|
|
|
|
|
+ assert (i == 0);
|
|
|
|
|
+ assert (thread_result == (void *) 5UL);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork.c
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
|
|
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork.c 2009-08-04 07:17:58.000000000 +0200
|
2008-01-12 16:16:46 +00:00
|
|
|
|
@@ -0,0 +1,56 @@
|
|
|
|
|
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
|
|
|
|
|
+
|
|
|
|
|
+ Copyright 2008
|
|
|
|
|
+ Free Software Foundation, Inc.
|
|
|
|
|
+
|
|
|
|
|
+ This file is part of GDB.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 2 of the License, or
|
|
|
|
|
+ (at your option) any later version.
|
|
|
|
|
+
|
|
|
|
|
+ This program 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 <assert.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+#include <sys/wait.h>
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <stdlib.h>
|
|
|
|
|
+
|
|
|
|
|
+static volatile int var;
|
|
|
|
|
+
|
|
|
|
|
+static void breakpoint (void)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Include here the function:
|
|
|
|
|
+ static void forkoff (int nr); */
|
|
|
|
|
+
|
|
|
|
|
+#include "watchpoint-fork-forkoff.c"
|
|
|
|
|
+
|
|
|
|
|
+int main (void)
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+{
|
|
|
|
|
+ setbuf (stdout, NULL);
|
|
|
|
|
+ printf ("main: %d\n", (int) getpid ());
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ /* General watchpoints validity. */
|
|
|
|
|
+ var++;
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+ /* Hardware watchpoints got disarmed here. */
|
|
|
|
|
+ forkoff (1);
|
|
|
|
|
+ /* This watchpoint got lost before. */
|
|
|
|
|
+ var++;
|
|
|
|
|
+ /* A sanity check for double hardware watchpoints removal. */
|
|
|
|
|
+ forkoff (2);
|
|
|
|
|
+ var++;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork.exp
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
|
|
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/testsuite/gdb.threads/watchpoint-fork.exp 2009-08-04 07:17:58.000000000 +0200
|
2008-01-12 16:16:46 +00:00
|
|
|
|
@@ -0,0 +1,140 @@
|
|
|
|
|
+# Copyright 2008 Free Software Foundation, Inc.
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
|
|
|
|
+# This program 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.
|
|
|
|
|
+#
|
|
|
|
|
+# This program 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+# Test case for forgotten hw-watchpoints after fork()-off of a process.
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+proc test {type symbol} {
|
|
|
|
|
+ global objdir subdir srcdir
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ global pf_prefix
|
|
|
|
|
+ set prefix_test $pf_prefix
|
|
|
|
|
+ lappend pf_prefix "$type:"
|
|
|
|
|
+ set prefix_mt $pf_prefix
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ # no threads
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ set pf_prefix $prefix_mt
|
|
|
|
|
+ lappend pf_prefix "singlethreaded:"
|
2007-10-14 20:11:42 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ set testfile watchpoint-fork
|
|
|
|
|
+ set srcfile ${testfile}.c
|
|
|
|
|
+ set binfile ${objdir}/${subdir}/${testfile}
|
|
|
|
|
+
|
|
|
|
|
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } {
|
|
|
|
|
+ untested "Couldn't compile test program"
|
|
|
|
|
+ return -1
|
|
|
|
|
+ }
|
2008-01-07 15:10:23 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ gdb_exit
|
|
|
|
|
+ gdb_start
|
|
|
|
|
+ gdb_reinitialize_dir $srcdir/$subdir
|
|
|
|
|
+ gdb_load ${binfile}
|
2008-01-07 15:10:23 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ gdb_test "set follow-fork-mode $type"
|
|
|
|
|
+ # Testcase uses it for the `follow-fork-mode child' type.
|
|
|
|
|
+ gdb_test "handle SIGUSR1 nostop noprint pass"
|
|
|
|
|
+
|
|
|
|
|
+ if { ![runto_main] } then {
|
|
|
|
|
+ gdb_suppress_tests
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
2008-01-07 15:10:23 +00:00
|
|
|
|
+
|
2008-01-12 16:16:46 +00:00
|
|
|
|
+ # Install the watchpoint only after getting into MAIN - workaround some PPC
|
|
|
|
|
+ # problem.
|
|
|
|
|
+ gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
|
|
|
|
|
+
|
|
|
|
|
+ # It is never hit but it should not be left over in the fork()ed-off child.
|
|
|
|
|
+ gdb_breakpoint "breakpoint"
|
|
|
|
|
+
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "reakpoint 3, breakpoint.*" "breakpoint after the first fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "reakpoint 3, breakpoint.*" "breakpoint after the second fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork"
|
|
|
|
|
+ gdb_test "continue" "Continuing..*Program exited normally." "finish"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ # threads
|
|
|
|
|
+
|
|
|
|
|
+ set pf_prefix $prefix_mt
|
|
|
|
|
+ lappend pf_prefix "multithreaded:"
|
|
|
|
|
+
|
|
|
|
|
+ set testfile watchpoint-fork-mt
|
|
|
|
|
+ set srcfile ${testfile}.c
|
|
|
|
|
+ set binfile ${objdir}/${subdir}/${testfile}
|
|
|
|
|
+
|
|
|
|
|
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } {
|
|
|
|
|
+ untested "Couldn't compile test program"
|
|
|
|
|
+ return -1
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ gdb_exit
|
|
|
|
|
+ gdb_start
|
|
|
|
|
+ gdb_reinitialize_dir $srcdir/$subdir
|
|
|
|
|
+ gdb_load ${binfile}
|
|
|
|
|
+
|
|
|
|
|
+ gdb_test "set follow-fork-mode $type"
|
|
|
|
|
+ # Testcase uses it for the `follow-fork-mode child' type.
|
|
|
|
|
+ gdb_test "handle SIGUSR1 nostop noprint pass"
|
|
|
|
|
+
|
|
|
|
|
+ if { ![runto_main] } then {
|
|
|
|
|
+ gdb_suppress_tests
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # Install the watchpoint only after getting into MAIN - workaround some PPC
|
|
|
|
|
+ # problem.
|
|
|
|
|
+ gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
|
|
|
|
|
+
|
|
|
|
|
+ # It is never hit but it should not be left over in the fork()ed-off child.
|
|
|
|
|
+ gdb_breakpoint "breakpoint"
|
|
|
|
|
+
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork"
|
|
|
|
|
+ gdb_test "continue" \
|
|
|
|
|
+ "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork"
|
|
|
|
|
+ gdb_test "continue" "Continuing..*Program exited normally." "finish"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ # cleanup
|
|
|
|
|
+
|
|
|
|
|
+ set pf_prefix $prefix_test
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+test parent FOLLOW_PARENT
|
|
|
|
|
+
|
|
|
|
|
+# Only GNU/Linux is known to support `set follow-fork-mode child'.
|
|
|
|
|
+if {[istarget "*-*-linux*"]} {
|
|
|
|
|
+ test child FOLLOW_CHILD
|
|
|
|
|
+}
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/doc/gdb.texinfo
|
2008-01-07 15:10:23 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/doc/gdb.texinfo 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/doc/gdb.texinfo 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -3625,6 +3625,14 @@ confident that no other thread can becom
|
2008-01-07 15:10:23 +00:00
|
|
|
|
software watchpoints as usual. However, @value{GDBN} may not notice
|
|
|
|
|
when a non-current thread's activity changes the expression. (Hardware
|
|
|
|
|
watchpoints, in contrast, watch an expression in all threads.)
|
|
|
|
|
+
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+Software watchpoints single-step the current thread to track the changes.
|
2008-01-07 15:10:23 +00:00
|
|
|
|
+Other threads are left freely running on @code{continue}; therefore, their
|
|
|
|
|
+changes cannot be caught. To get more reliable software watchpoints, please
|
|
|
|
|
+use @code{set scheduler-locking on}. The default for Red Hat/Fedora
|
|
|
|
|
+@value{GDBN} is @code{set scheduler-locking step}, which makes the software
|
|
|
|
|
+watchpoints safe for the @code{step} command, but not for the @code{continue}
|
|
|
|
|
+command. @xref{Thread Stops}.
|
|
|
|
|
@end quotation
|
|
|
|
|
|
|
|
|
|
@xref{set remote hardware-watchpoint-limit}.
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/config/i386/nm-linux.h
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/config/i386/nm-linux.h 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/config/i386/nm-linux.h 2009-08-04 07:17:58.000000000 +0200
|
|
|
|
|
@@ -29,4 +29,14 @@
|
|
|
|
|
#define FILL_FPXREGSET
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-03-03 16:13:47 +00:00
|
|
|
|
+/* Remove a watchpoint that watched the memory region which starts at
|
|
|
|
|
+ * address ADDR, whose length is LEN bytes, and for accesses of the
|
|
|
|
|
+ * type TYPE. Return 0 on success, -1 on failure. */
|
|
|
|
|
+extern int i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type);
|
|
|
|
|
+
|
|
|
|
|
+/* Override basic i386 macros for watchpoint and hardware breakpoint
|
|
|
|
|
+ insertion/removal to support threads. */
|
|
|
|
|
+#define target_remove_watchpoint(addr, len, type) \
|
|
|
|
|
+ i386_linux_remove_watchpoint (addr, len, type)
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+
|
|
|
|
|
#endif /* nm-linux.h */
|
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/config/i386/nm-linux64.h
|
2008-03-03 16:13:47 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/config/i386/nm-linux64.h 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/config/i386/nm-linux64.h 2009-08-04 07:17:58.000000000 +0200
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -51,4 +51,14 @@ extern unsigned long amd64_linux_dr_get_
|
2008-03-03 16:13:47 +00:00
|
|
|
|
#define I386_DR_LOW_GET_STATUS() \
|
|
|
|
|
amd64_linux_dr_get_status ()
|
|
|
|
|
|
|
|
|
|
+/* Remove a watchpoint that watched the memory region which starts at
|
|
|
|
|
+ * address ADDR, whose length is LEN bytes, and for accesses of the
|
|
|
|
|
+ * type TYPE. Return 0 on success, -1 on failure. */
|
|
|
|
|
+extern int amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type);
|
|
|
|
|
+
|
|
|
|
|
+/* Override basic amd64 macros for watchpoint and hardware breakpoint
|
|
|
|
|
+ insertion/removal to support threads. */
|
|
|
|
|
+#define target_remove_watchpoint(addr, len, type) \
|
|
|
|
|
+ amd64_linux_remove_watchpoint (addr, len, type)
|
|
|
|
|
+
|
|
|
|
|
#endif /* nm-linux64.h */
|
2009-08-04 05:37:29 +00:00
|
|
|
|
Index: gdb-6.8.50.20090803/gdb/target.h
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2009-08-04 05:37:29 +00:00
|
|
|
|
--- gdb-6.8.50.20090803.orig/gdb/target.h 2009-08-04 07:17:19.000000000 +0200
|
|
|
|
|
+++ gdb-6.8.50.20090803/gdb/target.h 2009-08-04 07:35:13.000000000 +0200
|
|
|
|
|
@@ -1114,11 +1114,15 @@ extern char *normal_pid_to_str (ptid_t p
|
|
|
|
|
for write, 1 for read, and 2 for read/write accesses. Returns 0 for
|
|
|
|
|
success, non-zero for failure. */
|
|
|
|
|
|
|
|
|
|
+#ifndef target_insert_watchpoint
|
2008-12-14 14:05:20 +00:00
|
|
|
|
#define target_insert_watchpoint(addr, len, type) \
|
|
|
|
|
(*current_target.to_insert_watchpoint) (addr, len, type)
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
+#ifndef target_remove_watchpoint
|
|
|
|
|
#define target_remove_watchpoint(addr, len, type) \
|
|
|
|
|
(*current_target.to_remove_watchpoint) (addr, len, type)
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
#define target_insert_hw_breakpoint(gdbarch, bp_tgt) \
|
|
|
|
|
(*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt)
|