GDB copyright headers update after running GDB's copyright.py script.
[deliverable/binutils-gdb.git] / gdb / nat / aarch64-linux-hw-point.c
index ba235e54c783b74c403ab3dd05417b65bba94065..a06a6e628fedc90a4c17ebb95f529c425ad2c76d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GDB.
@@ -18,6 +18,7 @@
 
 #include "common-defs.h"
 #include "break-common.h"
+#include "common-regcache.h"
 #include "nat/linux-nat.h"
 #include "aarch64-linux-hw-point.h"
 
@@ -112,8 +113,23 @@ aarch64_point_encode_ctrl_reg (enum target_hw_bp_type type, int len)
 static int
 aarch64_point_is_aligned (int is_watchpoint, CORE_ADDR addr, int len)
 {
-  unsigned int alignment = is_watchpoint ? AARCH64_HWP_ALIGNMENT
-    : AARCH64_HBP_ALIGNMENT;
+  unsigned int alignment = 0;
+
+  if (is_watchpoint)
+    alignment = AARCH64_HWP_ALIGNMENT;
+  else
+    {
+      struct regcache *regcache
+       = get_thread_regcache_for_ptid (current_lwp_ptid ());
+
+      /* Set alignment to 2 only if the current process is 32-bit,
+        since thumb instruction can be 2-byte aligned.  Otherwise, set
+        alignment to AARCH64_HBP_ALIGNMENT.  */
+      if (regcache_register_size (regcache, 0) == 8)
+       alignment = AARCH64_HBP_ALIGNMENT;
+      else
+       alignment = 2;
+    }
 
   if (addr & (alignment - 1))
     return 0;
@@ -239,7 +255,7 @@ debug_reg_change_callback (struct lwp_info *lwp, void *ptr)
 {
   struct aarch64_dr_update_callback_param *param_p
     = (struct aarch64_dr_update_callback_param *) ptr;
-  int pid = ptid_get_pid (ptid_of_lwp (lwp));
+  int tid = ptid_get_lwp (ptid_of_lwp (lwp));
   int idx = param_p->idx;
   int is_watchpoint = param_p->is_watchpoint;
   struct arch_lwp_info *info = lwp_arch_private_info (lwp);
@@ -255,8 +271,8 @@ debug_reg_change_callback (struct lwp_info *lwp, void *ptr)
   if (show_debug_regs)
     {
       debug_printf ("debug_reg_change_callback: \n\tOn entry:\n");
-      debug_printf ("\tpid%d, dr_changed_bp=0x%s, "
-                   "dr_changed_wp=0x%s\n", pid,
+      debug_printf ("\ttid%d, dr_changed_bp=0x%s, "
+                   "dr_changed_wp=0x%s\n", tid,
                    phex (info->dr_changed_bp, 8),
                    phex (info->dr_changed_wp, 8));
     }
@@ -281,8 +297,8 @@ debug_reg_change_callback (struct lwp_info *lwp, void *ptr)
 
   if (show_debug_regs)
     {
-      debug_printf ("\tOn exit:\n\tpid%d, dr_changed_bp=0x%s, "
-                   "dr_changed_wp=0x%s\n", pid,
+      debug_printf ("\tOn exit:\n\ttid%d, dr_changed_bp=0x%s, "
+                   "dr_changed_wp=0x%s\n", tid,
                    phex (info->dr_changed_bp, 8),
                    phex (info->dr_changed_wp, 8));
     }
@@ -395,7 +411,6 @@ aarch64_dr_state_remove_one_point (struct aarch64_debug_reg_state *state,
 
   /* Set up state pointers.  */
   is_watchpoint = (type != hw_execute);
-  gdb_assert (aarch64_point_is_aligned (is_watchpoint, addr, len));
   if (is_watchpoint)
     {
       num_regs = aarch64_num_wp_regs;
@@ -444,13 +459,21 @@ aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
                           int len, int is_insert,
                           struct aarch64_debug_reg_state *state)
 {
-  /* The hardware breakpoint on AArch64 should always be 4-byte
-     aligned.  */
-  if (!aarch64_point_is_aligned (0 /* is_watchpoint */ , addr, len))
-    return -1;
-
   if (is_insert)
-    return aarch64_dr_state_insert_one_point (state, type, addr, len);
+    {
+      /* The hardware breakpoint on AArch64 should always be 4-byte
+        aligned, but on AArch32, it can be 2-byte aligned.  Note that
+        we only check the alignment on inserting breakpoint because
+        aarch64_point_is_aligned needs the inferior_ptid inferior's
+        regcache to decide whether the inferior is 32-bit or 64-bit.
+        However when GDB follows the parent process and detach breakpoints
+        from child process, inferior_ptid is the child ptid, but the
+        child inferior doesn't exist in GDB's view yet.  */
+      if (!aarch64_point_is_aligned (0 /* is_watchpoint */ , addr, len))
+       return -1;
+
+      return aarch64_dr_state_insert_one_point (state, type, addr, len);
+    }
   else
     return aarch64_dr_state_remove_one_point (state, type, addr, len);
 }
@@ -545,8 +568,8 @@ aarch64_linux_set_debug_regs (const struct aarch64_debug_reg_state *state,
   ctrl = watchpoint ? state->dr_ctrl_wp : state->dr_ctrl_bp;
   if (count == 0)
     return;
-  iov.iov_len = (offsetof (struct user_hwdebug_state, dbg_regs[count - 1])
-                + sizeof (regs.dbg_regs [count - 1]));
+  iov.iov_len = (offsetof (struct user_hwdebug_state, dbg_regs)
+                + count * sizeof (regs.dbg_regs[0]));
 
   for (i = 0; i < count; i++)
     {
@@ -645,3 +668,43 @@ aarch64_linux_get_debug_reg_capacity (int tid)
       aarch64_num_bp_regs = 0;
     }
 }
+
+/* Return true if we can watch a memory region that starts address
+   ADDR and whose length is LEN in bytes.  */
+
+int
+aarch64_linux_region_ok_for_watchpoint (CORE_ADDR addr, int len)
+{
+  CORE_ADDR aligned_addr;
+
+  /* Can not set watchpoints for zero or negative lengths.  */
+  if (len <= 0)
+    return 0;
+
+  /* Must have hardware watchpoint debug register(s).  */
+  if (aarch64_num_wp_regs == 0)
+    return 0;
+
+  /* We support unaligned watchpoint address and arbitrary length,
+     as long as the size of the whole watched area after alignment
+     doesn't exceed size of the total area that all watchpoint debug
+     registers can watch cooperatively.
+
+     This is a very relaxed rule, but unfortunately there are
+     limitations, e.g. false-positive hits, due to limited support of
+     hardware debug registers in the kernel.  See comment above
+     aarch64_align_watchpoint for more information.  */
+
+  aligned_addr = addr & ~(AARCH64_HWP_MAX_LEN_PER_REG - 1);
+  if (aligned_addr + aarch64_num_wp_regs * AARCH64_HWP_MAX_LEN_PER_REG
+      < addr + len)
+    return 0;
+
+  /* All tests passed so we are likely to be able to set the watchpoint.
+     The reason that it is 'likely' rather than 'must' is because
+     we don't check the current usage of the watchpoint registers, and
+     there may not be enough registers available for this watchpoint.
+     Ideally we should check the cached debug register state, however
+     the checking is costly.  */
+  return 1;
+}
This page took 0.028424 seconds and 4 git commands to generate.