add "this" pointers to more target APIs
[deliverable/binutils-gdb.git] / gdb / i386-nat.c
index 82c51d70c20d2d3e41f55aa71a50f3517431967d..23edc38a4044184cf64fd3e8b27caeebbadcbb5c 100644 (file)
@@ -1,7 +1,6 @@
 /* Native-dependent code for the i386.
 
-   Copyright (C) 2001, 2004, 2005, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2001-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include "i386-nat.h"
 #include "defs.h"
+#include "i386-nat.h"
 #include "breakpoint.h"
 #include "command.h"
 #include "gdbcmd.h"
 #include "target.h"
 #include "gdb_assert.h"
+#include "inferior.h"
 
 /* Support for hardware watchpoints and breakpoints using the i386
    debug registers.
@@ -43,11 +43,6 @@ struct i386_dr_low_type i386_dr_low;
 /* Support for 8-byte wide hw watchpoints.  */
 #define TARGET_HAS_DR_LEN_8 (i386_dr_low.debug_register_length == 8)
 
-/* Debug registers' indices.  */
-#define DR_NADDR       4       /* The number of debug address registers.  */
-#define DR_STATUS      6       /* Index of debug status register (DR6).  */
-#define DR_CONTROL     7       /* Index of debug control register (DR7). */
-
 /* DR7 Debug Control register fields.  */
 
 /* How many bits to skip in DR7 to get to R/W and LEN fields.  */
@@ -111,48 +106,150 @@ struct i386_dr_low_type i386_dr_low;
 
 /* The I'th debug register is vacant if its Local and Global Enable
    bits are reset in the Debug Control register.  */
-#define I386_DR_VACANT(i) \
-  ((dr_control_mirror & (3 << (DR_ENABLE_SIZE * (i)))) == 0)
+#define I386_DR_VACANT(state, i)                                       \
+  (((state)->dr_control_mirror & (3 << (DR_ENABLE_SIZE * (i)))) == 0)
 
 /* Locally enable the break/watchpoint in the I'th debug register.  */
-#define I386_DR_LOCAL_ENABLE(i) \
-  dr_control_mirror |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
+#define I386_DR_LOCAL_ENABLE(state, i) \
+  do { \
+    (state)->dr_control_mirror |= \
+      (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \
+  } while (0)
 
 /* Globally enable the break/watchpoint in the I'th debug register.  */
-#define I386_DR_GLOBAL_ENABLE(i) \
-  dr_control_mirror |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
+#define I386_DR_GLOBAL_ENABLE(state, i) \
+  do { \
+    (state)->dr_control_mirror |= \
+      (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \
+  } while (0)
 
 /* Disable the break/watchpoint in the I'th debug register.  */
-#define I386_DR_DISABLE(i) \
-  dr_control_mirror &= ~(3 << (DR_ENABLE_SIZE * (i)))
+#define I386_DR_DISABLE(state, i) \
+  do { \
+    (state)->dr_control_mirror &= \
+      ~(3 << (DR_ENABLE_SIZE * (i))); \
+  } while (0)
 
 /* Set in DR7 the RW and LEN fields for the I'th debug register.  */
-#define I386_DR_SET_RW_LEN(i,rwlen) \
+#define I386_DR_SET_RW_LEN(state, i, rwlen) \
   do { \
-    dr_control_mirror &= ~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i)));   \
-    dr_control_mirror |= ((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \
+    (state)->dr_control_mirror &= \
+      ~(0x0f << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \
+    (state)->dr_control_mirror |= \
+      ((rwlen) << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \
   } while (0)
 
 /* Get from DR7 the RW and LEN fields for the I'th debug register.  */
-#define I386_DR_GET_RW_LEN(i) \
-  ((dr_control_mirror >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
+#define I386_DR_GET_RW_LEN(dr7, i) \
+  (((dr7) \
+    >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
 
 /* Mask that this I'th watchpoint has triggered.  */
 #define I386_DR_WATCH_MASK(i)  (1 << (i))
 
 /* Did the watchpoint whose address is in the I'th register break?  */
-#define I386_DR_WATCH_HIT(i)   (dr_status_mirror & I386_DR_WATCH_MASK (i))
+#define I386_DR_WATCH_HIT(dr6, i) ((dr6) & (1 << (i)))
 
 /* A macro to loop over all debug registers.  */
 #define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++)
 
-/* Mirror the inferior's DRi registers.  We keep the status and
-   control registers separated because they don't hold addresses.  */
-static CORE_ADDR dr_mirror[DR_NADDR];
-static unsigned long dr_status_mirror, dr_control_mirror;
+/* Per-process data.  We don't bind this to a per-inferior registry
+   because of targets like x86 GNU/Linux that need to keep track of
+   processes that aren't bound to any inferior (e.g., fork children,
+   checkpoints).  */
+
+struct i386_process_info
+{
+  /* Linked list.  */
+  struct i386_process_info *next;
+
+  /* The process identifier.  */
+  pid_t pid;
+
+  /* Copy of i386 hardware debug registers.  */
+  struct i386_debug_reg_state state;
+};
+
+static struct i386_process_info *i386_process_list = NULL;
+
+/* Find process data for process PID.  */
+
+static struct i386_process_info *
+i386_find_process_pid (pid_t pid)
+{
+  struct i386_process_info *proc;
+
+  for (proc = i386_process_list; proc; proc = proc->next)
+    if (proc->pid == pid)
+      return proc;
+
+  return NULL;
+}
 
-/* Reference counts for each debug register.  */
-static int dr_ref_count[DR_NADDR];
+/* Add process data for process PID.  Returns newly allocated info
+   object.  */
+
+static struct i386_process_info *
+i386_add_process (pid_t pid)
+{
+  struct i386_process_info *proc;
+
+  proc = xcalloc (1, sizeof (*proc));
+  proc->pid = pid;
+
+  proc->next = i386_process_list;
+  i386_process_list = proc;
+
+  return proc;
+}
+
+/* Get data specific info for process PID, creating it if necessary.
+   Never returns NULL.  */
+
+static struct i386_process_info *
+i386_process_info_get (pid_t pid)
+{
+  struct i386_process_info *proc;
+
+  proc = i386_find_process_pid (pid);
+  if (proc == NULL)
+    proc = i386_add_process (pid);
+
+  return proc;
+}
+
+/* Get debug registers state for process PID.  */
+
+struct i386_debug_reg_state *
+i386_debug_reg_state (pid_t pid)
+{
+  return &i386_process_info_get (pid)->state;
+}
+
+/* See declaration in i386-nat.h.  */
+
+void
+i386_forget_process (pid_t pid)
+{
+  struct i386_process_info *proc, **proc_link;
+
+  proc = i386_process_list;
+  proc_link = &i386_process_list;
+
+  while (proc != NULL)
+    {
+      if (proc->pid == pid)
+       {
+         *proc_link = proc->next;
+
+         xfree (proc);
+         return;
+       }
+
+      proc_link = &proc->next;
+      proc = *proc_link;
+    }
+}
 
 /* Whether or not to print the mirrored debug registers.  */
 static int maint_show_dr;
@@ -172,7 +269,8 @@ static unsigned i386_length_and_rw_bits (int len, enum target_hw_bp_type type);
    value of the bit-field from DR7 which describes the length and
    access type of the region to be watched by this watchpoint.  Return
    0 on success, -1 on failure.  */
-static int i386_insert_aligned_watchpoint (CORE_ADDR addr,
+static int i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state,
+                                          CORE_ADDR addr,
                                           unsigned len_rw_bits);
 
 /* Remove a watchpoint at address ADDR, which is assumed to be aligned
@@ -180,7 +278,8 @@ static int i386_insert_aligned_watchpoint (CORE_ADDR addr,
    value of the bits from DR7 which describes the length and access
    type of the region watched by this watchpoint.  Return 0 on
    success, -1 on failure.  */
-static int i386_remove_aligned_watchpoint (CORE_ADDR addr,
+static int i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state,
+                                          CORE_ADDR addr,
                                           unsigned len_rw_bits);
 
 /* Insert or remove a (possibly non-aligned) watchpoint, or count the
@@ -189,7 +288,8 @@ static int i386_remove_aligned_watchpoint (CORE_ADDR addr,
    successful insertion or removal, a positive number when queried
    about the number of registers, or -1 on failure.  If WHAT is not a
    valid value, bombs through internal_error.  */
-static int i386_handle_nonaligned_watchpoint (i386_wp_op_t what,
+static int i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state,
+                                             i386_wp_op_t what,
                                              CORE_ADDR addr, int len,
                                              enum target_hw_bp_type type);
 
@@ -201,15 +301,8 @@ static int i386_handle_nonaligned_watchpoint (i386_wp_op_t what,
 void
 i386_cleanup_dregs (void)
 {
-  int i;
-
-  ALL_DEBUG_REGISTERS(i)
-    {
-      dr_mirror[i] = 0;
-      dr_ref_count[i] = 0;
-    }
-  dr_control_mirror = 0;
-  dr_status_mirror  = 0;
+  /* Starting from scratch has the same effect.  */
+  i386_forget_process (ptid_get_pid (inferior_ptid));
 }
 
 /* Print the values of the mirrored debug registers.  This is called
@@ -217,10 +310,11 @@ i386_cleanup_dregs (void)
    show-debug-regs" at GDB's prompt.  */
 
 static void
-i386_show_dr (const char *func, CORE_ADDR addr,
+i386_show_dr (struct i386_debug_reg_state *state,
+             const char *func, CORE_ADDR addr,
              int len, enum target_hw_bp_type type)
 {
-  int addr_size = gdbarch_addr_bit (target_gdbarch) / 8;
+  int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
   int i;
 
   puts_unfiltered (func);
@@ -239,13 +333,16 @@ i386_show_dr (const char *func, CORE_ADDR addr,
                                : "??unknown??"))));
   puts_unfiltered (":\n");
   printf_unfiltered ("\tCONTROL (DR7): %s          STATUS (DR6): %s\n",
-                    phex (dr_control_mirror, 8), phex (dr_status_mirror, 8));
+                    phex (state->dr_control_mirror, 8),
+                    phex (state->dr_status_mirror, 8));
   ALL_DEBUG_REGISTERS(i)
     {
       printf_unfiltered ("\
 \tDR%d: addr=0x%s, ref.count=%d  DR%d: addr=0x%s, ref.count=%d\n",
-                i, phex (dr_mirror[i], addr_size), dr_ref_count[i],
-                i+1, phex (dr_mirror[i+1], addr_size), dr_ref_count[i+1]);
+                        i, phex (state->dr_mirror[i], addr_size),
+                        state->dr_ref_count[i],
+                        i + 1, phex (state->dr_mirror[i + 1], addr_size),
+                        state->dr_ref_count[i+1]);
       i++;
     }
 }
@@ -269,7 +366,8 @@ i386_length_and_rw_bits (int len, enum target_hw_bp_type type)
        break;
       case hw_read:
        internal_error (__FILE__, __LINE__,
-                       _("The i386 doesn't support data-read watchpoints.\n"));
+                       _("The i386 doesn't support "
+                         "data-read watchpoints.\n"));
       case hw_access:
        rw = DR_RW_READ;
        break;
@@ -296,6 +394,7 @@ Invalid hardware breakpoint type %d in i386_length_and_rw_bits.\n"),
       case 8:
         if (TARGET_HAS_DR_LEN_8)
          return (DR_LEN_8 | rw);
+       /* ELSE FALL THROUGH */
       default:
        internal_error (__FILE__, __LINE__, _("\
 Invalid hardware breakpoint length %d in i386_length_and_rw_bits.\n"), len);
@@ -309,7 +408,8 @@ Invalid hardware breakpoint length %d in i386_length_and_rw_bits.\n"), len);
    success, -1 on failure.  */
 
 static int
-i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state,
+                               CORE_ADDR addr, unsigned len_rw_bits)
 {
   int i;
 
@@ -321,11 +421,11 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
      reuse it for this watchpoint as well (and save a register).  */
   ALL_DEBUG_REGISTERS(i)
     {
-      if (!I386_DR_VACANT (i)
-         && dr_mirror[i] == addr
-         && I386_DR_GET_RW_LEN (i) == len_rw_bits)
+      if (!I386_DR_VACANT (state, i)
+         && state->dr_mirror[i] == addr
+         && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
        {
-         dr_ref_count[i]++;
+         state->dr_ref_count[i]++;
          return 0;
        }
     }
@@ -333,7 +433,7 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
   /* Next, look for a vacant debug register.  */
   ALL_DEBUG_REGISTERS(i)
     {
-      if (I386_DR_VACANT (i))
+      if (I386_DR_VACANT (state, i))
        break;
     }
 
@@ -344,9 +444,9 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
   /* Now set up the register I to watch our region.  */
 
   /* Record the info in our local mirrored array.  */
-  dr_mirror[i] = addr;
-  dr_ref_count[i] = 1;
-  I386_DR_SET_RW_LEN (i, len_rw_bits);
+  state->dr_mirror[i] = addr;
+  state->dr_ref_count[i] = 1;
+  I386_DR_SET_RW_LEN (state, i, len_rw_bits);
   /* Note: we only enable the watchpoint locally, i.e. in the current
      task.  Currently, no i386 target allows or supports global
      watchpoints; however, if any target would want that in the
@@ -354,17 +454,9 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
      to enable watchpoints globally or locally, and the code below
      should use global or local enable and slow-down flags as
      appropriate.  */
-  I386_DR_LOCAL_ENABLE (i);
-  dr_control_mirror |= DR_LOCAL_SLOWDOWN;
-  dr_control_mirror &= I386_DR_CONTROL_MASK;
-
-  /* Finally, actually pass the info to the inferior.  */
-  i386_dr_low.set_addr (i, addr);
-  i386_dr_low.set_control (dr_control_mirror);
-
-  /* Only a sanity check for leftover bits (set possibly only by inferior).  */
-  if (i386_dr_low.unset_status)
-    i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
+  I386_DR_LOCAL_ENABLE (state, i);
+  state->dr_control_mirror |= DR_LOCAL_SLOWDOWN;
+  state->dr_control_mirror &= I386_DR_CONTROL_MASK;
 
   return 0;
 }
@@ -376,25 +468,22 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
    success, -1 on failure.  */
 
 static int
-i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state,
+                               CORE_ADDR addr, unsigned len_rw_bits)
 {
   int i, retval = -1;
 
   ALL_DEBUG_REGISTERS(i)
     {
-      if (!I386_DR_VACANT (i)
-         && dr_mirror[i] == addr
-         && I386_DR_GET_RW_LEN (i) == len_rw_bits)
+      if (!I386_DR_VACANT (state, i)
+         && state->dr_mirror[i] == addr
+         && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
        {
-         if (--dr_ref_count[i] == 0) /* no longer in use? */
+         if (--state->dr_ref_count[i] == 0) /* no longer in use?  */
            {
              /* Reset our mirror.  */
-             dr_mirror[i] = 0;
-             I386_DR_DISABLE (i);
-             /* Reset it in the inferior.  */
-             i386_dr_low.set_control (dr_control_mirror);
-             if (i386_dr_low.reset_addr)
-               i386_dr_low.reset_addr (i);
+             state->dr_mirror[i] = 0;
+             I386_DR_DISABLE (state, i);
            }
          retval = 0;
        }
@@ -411,10 +500,11 @@ i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
    valid value, bombs through internal_error.  */
 
 static int
-i386_handle_nonaligned_watchpoint (i386_wp_op_t what, CORE_ADDR addr, int len,
+i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state,
+                                  i386_wp_op_t what, CORE_ADDR addr, int len,
                                   enum target_hw_bp_type type)
 {
-  int retval = 0, status = 0;
+  int retval = 0;
   int max_wp_len = TARGET_HAS_DR_LEN_8 ? 8 : 4;
 
   static int size_try_array[8][8] =
@@ -452,24 +542,15 @@ i386_handle_nonaligned_watchpoint (i386_wp_op_t what, CORE_ADDR addr, int len,
          unsigned len_rw = i386_length_and_rw_bits (size, type);
 
          if (what == WP_INSERT)
-           status = i386_insert_aligned_watchpoint (addr, len_rw);
+           retval = i386_insert_aligned_watchpoint (state, addr, len_rw);
          else if (what == WP_REMOVE)
-           status = i386_remove_aligned_watchpoint (addr, len_rw);
+           retval = i386_remove_aligned_watchpoint (state, addr, len_rw);
          else
            internal_error (__FILE__, __LINE__, _("\
 Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n"),
                            (int)what);
-         /* We keep the loop going even after a failure, because some
-            of the other aligned watchpoints might still succeed
-            (e.g. if they watch addresses that are already watched,
-            in which case we just increment the reference counts of
-            occupied debug registers).  If we break out of the loop
-            too early, we could cause those addresses watched by
-            other watchpoints to be disabled when breakpoint.c reacts
-            to our failure to insert this watchpoint and tries to
-            remove it.  */
-         if (status)
-           retval = status;
+         if (retval)
+           break;
        }
 
       addr += size;
@@ -479,30 +560,65 @@ Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n"),
   return retval;
 }
 
+/* Update the inferior's debug registers with the new debug registers
+   state, in NEW_STATE, and then update our local mirror to match.  */
+
+static void
+i386_update_inferior_debug_regs (struct i386_debug_reg_state *new_state)
+{
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
+  int i;
+
+  ALL_DEBUG_REGISTERS (i)
+    {
+      if (I386_DR_VACANT (new_state, i) != I386_DR_VACANT (state, i))
+       i386_dr_low.set_addr (i, new_state->dr_mirror[i]);
+      else
+       gdb_assert (new_state->dr_mirror[i] == state->dr_mirror[i]);
+    }
+
+  if (new_state->dr_control_mirror != state->dr_control_mirror)
+    i386_dr_low.set_control (new_state->dr_control_mirror);
+
+  *state = *new_state;
+}
+
 /* Insert a watchpoint to watch a memory region which starts at
    address ADDR and whose length is LEN bytes.  Watch memory accesses
    of the type TYPE.  Return 0 on success, -1 on failure.  */
 
 static int
-i386_insert_watchpoint (CORE_ADDR addr, int len, int type)
+i386_insert_watchpoint (CORE_ADDR addr, int len, int type,
+                       struct expression *cond)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   int retval;
+  /* Work on a local copy of the debug registers, and on success,
+     commit the change back to the inferior.  */
+  struct i386_debug_reg_state local_state = *state;
 
   if (type == hw_read)
     return 1; /* unsupported */
 
   if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8))
       || addr % len != 0)
-    retval = i386_handle_nonaligned_watchpoint (WP_INSERT, addr, len, type);
+    retval = i386_handle_nonaligned_watchpoint (&local_state,
+                                               WP_INSERT, addr, len, type);
   else
     {
       unsigned len_rw = i386_length_and_rw_bits (len, type);
 
-      retval = i386_insert_aligned_watchpoint (addr, len_rw);
+      retval = i386_insert_aligned_watchpoint (&local_state,
+                                              addr, len_rw);
     }
 
+  if (retval == 0)
+    i386_update_inferior_debug_regs (&local_state);
+
   if (maint_show_dr)
-    i386_show_dr ("insert_watchpoint", addr, len, type);
+    i386_show_dr (state, "insert_watchpoint", addr, len, type);
 
   return retval;
 }
@@ -511,22 +627,33 @@ i386_insert_watchpoint (CORE_ADDR addr, int len, int type)
    address ADDR, whose length is LEN bytes, and for accesses of the
    type TYPE.  Return 0 on success, -1 on failure.  */
 static int
-i386_remove_watchpoint (CORE_ADDR addr, int len, int type)
+i386_remove_watchpoint (CORE_ADDR addr, int len, int type,
+                       struct expression *cond)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   int retval;
+  /* Work on a local copy of the debug registers, and on success,
+     commit the change back to the inferior.  */
+  struct i386_debug_reg_state local_state = *state;
 
   if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8))
       || addr % len != 0)
