Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andreas Arnez <arnez@linux.vnet.ibm.com>
To: gdb-patches@sourceware.org
Cc: Ulrich Weigand <uweigand@de.ibm.com>
Subject: [PATCH 3/6] S390: Multi-inferior watchpoint support
Date: Thu, 15 Sep 2016 12:01:00 -0000	[thread overview]
Message-ID: <1473940907-4449-2-git-send-email-arnez@linux.vnet.ibm.com> (raw)
In-Reply-To: <1473940399-2891-1-git-send-email-arnez@linux.vnet.ibm.com>

Support different sets of watchpoints in multiple inferiors.

gdb/ChangeLog:

	* s390-linux-nat.c (watch_areas): Remove variable.  Replace by a
	member of...
	(struct s390_debug_reg_state): ...this.  New struct.
	(struct s390_process_info): New struct.
	(s390_process_list): New variable.
	(s390_find_process_pid, s390_add_process, s390_process_info_get)
	(s390_get_debug_reg_state): New functions.
	(s390_stopped_by_watchpoint): Now access the watch_areas VEC via
	s390_get_debug_reg_state.
	(s390_prepare_to_resume): Likewise.
	(s390_insert_watchpoint): Likewise.
	(s390_remove_watchpoint): Likewise.
	(s390_forget_process, s390_linux_new_fork): New linux_nat target
	methods.
	(_initialize_s390_nat): Register them.
---
 gdb/s390-linux-nat.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 139 insertions(+), 10 deletions(-)

diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index 13bf7fd..b549246 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -430,8 +430,8 @@ s390_linux_store_inferior_registers (struct target_ops *ops,
 
 /* Hardware-assisted watchpoint handling.  */
 
-/* We maintain a list of all currently active watchpoints in order
-   to properly handle watchpoint removal.
+/* For each process we maintain a list of all currently active
+   watchpoints, in order to properly handle watchpoint removal.
 
    The only thing we actually need is the total address space area
    spanned by the watchpoints.  */
@@ -444,17 +444,138 @@ typedef struct watch_area
 
 DEF_VEC_O (s390_watch_area);
 
-VEC_s390_watch_area *watch_areas = NULL;
+/* Hardware debug state.  */
+
+struct s390_debug_reg_state
+{
+  VEC_s390_watch_area *watch_areas;
+};
+
+/* Per-process data.  */
+
+struct s390_process_info
+{
+  struct s390_process_info *next;
+  pid_t pid;
+  struct s390_debug_reg_state state;
+};
+
+static struct s390_process_info *s390_process_list = NULL;
+
+/* Find process data for process PID.  */
+
+static struct s390_process_info *
+s390_find_process_pid (pid_t pid)
+{
+  struct s390_process_info *proc;
+
+  for (proc = s390_process_list; proc; proc = proc->next)
+    if (proc->pid == pid)
+      return proc;
+
+  return NULL;
+}
+
+/* Add process data for process PID.  Returns newly allocated info
+   object.  */
+
+static struct s390_process_info *
+s390_add_process (pid_t pid)
+{
+  struct s390_process_info *proc = XCNEW (struct s390_process_info);
+
+  proc->pid = pid;
+  proc->next = s390_process_list;
+  s390_process_list = proc;
+
+  return proc;
+}
+
+/* Get data specific info for process PID, creating it if necessary.
+   Never returns NULL.  */
+
+static struct s390_process_info *
+s390_process_info_get (pid_t pid)
+{
+  struct s390_process_info *proc;
+
+  proc = s390_find_process_pid (pid);
+  if (proc == NULL)
+    proc = s390_add_process (pid);
+
+  return proc;
+}
+
+/* Get hardware debug state for process PID.  */
+
+static struct s390_debug_reg_state *
+s390_get_debug_reg_state (pid_t pid)
+{
+  return &s390_process_info_get (pid)->state;
+}
+
+/* Called whenever GDB is no longer debugging process PID.  It deletes
+   data structures that keep track of hardware debug state.  */
+
+static void
+s390_forget_process (pid_t pid)
+{
+  struct s390_process_info *proc, **proc_link;
+
+  proc = s390_process_list;
+  proc_link = &s390_process_list;
+
+  while (proc != NULL)
+    {
+      if (proc->pid == pid)
+	{
+	  VEC_free (s390_watch_area, proc->state.watch_areas);
+	  *proc_link = proc->next;
+	  xfree (proc);
+	  return;
+	}
+
+      proc_link = &proc->next;
+      proc = *proc_link;
+    }
+}
+
+/* linux_nat_new_fork hook.   */
+
+static void
+s390_linux_new_fork (struct lwp_info *parent, pid_t child_pid)
+{
+  pid_t parent_pid;
+  struct s390_debug_reg_state *parent_state;
+  struct s390_debug_reg_state *child_state;
+
+  /* NULL means no watchpoint has ever been set in the parent.  In
+     that case, there's nothing to do.  */
+  if (lwp_arch_private_info (parent) == NULL)
+    return;
+
+  /* GDB core assumes the child inherits the watchpoints/hw breakpoints of
+     the parent.  So copy the debug state from parent to child.  */
+
+  parent_pid = ptid_get_pid (parent->ptid);
+  parent_state = s390_get_debug_reg_state (parent_pid);
+  child_state = s390_get_debug_reg_state (child_pid);
+
+  child_state->watch_areas = VEC_copy (s390_watch_area,
+				       parent_state->watch_areas);
+}
 
 static int
 s390_stopped_by_watchpoint (struct target_ops *ops)
 {
+  struct s390_debug_reg_state *state
+    = s390_get_debug_reg_state (ptid_get_pid (inferior_ptid));
   per_lowcore_bits per_lowcore;
   ptrace_area parea;
   int result;
 
   /* Speed up common case.  */
-  if (VEC_empty (s390_watch_area, watch_areas))
+  if (VEC_empty (s390_watch_area, state->watch_areas))
     return 0;
 
   parea.len = sizeof (per_lowcore);
@@ -483,6 +604,7 @@ static void
 s390_prepare_to_resume (struct lwp_info *lp)
 {
   int tid;
+  pid_t pid = ptid_get_pid (ptid_of_lwp (lp));
 
   per_struct per_info;
   ptrace_area parea;
@@ -491,6 +613,7 @@ s390_prepare_to_resume (struct lwp_info *lp)
   unsigned ix;
   s390_watch_area *area;
   struct arch_lwp_info *lp_priv = lwp_arch_private_info (lp);
+  struct s390_debug_reg_state *state = s390_get_debug_reg_state (pid);
 
   if (lp_priv == NULL || !lp_priv->per_info_changed)
     return;
@@ -499,7 +622,7 @@ s390_prepare_to_resume (struct lwp_info *lp)
 
   tid = ptid_get_lwp (ptid_of_lwp (lp));
   if (tid == 0)
-    tid = ptid_get_pid (ptid_of_lwp (lp));
+    tid = pid;
 
   parea.len = sizeof (per_info);
   parea.process_addr = (addr_t) & per_info;
@@ -507,10 +630,10 @@ s390_prepare_to_resume (struct lwp_info *lp)
   if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, 0) < 0)
     perror_with_name (_("Couldn't retrieve watchpoint status"));
 
-  if (!VEC_empty (s390_watch_area, watch_areas))
+  if (!VEC_empty (s390_watch_area, state->watch_areas))
     {
       for (ix = 0;
-	   VEC_iterate (s390_watch_area, watch_areas, ix, area);
+	   VEC_iterate (s390_watch_area, state->watch_areas, ix, area);
 	   ix++)
 	{
 	  watch_lo_addr = min (watch_lo_addr, area->lo_addr);
@@ -580,10 +703,12 @@ s390_insert_watchpoint (struct target_ops *self,
 			struct expression *cond)
 {
   s390_watch_area area;
+  struct s390_debug_reg_state *state
+    = s390_get_debug_reg_state (ptid_get_pid (inferior_ptid));
 
   area.lo_addr = addr;
   area.hi_addr = addr + len - 1;
-  VEC_safe_push (s390_watch_area, watch_areas, &area);
+  VEC_safe_push (s390_watch_area, state->watch_areas, &area);
 
   return s390_refresh_per_info ();
 }
@@ -595,14 +720,16 @@ s390_remove_watchpoint (struct target_ops *self,
 {
   unsigned ix;
   s390_watch_area *area;
+  struct s390_debug_reg_state *state
+    = s390_get_debug_reg_state (ptid_get_pid (inferior_ptid));
 
   for (ix = 0;
-       VEC_iterate (s390_watch_area, watch_areas, ix, area);
+       VEC_iterate (s390_watch_area, state->watch_areas, ix, area);
        ix++)
     {
       if (area->lo_addr == addr && area->hi_addr == addr + len - 1)
 	{
-	  VEC_unordered_remove (s390_watch_area, watch_areas, ix);
+	  VEC_unordered_remove (s390_watch_area, state->watch_areas, ix);
 	  return s390_refresh_per_info ();
 	}
     }
@@ -753,4 +880,6 @@ _initialize_s390_nat (void)
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, s390_new_thread);
   linux_nat_set_prepare_to_resume (t, s390_prepare_to_resume);
+  linux_nat_set_forget_process (t, s390_forget_process);
+  linux_nat_set_new_fork (t, s390_linux_new_fork);
 }
-- 
2.5.0


  parent reply	other threads:[~2016-09-15 12:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-15 11:53 [PATCH 0/6] S390: Watchpoint enhancements and hardware breakpoints Andreas Arnez
2016-09-15 11:54 ` [PATCH] Fix order of inferiors in "thread apply all" Andreas Arnez
2016-09-15 12:03   ` Andreas Arnez
2016-09-15 11:59 ` [PATCH 1/6] S390: Avoid direct access to lwp_info structure Andreas Arnez
2016-09-15 12:01 ` Andreas Arnez [this message]
2016-09-15 12:02 ` [PATCH 6/6] S390: Hardware breakpoint support Andreas Arnez
2016-09-15 12:02 ` [PATCH 2/6] S390: Migrate watch areas from list to VEC type Andreas Arnez
2016-09-15 12:02 ` [PATCH 4/6] S390: Enable "maint set show-debug-regs" Andreas Arnez
2016-09-15 12:02 ` [PATCH 5/6] linux-nat: Add function lwp_is_stepping Andreas Arnez
2016-09-15 15:08   ` Yao Qi
2016-09-15 14:11 ` [PATCH 0/6] S390: Watchpoint enhancements and hardware breakpoints Pedro Alves
2016-09-16 12:43   ` Ulrich Weigand
2016-09-16 15:43     ` Pedro Alves
2016-09-16 17:30       ` Andreas Arnez
2016-09-15 14:58 ` Yao Qi
2016-09-15 17:14   ` Andreas Arnez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1473940907-4449-2-git-send-email-arnez@linux.vnet.ibm.com \
    --to=arnez@linux.vnet.ibm.com \
    --cc=gdb-patches@sourceware.org \
    --cc=uweigand@de.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox