* gdbthread.h (struct thread_info): Add comments around
[deliverable/binutils-gdb.git] / gdb / i386-nat.c
index a20e9b06635435f550430454353998e4e3d90428..f6ae5bfc11014aaa641fc07cdd0c0f4d6d36a8e2 100644 (file)
@@ -1,12 +1,12 @@
 /* Native-dependent code for the i386.
 
-   Copyright 2001, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "breakpoint.h"
 #include "command.h"
 #include "gdbcmd.h"
+#include "target.h"
 
 /* Support for hardware watchpoints and breakpoints using the i386
    debug registers.
@@ -231,8 +230,6 @@ i386_cleanup_dregs (void)
   dr_status_mirror  = 0;
 }
 
-#ifndef LINUX_CHILD_POST_STARTUP_INFERIOR
-
 /* Reset all debug registers at each new startup to avoid missing
    watchpoints after restart.  */
 
@@ -242,8 +239,6 @@ child_post_startup_inferior (ptid_t ptid)
   i386_cleanup_dregs ();
 }
 
-#endif /* LINUX_CHILD_POST_STARTUP_INFERIOR */
-
 /* Print the values of the mirrored debug registers.  This is called
    when maint_show_dr is non-zero.  To set that up, type "maint
    show-debug-regs" at GDB's prompt.  */
@@ -310,8 +305,8 @@ i386_length_and_rw_bits (int len, enum target_hw_bp_type type)
        break;
 #endif
       default:
-       internal_error (__FILE__, __LINE__, "\
-Invalid hardware breakpoint type %d in i386_length_and_rw_bits.\n",
+       internal_error (__FILE__, __LINE__, _("\
+Invalid hardware breakpoint type %d in i386_length_and_rw_bits.\n"),
                        (int) type);
     }
 
@@ -327,8 +322,8 @@ Invalid hardware breakpoint type %d in i386_length_and_rw_bits.\n",
         if (TARGET_HAS_DR_LEN_8)
          return (DR_LEN_8 | rw);
       default:
-       internal_error (__FILE__, __LINE__, "\
-Invalid hardware breakpoint length %d in i386_length_and_rw_bits.\n", len);
+       internal_error (__FILE__, __LINE__, _("\
+Invalid hardware breakpoint length %d in i386_length_and_rw_bits.\n"), len);
     }
 }
 
