public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-jankratochvil-watchpoint3: Provide workarounds for both RHBZ#660003 and RHBZ#660204.
@ 2010-12-06  3:54 jkratoch
  0 siblings, 0 replies; only message in thread
From: jkratoch @ 2010-12-06  3:54 UTC (permalink / raw)
  To: archer-commits

The branch, archer-jankratochvil-watchpoint3 has been updated
       via  0fb20226dad52db5c9a6a8bb0d3e308cbee76a6f (commit)
      from  f4b3b3c77e4892760da95092c082e26be011d617 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 0fb20226dad52db5c9a6a8bb0d3e308cbee76a6f
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Mon Dec 6 04:53:12 2010 +0100

    Provide workarounds for both RHBZ#660003 and RHBZ#660204.

-----------------------------------------------------------------------

Summary of changes:
 gdb/amd64-linux-nat.c |   85 +++++++++++++++++++++++++-----------------------
 gdb/linux-nat.c       |   46 ++++++++++++++++++++++++++
 gdb/linux-nat.h       |    5 +++
 3 files changed, 95 insertions(+), 41 deletions(-)

First 500 lines of diff:
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 03a0c74..c1e88a6 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -268,15 +268,10 @@ amd64_linux_store_inferior_registers (struct target_ops *ops,
 static unsigned long amd64_linux_dr[DR_CONTROL + 1];
 
 static unsigned long
-amd64_linux_dr_get (ptid_t ptid, int regnum)
+amd64_linux_dr_get (int tid, int regnum)
 {
-  int tid;
   unsigned long value;
 
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
-
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
      ptrace call fails breaks debugging remote targets.  The correct
      way to fix this is to add the hardware breakpoint and watchpoint
@@ -298,14 +293,8 @@ amd64_linux_dr_get (ptid_t ptid, int regnum)
 /* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
 
 static void
-amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+amd64_linux_dr_set (int tid, int regnum, unsigned long value)
 {
-  int tid;
-
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
-
   errno = 0;
   ptrace (PTRACE_POKEUSER, tid,
 	  offsetof (struct user, u_debugreg[regnum]), value);
@@ -315,15 +304,26 @@ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
 
 /* Helper for amd64_linux_dr_set_control.  */
 
-static int
-amd64_linux_dr_set_control_callback (struct lwp_info *lp, void *control_voidp)
+static void
+amd64_linux_dr_set_control_callback (int tid, void *control_voidp)
 {
   unsigned long control = (unsigned long) control_voidp;
+  int inferior_pid = ptid_get_pid (inferior_ptid);
+  struct inferior *inf = current_inferior ();
+
+  if (inf->pid != inferior_pid)
+    {
+      int i;
+
+      /* Workaround some kernel versions reporting EINVAL on setting
+         DR_CONTROL with still unset DR_*ADDR registers.
+         See: https://bugzilla.redhat.com/show_bug.cgi?id=660204  */
 
-  amd64_linux_dr_set (lp->ptid, DR_CONTROL, control);
+      for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+	amd64_linux_dr_set (tid, i, amd64_linux_dr[i]);
+    }
 
-  /* Continue the traversal.  */
-  return 0;
+  amd64_linux_dr_set (tid, DR_CONTROL, control);
 }
 
 /* Set DR_CONTROL to ADDR in all LWPs of CURRENT_INFERIOR.  */
@@ -333,8 +333,8 @@ amd64_linux_dr_set_control (unsigned long control)
 {
   amd64_linux_dr[DR_CONTROL] = control;
 
-  iterate_over_lwps (pid_to_ptid (GET_PID (inferior_ptid)),
-		     amd64_linux_dr_set_control_callback, (void *) control);
+  linux_nat_iterate_watchpoint_lwps (amd64_linux_dr_set_control_callback,
+				     (void *) control);
 }
 
 /* Helper for amd64_linux_dr_set_addr.  */
@@ -345,15 +345,12 @@ struct amd64_linux_dr_set_addr_data
     CORE_ADDR addr;
   };
 
-static int
-amd64_linux_dr_set_addr_callback (struct lwp_info *lp, void *datap_voidp)
+static void
+amd64_linux_dr_set_addr_callback (int tid, void *datap_voidp)
 {
   const struct amd64_linux_dr_set_addr_data *datap = datap_voidp;
 
-  amd64_linux_dr_set (lp->ptid, DR_FIRSTADDR + datap->regnum, datap->addr);
-
-  /* Continue the traversal.  */
-  return 0;
+  amd64_linux_dr_set (tid, DR_FIRSTADDR + datap->regnum, datap->addr);
 }
 
 /* Set address REGNUM (zero based) to ADDR in all LWPs of CURRENT_INFERIOR.
@@ -370,8 +367,7 @@ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
 
   data.regnum = regnum;
   data.addr = addr;
-  iterate_over_lwps (pid_to_ptid (GET_PID (inferior_ptid)),
-		     amd64_linux_dr_set_addr_callback, &data);
+  linux_nat_iterate_watchpoint_lwps (amd64_linux_dr_set_addr_callback, &data);
 }
 
 /* Set address REGNUM (zero based) to zero in all LWPs of CURRENT_INFERIOR.
@@ -388,23 +384,26 @@ amd64_linux_dr_reset_addr (int regnum)
 static unsigned long
 amd64_linux_dr_get_status (void)
 {
-  return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
+  int tid;
+
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
+
+  return amd64_linux_dr_get (tid, DR_STATUS);
 }
 
 /* Helper for amd64_linux_dr_unset_status.  */
 
-static int
-amd64_linux_dr_unset_status_callback (struct lwp_info *lp, void *mask_voidp)
+static void
+amd64_linux_dr_unset_status_callback (int tid, void *mask_voidp)
 {
   unsigned long mask = (unsigned long) mask_voidp;
   unsigned long value;
       
-  value = amd64_linux_dr_get (lp->ptid, DR_STATUS);
+  value = amd64_linux_dr_get (tid, DR_STATUS);
   value &= ~mask;
-  amd64_linux_dr_set (lp->ptid, DR_STATUS, value);
-
-  /* Continue the traversal.  */
-  return 0;
+  amd64_linux_dr_set (tid, DR_STATUS, value);
 }
 
 /* Unset MASK bits in DR_STATUS in all LWPs of CURRENT_INFERIOR.  */
@@ -412,19 +411,23 @@ amd64_linux_dr_unset_status_callback (struct lwp_info *lp, void *mask_voidp)
 static void
 amd64_linux_dr_unset_status (unsigned long mask)
 {
-  iterate_over_lwps (pid_to_ptid (GET_PID (inferior_ptid)),
-		     amd64_linux_dr_unset_status_callback, (void *) mask);
+  linux_nat_iterate_watchpoint_lwps (amd64_linux_dr_unset_status_callback,
+				     (void *) mask);
 }
 
 static void
 amd64_linux_new_thread (ptid_t ptid)
 {
-  int i;
+  int i, tid;
+
+  tid = TIDGET (ptid);
+  if (tid == 0)
+    tid = PIDGET (ptid);
 
   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
-    amd64_linux_dr_set (ptid, i, amd64_linux_dr[i]);
+    amd64_linux_dr_set (tid, i, amd64_linux_dr[i]);
 
-  amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
+  amd64_linux_dr_set (tid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
 }
 \f
 
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 56490cc..6794517 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1243,6 +1243,52 @@ iterate_over_lwps (ptid_t filter,
   return NULL;
 }
 
+/* Helper for linux_nat_iterate_watchpoint_lwps.  */
+
+struct iterate_watchpoint_lwps_data
+  {
+    linux_nat_iterate_watchpoint_lwps_ftype callback;
+    void *callback_data;
+  };
+
+static int
+iterate_watchpoint_lwps_callback (struct lwp_info *lp, void *datap_voidp)
+{
+  struct iterate_watchpoint_lwps_data *datap = datap_voidp;
+  int tid;
+
+  tid = TIDGET (lp->ptid);
+  if (tid == 0)
+    tid = PIDGET (lp->ptid);
+
+  datap->callback (tid, datap->callback_data);
+
+  /* Continue the traversal.  */
+  return 0;
+}
+
+/* Iterate the same style like iterate_over_lwps does except when forking-off
+   a child call CALLBACK with CALLBACK_DATA specifically only for that new
+   child PID.  */
+
+void
+linux_nat_iterate_watchpoint_lwps
+  (linux_nat_iterate_watchpoint_lwps_ftype callback, void *callback_data)
+{
+  struct iterate_watchpoint_lwps_data data;
+  int inferior_pid = ptid_get_pid (inferior_ptid);
+  struct inferior *inf = current_inferior ();
+
+  data.callback = callback;
+  data.callback_data = callback_data;
+
+  if (inf->pid == inferior_pid)
+    iterate_over_lwps (pid_to_ptid (inferior_pid),
+		       iterate_watchpoint_lwps_callback, &data);
+  else
+    callback (inferior_pid, callback_data);
+}
+
 /* Update our internal state when changing from one checkpoint to
    another indicated by NEW_PTID.  We can only switch single-threaded
    applications, so we only create one new LWP, and the previous list
diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
index 64393fd..a053cbd 100644
--- a/gdb/linux-nat.h
+++ b/gdb/linux-nat.h
@@ -139,6 +139,11 @@ struct lwp_info *iterate_over_lwps (ptid_t filter,
 						     void *), 
 				    void *data);
 
+typedef void (*linux_nat_iterate_watchpoint_lwps_ftype) (int tid, void *data);
+
+extern void linux_nat_iterate_watchpoint_lwps
+  (linux_nat_iterate_watchpoint_lwps_ftype callback, void *callback_data);
+
 /* Create a prototype generic GNU/Linux target.  The client can
    override it with local methods.  */
 struct target_ops * linux_target (void);


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-12-06  3:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-06  3:54 [SCM] archer-jankratochvil-watchpoint3: Provide workarounds for both RHBZ#660003 and RHBZ#660204 jkratoch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).