This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 3/4] hw watchpoints kernel workaround


Hi,

there has been a change in upstream Linux kernels behavior.  Formerly newly
created processes/threads inherited the debug registers content.  Very
recently the new processes/threads get the debug registers cleared.

ptrace: watchpoint-fork (DR fork() inheritance)
https://bugzilla.redhat.com/show_bug.cgi?id=660003
http://sources.redhat.com/cgi-bin/cvsweb.cgi/tests/ptrace-tests/tests/Attic/watchpoint-fork.c?rev=1.3&cvsroot=systemtap
if $? == 0 then it is old-style kernel - debug registers get inherited
if $? == 1 then it is new-style kernel - debug registers get zeroed

In fact so far I do not know it would cause any problem.  It rather
workarounds a GDB bug described in [patch 2/4] (b).  For threads GDB is
already ensuring the right debug registers content:
	linux_nat_set_new_thread (t, amd64_linux_new_thread);

But together with the second change in upstream Linux kernels behavior:

ptrace: watchpoint-zeroaddr: EINVAL on PTRACE_POKEUSER of DR7
https://bugzilla.redhat.com/show_bug.cgi?id=660204
http://sources.redhat.com/cgi-bin/cvsweb.cgi/tests/ptrace-tests/tests/watchpoint-zeroaddr.c?rev=1.1&cvsroot=systemtap
if $? == 0 then it is old-style kernel - anything is allowed
if $? == 1 then it is new-style kernel - EINVAL given on invalid DRs state

there is a problem GDB tries to remove watchpoints from registers where are
already zeroes (due to the first kernel change/bug).  And despite GDB "safely"
tries to unset control register first and only then reset the address
registers still for 2+ watchpoints it causes the kernel EINVAL.

I tried to make GDB working with any combination of these two behavior changes
present as such kernels are already released in the wild.

Therefore here is the workaround.  It is needed only on the new-style kernels.
(scope: RHEL-6 is old-style, updated Fedora 13 is already new-style)

BTW these are upstream Linux kernel behavior changes unrelated to utrace.
I do not know exact kernel version/commit of the change(s).


Thanks,
Jan


gdb/
2010-12-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Workaround Linux kernel Bug - Red Hat Bugzilla #660204.
	* i386-nat.c (i386_remove_aligned_watchpoint): New variables
	inferior_pid and inf.
	<inf->pid != inferior_pid>: New.

--- a/gdb/i386-nat.c
+++ b/gdb/i386-nat.c
@@ -453,6 +453,24 @@ i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
 {
   struct dr_mirror *dr_mirror = dr_mirror_get ();
   int i, retval = -1;
+  int inferior_pid = ptid_get_pid (inferior_ptid);
+  struct inferior *inf = current_inferior ();
+
+  /* Are we detaching breakpoints from a fork-ed child?
+     See linux_nat_iterate_watchpoint_lwps.  */
+  if (inf->pid != inferior_pid)
+    {
+      int i;
+
+      /* Workaround some kernel versions reporting EINVAL on setting
+	 DR_CONTROL with still unset (and thus zero) DR_*ADDR registers.
+	 See: https://bugzilla.redhat.com/show_bug.cgi?id=660204
+	 It can happen as some kernel versions reset all DR registers to zero
+	 for the fork-ed child; other kernels copy them from the parent.  */
+
+      ALL_DEBUG_REGISTERS(i)
+	i386_dr_low.set_addr (i, dr_mirror->addr[i]);
+    }
 
   ALL_DEBUG_REGISTERS(i)
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]