Blame SOURCES/gdb-rhbz1347993-aarch64-hw-watchpoint.patch

120562
commit a3b60e4588606354b93508a0008a5ca04b68fad8
120562
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
120562
Date:   Fri May 4 22:22:04 2018 +0200
120562
120562
    aarch64: PR 19806: watchpoints: false negatives + PR 20207 contiguous ones
120562
    
120562
    Some unaligned watchpoints were currently missed.
120562
    
120562
    On old kernels as specified in
120562
            kernel RFE: aarch64: ptrace: BAS: Support any contiguous range (edit)
120562
            https://sourceware.org/bugzilla/show_bug.cgi?id=20207
120562
    after this patch some other unaligned watchpoints will get reported as false
120562
    positives.
120562
    
120562
    With new kernels all the watchpoints should work exactly.
120562
    
120562
    There may be a regresion that it now less merges watchpoints so that with
120562
    multiple overlapping watchpoints it may run out of the 4 hardware watchpoint
120562
    registers.  But as discussed in the original thread GDB needs some generic
120562
    watchpoints merging framework to be used by all the target specific code.
120562
    Even current FSF GDB code does not merge it perfectly.  Also with the more
120562
    precise watchpoints one can technically merge them less.  And I do not think
120562
    it matters too much to improve mergeability only for old kernels.
120562
    Still even on new kernels some better merging logic would make sense.
120562
    
120562
    There remains one issue:
120562
            kernel-4.15.14-300.fc27.armv7hl
120562
            FAIL: gdb.base/watchpoint-unaligned.exp: continue
120562
            FAIL: gdb.base/watchpoint-unaligned.exp: continue
120562
            (gdb) continue
120562
            Continuing.
120562
            Unexpected error setting watchpoint: Invalid argument.
120562
            (gdb) FAIL: gdb.base/watchpoint-unaligned.exp: continue
120562
    But that looks as a kernel bug to me.
120562
    (1) It is not a regression by this patch.
120562
    (2) It is unrelated to this patch.
120562
    
120562
    gdb/ChangeLog
120562
    2018-05-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
120562
                Pedro Alves <palves@redhat.com>
120562
    
120562
            PR breakpoints/19806 and support for PR external/20207.
120562
            * NEWS: Mention Aarch64 watchpoint improvements.
120562
            * aarch64-linux-nat.c (aarch64_linux_stopped_data_address): Fix missed
120562
            watchpoints and PR external/20207 watchpoints.
120562
            * nat/aarch64-linux-hw-point.c
120562
            (kernel_supports_any_contiguous_range): New.
120562
            (aarch64_watchpoint_offset): New.
120562
            (aarch64_watchpoint_length): Support PR external/20207 watchpoints.
120562
            (aarch64_point_encode_ctrl_reg): New parameter offset, new asserts.
120562
            (aarch64_point_is_aligned): Support PR external/20207 watchpoints.
120562
            (aarch64_align_watchpoint): New parameters aligned_offset_p and
120562
            next_addr_orig_p.  Support PR external/20207 watchpoints.
120562
            (aarch64_downgrade_regs): New.
120562
            (aarch64_dr_state_insert_one_point): New parameters offset and
120562
            addr_orig.
120562
            (aarch64_dr_state_remove_one_point): Likewise.
120562
            (aarch64_handle_breakpoint): Update caller.
120562
            (aarch64_handle_aligned_watchpoint): Likewise.
120562
            (aarch64_handle_unaligned_watchpoint): Support addr_orig and
120562
            aligned_offset.
120562
            (aarch64_linux_set_debug_regs): Remove const from state.  Call
120562
            aarch64_downgrade_regs.
120562
            (aarch64_show_debug_reg_state): Print also dr_addr_orig_wp.
120562
            * nat/aarch64-linux-hw-point.h (DR_CONTROL_LENGTH): Rename to ...
120562
            (DR_CONTROL_MASK): ... this.
120562
            (struct aarch64_debug_reg_state): New field dr_addr_orig_wp.
120562
            (unsigned int aarch64_watchpoint_offset): New prototype.
120562
            (aarch64_linux_set_debug_regs): Remove const from state.
120562
            * utils.c (align_up, align_down): Move to ...
120562
            * common/common-utils.c (align_up, align_down): ... here.
120562
            * utils.h (align_up, align_down): Move to ...
120562
            * common/common-utils.h (align_up, align_down): ... here.
120562
    
120562
    gdb/gdbserver/ChangeLog
120562
    2018-05-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
120562
                Pedro Alves <palves@redhat.com>
120562
    
120562
            * linux-aarch64-low.c (aarch64_stopped_data_address):
120562
            Likewise.
120562
    
120562
    gdb/testsuite/ChangeLog
120562
    2018-05-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
120562
                Pedro Alves <palves@redhat.com>
120562
    
120562
            PR breakpoints/19806 and support for PR external/20207.
120562
            * gdb.base/watchpoint-unaligned.c: New file.
120562
            * gdb.base/watchpoint-unaligned.exp: New file.
120562
120562
### a/gdb/ChangeLog
120562
### b/gdb/ChangeLog
120562
## -1,3 +1,39 @@
120562
+2018-05-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
120562
+	    Pedro Alves <palves@redhat.com>
120562
+
120562
+	PR breakpoints/19806 and support for PR external/20207.
120562
+	* NEWS: Mention Aarch64 watchpoint improvements.
120562
+	* aarch64-linux-nat.c (aarch64_linux_stopped_data_address): Fix missed
120562
+	watchpoints and PR external/20207 watchpoints.
120562
+	* nat/aarch64-linux-hw-point.c
120562
+	(kernel_supports_any_contiguous_range): New.
120562
+	(aarch64_watchpoint_offset): New.
120562
+	(aarch64_watchpoint_length): Support PR external/20207 watchpoints.
120562
+	(aarch64_point_encode_ctrl_reg): New parameter offset, new asserts.
120562
+	(aarch64_point_is_aligned): Support PR external/20207 watchpoints.
120562
+	(aarch64_align_watchpoint): New parameters aligned_offset_p and
120562
+	next_addr_orig_p.  Support PR external/20207 watchpoints.
120562
+	(aarch64_downgrade_regs): New.
120562
+	(aarch64_dr_state_insert_one_point): New parameters offset and
120562
+	addr_orig.
120562
+	(aarch64_dr_state_remove_one_point): Likewise.
120562
+	(aarch64_handle_breakpoint): Update caller.
120562
+	(aarch64_handle_aligned_watchpoint): Likewise.
120562
+	(aarch64_handle_unaligned_watchpoint): Support addr_orig and
120562
+	aligned_offset.
120562
+	(aarch64_linux_set_debug_regs): Remove const from state.  Call
120562
+	aarch64_downgrade_regs.
120562
+	(aarch64_show_debug_reg_state): Print also dr_addr_orig_wp.
120562
+	* nat/aarch64-linux-hw-point.h (DR_CONTROL_LENGTH): Rename to ...
120562
+	(DR_CONTROL_MASK): ... this.
120562
+	(struct aarch64_debug_reg_state): New field dr_addr_orig_wp.
120562
+	(unsigned int aarch64_watchpoint_offset): New prototype.
120562
+	(aarch64_linux_set_debug_regs): Remove const from state.
120562
+	* utils.c (align_up, align_down): Move to ...
120562
+	* common/common-utils.c (align_up, align_down): ... here.
120562
+	* utils.h (align_up, align_down): Move to ...
120562
+	* common/common-utils.h (align_up, align_down): ... here.
120562
+
120562
 2018-05-04  Joel Brobecker  <brobecker@adacore.com>
120562
 
120562
 	* sparc-tdep.c (sparc_structure_return_p): Re-implement to
120562
Index: gdb-7.6.1/gdb/NEWS
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/NEWS	2018-05-05 17:12:48.170769374 +0200
120562
+++ gdb-7.6.1/gdb/NEWS	2018-05-05 17:12:49.569781872 +0200
120562
@@ -4,6 +4,16 @@
120562
 * Newly installed $prefix/bin/gcore acts as a shell interface for the
120562
   GDB command gcore.
120562
 
120562
+* Aarch64/Linux hardware watchpoints improvements
120562
+
120562
+  Hardware watchpoints on unaligned addresses are now properly
120562
+  supported when running Linux kernel 4.10 or higher: read and access
120562
+  watchpoints are no longer spuriously missed, and all watchpoints
120562
+  lengths between 1 and 8 bytes are supported.  On older kernels,
120562
+  watchpoints set on unaligned addresses are no longer missed, with
120562
+  the tradeoff that there is a possibility of false hits being
120562
+  reported.
120562
+
120562
 *** Changes in GDB 7.6
120562
 
120562
 * Target record has been renamed to record-full.
120562
Index: gdb-7.6.1/gdb/aarch64-linux-nat.c
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/aarch64-linux-nat.c	2018-05-05 17:12:47.474763150 +0200
120562
+++ gdb-7.6.1/gdb/aarch64-linux-nat.c	2018-05-05 17:12:49.570781881 +0200
120562
@@ -45,6 +45,18 @@
120562
 #define TRAP_HWBKPT 0x0004
120562
 #endif
120562
 
120562
+/* ptrace expects control registers to be formatted as follows:
120562
+
120562
+   31                             13          5      3      1     0
120562
+   +--------------------------------+----------+------+------+----+
120562
+   |         RESERVED (SBZ)         |   MASK   | TYPE | PRIV | EN |
120562
+   +--------------------------------+----------+------+------+----+
120562
+
120562
+   The TYPE field is ignored for breakpoints.  */
120562
+
120562
+#define DR_CONTROL_ENABLED(ctrl)	(((ctrl) & 0x1) == 1)
120562
+#define DR_CONTROL_MASK(ctrl)		(((ctrl) >> 5) & 0xff)
120562
+
120562
 /* On GNU/Linux, threads are implemented as pseudo-processes, in which
120562
    case we may be tracing more than one process at a time.  In that
120562
    case, inferior_ptid will contain the main process ID and the
120562
@@ -118,6 +130,29 @@
120562
 static int aarch64_num_bp_regs;
120562
 static int aarch64_num_wp_regs;
120562
 
120562
+/* True if this kernel does not have the bug described by PR
120562
+   external/20207 (Linux >= 4.10).  A fixed kernel supports any
120562
+   contiguous range of bits in 8-bit byte DR_CONTROL_MASK.  A buggy
120562
+   kernel supports only 0x01, 0x03, 0x0f and 0xff.  We start by
120562
+   assuming the bug is fixed, and then detect the bug at
120562
+   PTRACE_SETREGSET time.  */
120562
+static int kernel_supports_any_contiguous_range = 1;
120562
+
120562
+/* Return starting byte 0..7 incl. of a watchpoint encoded by CTRL.  */
120562
+
120562
+static unsigned int
120562
+aarch64_watchpoint_offset (unsigned int ctrl)
120562
+{
120562
+  uint8_t mask = DR_CONTROL_MASK (ctrl);
120562
+  unsigned retval;
120562
+
120562
+  /* Shift out bottom zeros.  */
120562
+  for (retval = 0; mask && (mask & 1) == 0; ++retval)
120562
+    mask >>= 1;
120562
+
120562
+  return retval;
120562
+}
120562
+
120562
 /* Debugging of hardware breakpoint/watchpoint support.  */
120562
 
120562
 static int debug_hw_points;
120562
@@ -184,7 +219,10 @@
120562
   unsigned int dr_ref_count_bp[AARCH64_HBP_MAX_NUM];
120562
 
120562
   /* hardware watchpoint */
120562
+  /* Address aligned down to AARCH64_HWP_ALIGNMENT.  */
120562
   CORE_ADDR dr_addr_wp[AARCH64_HWP_MAX_NUM];
120562
+  /* Address as entered by user without any forced alignment.  */
120562
+  CORE_ADDR dr_addr_orig_wp[AARCH64_HWP_MAX_NUM];
120562
   unsigned int dr_ctrl_wp[AARCH64_HWP_MAX_NUM];
120562
   unsigned int dr_ref_count_wp[AARCH64_HWP_MAX_NUM];
120562
 };
120562
@@ -299,11 +337,76 @@
120562
   dr_changed_t dr_changed_wp;
120562
 };
120562
 
120562
+/* Reconfigure STATE to be compatible with Linux kernels with the PR
120562
+   external/20207 bug.  This is called when
120562
+   KERNEL_SUPPORTS_ANY_CONTIGUOUS_RANGE transitions to false.  Note we
120562
+   don't try to support combining watchpoints with matching (and thus
120562
+   shared) masks, as it's too late when we get here.  On buggy
120562
+   kernels, GDB will try to first setup the perfect matching ranges,
120562
+   which will run out of registers before this function can merge
120562
+   them.  It doesn't look like worth the effort to improve that, given
120562
+   eventually buggy kernels will be phased out.  */
120562
+
120562
+static void aarch64_notify_debug_reg_change (const struct aarch64_debug_reg_state *state, int is_watchpoint, unsigned int idx);
120562
+
120562
+static void
120562
+aarch64_downgrade_regs (struct aarch64_debug_reg_state *state)
120562
+{
120562
+  int i;
120562
+
120562
+  for (i = 0; i < aarch64_num_wp_regs; ++i)
120562
+    if ((state->dr_ctrl_wp[i] & 1) != 0)
120562
+      {
120562
+	uint8_t mask_orig;
120562
+	static const uint8_t old_valid[] = { 0x01, 0x03, 0x0f, 0xff };
120562
+	int old_validi;
120562
+	uint8_t mask = 0;
120562
+	int j;
120562
+
120562
+	gdb_assert (state->dr_ref_count_wp[i] != 0);
120562
+	mask_orig = (state->dr_ctrl_wp[i] >> 5) & 0xff;
120562
+	gdb_assert (mask_orig != 0);
120562
+	for (old_validi = 0; old_validi < sizeof(old_valid) / sizeof (*old_valid); old_validi++) {
120562
+	  const uint8_t old_mask = old_valid[old_validi];
120562
+	  if (mask_orig <= old_mask)
120562
+	    {
120562
+	      mask = old_mask;
120562
+	      break;
120562
+	    }
120562
+	}
120562
+	gdb_assert (mask != 0);
120562
+
120562
+	/* No update needed for this watchpoint?  */
120562
+	if (mask == mask_orig)
120562
+	  continue;
120562
+	state->dr_ctrl_wp[i] |= mask << 5;
120562
+	state->dr_addr_wp[i]
120562
+	  = align_down (state->dr_addr_wp[i], AARCH64_HWP_ALIGNMENT);
120562
+
120562
+	/* Try to match duplicate entries.  */
120562
+	for (j = 0; j < i; ++j)
120562
+	  if ((state->dr_ctrl_wp[j] & 1) != 0
120562
+	      && state->dr_addr_wp[j] == state->dr_addr_wp[i]
120562
+	      && state->dr_addr_orig_wp[j] == state->dr_addr_orig_wp[i]
120562
+	      && state->dr_ctrl_wp[j] == state->dr_ctrl_wp[i])
120562
+	    {
120562
+	      state->dr_ref_count_wp[j] += state->dr_ref_count_wp[i];
120562
+	      state->dr_ref_count_wp[i] = 0;
120562
+	      state->dr_addr_wp[i] = 0;
120562
+	      state->dr_addr_orig_wp[i] = 0;
120562
+	      state->dr_ctrl_wp[i] &= ~1;
120562
+	      break;
120562
+	    }
120562
+
120562
+	aarch64_notify_debug_reg_change (state, 1 /* is_watchpoint */, i);
120562
+      }
120562
+}
120562
+
120562
 /* Call ptrace to set the thread TID's hardware breakpoint/watchpoint
120562
    registers with data from *STATE.  */
120562
 
120562
 static void
120562
-aarch64_linux_set_debug_regs (const struct aarch64_debug_reg_state *state,
120562
+aarch64_linux_set_debug_regs (struct aarch64_debug_reg_state *state,
120562
 			      int tid, int watchpoint)
120562
 {
120562
   int i, count;
120562
@@ -331,7 +434,18 @@
120562
   if (ptrace (PTRACE_SETREGSET, tid,
120562
 	      watchpoint ? NT_ARM_HW_WATCH : NT_ARM_HW_BREAK,
120562
 	      (void *) &iov))
120562
-    error (_("Unexpected error setting hardware debug registers"));
120562
+    {
120562
+      /* Handle Linux kernels with the PR external/20207 bug.  */
120562
+      if (watchpoint && errno == EINVAL
120562
+	  && kernel_supports_any_contiguous_range)
120562
+	{
120562
+	  kernel_supports_any_contiguous_range = 0;
120562
+	  aarch64_downgrade_regs (state);
120562
+	  aarch64_linux_set_debug_regs (state, tid, watchpoint);
120562
+	  return;
120562
+	}
120562
+      error (_("Unexpected error setting hardware debug registers"));
120562
+    }
120562
 }
120562
 
120562
 struct aarch64_dr_update_callback_param
120562
@@ -452,8 +566,8 @@
120562
   fprintf_unfiltered (gdb_stdlog, "\tWATCHPOINTs:\n");
120562
   for (i = 0; i < aarch64_num_wp_regs; i++)
120562
     fprintf_unfiltered (gdb_stdlog,
120562
-			"\tWP%d: addr=0x%08lx, ctrl=0x%08x, ref.count=%d\n",
120562
-			i, state->dr_addr_wp[i],
120562
+			"\tWP%d: addr=0x%08lx (orig=0x%08lx), ctrl=0x%08x, ref.count=%d\n",
120562
+			i, state->dr_addr_wp[i], state->dr_addr_orig_wp[i],
120562
 			state->dr_ctrl_wp[i], state->dr_ref_count_wp[i]);
120562
 }
120562
 
120562
@@ -850,28 +964,30 @@
120562
 }
120562
 
120562
 /* Given the (potentially unaligned) watchpoint address in ADDR and
120562
-   length in LEN, return the aligned address and aligned length in
120562
-   *ALIGNED_ADDR_P and *ALIGNED_LEN_P, respectively.  The returned
120562
-   aligned address and length will be valid values to write to the
120562
-   hardware watchpoint value and control registers.
120562
+   length in LEN, return the aligned address, offset from that base
120562
+   address, and aligned length in *ALIGNED_ADDR_P, *ALIGNED_OFFSET_P
120562
+   and *ALIGNED_LEN_P, respectively.  The returned values will be
120562
+   valid values to write to the hardware watchpoint value and control
120562
+   registers.
120562
 
120562
    The given watchpoint may get truncated if more than one hardware
120562
    register is needed to cover the watched region.  *NEXT_ADDR_P
120562
    and *NEXT_LEN_P, if non-NULL, will return the address and length
120562
    of the remaining part of the watchpoint (which can be processed
120562
-   by calling this routine again to generate another aligned address
120562
-   and length pair.
120562
+   by calling this routine again to generate another aligned address,
120562
+   offset and length tuple.
120562
 
120562
    See the comment above the function of the same name in
120562
    gdbserver/linux-aarch64-low.c for more information.  */
120562
 
120562
 static void