-    retval = i386_handle_nonaligned_watchpoint (WP_REMOVE, addr, len, type);
+    retval = i386_handle_nonaligned_watchpoint (&local_state,
+                                               WP_REMOVE, addr, len, type);
   else
     {
       unsigned len_rw = i386_length_and_rw_bits (len, type);
 
-      retval = i386_remove_aligned_watchpoint (addr, len_rw);
+      retval = i386_remove_aligned_watchpoint (&local_state,
+                                              addr, len_rw);
     }
 
+  if (retval == 0)
+    i386_update_inferior_debug_regs (&local_state);
+
   if (maint_show_dr)
-    i386_show_dr ("remove_watchpoint", addr, len, type);
+    i386_show_dr (state, "remove_watchpoint", addr, len, type);
 
   return retval;
 }
@@ -537,48 +664,91 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type)
 static int
 i386_region_ok_for_watchpoint (CORE_ADDR addr, int len)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   int nregs;
 
   /* Compute how many aligned watchpoints we would need to cover this
      region.  */
-  nregs = i386_handle_nonaligned_watchpoint (WP_COUNT, addr, len, hw_write);
+  nregs = i386_handle_nonaligned_watchpoint (state,
+                                            WP_COUNT, addr, len, hw_write);
   return nregs <= DR_NADDR ? 1 : 0;
 }
 
 /* If the inferior has some watchpoint that triggered, set the
-   address associated with that watchpoint and return non-zero.  
+   address associated with that watchpoint and return non-zero.
    Otherwise, return zero.  */
 
 static int
 i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   CORE_ADDR addr = 0;
   int i;
   int rc = 0;