@@ -454,7 +449,7 @@ i386_handle_nonaligned_watchpoint (i386_wp_op_t what, CORE_ADDR addr, int len,
   while (len > 0)
     {
       int align = addr % max_wp_len;
-      /* Four (eigth on AMD64) is the maximum length a debug register
+      /* Four (eight on AMD64) is the maximum length a debug register
         can watch.  */
       int try = (len > max_wp_len ? (max_wp_len - 1) : len - 1);
       int size = size_try_array[try][align];
@@ -478,8 +473,8 @@ i386_handle_nonaligned_watchpoint (i386_wp_op_t what, CORE_ADDR addr, int len,
          else if (what == WP_REMOVE)
            status = i386_remove_aligned_watchpoint (addr, len_rw);
          else
-           internal_error (__FILE__, __LINE__, "\
-Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n",
+           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
@@ -564,14 +559,16 @@ i386_region_ok_for_watchpoint (CORE_ADDR addr, int len)
   return nregs <= DR_NADDR ? 1 : 0;
 }
 
-/* If the inferior has some watchpoint that triggered, return the
-   address associated with that watchpoint.  Otherwise, return zero.  */
+/* If the inferior has some watchpoint that triggered, set the
+   address associated with that watchpoint and return non-zero.  
+   Otherwise, return zero.  */
 
-CORE_ADDR
-i386_stopped_data_address (void)
+int
+i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 {
   CORE_ADDR addr = 0;
   int i;
+  int rc = 0;
 
   dr_status_mirror = I386_DR_LOW_GET_STATUS ();
 
@@ -582,10 +579,11 @@ i386_stopped_data_address (void)
             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 paranoid.  */
+            being paranoiac.  */
          && I386_DR_GET_RW_LEN (i) != 0)
        {
          addr = dr_mirror[i];
+         rc = 1;
          if (maint_show_dr)
            i386_show_dr ("watchpoint_hit", addr, -1, hw_write);
        }
@@ -593,7 +591,16 @@ i386_stopped_data_address (void)
   if (maint_show_dr && addr == 0)
     i386_show_dr ("stopped_data_addr", 0, 0, hw_write);
 
-  return addr;
+  if (rc)
+    *addr_p = addr;
+  return rc;
+}
+
+int
+i386_stopped_by_watchpoint (void)
+{
+  CORE_ADDR addr = 0;
+  return i386_stopped_data_address (&current_target, &addr);
 }
 
 /* Return non-zero if the inferior has some break/watchpoint that
@@ -617,12 +624,13 @@ i386_stopped_by_hwbp (void)
   return 0;
 }
 
-/* Insert a hardware-assisted breakpoint at address ADDR.  SHADOW is
-   unused.  Return 0 on success, EBUSY on failure.  */
+/* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
+   Return 0 on success, EBUSY on failure.  */
 int
-i386_insert_hw_breakpoint (CORE_ADDR addr, void *shadow)
+i386_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
 {
   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;
 
   if (maint_show_dr)
@@ -631,13 +639,14 @@ i386_insert_hw_breakpoint (CORE_ADDR addr, void *shadow)
   return retval;
 }
 
-/* Remove a hardware-assisted breakpoint at address ADDR.  SHADOW is
-   unused.  Return 0 on success, -1 on failure.  */
+/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address.
+   Return 0 on success, -1 on failure.  */
 
 int
-i386_remove_hw_breakpoint (CORE_ADDR addr, void *shadow)
+i386_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
 {
   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);
 
   if (maint_show_dr)
@@ -646,6 +655,47 @@ i386_remove_hw_breakpoint (CORE_ADDR addr, void *shadow)
   return retval;
 }
 
+/* Returns the number of hardware watchpoints of type TYPE that we can
+   set.  Value is positive if we can set CNT watchpoints, zero if
+   setting watchpoints of type TYPE is not supported, and negative if
+   CNT is more than the maximum number of watchpoints of type TYPE
+   that we can support.  TYPE is one of bp_hardware_watchpoint,
+   bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint.
+   CNT is the number of such watchpoints used so far (including this
+   one).  OTHERTYPE is non-zero if other types of watchpoints are
+   currently enabled.
+
+   We always return 1 here because we don't have enough information
+   about possible overlap of addresses that they want to watch.  As an
+   extreme example, consider the case where all the watchpoints watch
+   the same address and the same region length: then we can handle a
+   virtually unlimited number of watchpoints, due to debug register
+   sharing implemented via reference counts in i386-nat.c.  */
+
+static int
+i386_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+  return 1;
+}
+
+void
+i386_use_watchpoints (struct target_ops *t)
+{
+  /* After a watchpoint trap, the PC points to the instruction after the
+     one that caused the trap.  Therefore we don't need to step over it.
+     But we do need to reset the status register to avoid another trap.  */
+  t->to_have_continuable_watchpoint = 1;
+
+  t->to_can_use_hw_breakpoint = i386_can_use_hw_breakpoint;
+  t->to_region_ok_for_hw_watchpoint = i386_region_ok_for_watchpoint;
+  t->to_stopped_by_watchpoint = i386_stopped_by_watchpoint;
+  t->to_stopped_data_address = i386_stopped_data_address;
+  t->to_insert_watchpoint = i386_insert_watchpoint;
+  t->to_remove_watchpoint = i386_remove_watchpoint;
+  t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint;
+  t->to_remove_hw_breakpoint = i386_remove_hw_breakpoint;
+}
+
 #endif /* I386_USE_GENERIC_WATCHPOINTS */
 \f
 
@@ -658,13 +708,13 @@ _initialize_i386_nat (void)
 #ifdef I386_USE_GENERIC_WATCHPOINTS
   /* A maintenance command to enable printing the internal DRi mirror
      variables.  */
-  add_set_cmd ("show-debug-regs", class_maintenance,
-              var_boolean, (char *) &maint_show_dr,
-              "\
+  deprecated_add_set_cmd ("show-debug-regs", class_maintenance,
+                         var_boolean, (char *) &maint_show_dr, _("\
 Set whether to show variables that mirror the x86 debug registers.\n\
 Use \"on\" to enable, \"off\" to disable.\n\
 If enabled, the debug registers values are shown when GDB inserts\n\
 or removes a hardware breakpoint or watchpoint, and when the inferior\n\
-triggers a breakpoint or watchpoint.", &maintenancelist);
+triggers a breakpoint or watchpoint."),
+                         &maintenancelist);
 #endif
 }
This page took 0.027305 seconds and 4 git commands to generate.