120562
 aarch64_align_watchpoint (CORE_ADDR addr, int len, CORE_ADDR *aligned_addr_p,
120562
-			  int *aligned_len_p, CORE_ADDR *next_addr_p,
120562
-			  int *next_len_p)
120562
+			  int *aligned_offset_p, int *aligned_len_p,
120562
+			  CORE_ADDR *next_addr_p, int *next_len_p,
120562
+			  CORE_ADDR *next_addr_orig_p)
120562
 {
120562
   int aligned_len;
120562
-  unsigned int offset;
120562
+  unsigned int offset, aligned_offset;
120562
   CORE_ADDR aligned_addr;
120562
   const unsigned int alignment = AARCH64_HWP_ALIGNMENT;
120562
   const unsigned int max_wp_len = AARCH64_HWP_MAX_LEN_PER_REG;
120562
@@ -882,10 +998,12 @@
120562
   if (len <= 0)
120562
     return;
120562
 
120562
-  /* Address to be put into the hardware watchpoint value register
120562
-     must be aligned.  */
120562
+  /* The address put into the hardware watchpoint value register must
120562
+     be aligned.  */
120562
   offset = addr & (alignment - 1);
120562
   aligned_addr = addr - offset;
120562
+  aligned_offset
120562
+    = kernel_supports_any_contiguous_range ? addr & (alignment - 1) : 0;
120562
 
120562
   gdb_assert (offset >= 0 && offset < alignment);
120562
   gdb_assert (aligned_addr >= 0 && aligned_addr <= addr);
120562
@@ -893,9 +1011,10 @@
120562
 
120562
   if (offset + len >= max_wp_len)
120562
     {
120562
-      /* Need more than one watchpoint registers; truncate it at the
120562
+      /* Need more than one watchpoint register; truncate at the
120562
          alignment boundary.  */
120562
-      aligned_len = max_wp_len;
120562
+      aligned_len
120562
+	= max_wp_len - (kernel_supports_any_contiguous_range ? offset : 0);
120562
       len -= (max_wp_len - offset);
120562
       addr += (max_wp_len - offset);
120562
       gdb_assert ((addr & (alignment - 1)) == 0);
120562
@@ -908,19 +1027,24 @@
120562
 	aligned_len_array[AARCH64_HWP_MAX_LEN_PER_REG] =
120562
 	{ 1, 2, 4, 4, 8, 8, 8, 8 };
120562
 
120562
-      aligned_len = aligned_len_array[offset + len - 1];
120562
+      aligned_len = (kernel_supports_any_contiguous_range
120562
+		     ? len : aligned_len_array[offset + len - 1]);
120562
       addr += len;
120562
       len = 0;
120562
     }
120562
 
120562
   if (aligned_addr_p)
120562
     *aligned_addr_p = aligned_addr;
120562
+  if (aligned_offset_p)
120562
+    *aligned_offset_p = aligned_offset;
120562
   if (aligned_len_p)
120562
     *aligned_len_p = aligned_len;
120562
   if (next_addr_p)
120562
     *next_addr_p = addr;
120562
   if (next_len_p)
120562
     *next_len_p = len;
120562
+  if (next_addr_orig_p)
120562
+    *next_addr_orig_p = align_down (*next_addr_orig_p + alignment, alignment);
120562
 }
120562
 
120562
 /* Returns the number of hardware watchpoints of type TYPE that we can
120562
@@ -946,41 +1070,29 @@
120562
   return 1;
120562
 }
120562
 
120562
-/* ptrace expects control registers to be formatted as follows:
120562
-
120562
-   31                             13          5      3      1     0
120562
-   +--------------------------------+----------+------+------+----+
120562
-   |         RESERVED (SBZ)         |  LENGTH  | TYPE | PRIV | EN |
120562
-   +--------------------------------+----------+------+------+----+
120562
-
120562
-   The TYPE field is ignored for breakpoints.  */
120562
-
120562
-#define DR_CONTROL_ENABLED(ctrl)	(((ctrl) & 0x1) == 1)
120562
-#define DR_CONTROL_LENGTH(ctrl)		(((ctrl) >> 5) & 0xff)
120562
-
120562
 /* Utility function that returns the length in bytes of a watchpoint
120562
    according to the content of a hardware debug control register CTRL.
120562
-   Note that the kernel currently only supports the following Byte
120562
-   Address Select (BAS) values: 0x1, 0x3, 0xf and 0xff, which means
120562
-   that for a hardware watchpoint, its valid length can only be 1
120562
-   byte, 2 bytes, 4 bytes or 8 bytes.  */
120562
+   Any contiguous range of bytes in CTRL is supported.  The returned
120562
+   value can be between 0..8 (inclusive).  */
120562
 
120562
 static inline unsigned int
120562
 aarch64_watchpoint_length (unsigned int ctrl)
120562
 {
120562
-  switch (DR_CONTROL_LENGTH (ctrl))
120562
-    {
120562
-    case 0x01:
120562
-      return 1;
120562
-    case 0x03:
120562
-      return 2;
120562
-    case 0x0f:
120562
-      return 4;
120562
-    case 0xff:
120562
-      return 8;
120562
-    default:
120562
-      return 0;
120562
-    }
120562
+  uint8_t mask = DR_CONTROL_MASK (ctrl);
120562
+  unsigned retval;
120562
+
120562
+  /* Shift out bottom zeros.  */
120562
+  mask >>= aarch64_watchpoint_offset (ctrl);
120562
+
120562
+  /* Count bottom ones.  */
120562
+  for (retval = 0; (mask & 1) != 0; ++retval)
120562
+    mask >>= 1;
120562
+
120562
+  if (mask != 0)
120562
+    error (_("Unexpected hardware watchpoint length register value 0x%x"),
120562
+	   DR_CONTROL_MASK (ctrl));
120562
+
120562
+  return retval;
120562
 }
120562
 
120562
 /* Given the hardware breakpoint or watchpoint type TYPE and its
120562
@@ -988,10 +1100,13 @@
120562
    breakpoint/watchpoint control register.  */
120562
 
120562
 static unsigned int
120562
-aarch64_point_encode_ctrl_reg (int type, int len)
120562
+aarch64_point_encode_ctrl_reg (int type, int offset, int len)
120562
 {
120562
   unsigned int ctrl, ttype;
120562
 
120562
+  gdb_assert (offset == 0 || kernel_supports_any_contiguous_range);
120562
+  gdb_assert (offset + len <= AARCH64_HWP_MAX_LEN_PER_REG);
120562
+
120562
   /* type */
120562
   switch (type)
120562
     {
120562
@@ -1012,8 +1127,8 @@
120562
     }
120562
   ctrl = ttype << 3;
120562
 
120562
-  /* length bitmask */
120562
-  ctrl |= ((1 << len) - 1) << 5;
120562
+  /* offset and length bitmask */
120562
+  ctrl |= ((1 << len) - 1) << (5 + offset);
120562
   /* enabled at el0 */
120562
   ctrl |= (2 << 1) | 1;
120562
 
120562
@@ -1042,7 +1157,10 @@
120562
   if (addr & (alignment - 1))
120562
     return 0;
120562
 
120562
-  if (len != 8 && len != 4 && len != 2 && len != 1)
120562
+  if ((!kernel_supports_any_contiguous_range
120562
+       && len != 8 && len != 4 && len != 2 && len != 1)
120562
+      || (kernel_supports_any_contiguous_range
120562
+	  && (len < 1 || len > 8)))
120562
     return 0;
120562
 
120562
   return 1;
120562
@@ -1053,11 +1171,12 @@
120562
 
120562
 static int
120562
 aarch64_dr_state_insert_one_point (struct aarch64_debug_reg_state *state,
120562
-				   int type, CORE_ADDR addr, int len)
120562
+				   int type, CORE_ADDR addr, int offset, int len,
120562
+				   CORE_ADDR addr_orig)
120562
 {
120562
   int i, idx, num_regs, is_watchpoint;
120562
   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
120562
-  CORE_ADDR *dr_addr_p;
120562
+  CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
120562
 
120562
   /* Set up state pointers.  */
120562
   is_watchpoint = (type != hw_execute);
120562
@@ -1066,6 +1185,7 @@
120562
     {
120562
       num_regs = aarch64_num_wp_regs;
120562
       dr_addr_p = state->dr_addr_wp;
120562
+      dr_addr_orig_p = state->dr_addr_orig_wp;
120562
       dr_ctrl_p = state->dr_ctrl_wp;
120562
       dr_ref_count = state->dr_ref_count_wp;
120562
     }
120562
@@ -1073,11 +1193,12 @@
120562
     {
120562
       num_regs = aarch64_num_bp_regs;
120562
       dr_addr_p = state->dr_addr_bp;
120562
+      dr_addr_orig_p = NULL;
120562
       dr_ctrl_p = state->dr_ctrl_bp;
120562
       dr_ref_count = state->dr_ref_count_bp;
120562
     }
120562
 
120562
-  ctrl = aarch64_point_encode_ctrl_reg (type, len);
120562
+  ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
120562
 
120562
   /* Find an existing or free register in our cache.  */
120562
   idx = -1;
120562
@@ -1089,7 +1210,9 @@
120562
 	  idx = i;
120562
 	  /* no break; continue hunting for an existing one.  */
120562
 	}
120562
-      else if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
120562
+      else if (dr_addr_p[i] == addr
120562
+	       && (dr_addr_orig_p == NULL || dr_addr_orig_p[i] == addr_orig)
120562
+	       && dr_ctrl_p[i] == ctrl)
120562
 	{
120562
 	  gdb_assert (dr_ref_count[i] != 0);
120562
 	  idx = i;
120562
@@ -1106,6 +1229,8 @@
120562
     {
120562
       /* new entry */
120562
       dr_addr_p[idx] = addr;
120562
+      if (dr_addr_orig_p != NULL)
120562
+	dr_addr_orig_p[idx] = addr_orig;
120562
       dr_ctrl_p[idx] = ctrl;
120562
       dr_ref_count[idx] = 1;
120562
       /* Notify the change.  */
120562
@@ -1125,11 +1250,12 @@
120562
 
120562
 static int
120562
 aarch64_dr_state_remove_one_point (struct aarch64_debug_reg_state *state,
120562
-				   int type, CORE_ADDR addr, int len)
120562
+				   int type, CORE_ADDR addr, int offset, int len,
120562
+				   CORE_ADDR addr_orig)
120562
 {
120562
   int i, num_regs, is_watchpoint;
120562
   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
120562
-  CORE_ADDR *dr_addr_p;
120562
+  CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
120562
 
120562
   /* Set up state pointers.  */
120562
   is_watchpoint = (type != hw_execute);
120562
@@ -1138,6 +1264,7 @@
120562
     {
120562
       num_regs = aarch64_num_wp_regs;
120562
       dr_addr_p = state->dr_addr_wp;
120562
+      dr_addr_orig_p = state->dr_addr_orig_wp;
120562
       dr_ctrl_p = state->dr_ctrl_wp;
120562
       dr_ref_count = state->dr_ref_count_wp;
120562
     }
120562
@@ -1145,15 +1272,18 @@
120562
     {
120562
       num_regs = aarch64_num_bp_regs;
120562
       dr_addr_p = state->dr_addr_bp;
120562
+      dr_addr_orig_p = NULL;
120562
       dr_ctrl_p = state->dr_ctrl_bp;
120562
       dr_ref_count = state->dr_ref_count_bp;
120562
     }
120562
 
120562
-  ctrl = aarch64_point_encode_ctrl_reg (type, len);
120562
+  ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
120562
 
120562
   /* Find the entry that matches the ADDR and CTRL.  */
120562
   for (i = 0; i < num_regs; ++i)
120562
-    if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
120562
+    if (dr_addr_p[i] == addr
120562
+	&& (dr_addr_orig_p == NULL || dr_addr_orig_p[i] == addr_orig)
120562
+	&& dr_ctrl_p[i] == ctrl)
120562
       {
120562
 	gdb_assert (dr_ref_count[i] != 0);
120562
 	break;
120562
@@ -1169,6 +1299,8 @@
120562
       /* Clear the enable bit.  */
120562
       ctrl &= ~1;
120562
       dr_addr_p[i] = 0;
120562
+      if (dr_addr_orig_p != NULL)
120562
+	dr_addr_orig_p[i] = 0;
120562
       dr_ctrl_p[i] = ctrl;
120562
       /* Notify the change.  */
120562
       aarch64_notify_debug_reg_change (state, is_watchpoint, i);
120562
@@ -1192,9 +1324,9 @@
120562
   state = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid));
120562
 
120562
   if (is_insert)
120562
-    return aarch64_dr_state_insert_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_insert_one_point (state, type, addr, 0, len, -1);
120562
   else
120562
-    return aarch64_dr_state_remove_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_remove_one_point (state, type, addr, 0, len, -1);
120562
 }