-
-  dr_status_mirror = i386_dr_low.get_status ();
+  /* The current thread's DR_STATUS.  We always need to read this to
+     check whether some watchpoint caused the trap.  */
+  unsigned status;
+  /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a
+     data breakpoint trap.  Only fetch it when necessary, to avoid an
+     unnecessary extra syscall when no watchpoint triggered.  */
+  int control_p = 0;
+  unsigned control = 0;
+
+  /* In non-stop/async, threads can be running while we change the
+     STATE (and friends).  Say, we set a watchpoint, and let threads
+     resume.  Now, say you delete the watchpoint, or add/remove
+     watchpoints such that STATE changes while threads are running.
+     On targets that support non-stop, inserting/deleting watchpoints
+     updates the STATE only.  It does not update the real thread's
+     debug registers; that's only done prior to resume.  Instead, if
+     threads are running when the mirror changes, a temporary and
+     transparent stop on all threads is forced so they can get their
+     copy of the debug registers updated on re-resume.  Now, say,
+     a thread hit a watchpoint before having been updated with the new
+     STATE contents, and we haven't yet handled the corresponding
+     SIGTRAP.  If we trusted STATE below, we'd mistake the real
+     trapped address (from the last time we had updated debug
+     registers in the thread) with whatever was currently in STATE.
+     So to fix this, STATE always represents intention, what we _want_
+     threads to have in debug registers.  To get at the address and
+     cause of the trap, we need to read the state the thread still has
+     in its debug registers.
+
+     In sum, always get the current debug register values the current
+     thread has, instead of trusting the global mirror.  If the thread
+     was running when we last changed watchpoints, the mirror no
+     longer represents what was set in this thread's debug
+     registers.  */
+  status = i386_dr_low.get_status ();
 
   ALL_DEBUG_REGISTERS(i)
     {
-      if (I386_DR_WATCH_HIT (i)
-         /* This second condition makes sure DRi is set up for a data
-            watchpoint, not a hardware breakpoint.  The reason is
-            that GDB doesn't call the target_stopped_data_address
-            method except for data watchpoints.  In other words, I'm
-            being paranoiac.  */
-         && I386_DR_GET_RW_LEN (i) != 0
-         /* This third condition makes sure DRi is not vacant, this
-            avoids false positives in windows-nat.c.  */
-         && !I386_DR_VACANT (i))
+      if (!I386_DR_WATCH_HIT (status, i))
+       continue;
+
+      if (!control_p)
        {
-         addr = dr_mirror[i];
+         control = i386_dr_low.get_control ();
+         control_p = 1;
+       }
+
+      /* This second condition makes sure DRi is set up for a data
+        watchpoint, not a hardware breakpoint.  The reason is that
+        GDB doesn't call the target_stopped_data_address method
+        except for data watchpoints.  In other words, I'm being
+        paranoiac.  */
+      if (I386_DR_GET_RW_LEN (control, i) != 0)
+       {
+         addr = i386_dr_low.get_addr (i);
          rc = 1;
          if (maint_show_dr)
-           i386_show_dr ("watchpoint_hit", addr, -1, hw_write);
+           i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write);
        }
     }
   if (maint_show_dr && addr == 0)
