Add "volatile" keyword to "struct gdb_exception" declaration
[deliverable/binutils-gdb.git] / gdb / i386-nat.c
index fa17823a564f3a47356caa422652ff24d43809f9..034bf5126b0af35572c9e8be595b50a18c922538 100644 (file)
@@ -1,7 +1,6 @@
 /* Native-dependent code for the i386.
 
-   Copyright (C) 2001, 2004-2005, 2007-2012 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.
@@ -153,31 +153,102 @@ struct i386_dr_low_type i386_dr_low;
 /* A macro to loop over all debug registers.  */
 #define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++)
 
-/* Clear the reference counts and forget everything we knew about the
-   debug registers.  */
+/* 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).  */
 
-static void
-i386_init_dregs (struct i386_debug_reg_state *state)
+struct i386_process_info
 {
-  int i;
+  /* Linked list.  */
+  struct i386_process_info *next;
 
-  ALL_DEBUG_REGISTERS (i)
-    {
-      state->dr_mirror[i] = 0;
-      state->dr_ref_count[i] = 0;
-    }
-  state->dr_control_mirror = 0;
-  state->dr_status_mirror  = 0;
+  /* 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;
+}
+
+/* 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;
 }
 
-/* The local mirror of the inferior's debug registers.  Currently this
-   is a global, but it should really be per-inferior.  */
-static struct i386_debug_reg_state dr_mirror;
+/* 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 (void)
+i386_debug_reg_state (pid_t pid)
 {
-  return &dr_mirror;
+  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.  */
@@ -230,7 +301,8 @@ static int i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state
 void
 i386_cleanup_dregs (void)
 {
-  i386_init_dregs (&dr_mirror);
+  /* 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
@@ -242,7 +314,7 @@ 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);
@@ -494,20 +566,22 @@ Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n"),
 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 (&dr_mirror, 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] == dr_mirror.dr_mirror[i]);
+       gdb_assert (new_state->dr_mirror[i] == state->dr_mirror[i]);
     }
 
-  if (new_state->dr_control_mirror != dr_mirror.dr_control_mirror)
+  if (new_state->dr_control_mirror != state->dr_control_mirror)
     i386_dr_low.set_control (new_state->dr_control_mirror);
 
-  dr_mirror = *new_state;
+  *state = *new_state;
 }
 
 /* Insert a watchpoint to watch a memory region which starts at
@@ -518,10 +592,12 @@ static int
 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 = dr_mirror;
+  struct i386_debug_reg_state local_state = *state;
 
   if (type == hw_read)
     return 1; /* unsupported */
@@ -542,7 +618,7 @@ i386_insert_watchpoint (CORE_ADDR addr, int len, int type,
     i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr (&dr_mirror, "insert_watchpoint", addr, len, type);
+    i386_show_dr (state, "insert_watchpoint", addr, len, type);
 
   return retval;
 }
@@ -554,10 +630,12 @@ static int
 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 = dr_mirror;
+  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)
@@ -575,7 +653,7 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type,
     i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr (&dr_mirror, "remove_watchpoint", addr, len, type);
+    i386_show_dr (state, "remove_watchpoint", addr, len, type);
 
   return retval;
 }
@@ -586,11 +664,13 @@ 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 (&dr_mirror,
+  nregs = i386_handle_nonaligned_watchpoint (state,
                                             WP_COUNT, addr, len, hw_write);
   return nregs <= DR_NADDR ? 1 : 0;
 }
@@ -602,6 +682,8 @@ i386_region_ok_for_watchpoint (CORE_ADDR addr, int len)
 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;
@@ -615,25 +697,24 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
   unsigned control = 0;
 
   /* In non-stop/async, threads can be running while we change the
-     global dr_mirror (and friends).  Say, we set a watchpoint, and
-     let threads resume.  Now, say you delete the watchpoint, or
-     add/remove watchpoints such that dr_mirror changes while threads
-     are running.  On targets that support non-stop,
-     inserting/deleting watchpoints updates the global dr_mirror 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 dr_mirror contents, and we
-     haven't yet handled the corresponding SIGTRAP.  If we trusted
-     dr_mirror 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 dr_mirror.  So to fix this, dr_mirror
-     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.
+     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
@@ -663,11 +744,11 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
          addr = i386_dr_low.get_addr (i);
          rc = 1;
          if (maint_show_dr)
-           i386_show_dr (&dr_mirror, "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 (&dr_mirror, "stopped_data_addr", 0, 0, hw_write);
+    i386_show_dr (state, "stopped_data_addr", 0, 0, hw_write);
 
   if (rc)
     *addr_p = addr;
@@ -687,11 +768,13 @@ 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;
   /* 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 = dr_mirror;
+  struct i386_debug_reg_state local_state = *state;
   int retval = i386_insert_aligned_watchpoint (&local_state,
                                               addr, len_rw) ? EBUSY : 0;
 
@@ -699,7 +782,7 @@ i386_insert_hw_breakpoint (struct gdbarch *gdbarch,
     i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr (&dr_mirror, "insert_hwbp", addr, 1, hw_execute);
+    i386_show_dr (state, "insert_hwbp", addr, 1, hw_execute);
 
   return retval;
 }
@@ -711,11 +794,13 @@ 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;
   /* 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 = dr_mirror;
+  struct i386_debug_reg_state local_state = *state;
   int retval = i386_remove_aligned_watchpoint (&local_state,
                                               addr, len_rw);
 
@@ -723,7 +808,7 @@ i386_remove_hw_breakpoint (struct gdbarch *gdbarch,
     i386_update_inferior_debug_regs (&local_state);
 
   if (maint_show_dr)
-    i386_show_dr (&dr_mirror, "remove_hwbp", addr, 1, hw_execute);
+    i386_show_dr (state, "remove_hwbp", addr, 1, hw_execute);
 
   return retval;
 }
This page took 0.02716 seconds and 4 git commands to generate.