120562
 
120562
 /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
120562
@@ -1271,9 +1403,9 @@
120562
     = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid));
120562
 
120562
   if (is_insert)
120562
-    return aarch64_dr_state_insert_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_insert_one_point (state, type, addr, 0, len, addr);
120562
   else
120562
-    return aarch64_dr_state_remove_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_remove_one_point (state, type, addr, 0, len, addr);
120562
 }
120562
 
120562
 /* Insert/remove unaligned watchpoint by calling
120562
@@ -1289,28 +1421,41 @@
120562
 {
120562
   struct aarch64_debug_reg_state *state
120562
     = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid));
120562
+  CORE_ADDR addr_orig = addr;
120562
 
120562
   while (len > 0)
120562
     {
120562
       CORE_ADDR aligned_addr;
120562
-      int aligned_len, ret;
120562
+      int aligned_offset, aligned_len, ret;
120562
+      CORE_ADDR addr_orig_next = addr_orig;
120562
 
120562
-      aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_len,
120562
-				&addr, &len;;
120562
+      aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_offset,
120562
+				&aligned_len, &addr, &len, &addr_orig_next);
120562
 
120562
       if (is_insert)
120562
 	ret = aarch64_dr_state_insert_one_point (state, type, aligned_addr,
120562
-						 aligned_len);
120562
+						 aligned_offset,
120562
+						 aligned_len, addr_orig);
120562
       else
120562
 	ret = aarch64_dr_state_remove_one_point (state, type, aligned_addr,
120562
-						 aligned_len);
120562
+						 aligned_offset,
120562
+						 aligned_len, addr_orig);
120562
 
120562
       if (debug_hw_points)
120562
 	fprintf_unfiltered (gdb_stdlog,
120562
 "handle_unaligned_watchpoint: is_insert: %d\n"
120562
 "                             aligned_addr: 0x%08lx, aligned_len: %d\n"
120562
-"                                next_addr: 0x%08lx,    next_len: %d\n",
120562
-		 is_insert, aligned_addr, aligned_len, addr, len);
120562
+"                                addr_orig: %s\n"
120562
+"                                                                "
120562
+"                                next_addr: %s,    next_len: %d\n"
120562
+"                                                           "
120562
+"                                addr_orig_next: %s\n",
120562
+		 is_insert, aligned_addr,
120562
+		      aligned_len, core_addr_to_string_nz (addr_orig),
120562
+		      core_addr_to_string_nz (addr), len,
120562
+		      core_addr_to_string_nz (addr_orig_next));
120562
+
120562
+      addr_orig = addr_orig_next;
120562
 
120562
       if (ret != 0)
120562
 	return ret;
120562
@@ -1456,16 +1601,38 @@
120562
   state = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid));
120562
   for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
120562
     {
120562
+      const unsigned int offset
120562
+	= aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
120562
       const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
120562
       const CORE_ADDR addr_trap = (CORE_ADDR) siginfo.si_addr;
120562
-      const CORE_ADDR addr_watch = state->dr_addr_wp[i];
120562
+      const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
120562
+      const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
120562
+      const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
120562
 
120562
       if (state->dr_ref_count_wp[i]
120562
 	  && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
120562
-	  && addr_trap >= addr_watch
120562
+	  && addr_trap >= addr_watch_aligned
120562
 	  && addr_trap < addr_watch + len)
120562
 	{
120562
-	  *addr_p = addr_trap;
120562
+	  /* ADDR_TRAP reports the first address of the memory range
120562
+	     accessed by the CPU, regardless of what was the memory
120562
+	     range watched.  Thus, a large CPU access that straddles
120562
+	     the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
120562
+	     ADDR_TRAP that is lower than the
120562
+	     ADDR_WATCH..ADDR_WATCH+LEN range.  E.g.:
120562
+
120562
+	     addr: |   4   |   5   |   6   |   7   |   8   |
120562
+				   |---- range watched ----|
120562
+		   |----------- range accessed ------------|
120562
+
120562
+	     In this case, ADDR_TRAP will be 4.
120562
+
120562
+	     To match a watchpoint known to GDB core, we must never
120562
+	     report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
120562
+	     range.  ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
120562
+	     positive on kernels older than 4.10.  See PR
120562
+	     external/20207.  */
120562
+	  *addr_p = addr_orig;
120562
 	  return 1;
120562
 	}
120562
     }
120562
Index: gdb-7.6.1/gdb/common/common-utils.c
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/common/common-utils.c	2013-02-14 18:11:41.000000000 +0100
120562
+++ gdb-7.6.1/gdb/common/common-utils.c	2018-05-05 17:12:49.570781881 +0200
120562
@@ -161,3 +161,23 @@
120562
   p[len] = 0;
120562
   return p;
120562
 }
120562
+
120562
+/* See common/common-utils.h.  */
120562
+
120562
+ULONGEST
120562
+align_up (ULONGEST v, int n)
120562
+{
120562
+  /* Check that N is really a power of two.  */
120562
+  gdb_assert (n && (n & (n-1)) == 0);
120562
+  return (v + n - 1) & -n;
120562
+}
120562
+
120562
+/* See common/common-utils.h.  */
120562
+
120562
+ULONGEST
120562
+align_down (ULONGEST v, int n)
120562
+{
120562
+  /* Check that N is really a power of two.  */
120562
+  gdb_assert (n && (n & (n-1)) == 0);
120562
+  return (v & -n);
120562
+}
120562
Index: gdb-7.6.1/gdb/common/common-utils.h
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/common/common-utils.h	2013-02-14 18:11:41.000000000 +0100
120562
+++ gdb-7.6.1/gdb/common/common-utils.h	2018-05-05 17:12:49.570781881 +0200
120562
@@ -53,4 +53,36 @@
120562
 
120562
 char *savestring (const char *ptr, size_t len);
120562
 
120562
+/* Ensure that V is aligned to an N byte boundary (B's assumed to be a
120562
+   power of 2).  Round up/down when necessary.  Examples of correct
120562
+   use include:
120562
+
120562
+    addr = align_up (addr, 8); -- VALUE needs 8 byte alignment
120562
+    write_memory (addr, value, len);
120562
+    addr += len;
120562
+
120562
+   and:
120562
+
120562
+    sp = align_down (sp - len, 16); -- Keep SP 16 byte aligned
120562
+    write_memory (sp, value, len);
120562
+
120562
+   Note that uses such as:
120562
+
120562
+    write_memory (addr, value, len);
120562
+    addr += align_up (len, 8);
120562
+
120562
+   and:
120562
+
120562
+    sp -= align_up (len, 8);
120562
+    write_memory (sp, value, len);
120562
+
120562
+   are typically not correct as they don't ensure that the address (SP
120562
+   or ADDR) is correctly aligned (relying on previous alignment to
120562
+   keep things right).  This is also why the methods are called
120562
+   "align_..." instead of "round_..." as the latter reads better with
120562
+   this incorrect coding style.  */
120562
+
120562
+extern ULONGEST align_up (ULONGEST v, int n);
120562
+extern ULONGEST align_down (ULONGEST v, int n);
120562
+
120562
 #endif
120562
Index: gdb-7.6.1/gdb/gdbserver/linux-aarch64-low.c
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/gdbserver/linux-aarch64-low.c	2018-05-05 17:12:47.501763392 +0200
120562
+++ gdb-7.6.1/gdb/gdbserver/linux-aarch64-low.c	2018-05-05 17:12:49.570781881 +0200
120562
@@ -40,6 +40,18 @@
120562
 #include <sys/reg.h>
120562
 #endif
120562
 
120562
+/* ptrace expects control registers to be formatted as follows:
120562
+
120562
+   31                             13          5      3      1     0
120562
+   +--------------------------------+----------+------+------+----+
120562
+   |         RESERVED (SBZ)         |   MASK   | TYPE | PRIV | EN |
120562
+   +--------------------------------+----------+------+------+----+
120562
+
120562
+   The TYPE field is ignored for breakpoints.  */
120562
+
120562
+#define DR_CONTROL_ENABLED(ctrl)	(((ctrl) & 0x1) == 1)
120562
+#define DR_CONTROL_MASK(ctrl)		(((ctrl) >> 5) & 0xff)
120562
+
120562
 #define AARCH64_X_REGS_NUM 31
120562
 #define AARCH64_V_REGS_NUM 32
120562
 #define AARCH64_X0_REGNO    0
120562
@@ -170,7 +182,10 @@
120562
   unsigned int dr_ref_count_bp[AARCH64_HBP_MAX_NUM];
120562
 
120562
   /* hardware watchpoint */
120562
+  /* Address aligned down to AARCH64_HWP_ALIGNMENT.  */
120562
   CORE_ADDR dr_addr_wp[AARCH64_HWP_MAX_NUM];
120562
+  /* Address as entered by user without any forced alignment.  */
120562
+  CORE_ADDR dr_addr_orig_wp[AARCH64_HWP_MAX_NUM];
120562
   unsigned int dr_ctrl_wp[AARCH64_HWP_MAX_NUM];
120562
   unsigned int dr_ref_count_wp[AARCH64_HWP_MAX_NUM];
120562
 };
120562
@@ -311,6 +326,29 @@
120562
     supply_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
120562
 }
120562
 
120562
+/* True if this kernel does not have the bug described by PR
120562
+   external/20207 (Linux >= 4.10).  A fixed kernel supports any
120562
+   contiguous range of bits in 8-bit byte DR_CONTROL_MASK.  A buggy
120562
+   kernel supports only 0x01, 0x03, 0x0f and 0xff.  We start by
120562
+   assuming the bug is fixed, and then detect the bug at
120562
+   PTRACE_SETREGSET time.  */
120562
+static int kernel_supports_any_contiguous_range = 1;
120562
+
120562
+/* Return starting byte 0..7 incl. of a watchpoint encoded by CTRL.  */
120562
+
120562
+static unsigned int
120562
+aarch64_watchpoint_offset (unsigned int ctrl)
120562
+{
120562
+  uint8_t mask = DR_CONTROL_MASK (ctrl);
120562
+  unsigned retval;
120562
+
120562
+  /* Shift out bottom zeros.  */
120562
+  for (retval = 0; mask && (mask & 1) == 0; ++retval)
120562
+    mask >>= 1;
120562
+
120562
+  return retval;
120562
+}
120562
+
120562
 /* Debugging of hardware breakpoint/watchpoint support.  */
120562
 extern int debug_hw_points;
120562
 
120562
@@ -383,8 +421,8 @@
120562
 
120562
   fprintf (stderr, "\tWATCHPOINTs:\n");
120562
   for (i = 0; i < aarch64_num_wp_regs; i++)
120562
-    fprintf (stderr, "\tWP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
120562
-	     i, paddress (state->dr_addr_wp[i]),
120562
+    fprintf (stderr, "\tWP%d: addr=0x%s (orig=0x%s), ctrl=0x%08x, ref.count=%d\n",
120562
+	     i, paddress (state->dr_addr_wp[i]), paddress (state->dr_addr_orig_wp[i]),
120562
 	     state->dr_ctrl_wp[i], state->dr_ref_count_wp[i]);
120562
 }
120562
 
120562
@@ -422,27 +460,27 @@
120562
 
120562
 /* Utility function that returns the length in bytes of a watchpoint
120562
    according to the content of a hardware debug control register CTRL.
120562
-   Note that the kernel currently only supports the following Byte
120562
-   Address Select (BAS) values: 0x1, 0x3, 0xf and 0xff, which means
120562
-   that for a hardware watchpoint, its valid length can only be 1
120562
-   byte, 2 bytes, 4 bytes or 8 bytes.  */
120562
+   Any contiguous range of bytes in CTRL is supported.  The returned
120562
+   value can be between 0..8 (inclusive).  */
120562
 
120562
 static inline unsigned int
120562
 aarch64_watchpoint_length (unsigned int ctrl)
120562
 {
120562
-  switch (DR_CONTROL_LENGTH (ctrl))
120562
-    {
120562
-    case 0x01:
120562
-      return 1;
120562
-    case 0x03:
120562
-      return 2;
120562
-    case 0x0f:
120562
-      return 4;
120562
-    case 0xff:
120562
-      return 8;
120562
-    default:
120562
-      return 0;
120562
-    }
120562
+  uint8_t mask = DR_CONTROL_MASK (ctrl);
120562
+  unsigned retval;
120562
+
120562
+  /* Shift out bottom zeros.  */
120562
+  mask >>= aarch64_watchpoint_offset (ctrl);
120562
+
120562
+  /* Count bottom ones.  */
120562
+  for (retval = 0; (mask & 1) != 0; ++retval)
120562
+    mask >>= 1;
120562
+
120562
+  if (mask != 0)
120562
+    error (_("Unexpected hardware watchpoint length register value 0x%x"),
120562
+	   DR_CONTROL_MASK (ctrl));
120562
+
120562
+  return retval;
120562
 }
120562
 
120562
 /* Given the hardware breakpoint or watchpoint type TYPE and its
120562
@@ -450,14 +488,17 @@
120562
    breakpoint/watchpoint control register.  */
120562
 
120562
 static unsigned int
120562
-aarch64_point_encode_ctrl_reg (enum target_point_type type, int len)
120562
+aarch64_point_encode_ctrl_reg (enum target_point_type type, int offset, int len)
120562
 {
120562
   unsigned int ctrl;
120562
 
120562
+  gdb_assert (offset == 0 || kernel_supports_any_contiguous_range);
120562
+  gdb_assert (offset + len <= AARCH64_HWP_MAX_LEN_PER_REG);
120562
+
120562
   /* type */
120562
   ctrl = type << 3;
120562
-  /* length bitmask */
120562
-  ctrl |= ((1 << len) - 1) << 5;
120562
+  /* offset and length bitmask */
120562
+  ctrl |= ((1 << len) - 1) << (5 + offset);
120562
   /* enabled at el0 */
120562
   ctrl |= (2 << 1) | 1;
120562
 
120562
@@ -486,17 +527,23 @@
120562
   if (addr & (alignment - 1))
120562
     return 0;
120562
 
120562
-  if (len != 8 && len != 4 && len != 2 && len != 1)
120562
+  if ((!kernel_supports_any_contiguous_range
120562
+       && len != 8 && len != 4 && len != 2 && len != 1)
120562
+      || (kernel_supports_any_contiguous_range
120562
+	  && (len < 1 || len > 8)))
120562
     return 0;
120562
 
120562
   return 1;
120562
 }
120562
 
120562
 /* Given the (potentially unaligned) watchpoint address in ADDR and
120562
-   length in LEN, return the aligned address and aligned length in
120562
-   *ALIGNED_ADDR_P and *ALIGNED_LEN_P, respectively.  The returned
120562
-   aligned address and length will be valid to be written to the
120562
-   hardware watchpoint value and control registers.  See the comment
120562
+   length in LEN, return the aligned address, offset from that base
120562
+   address, and aligned length in *ALIGNED_ADDR_P, *ALIGNED_OFFSET_P
120562
+   and *ALIGNED_LEN_P, respectively.  The returned values will be
120562
+   valid values to write to the hardware watchpoint value and control
120562
+   registers.
120562
+
120562
+   See the comment
120562
    above aarch64_point_is_aligned for the information about the
120562
    alignment requirement.  The given watchpoint may get truncated if
120562
    more than one hardware register is needed to cover the watched
120562
@@ -533,11 +580,12 @@
120562
 
120562
 static void
120562
 aarch64_align_watchpoint (CORE_ADDR addr, int len, CORE_ADDR *aligned_addr_p,
120562
-			  int *aligned_len_p, CORE_ADDR *next_addr_p,
120562
-			  int *next_len_p)
120562
+			  int *aligned_offset_p, int *aligned_len_p,
120562
+			  CORE_ADDR *next_addr_p, int *next_len_p,
120562
+			  CORE_ADDR *next_addr_orig_p)
120562
 {
120562
   int aligned_len;
120562
-  unsigned int offset;
120562
+  unsigned int offset, aligned_offset;
120562
   CORE_ADDR aligned_addr;
120562
   const unsigned int alignment = AARCH64_HWP_ALIGNMENT;
120562
   const unsigned int max_wp_len = AARCH64_HWP_MAX_LEN_PER_REG;
120562
@@ -548,10 +596,12 @@
120562
   if (len <= 0)
120562
     return;
120562
 
120562
-  /* Address to be put into the hardware watchpoint value register
120562
-     must be aligned.  */
120562
+  /* The address put into the hardware watchpoint value register must
120562
+     be aligned.  */
120562
   offset = addr & (alignment - 1);
120562
   aligned_addr = addr - offset;
120562
+  aligned_offset
120562
+    = kernel_supports_any_contiguous_range ? addr & (alignment - 1) : 0;
120562
 
120562
   gdb_assert (offset >= 0 && offset < alignment);
120562
   gdb_assert (aligned_addr >= 0 && aligned_addr <= addr);
120562
@@ -559,9 +609,10 @@
120562
 
120562
   if (offset + len >= max_wp_len)
120562
     {
120562
-      /* Need more than one watchpoint registers; truncate it at the
120562
+      /* Need more than one watchpoint register; truncate at the
120562
 	 alignment boundary.  */
120562
-      aligned_len = max_wp_len;
120562
+      aligned_len
120562
+	= max_wp_len - (kernel_supports_any_contiguous_range ? offset : 0);
120562
       len -= (max_wp_len - offset);
120562
       addr += (max_wp_len - offset);
120562
       gdb_assert ((addr & (alignment - 1)) == 0);
120562
@@ -574,26 +625,96 @@
120562
 	aligned_len_array[AARCH64_HWP_MAX_LEN_PER_REG] =
120562
 	{ 1, 2, 4, 4, 8, 8, 8, 8 };
120562
 
120562
-      aligned_len = aligned_len_array[offset + len - 1];
120562
+      aligned_len = (kernel_supports_any_contiguous_range
120562
+		     ? len : aligned_len_array[offset + len - 1]);
120562
       addr += len;
120562
       len = 0;
120562
     }
120562
 
120562
   if (aligned_addr_p != NULL)
120562
     *aligned_addr_p = aligned_addr;
120562
+  if (aligned_offset_p)
120562
+    *aligned_offset_p = aligned_offset;
120562
   if (aligned_len_p != NULL)
120562
     *aligned_len_p = aligned_len;
120562
   if (next_addr_p != NULL)
120562
     *next_addr_p = addr;
120562
   if (next_len_p != NULL)
120562
     *next_len_p = len;