-    i386_show_dr ("stopped_data_addr", 0, 0, hw_write);
+    i386_show_dr (state, "stopped_data_addr", 0, 0, hw_write);
 
   if (rc)
     *addr_p = addr;
@@ -586,10 +756,10 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 }
 
 static int
-i386_stopped_by_watchpoint (void)
+i386_stopped_by_watchpoint (struct target_ops *ops)
 {
   CORE_ADDR addr = 0;
-  return i386_stopped_data_address (&current_target, &addr);
+  return i386_stopped_data_address (ops, &addr);
 }
 
 /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
@@ -598,12 +768,21 @@ static int
 i386_insert_hw_breakpoint (struct gdbarch *gdbarch,
                           struct bp_target_info *bp_tgt)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   unsigned len_rw = i386_length_and_rw_bits (1, hw_execute);
   CORE_ADDR addr = bp_tgt->placed_address;
-  int retval = i386_insert_aligned_watchpoint (addr, len_rw) ? EBUSY : 0;
+  /* Work on a local copy of the debug registers, and on success,
+     commit the change back to the inferior.  */
+  struct i386_debug_reg_state local_state = *state;
+  int retval = i386_insert_aligned_watchpoint (&local_state,
+                                              addr, len_rw) ? EBUSY : 0;
+
+  if (retval == 0)
+    i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr ("insert_hwbp", addr, 1, hw_execute);
+    i386_show_dr (state, "insert_hwbp", addr, 1, hw_execute);
 
   return retval;
 }
@@ -615,12 +794,21 @@ static int
 i386_remove_hw_breakpoint (struct gdbarch *gdbarch,
                           struct bp_target_info *bp_tgt)
 {
+  struct i386_debug_reg_state *state
+    = i386_debug_reg_state (ptid_get_pid (inferior_ptid));
   unsigned len_rw = i386_length_and_rw_bits (1, hw_execute);
   CORE_ADDR addr = bp_tgt->placed_address;
-  int retval = i386_remove_aligned_watchpoint (addr, len_rw);
+  /* Work on a local copy of the debug registers, and on success,
+     commit the change back to the inferior.  */
+  struct i386_debug_reg_state local_state = *state;
+  int retval = i386_remove_aligned_watchpoint (&local_state,
+                                              addr, len_rw);
+
+  if (retval == 0)
+    i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr ("remove_hwbp", addr, 1, hw_execute);
+    i386_show_dr (state, "remove_hwbp", addr, 1, hw_execute);
 
   return retval;
 }
This page took 0.051307 seconds and 4 git commands to generate.