120562
+  if (next_addr_orig_p)
120562
+    *next_addr_orig_p = align_down (*next_addr_orig_p + alignment, alignment);
120562
+}
120562
+
120562
+/* Reconfigure STATE to be compatible with Linux kernels with the PR
120562
+   external/20207 bug.  This is called when
120562
+   KERNEL_SUPPORTS_ANY_CONTIGUOUS_RANGE transitions to false.  Note we
120562
+   don't try to support combining watchpoints with matching (and thus
120562
+   shared) masks, as it's too late when we get here.  On buggy
120562
+   kernels, GDB will try to first setup the perfect matching ranges,
120562
+   which will run out of registers before this function can merge
120562
+   them.  It doesn't look like worth the effort to improve that, given
120562
+   eventually buggy kernels will be phased out.  */
120562
+
120562
+static void aarch64_notify_debug_reg_change (const struct aarch64_debug_reg_state *state, int is_watchpoint, unsigned int idx);
120562
+
120562
+static void
120562
+aarch64_downgrade_regs (struct aarch64_debug_reg_state *state)
120562
+{
120562
+  int i;
120562
+
120562
+  for (i = 0; i < aarch64_num_wp_regs; ++i)
120562
+    if ((state->dr_ctrl_wp[i] & 1) != 0)
120562
+      {
120562
+	uint8_t mask_orig;
120562
+	static const uint8_t old_valid[] = { 0x01, 0x03, 0x0f, 0xff };
120562
+	int old_validi;
120562
+	uint8_t mask = 0;
120562
+	int j;
120562
+
120562
+	gdb_assert (state->dr_ref_count_wp[i] != 0);
120562
+	mask_orig = (state->dr_ctrl_wp[i] >> 5) & 0xff;
120562
+	gdb_assert (mask_orig != 0);
120562
+	for (old_validi = 0; old_validi < sizeof(old_valid) / sizeof (*old_valid); old_validi++) {
120562
+	  const uint8_t old_mask = old_valid[old_validi];
120562
+	  if (mask_orig <= old_mask)
120562
+	    {
120562
+	      mask = old_mask;
120562
+	      break;
120562
+	    }
120562
+	}
120562
+	gdb_assert (mask != 0);
120562
+
120562
+	/* No update needed for this watchpoint?  */
120562
+	if (mask == mask_orig)
120562
+	  continue;
120562
+	state->dr_ctrl_wp[i] |= mask << 5;
120562
+	state->dr_addr_wp[i]
120562
+	  = align_down (state->dr_addr_wp[i], AARCH64_HWP_ALIGNMENT);
120562
+
120562
+	/* Try to match duplicate entries.  */
120562
+	for (j = 0; j < i; ++j)
120562
+	  if ((state->dr_ctrl_wp[j] & 1) != 0
120562
+	      && state->dr_addr_wp[j] == state->dr_addr_wp[i]
120562
+	      && state->dr_addr_orig_wp[j] == state->dr_addr_orig_wp[i]
120562
+	      && state->dr_ctrl_wp[j] == state->dr_ctrl_wp[i])
120562
+	    {
120562
+	      state->dr_ref_count_wp[j] += state->dr_ref_count_wp[i];
120562
+	      state->dr_ref_count_wp[i] = 0;
120562
+	      state->dr_addr_wp[i] = 0;
120562
+	      state->dr_addr_orig_wp[i] = 0;
120562
+	      state->dr_ctrl_wp[i] &= ~1;
120562
+	      break;
120562
+	    }
120562
+
120562
+	aarch64_notify_debug_reg_change (state, 1 /* is_watchpoint */, i);
120562
+      }
120562
 }
120562
 
120562
 /* Call ptrace to set the thread TID's hardware breakpoint/watchpoint
120562
    registers with data from *STATE.  */
120562
 
120562
 static void
120562
-aarch64_linux_set_debug_regs (const struct aarch64_debug_reg_state *state,
120562
+aarch64_linux_set_debug_regs (struct aarch64_debug_reg_state *state,
120562
 			      int tid, int watchpoint)
120562
 {
120562
   int i, count;
120562
@@ -621,7 +742,18 @@
120562
   if (ptrace (PTRACE_SETREGSET, tid,
120562
 	      watchpoint ? NT_ARM_HW_WATCH : NT_ARM_HW_BREAK,
120562
 	      (void *) &iov))
120562
-    error (_("Unexpected error setting hardware debug registers"));
120562
+    {
120562
+      /* Handle Linux kernels with the PR external/20207 bug.  */
120562
+      if (watchpoint && errno == EINVAL
120562
+	  && kernel_supports_any_contiguous_range)
120562
+	{
120562
+	  kernel_supports_any_contiguous_range = 0;
120562
+	  aarch64_downgrade_regs (state);
120562
+	  aarch64_linux_set_debug_regs (state, tid, watchpoint);
120562
+	  return;
120562
+	}
120562
+      error (_("Unexpected error setting hardware debug registers"));
120562
+    }
120562
 }
120562
 
120562
 struct aarch64_dr_update_callback_param
120562
@@ -750,11 +882,12 @@
120562
 static int
120562
 aarch64_dr_state_insert_one_point (struct aarch64_debug_reg_state *state,
120562
 				   enum target_point_type type,
120562
-				   CORE_ADDR addr, int len)
120562
+				   CORE_ADDR addr, int offset, int len,
120562
+				   CORE_ADDR addr_orig)
120562
 {
120562
   int i, idx, num_regs, is_watchpoint;
120562
   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
120562
-  CORE_ADDR *dr_addr_p;
120562
+  CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
120562
 
120562
   /* Set up state pointers.  */
120562
   is_watchpoint = (type != hw_execute);
120562
@@ -763,6 +896,7 @@
120562
     {
120562
       num_regs = aarch64_num_wp_regs;
120562
       dr_addr_p = state->dr_addr_wp;
120562
+      dr_addr_orig_p = state->dr_addr_orig_wp;
120562
       dr_ctrl_p = state->dr_ctrl_wp;
120562
       dr_ref_count = state->dr_ref_count_wp;
120562
     }
120562
@@ -770,11 +904,12 @@
120562
     {
120562
       num_regs = aarch64_num_bp_regs;
120562
       dr_addr_p = state->dr_addr_bp;
120562
+      dr_addr_orig_p = NULL;
120562
       dr_ctrl_p = state->dr_ctrl_bp;
120562
       dr_ref_count = state->dr_ref_count_bp;
120562
     }
120562
 
120562
-  ctrl = aarch64_point_encode_ctrl_reg (type, len);
120562
+  ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
120562
 
120562
   /* Find an existing or free register in our cache.  */
120562
   idx = -1;
120562
@@ -786,7 +921,9 @@
120562
 	  idx = i;
120562
 	  /* no break; continue hunting for an exising one.  */
120562
 	}
120562
-      else if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
120562
+      else if (dr_addr_p[i] == addr
120562
+	       && (dr_addr_orig_p == NULL || dr_addr_orig_p[i] == addr_orig)
120562
+	       && dr_ctrl_p[i] == ctrl)
120562
 	{
120562
 	  gdb_assert (dr_ref_count[i] != 0);
120562
 	  idx = i;
120562
@@ -803,6 +940,8 @@
120562
     {
120562
       /* new entry */
120562
       dr_addr_p[idx] = addr;
120562
+      if (dr_addr_orig_p != NULL)
120562
+	dr_addr_orig_p[idx] = addr_orig;
120562
       dr_ctrl_p[idx] = ctrl;
120562
       dr_ref_count[idx] = 1;
120562
       /* Notify the change.  */
120562
@@ -823,11 +962,12 @@
120562
 static int
120562
 aarch64_dr_state_remove_one_point (struct aarch64_debug_reg_state *state,
120562
 				   enum target_point_type type,
120562
-				   CORE_ADDR addr, int len)
120562
+				   CORE_ADDR addr, int offset, int len,
120562
+				   CORE_ADDR addr_orig)
120562
 {
120562
   int i, num_regs, is_watchpoint;
120562
   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
120562
-  CORE_ADDR *dr_addr_p;
120562
+  CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
120562
 
120562
   /* Set up state pointers.  */
120562
   is_watchpoint = (type != hw_execute);
120562
@@ -836,6 +976,7 @@
120562
     {
120562
       num_regs = aarch64_num_wp_regs;
120562
       dr_addr_p = state->dr_addr_wp;
120562
+      dr_addr_orig_p = state->dr_addr_orig_wp;
120562
       dr_ctrl_p = state->dr_ctrl_wp;
120562
       dr_ref_count = state->dr_ref_count_wp;
120562
     }
120562
@@ -843,15 +984,18 @@
120562
     {
120562
       num_regs = aarch64_num_bp_regs;
120562
       dr_addr_p = state->dr_addr_bp;
120562
+      dr_addr_orig_p = NULL;
120562
       dr_ctrl_p = state->dr_ctrl_bp;
120562
       dr_ref_count = state->dr_ref_count_bp;
120562
     }
120562
 
120562
-  ctrl = aarch64_point_encode_ctrl_reg (type, len);
120562
+  ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
120562
 
120562
   /* Find the entry that matches the ADDR and CTRL.  */
120562
   for (i = 0; i < num_regs; ++i)
120562
-    if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
120562
+    if (dr_addr_p[i] == addr
120562
+	&& (dr_addr_orig_p == NULL || dr_addr_orig_p[i] == addr_orig)
120562
+	&& dr_ctrl_p[i] == ctrl)
120562
       {
120562
 	gdb_assert (dr_ref_count[i] != 0);
120562
 	break;
120562
@@ -867,6 +1011,8 @@
120562
       /* Clear the enable bit.  */
120562
       ctrl &= ~1;
120562
       dr_addr_p[i] = 0;
120562
+      if (dr_addr_orig_p != NULL)
120562
+	dr_addr_orig_p[i] = 0;
120562
       dr_ctrl_p[i] = ctrl;
120562
       /* Notify the change.  */
120562
       aarch64_notify_debug_reg_change (state, is_watchpoint, i);
120562
@@ -889,9 +1035,9 @@
120562
   state = aarch64_get_debug_reg_state ();
120562
 
120562
   if (is_insert)
120562
-    return aarch64_dr_state_insert_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_insert_one_point (state, type, addr, 0, len, -1);
120562
   else
120562
-    return aarch64_dr_state_remove_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_remove_one_point (state, type, addr, 0, len, -1);
120562
 }
120562
 
120562
 /* This is essentially the same as aarch64_handle_breakpoint, apart
120562
@@ -906,9 +1052,9 @@
120562
   state = aarch64_get_debug_reg_state ();
120562
 
120562
   if (is_insert)
120562
-    return aarch64_dr_state_insert_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_insert_one_point (state, type, addr, 0, len, addr);
120562
   else
120562
-    return aarch64_dr_state_remove_one_point (state, type, addr, len);
120562
+    return aarch64_dr_state_remove_one_point (state, type, addr, 0, len, addr);
120562
 }
120562
 
120562
 /* Insert/remove unaligned watchpoint by calling
120562
@@ -924,29 +1070,41 @@
120562
 {
120562
   struct aarch64_debug_reg_state *state
120562
     = aarch64_get_debug_reg_state ();
120562
+  CORE_ADDR addr_orig = addr;
120562
 
120562
   while (len > 0)
120562
     {
120562
       CORE_ADDR aligned_addr;
120562
-      int aligned_len, ret;
120562
+      int aligned_offset, aligned_len, ret;
120562
+      CORE_ADDR addr_orig_next = addr_orig;
120562
 
120562
-      aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_len,
120562
-				&addr, &len;;
120562
+      aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_offset,
120562
+				&aligned_len, &addr, &len, &addr_orig_next);
120562
 
120562
       if (is_insert)
120562
 	ret = aarch64_dr_state_insert_one_point (state, type, aligned_addr,
120562
-						 aligned_len);
120562
+						 aligned_offset,
120562
+						 aligned_len, addr_orig);
120562
       else
120562
 	ret = aarch64_dr_state_remove_one_point (state, type, aligned_addr,
120562
-						 aligned_len);
120562
+						 aligned_offset,
120562
+						 aligned_len, addr_orig);
120562
 
120562
       if (debug_hw_points)
120562
 	fprintf (stderr,
120562
  "handle_unaligned_watchpoint: is_insert: %d\n"
120562
  "                             aligned_addr: 0x%s, aligned_len: %d\n"
120562
- "                                next_addr: 0x%s,    next_len: %d\n",
120562
-		 is_insert, paddress (aligned_addr), aligned_len,
120562
-		 paddress (addr), len);
120562
+ "                                addr_orig: %s\n"
120562
+ "                                                                "
120562
+ "                                next_addr: %s,    next_len: %d\n"
120562
+ "                                                           "
120562
+ "                                addr_orig_next: %s\n",
120562
+		 is_insert, paddress (aligned_addr),
120562
+		      aligned_len, paddress (addr_orig),
120562
+		      paddress (addr), len,
120562
+		      paddress (addr_orig_next));
120562
+ 
120562
+       addr_orig = addr_orig_next;
120562
 
120562
       if (ret != 0)
120562
 	return ret;
120562
@@ -1065,14 +1223,39 @@
120562
   state = aarch64_get_debug_reg_state ();
120562
   for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
120562
     {
120562
+      const unsigned int offset
120562
+	= aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
120562
       const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
120562
       const CORE_ADDR addr_trap = (CORE_ADDR) siginfo.si_addr;
120562
-      const CORE_ADDR addr_watch = state->dr_addr_wp[i];
120562
+      const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
120562
+      const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
120562
+      const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
120562
+
120562
       if (state->dr_ref_count_wp[i]
120562
 	  && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
120562
-	  && addr_trap >= addr_watch
120562
+	  && addr_trap >= addr_watch_aligned
120562
 	  && addr_trap < addr_watch + len)
120562
-	return addr_trap;
120562
+	{
120562
+	  /* ADDR_TRAP reports the first address of the memory range
120562
+	     accessed by the CPU, regardless of what was the memory
120562
+	     range watched.  Thus, a large CPU access that straddles
120562
+	     the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
120562
+	     ADDR_TRAP that is lower than the
120562
+	     ADDR_WATCH..ADDR_WATCH+LEN range.  E.g.:
120562
+
120562
+	     addr: |   4   |   5   |   6   |   7   |   8   |
120562
+				   |---- range watched ----|
120562
+		   |----------- range accessed ------------|
120562
+
120562
+	     In this case, ADDR_TRAP will be 4.
120562
+
120562
+	     To match a watchpoint known to GDB core, we must never
120562
+	     report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
120562
+	     range.  ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
120562
+	     positive on kernels older than 4.10.  See PR
120562
+	     external/20207.  */
120562
+	  return addr_orig;
120562
+	}
120562
     }
120562
 
120562
   return (CORE_ADDR) 0;
120562
Index: gdb-7.6.1/gdb/testsuite/gdb.base/watchpoint-unaligned.c
120562
===================================================================
120562
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
120562
+++ gdb-7.6.1/gdb/testsuite/gdb.base/watchpoint-unaligned.c	2018-05-05 17:12:49.571781890 +0200
120562
@@ -0,0 +1,96 @@
120562
+/* This testcase is part of GDB, the GNU debugger.
120562
+
120562
+   Copyright 2017-2018 Free Software Foundation, Inc.
120562
+
120562
+   This program is free software; you can redistribute it and/or modify
120562
+   it under the terms of the GNU General Public License as published by
120562
+   the Free Software Foundation; either version 3 of the License, or
120562
+   (at your option) any later version.
120562
+
120562
+   This program is distributed in the hope that it will be useful,
120562
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
120562
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
120562
+   GNU General Public License for more details.
120562
+
120562
+   You should have received a copy of the GNU General Public License
120562
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
120562
+
120562
+#include <stdint.h>
120562
+#include <assert.h>
120562
+
120562
+static int again;
120562
+
120562
+static volatile struct
120562
+{
120562
+  uint64_t alignment;
120562
+  union
120562
+    {
120562
+      uint64_t size8[1];
120562
+      uint32_t size4[2];
120562
+      uint16_t size2[4];
120562
+      uint8_t size1[8];
120562
+      uint64_t size8twice[2];
120562
+    }
120562
+  u;
120562
+} data;
120562
+
120562
+static int size = 0;
120562
+static int offset;
120562
+
120562
+static void
120562
+write_size8twice (void)
120562
+{
120562
+  static const uint64_t first = 1;
120562
+  static const uint64_t second = 2;
120562
+
120562
+#ifdef __aarch64__
120562
+  asm volatile ("stp %1, %2, [%0]"
120562
+		: /* output */
120562
+		: "r" (data.u.size8twice), "r" (first), "r" (second) /* input */
120562
+		: "memory" /* clobber */);
120562
+#else
120562
+  data.u.size8twice[0] = first;
120562
+  data.u.size8twice[1] = second;
120562
+#endif
120562
+}
120562
+
120562
+int
120562
+main (void)
120562
+{
120562
+  volatile uint64_t local;
120562
+
120562
+  assert (sizeof (data) == 8 + 2 * 8);
120562
+
120562
+  write_size8twice ();
120562
+
120562
+  while (size)
120562
+    {
120562
+      switch (size)
120562
+	{
120562
+/* __s390x__ also defines __s390__ */
120562
+#ifdef __s390__
120562
+# define ACCESS(var) var = ~var
120562
+#else
120562
+# define ACCESS(var) local = var
120562
+#endif
120562
+	case 8:
120562
+	  ACCESS (data.u.size8[offset]);
120562
+	  break;
120562
+	case 4:
120562
+	  ACCESS (data.u.size4[offset]);
120562
+	  break;
120562
+	case 2:
120562
+	  ACCESS (data.u.size2[offset]);
120562
+	  break;
120562
+	case 1:
120562
+	  ACCESS (data.u.size1[offset]);
120562
+	  break;
120562
+#undef ACCESS
120562
+	default:
120562
+	  assert (0);
120562
+	}
120562
+      size = 0;
120562
+      size = size; /* start_again */
120562
+    }
120562
+  return 0; /* final_return */
120562
+}
120562
Index: gdb-7.6.1/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
120562
===================================================================
120562
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
120562
+++ gdb-7.6.1/gdb/testsuite/gdb.base/watchpoint-unaligned.exp	2018-05-05 17:12:49.571781890 +0200
120562
@@ -0,0 +1,184 @@
120562
+# Copyright 2017-2018 Free Software Foundation, Inc.
120562
+#
120562
+# This program is free software; you can redistribute it and/or modify
120562
+# it under the terms of the GNU General Public License as published by
120562
+# the Free Software Foundation; either version 3 of the License, or
120562
+# (at your option) any later version.
120562
+#
120562
+# This program is distributed in the hope that it will be useful,
120562
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
120562
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
120562
+# GNU General Public License for more details.
120562
+#
120562
+# You should have received a copy of the GNU General Public License
120562
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
120562
+#
120562
+# This file is part of the gdb testsuite.
120562
+
120562
+# Test inserting read watchpoints on unaligned addresses.
120562
+
120562
+standard_testfile
120562
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
120562
+    return -1
120562
+}
120562
+
120562
+if ![runto_main] {
120562
+    untested "could not run to main"
120562
+    return -1
120562
+}
120562
+
120562
+gdb_breakpoint [gdb_get_line_number "start_again"] "Breakpoint $decimal at $hex" "start_again"
120562
+
120562
+set sizes {1 2 4 8}
120562
+array set alignedend {1 1  2 2  3 4  4 4  5 8  6 8  7 8  8 8}
120562
+
120562
+set rwatch "rwatch"
120562
+set rwatch_exp "Hardware read watchpoint"
120562
+if {[istarget "s390*-*-*"]} {
120562
+    # Target does not support this type of hardware watchpoint."
120562
+    set rwatch "watch"
120562
+    set rwatch_exp "Hardware watchpoint"
120562
+}
120562
+
120562
+foreach wpsize $sizes {
120562
+    for {set wpoffset 0} {$wpoffset < 8 / $wpsize} {incr wpoffset} {
120562
+	set wpstart [expr $wpoffset * $wpsize]
120562
+	set wpend [expr ($wpoffset + 1) * $wpsize]
120562
+	set wpendaligned $alignedend($wpend)
120562
+	foreach rdsize $sizes {
120562
+	    for {set rdoffset 0} {$rdoffset < 8 / $rdsize} {incr rdoffset} {
120562
+		set rdstart [expr $rdoffset * $rdsize]
120562
+		set rdend [expr ($rdoffset + 1) * $rdsize]
120562
+		set expect_hit [expr max ($wpstart, $rdstart) < min ($wpend, $rdend)]
120562
+		set test "$rwatch data.u.size$wpsize\[$wpoffset\]"
120562
+		set wpnum ""
120562
+		gdb_test_multiple $test $test {
120562
+		    -re "$rwatch_exp (\[0-9\]+): .*\r\n$gdb_prompt $" {
120562
+			set wpnum $expect_out(1,string)
120562
+		    }
120562
+		    -re "Expression cannot be implemented with read/access watchpoint.\r\n$gdb_prompt $" {
120562
+			if {$wpsize == 8 && [istarget "arm*-*-*"]} {
120562
+			    untested $test
120562
+			    continue
120562
+			}
120562
+			fail $test
120562
+		    }
120562
+		}
120562
+		gdb_test_no_output "set variable size = $rdsize" ""
120562
+		gdb_test_no_output "set variable offset = $rdoffset" ""
120562
+		set test "continue"
120562
+		set got_hit 0
120562
+		gdb_test_multiple $test $test {
120562
+		    -re "$rwatch_exp $wpnum:.*alue = .*\r\n$gdb_prompt $" {
120562
+			set got_hit 1
120562
+			send_gdb "continue\n"
120562
+			exp_continue
120562
+		    }
120562
+		    -re " start_again .*\r\n$gdb_prompt $" {
120562
+		    }
120562
+		}
120562
+		gdb_test_no_output "delete $wpnum" ""
120562
+		set test "wp(size=$wpsize offset=$wpoffset) rd(size=$rdsize offset=$rdoffset) expect=$expect_hit"
120562
+		if {$expect_hit == $got_hit} {
120562
+		    pass $test
120562
+		} else {
120562
+		    # We do not know if we run on a fixed Linux kernel
120562
+		    # or not.  Report XFAIL only in the FAIL case.
120562
+		    if {$expect_hit == 0 && $rdstart < $wpendaligned} {
120562
+			setup_xfail external/20207 "aarch64*-*-linux*"
120562
+		    }
120562
+		    if {!$expect_hit && [expr max ($wpstart / 8, $rdstart / 8) < min (($wpend + 7) / 8, ($rdend + 7) / 8)]} {
120562
+			setup_xfail breakpoints/23131 "powerpc*-*-*"
120562
+		    }
120562
+		    fail $test
120562
+		}
120562
+	    }
120562
+	}
120562
+    }
120562
+}
120562
+
120562
+foreach wpcount {4 7} {
120562
+    array set wpoffset_to_wpnum {}
120562
+    for {set wpoffset 1} {$wpoffset <= $wpcount} {incr wpoffset} {
120562
+	set test "$rwatch data.u.size1\[$wpoffset\]"
120562
+	set wpnum ""
120562
+	gdb_test_multiple $test $test {
120562
+	    -re "$rwatch_exp (\[0-9\]+): .*\r\n$gdb_prompt $" {
120562
+		set wpoffset_to_wpnum($wpoffset) $expect_out(1,string)
120562
+	    }
120562
+	    -re "There are not enough available hardware resources for this watchpoint.\r\n$gdb_prompt $" {
120562
+		if {$wpoffset > 1} {
120562
+		    setup_xfail breakpoints/23131 "powerpc*-*-*"
120562
+		    setup_xfail breakpoints/23131 "arm*-*-*"
120562
+		}
120562
+		fail $test
120562
+		set wpoffset_to_wpnum($wpoffset) 0
120562
+	    }
120562
+	}
120562
+    }
120562
+    gdb_test_no_output "set variable size = 1" ""
120562
+    gdb_test_no_output "set variable offset = 1" ""
120562
+    set test "continue"
120562
+    set got_hit 0
120562
+    gdb_test_multiple $test $test {
120562
+	-re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
120562
+	}
120562
+	-re "$rwatch_exp $wpoffset_to_wpnum(1):.*alue = .*\r\n$gdb_prompt $" {
120562
+	    set got_hit 1
120562
+	    send_gdb "continue\n"
120562
+	    exp_continue
120562
+	}
120562
+	-re " start_again .*\r\n$gdb_prompt $" {
120562
+	}
120562
+    }
120562
+    for {set wpoffset 1} {$wpoffset <= $wpcount} {incr wpoffset} {
120562
+	if {$wpoffset_to_wpnum($wpoffset)} {
120562
+	    gdb_test_no_output "delete $wpoffset_to_wpnum($wpoffset)" ""
120562
+	}
120562
+    }
120562
+    set test "wpcount($wpcount)"
120562
+    if {!$wpoffset_to_wpnum([expr $wpcount - 1])} {
120562
+	untested $test
120562
+	continue
120562
+    }
120562
+    if {$wpcount > 4} {
120562
+	if {![istarget "s390*-*-*"]} {
120562
+	    setup_kfail tdep/22389 *-*-*
120562
+	}
120562
+    }
120562
+    gdb_assert $got_hit $test
120562
+}
120562
+
120562
+if ![runto_main] {
120562
+    return -1
120562
+}
120562
+gdb_breakpoint [gdb_get_line_number "final_return"] "Breakpoint $decimal at $hex" "final_return"
120562
+set test {watch data.u.size8twice[1]}
120562
+set wpnum ""
120562
+gdb_test_multiple $test $test {
120562
+    -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
120562
+	set wpnum $expect_out(1,string)
120562
+    }
120562
+    -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
120562
+	if {[istarget "arm*-*-*"]} {
120562
+	    untested $test
120562
+	    set wpnum 0
120562
+	}
120562
+    }
120562
+}
120562
+if {$wpnum} {
120562
+    set test "continue"
120562
+    set got_hit 0
120562
+    gdb_test_multiple $test $test {
120562
+	-re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
120562
+	}
120562
+	-re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
120562
+	    set got_hit 1
120562
+	    send_gdb "continue\n"
120562
+	    exp_continue
120562
+	}
120562
+	-re " final_return .*\r\n$gdb_prompt $" {
120562
+	}
120562
+    }
120562
+    gdb_assert $got_hit "size8twice write"
120562
+}
120562
Index: gdb-7.6.1/gdb/utils.c
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/utils.c	2018-05-05 17:12:47.002758937 +0200
120562
+++ gdb-7.6.1/gdb/utils.c	2018-05-05 17:12:49.571781890 +0200
120562
@@ -3316,22 +3316,6 @@
120562
   return xstrdup (filename);
120562
 }
120562
 
120562
-ULONGEST
120562
-align_up (ULONGEST v, int n)
120562
-{
120562
-  /* Check that N is really a power of two.  */
120562
-  gdb_assert (n && (n & (n-1)) == 0);
120562
-  return (v + n - 1) & -n;
120562
-}
120562
-
120562
-ULONGEST
120562
-align_down (ULONGEST v, int n)
120562
-{
120562
-  /* Check that N is really a power of two.  */
120562
-  gdb_assert (n && (n & (n-1)) == 0);
120562
-  return (v & -n);
120562
-}
120562
-
120562
 /* Allocation function for the libiberty hash table which uses an
120562
    obstack.  The obstack is passed as DATA.  */
120562
 
120562
Index: gdb-7.6.1/gdb/utils.h
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/utils.h	2018-05-05 17:12:47.002758937 +0200
120562
+++ gdb-7.6.1/gdb/utils.h	2018-05-05 17:12:49.572781899 +0200
120562
@@ -346,38 +346,6 @@
120562
 
120562
 extern int myread (int, char *, int);
120562
 
120562
-/* Ensure that V is aligned to an N byte boundary (B's assumed to be a
120562
-   power of 2).  Round up/down when necessary.  Examples of correct
120562
-   use include:
120562
-
120562
-   addr = align_up (addr, 8); -- VALUE needs 8 byte alignment
120562
-   write_memory (addr, value, len);
120562
-   addr += len;
120562
-
120562
-   and:
120562
-
120562
-   sp = align_down (sp - len, 16); -- Keep SP 16 byte aligned
120562
-   write_memory (sp, value, len);
120562
-
120562
-   Note that uses such as:
120562
-
120562
-   write_memory (addr, value, len);
120562
-   addr += align_up (len, 8);
120562
-
120562
-   and:
120562
-
120562
-   sp -= align_up (len, 8);
120562
-   write_memory (sp, value, len);
120562
-
120562
-   are typically not correct as they don't ensure that the address (SP
120562
-   or ADDR) is correctly aligned (relying on previous alignment to
120562
-   keep things right).  This is also why the methods are called
120562
-   "align_..." instead of "round_..." as the latter reads better with
120562
-   this incorrect coding style.  */
120562
-
120562
-extern ULONGEST align_up (ULONGEST v, int n);
120562
-extern ULONGEST align_down (ULONGEST v, int n);
120562
-
120562
 extern struct cleanup *make_cleanup_restore_selected_frame (void);
120562
 
120562
 #endif /* UTILS_H */
120562
Index: gdb-7.6.1/gdb/testsuite/lib/gdb.exp
120562
===================================================================
120562
--- gdb-7.6.1.orig/gdb/testsuite/lib/gdb.exp	2018-05-05 17:12:47.001758928 +0200
120562
+++ gdb-7.6.1/gdb/testsuite/lib/gdb.exp	2018-05-05 17:13:20.200055570 +0200
120562
@@ -1209,6 +1209,26 @@
120562
     }
120562
 }
120562
 
120562
+# Issue a PASS and return true if evaluating CONDITION in the caller's
120562
+# frame returns true, and issue a FAIL and return false otherwise.
120562
+# MESSAGE is the pass/fail message to be printed.  If MESSAGE is
120562
+# omitted or is empty, then the pass/fail messages use the condition
120562
+# string as the message.
120562
+
120562
+proc gdb_assert { condition {message ""} } {
120562
+    if { $message == ""} {
120562
+        set message $condition
120562
+    }
120562
+
120562
+    set res [uplevel 1 expr $condition]
120562
+    if {!$res} {
120562
+        fail $message
120562
+    } else {
120562
+        pass $message
120562
+    }
120562
+    return $res
120562
+}
120562
+
120562
 proc gdb_reinitialize_dir { subdir } {
120562
     global gdb_prompt
120562