Home | History | Annotate | Line # | Download | only in nat
aarch64-hw-point.c revision 1.1
      1  1.1  christos /* Copyright (C) 2009-2023 Free Software Foundation, Inc.
      2  1.1  christos 
      3  1.1  christos    This file is part of GDB.
      4  1.1  christos 
      5  1.1  christos    This program is free software; you can redistribute it and/or modify
      6  1.1  christos    it under the terms of the GNU General Public License as published by
      7  1.1  christos    the Free Software Foundation; either version 3 of the License, or
      8  1.1  christos    (at your option) any later version.
      9  1.1  christos 
     10  1.1  christos    This program is distributed in the hope that it will be useful,
     11  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos    GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos    You should have received a copy of the GNU General Public License
     16  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17  1.1  christos 
     18  1.1  christos #include "gdbsupport/common-defs.h"
     19  1.1  christos #include "gdbsupport/break-common.h"
     20  1.1  christos #include "gdbsupport/common-regcache.h"
     21  1.1  christos #include "aarch64-hw-point.h"
     22  1.1  christos 
     23  1.1  christos #ifdef __linux__
     24  1.1  christos /* For kernel_supports_any_contiguous_range.  */
     25  1.1  christos #include "aarch64-linux-hw-point.h"
     26  1.1  christos #else
     27  1.1  christos #define	kernel_supports_any_contiguous_range	true
     28  1.1  christos #endif
     29  1.1  christos 
     30  1.1  christos /* Number of hardware breakpoints/watchpoints the target supports.
     31  1.1  christos    They are initialized with values obtained via ptrace.  */
     32  1.1  christos 
     33  1.1  christos int aarch64_num_bp_regs;
     34  1.1  christos int aarch64_num_wp_regs;
     35  1.1  christos 
     36  1.1  christos /* Return starting byte 0..7 incl. of a watchpoint encoded by CTRL.  */
     37  1.1  christos 
     38  1.1  christos unsigned int
     39  1.1  christos aarch64_watchpoint_offset (unsigned int ctrl)
     40  1.1  christos {
     41  1.1  christos   uint8_t mask = DR_CONTROL_MASK (ctrl);
     42  1.1  christos   unsigned retval;
     43  1.1  christos 
     44  1.1  christos   /* Shift out bottom zeros.  */
     45  1.1  christos   for (retval = 0; mask && (mask & 1) == 0; ++retval)
     46  1.1  christos     mask >>= 1;
     47  1.1  christos 
     48  1.1  christos   return retval;
     49  1.1  christos }
     50  1.1  christos 
     51  1.1  christos /* Utility function that returns the length in bytes of a watchpoint
     52  1.1  christos    according to the content of a hardware debug control register CTRL.
     53  1.1  christos    Any contiguous range of bytes in CTRL is supported.  The returned
     54  1.1  christos    value can be between 0..8 (inclusive).  */
     55  1.1  christos 
     56  1.1  christos unsigned int
     57  1.1  christos aarch64_watchpoint_length (unsigned int ctrl)
     58  1.1  christos {
     59  1.1  christos   uint8_t mask = DR_CONTROL_MASK (ctrl);
     60  1.1  christos   unsigned retval;
     61  1.1  christos 
     62  1.1  christos   /* Shift out bottom zeros.  */
     63  1.1  christos   mask >>= aarch64_watchpoint_offset (ctrl);
     64  1.1  christos 
     65  1.1  christos   /* Count bottom ones.  */
     66  1.1  christos   for (retval = 0; (mask & 1) != 0; ++retval)
     67  1.1  christos     mask >>= 1;
     68  1.1  christos 
     69  1.1  christos   if (mask != 0)
     70  1.1  christos     error (_("Unexpected hardware watchpoint length register value 0x%x"),
     71  1.1  christos 	   DR_CONTROL_MASK (ctrl));
     72  1.1  christos 
     73  1.1  christos   return retval;
     74  1.1  christos }
     75  1.1  christos 
     76  1.1  christos /* Given the hardware breakpoint or watchpoint type TYPE and its
     77  1.1  christos    length LEN, return the expected encoding for a hardware
     78  1.1  christos    breakpoint/watchpoint control register.  */
     79  1.1  christos 
     80  1.1  christos static unsigned int
     81  1.1  christos aarch64_point_encode_ctrl_reg (enum target_hw_bp_type type, int offset, int len)
     82  1.1  christos {
     83  1.1  christos   unsigned int ctrl, ttype;
     84  1.1  christos 
     85  1.1  christos   gdb_assert (offset == 0 || kernel_supports_any_contiguous_range);
     86  1.1  christos   gdb_assert (offset + len <= AARCH64_HWP_MAX_LEN_PER_REG);
     87  1.1  christos 
     88  1.1  christos   /* type */
     89  1.1  christos   switch (type)
     90  1.1  christos     {
     91  1.1  christos     case hw_write:
     92  1.1  christos       ttype = 2;
     93  1.1  christos       break;
     94  1.1  christos     case hw_read:
     95  1.1  christos       ttype = 1;
     96  1.1  christos       break;
     97  1.1  christos     case hw_access:
     98  1.1  christos       ttype = 3;
     99  1.1  christos       break;
    100  1.1  christos     case hw_execute:
    101  1.1  christos       ttype = 0;
    102  1.1  christos       break;
    103  1.1  christos     default:
    104  1.1  christos       perror_with_name (_("Unrecognized breakpoint/watchpoint type"));
    105  1.1  christos     }
    106  1.1  christos 
    107  1.1  christos   ctrl = ttype << 3;
    108  1.1  christos 
    109  1.1  christos   /* offset and length bitmask */
    110  1.1  christos   ctrl |= ((1 << len) - 1) << (5 + offset);
    111  1.1  christos   /* enabled at el0 */
    112  1.1  christos   ctrl |= (2 << 1) | 1;
    113  1.1  christos 
    114  1.1  christos   return ctrl;
    115  1.1  christos }
    116  1.1  christos 
    117  1.1  christos /* Addresses to be written to the hardware breakpoint and watchpoint
    118  1.1  christos    value registers need to be aligned; the alignment is 4-byte and
    119  1.1  christos    8-type respectively.  Linux kernel rejects any non-aligned address
    120  1.1  christos    it receives from the related ptrace call.  Furthermore, the kernel
    121  1.1  christos    currently only supports the following Byte Address Select (BAS)
    122  1.1  christos    values: 0x1, 0x3, 0xf and 0xff, which means that for a hardware
    123  1.1  christos    watchpoint to be accepted by the kernel (via ptrace call), its
    124  1.1  christos    valid length can only be 1 byte, 2 bytes, 4 bytes or 8 bytes.
    125  1.1  christos    Despite these limitations, the unaligned watchpoint is supported in
    126  1.1  christos    this port.
    127  1.1  christos 
    128  1.1  christos    Return 0 for any non-compliant ADDR and/or LEN; return 1 otherwise.  */
    129  1.1  christos 
    130  1.1  christos static int
    131  1.1  christos aarch64_point_is_aligned (ptid_t ptid, int is_watchpoint, CORE_ADDR addr,
    132  1.1  christos 			  int len)
    133  1.1  christos {
    134  1.1  christos   unsigned int alignment = 0;
    135  1.1  christos 
    136  1.1  christos   if (is_watchpoint)
    137  1.1  christos     alignment = AARCH64_HWP_ALIGNMENT;
    138  1.1  christos   else
    139  1.1  christos     {
    140  1.1  christos       struct regcache *regcache
    141  1.1  christos 	= get_thread_regcache_for_ptid (ptid);
    142  1.1  christos 
    143  1.1  christos       /* Set alignment to 2 only if the current process is 32-bit,
    144  1.1  christos 	 since thumb instruction can be 2-byte aligned.  Otherwise, set
    145  1.1  christos 	 alignment to AARCH64_HBP_ALIGNMENT.  */
    146  1.1  christos       if (regcache_register_size (regcache, 0) == 8)
    147  1.1  christos 	alignment = AARCH64_HBP_ALIGNMENT;
    148  1.1  christos       else
    149  1.1  christos 	alignment = 2;
    150  1.1  christos     }
    151  1.1  christos 
    152  1.1  christos   if (addr & (alignment - 1))
    153  1.1  christos     return 0;
    154  1.1  christos 
    155  1.1  christos   if ((!kernel_supports_any_contiguous_range
    156  1.1  christos        && len != 8 && len != 4 && len != 2 && len != 1)
    157  1.1  christos       || (kernel_supports_any_contiguous_range
    158  1.1  christos 	  && (len < 1 || len > 8)))
    159  1.1  christos     return 0;
    160  1.1  christos 
    161  1.1  christos   return 1;
    162  1.1  christos }
    163  1.1  christos 
    164  1.1  christos /* Given the (potentially unaligned) watchpoint address in ADDR and
    165  1.1  christos    length in LEN, return the aligned address, offset from that base
    166  1.1  christos    address, and aligned length in *ALIGNED_ADDR_P, *ALIGNED_OFFSET_P
    167  1.1  christos    and *ALIGNED_LEN_P, respectively.  The returned values will be
    168  1.1  christos    valid values to write to the hardware watchpoint value and control
    169  1.1  christos    registers.
    170  1.1  christos 
    171  1.1  christos    The given watchpoint may get truncated if more than one hardware
    172  1.1  christos    register is needed to cover the watched region.  *NEXT_ADDR_P
    173  1.1  christos    and *NEXT_LEN_P, if non-NULL, will return the address and length
    174  1.1  christos    of the remaining part of the watchpoint (which can be processed
    175  1.1  christos    by calling this routine again to generate another aligned address,
    176  1.1  christos    offset and length tuple.
    177  1.1  christos 
    178  1.1  christos    Essentially, unaligned watchpoint is achieved by minimally
    179  1.1  christos    enlarging the watched area to meet the alignment requirement, and
    180  1.1  christos    if necessary, splitting the watchpoint over several hardware
    181  1.1  christos    watchpoint registers.
    182  1.1  christos 
    183  1.1  christos    On kernels that predate the support for Byte Address Select (BAS)
    184  1.1  christos    in the hardware watchpoint control register, the offset from the
    185  1.1  christos    base address is always zero, and so in that case the trade-off is
    186  1.1  christos    that there will be false-positive hits for the read-type or the
    187  1.1  christos    access-type hardware watchpoints; for the write type, which is more
    188  1.1  christos    commonly used, there will be no such issues, as the higher-level
    189  1.1  christos    breakpoint management in gdb always examines the exact watched
    190  1.1  christos    region for any content change, and transparently resumes a thread
    191  1.1  christos    from a watchpoint trap if there is no change to the watched region.
    192  1.1  christos 
    193  1.1  christos    Another limitation is that because the watched region is enlarged,
    194  1.1  christos    the watchpoint fault address discovered by
    195  1.1  christos    aarch64_stopped_data_address may be outside of the original watched
    196  1.1  christos    region, especially when the triggering instruction is accessing a
    197  1.1  christos    larger region.  When the fault address is not within any known
    198  1.1  christos    range, watchpoints_triggered in gdb will get confused, as the
    199  1.1  christos    higher-level watchpoint management is only aware of original
    200  1.1  christos    watched regions, and will think that some unknown watchpoint has
    201  1.1  christos    been triggered.  To prevent such a case,
    202  1.1  christos    aarch64_stopped_data_address implementations in gdb and gdbserver
    203  1.1  christos    try to match the trapped address with a watched region, and return
    204  1.1  christos    an address within the latter. */
    205  1.1  christos 
    206  1.1  christos static void
    207  1.1  christos aarch64_align_watchpoint (CORE_ADDR addr, int len, CORE_ADDR *aligned_addr_p,
    208  1.1  christos 			  int *aligned_offset_p, int *aligned_len_p,
    209  1.1  christos 			  CORE_ADDR *next_addr_p, int *next_len_p,
    210  1.1  christos 			  CORE_ADDR *next_addr_orig_p)
    211  1.1  christos {
    212  1.1  christos   int aligned_len;
    213  1.1  christos   unsigned int offset, aligned_offset;
    214  1.1  christos   CORE_ADDR aligned_addr;
    215  1.1  christos   const unsigned int alignment = AARCH64_HWP_ALIGNMENT;
    216  1.1  christos   const unsigned int max_wp_len = AARCH64_HWP_MAX_LEN_PER_REG;
    217  1.1  christos 
    218  1.1  christos   /* As assumed by the algorithm.  */
    219  1.1  christos   gdb_assert (alignment == max_wp_len);
    220  1.1  christos 
    221  1.1  christos   if (len <= 0)
    222  1.1  christos     return;
    223  1.1  christos 
    224  1.1  christos   /* The address put into the hardware watchpoint value register must
    225  1.1  christos      be aligned.  */
    226  1.1  christos   offset = addr & (alignment - 1);
    227  1.1  christos   aligned_addr = addr - offset;
    228  1.1  christos   aligned_offset
    229  1.1  christos     = kernel_supports_any_contiguous_range ? addr & (alignment - 1) : 0;
    230  1.1  christos 
    231  1.1  christos   gdb_assert (offset >= 0 && offset < alignment);
    232  1.1  christos   gdb_assert (aligned_addr >= 0 && aligned_addr <= addr);
    233  1.1  christos   gdb_assert (offset + len > 0);
    234  1.1  christos 
    235  1.1  christos   if (offset + len >= max_wp_len)
    236  1.1  christos     {
    237  1.1  christos       /* Need more than one watchpoint register; truncate at the
    238  1.1  christos 	 alignment boundary.  */
    239  1.1  christos       aligned_len
    240  1.1  christos 	= max_wp_len - (kernel_supports_any_contiguous_range ? offset : 0);
    241  1.1  christos       len -= (max_wp_len - offset);
    242  1.1  christos       addr += (max_wp_len - offset);
    243  1.1  christos       gdb_assert ((addr & (alignment - 1)) == 0);
    244  1.1  christos     }
    245  1.1  christos   else
    246  1.1  christos     {
    247  1.1  christos       /* Find the smallest valid length that is large enough to
    248  1.1  christos 	 accommodate this watchpoint.  */
    249  1.1  christos       static const unsigned char
    250  1.1  christos 	aligned_len_array[AARCH64_HWP_MAX_LEN_PER_REG] =
    251  1.1  christos 	{ 1, 2, 4, 4, 8, 8, 8, 8 };
    252  1.1  christos 
    253  1.1  christos       aligned_len = (kernel_supports_any_contiguous_range
    254  1.1  christos 		     ? len : aligned_len_array[offset + len - 1]);
    255  1.1  christos       addr += len;
    256  1.1  christos       len = 0;
    257  1.1  christos     }
    258  1.1  christos 
    259  1.1  christos   if (aligned_addr_p)
    260  1.1  christos     *aligned_addr_p = aligned_addr;
    261  1.1  christos   if (aligned_offset_p)
    262  1.1  christos     *aligned_offset_p = aligned_offset;
    263  1.1  christos   if (aligned_len_p)
    264  1.1  christos     *aligned_len_p = aligned_len;
    265  1.1  christos   if (next_addr_p)
    266  1.1  christos     *next_addr_p = addr;
    267  1.1  christos   if (next_len_p)
    268  1.1  christos     *next_len_p = len;
    269  1.1  christos   if (next_addr_orig_p)
    270  1.1  christos     *next_addr_orig_p = align_down (*next_addr_orig_p + alignment, alignment);
    271  1.1  christos }
    272  1.1  christos 
    273  1.1  christos /* Record the insertion of one breakpoint/watchpoint, as represented
    274  1.1  christos    by ADDR and CTRL, in the process' arch-specific data area *STATE.  */
    275  1.1  christos 
    276  1.1  christos static int
    277  1.1  christos aarch64_dr_state_insert_one_point (ptid_t ptid,
    278  1.1  christos 				   struct aarch64_debug_reg_state *state,
    279  1.1  christos 				   enum target_hw_bp_type type,
    280  1.1  christos 				   CORE_ADDR addr, int offset, int len,
    281  1.1  christos 				   CORE_ADDR addr_orig)
    282  1.1  christos {
    283  1.1  christos   int i, idx, num_regs, is_watchpoint;
    284  1.1  christos   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
    285  1.1  christos   CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
    286  1.1  christos 
    287  1.1  christos   /* Set up state pointers.  */
    288  1.1  christos   is_watchpoint = (type != hw_execute);
    289  1.1  christos   gdb_assert (aarch64_point_is_aligned (ptid, is_watchpoint, addr, len));
    290  1.1  christos   if (is_watchpoint)
    291  1.1  christos     {
    292  1.1  christos       num_regs = aarch64_num_wp_regs;
    293  1.1  christos       dr_addr_p = state->dr_addr_wp;
    294  1.1  christos       dr_addr_orig_p = state->dr_addr_orig_wp;
    295  1.1  christos       dr_ctrl_p = state->dr_ctrl_wp;
    296  1.1  christos       dr_ref_count = state->dr_ref_count_wp;
    297  1.1  christos     }
    298  1.1  christos   else
    299  1.1  christos     {
    300  1.1  christos       num_regs = aarch64_num_bp_regs;
    301  1.1  christos       dr_addr_p = state->dr_addr_bp;
    302  1.1  christos       dr_addr_orig_p = nullptr;
    303  1.1  christos       dr_ctrl_p = state->dr_ctrl_bp;
    304  1.1  christos       dr_ref_count = state->dr_ref_count_bp;
    305  1.1  christos     }
    306  1.1  christos 
    307  1.1  christos   ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
    308  1.1  christos 
    309  1.1  christos   /* Find an existing or free register in our cache.  */
    310  1.1  christos   idx = -1;
    311  1.1  christos   for (i = 0; i < num_regs; ++i)
    312  1.1  christos     {
    313  1.1  christos       if ((dr_ctrl_p[i] & 1) == 0)
    314  1.1  christos 	{
    315  1.1  christos 	  gdb_assert (dr_ref_count[i] == 0);
    316  1.1  christos 	  idx = i;
    317  1.1  christos 	  /* no break; continue hunting for an exising one.  */
    318  1.1  christos 	}
    319  1.1  christos       else if (dr_addr_p[i] == addr
    320  1.1  christos 	       && (dr_addr_orig_p == nullptr || dr_addr_orig_p[i] == addr_orig)
    321  1.1  christos 	       && dr_ctrl_p[i] == ctrl)
    322  1.1  christos 	{
    323  1.1  christos 	  gdb_assert (dr_ref_count[i] != 0);
    324  1.1  christos 	  idx = i;
    325  1.1  christos 	  break;
    326  1.1  christos 	}
    327  1.1  christos     }
    328  1.1  christos 
    329  1.1  christos   /* No space.  */
    330  1.1  christos   if (idx == -1)
    331  1.1  christos     return -1;
    332  1.1  christos 
    333  1.1  christos   /* Update our cache.  */
    334  1.1  christos   if ((dr_ctrl_p[idx] & 1) == 0)
    335  1.1  christos     {
    336  1.1  christos       /* new entry */
    337  1.1  christos       dr_addr_p[idx] = addr;
    338  1.1  christos       if (dr_addr_orig_p != nullptr)
    339  1.1  christos 	dr_addr_orig_p[idx] = addr_orig;
    340  1.1  christos       dr_ctrl_p[idx] = ctrl;
    341  1.1  christos       dr_ref_count[idx] = 1;
    342  1.1  christos       /* Notify the change.  */
    343  1.1  christos       aarch64_notify_debug_reg_change (ptid, is_watchpoint, idx);
    344  1.1  christos     }
    345  1.1  christos   else
    346  1.1  christos     {
    347  1.1  christos       /* existing entry */
    348  1.1  christos       dr_ref_count[idx]++;
    349  1.1  christos     }
    350  1.1  christos 
    351  1.1  christos   return 0;
    352  1.1  christos }
    353  1.1  christos 
    354  1.1  christos /* Record the removal of one breakpoint/watchpoint, as represented by
    355  1.1  christos    ADDR and CTRL, in the process' arch-specific data area *STATE.  */
    356  1.1  christos 
    357  1.1  christos static int
    358  1.1  christos aarch64_dr_state_remove_one_point (ptid_t ptid,
    359  1.1  christos 				   struct aarch64_debug_reg_state *state,
    360  1.1  christos 				   enum target_hw_bp_type type,
    361  1.1  christos 				   CORE_ADDR addr, int offset, int len,
    362  1.1  christos 				   CORE_ADDR addr_orig)
    363  1.1  christos {
    364  1.1  christos   int i, num_regs, is_watchpoint;
    365  1.1  christos   unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
    366  1.1  christos   CORE_ADDR *dr_addr_p, *dr_addr_orig_p;
    367  1.1  christos 
    368  1.1  christos   /* Set up state pointers.  */
    369  1.1  christos   is_watchpoint = (type != hw_execute);
    370  1.1  christos   if (is_watchpoint)
    371  1.1  christos     {
    372  1.1  christos       num_regs = aarch64_num_wp_regs;
    373  1.1  christos       dr_addr_p = state->dr_addr_wp;
    374  1.1  christos       dr_addr_orig_p = state->dr_addr_orig_wp;
    375  1.1  christos       dr_ctrl_p = state->dr_ctrl_wp;
    376  1.1  christos       dr_ref_count = state->dr_ref_count_wp;
    377  1.1  christos     }
    378  1.1  christos   else
    379  1.1  christos     {
    380  1.1  christos       num_regs = aarch64_num_bp_regs;
    381  1.1  christos       dr_addr_p = state->dr_addr_bp;
    382  1.1  christos       dr_addr_orig_p = nullptr;
    383  1.1  christos       dr_ctrl_p = state->dr_ctrl_bp;
    384  1.1  christos       dr_ref_count = state->dr_ref_count_bp;
    385  1.1  christos     }
    386  1.1  christos 
    387  1.1  christos   ctrl = aarch64_point_encode_ctrl_reg (type, offset, len);
    388  1.1  christos 
    389  1.1  christos   /* Find the entry that matches the ADDR and CTRL.  */
    390  1.1  christos   for (i = 0; i < num_regs; ++i)
    391  1.1  christos     if (dr_addr_p[i] == addr
    392  1.1  christos 	&& (dr_addr_orig_p == nullptr || dr_addr_orig_p[i] == addr_orig)
    393  1.1  christos 	&& dr_ctrl_p[i] == ctrl)
    394  1.1  christos       {
    395  1.1  christos 	gdb_assert (dr_ref_count[i] != 0);
    396  1.1  christos 	break;
    397  1.1  christos       }
    398  1.1  christos 
    399  1.1  christos   /* Not found.  */
    400  1.1  christos   if (i == num_regs)
    401  1.1  christos     return -1;
    402  1.1  christos 
    403  1.1  christos   /* Clear our cache.  */
    404  1.1  christos   if (--dr_ref_count[i] == 0)
    405  1.1  christos     {
    406  1.1  christos       /* Clear the enable bit.  */
    407  1.1  christos       ctrl &= ~1;
    408  1.1  christos       dr_addr_p[i] = 0;
    409  1.1  christos       if (dr_addr_orig_p != nullptr)
    410  1.1  christos 	dr_addr_orig_p[i] = 0;
    411  1.1  christos       dr_ctrl_p[i] = ctrl;
    412  1.1  christos       /* Notify the change.  */
    413  1.1  christos       aarch64_notify_debug_reg_change (ptid, is_watchpoint, i);
    414  1.1  christos     }
    415  1.1  christos 
    416  1.1  christos   return 0;
    417  1.1  christos }
    418  1.1  christos 
    419  1.1  christos int
    420  1.1  christos aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
    421  1.1  christos 			   int len, int is_insert, ptid_t ptid,
    422  1.1  christos 			   struct aarch64_debug_reg_state *state)
    423  1.1  christos {
    424  1.1  christos   if (is_insert)
    425  1.1  christos     {
    426  1.1  christos       /* The hardware breakpoint on AArch64 should always be 4-byte
    427  1.1  christos 	 aligned, but on AArch32, it can be 2-byte aligned.  Note that
    428  1.1  christos 	 we only check the alignment on inserting breakpoint because
    429  1.1  christos 	 aarch64_point_is_aligned needs the inferior_ptid inferior's
    430  1.1  christos 	 regcache to decide whether the inferior is 32-bit or 64-bit.
    431  1.1  christos 	 However when GDB follows the parent process and detach breakpoints
    432  1.1  christos 	 from child process, inferior_ptid is the child ptid, but the
    433  1.1  christos 	 child inferior doesn't exist in GDB's view yet.  */
    434  1.1  christos       if (!aarch64_point_is_aligned (ptid, 0 /* is_watchpoint */ , addr, len))
    435  1.1  christos 	return -1;
    436  1.1  christos 
    437  1.1  christos       return aarch64_dr_state_insert_one_point (ptid, state, type, addr, 0, len,
    438  1.1  christos 						-1);
    439  1.1  christos     }
    440  1.1  christos   else
    441  1.1  christos     return aarch64_dr_state_remove_one_point (ptid, state, type, addr, 0, len,
    442  1.1  christos 					      -1);
    443  1.1  christos }
    444  1.1  christos 
    445  1.1  christos /* This is essentially the same as aarch64_handle_breakpoint, apart
    446  1.1  christos    from that it is an aligned watchpoint to be handled.  */
    447  1.1  christos 
    448  1.1  christos static int
    449  1.1  christos aarch64_handle_aligned_watchpoint (enum target_hw_bp_type type,
    450  1.1  christos 				   CORE_ADDR addr, int len, int is_insert,
    451  1.1  christos 				   ptid_t ptid,
    452  1.1  christos 				   struct aarch64_debug_reg_state *state)
    453  1.1  christos {
    454  1.1  christos   if (is_insert)
    455  1.1  christos     return aarch64_dr_state_insert_one_point (ptid, state, type, addr, 0, len,
    456  1.1  christos 					      addr);
    457  1.1  christos   else
    458  1.1  christos     return aarch64_dr_state_remove_one_point (ptid, state, type, addr, 0, len,
    459  1.1  christos 					      addr);
    460  1.1  christos }
    461  1.1  christos 
    462  1.1  christos /* Insert/remove unaligned watchpoint by calling
    463  1.1  christos    aarch64_align_watchpoint repeatedly until the whole watched region,
    464  1.1  christos    as represented by ADDR and LEN, has been properly aligned and ready
    465  1.1  christos    to be written to one or more hardware watchpoint registers.
    466  1.1  christos    IS_INSERT indicates whether this is an insertion or a deletion.
    467  1.1  christos    Return 0 if succeed.  */
    468  1.1  christos 
    469  1.1  christos static int
    470  1.1  christos aarch64_handle_unaligned_watchpoint (enum target_hw_bp_type type,
    471  1.1  christos 				     CORE_ADDR addr, int len, int is_insert,
    472  1.1  christos 				     ptid_t ptid,
    473  1.1  christos 				     struct aarch64_debug_reg_state *state)
    474  1.1  christos {
    475  1.1  christos   CORE_ADDR addr_orig = addr;
    476  1.1  christos 
    477  1.1  christos   while (len > 0)
    478  1.1  christos     {
    479  1.1  christos       CORE_ADDR aligned_addr;
    480  1.1  christos       int aligned_offset, aligned_len, ret;
    481  1.1  christos       CORE_ADDR addr_orig_next = addr_orig;
    482  1.1  christos 
    483  1.1  christos       aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_offset,
    484  1.1  christos 				&aligned_len, &addr, &len, &addr_orig_next);
    485  1.1  christos 
    486  1.1  christos       if (is_insert)
    487  1.1  christos 	ret = aarch64_dr_state_insert_one_point (ptid, state, type,
    488  1.1  christos 						 aligned_addr, aligned_offset,
    489  1.1  christos 						 aligned_len, addr_orig);
    490  1.1  christos       else
    491  1.1  christos 	ret = aarch64_dr_state_remove_one_point (ptid, state, type,
    492  1.1  christos 						 aligned_addr, aligned_offset,
    493  1.1  christos 						 aligned_len, addr_orig);
    494  1.1  christos 
    495  1.1  christos       if (show_debug_regs)
    496  1.1  christos 	debug_printf ("handle_unaligned_watchpoint: is_insert: %d\n"
    497  1.1  christos 		      "                             "
    498  1.1  christos 		      "aligned_addr: %s, aligned_len: %d\n"
    499  1.1  christos 		      "                                "
    500  1.1  christos 		      "addr_orig: %s\n"
    501  1.1  christos 		      "                                "
    502  1.1  christos 		      "next_addr: %s,    next_len: %d\n"
    503  1.1  christos 		      "                           "
    504  1.1  christos 		      "addr_orig_next: %s\n",
    505  1.1  christos 		      is_insert, core_addr_to_string_nz (aligned_addr),
    506  1.1  christos 		      aligned_len, core_addr_to_string_nz (addr_orig),
    507  1.1  christos 		      core_addr_to_string_nz (addr), len,
    508  1.1  christos 		      core_addr_to_string_nz (addr_orig_next));
    509  1.1  christos 
    510  1.1  christos       addr_orig = addr_orig_next;
    511  1.1  christos 
    512  1.1  christos       if (ret != 0)
    513  1.1  christos 	return ret;
    514  1.1  christos     }
    515  1.1  christos 
    516  1.1  christos   return 0;
    517  1.1  christos }
    518  1.1  christos 
    519  1.1  christos int
    520  1.1  christos aarch64_handle_watchpoint (enum target_hw_bp_type type, CORE_ADDR addr,
    521  1.1  christos 			   int len, int is_insert, ptid_t ptid,
    522  1.1  christos 			   struct aarch64_debug_reg_state *state)
    523  1.1  christos {
    524  1.1  christos   if (aarch64_point_is_aligned (ptid, 1 /* is_watchpoint */ , addr, len))
    525  1.1  christos     return aarch64_handle_aligned_watchpoint (type, addr, len, is_insert, ptid,
    526  1.1  christos 					      state);
    527  1.1  christos   else
    528  1.1  christos     return aarch64_handle_unaligned_watchpoint (type, addr, len, is_insert,
    529  1.1  christos 						ptid, state);
    530  1.1  christos }
    531  1.1  christos 
    532  1.1  christos /* See nat/aarch64-hw-point.h.  */
    533  1.1  christos 
    534  1.1  christos bool
    535  1.1  christos aarch64_any_set_debug_regs_state (aarch64_debug_reg_state *state,
    536  1.1  christos 				  bool watchpoint)
    537  1.1  christos {
    538  1.1  christos   int count = watchpoint ? aarch64_num_wp_regs : aarch64_num_bp_regs;
    539  1.1  christos   if (count == 0)
    540  1.1  christos     return false;
    541  1.1  christos 
    542  1.1  christos   const CORE_ADDR *addr = watchpoint ? state->dr_addr_wp : state->dr_addr_bp;
    543  1.1  christos   const unsigned int *ctrl = watchpoint ? state->dr_ctrl_wp : state->dr_ctrl_bp;
    544  1.1  christos 
    545  1.1  christos   for (int i = 0; i < count; i++)
    546  1.1  christos     if (addr[i] != 0 || ctrl[i] != 0)
    547  1.1  christos       return true;
    548  1.1  christos 
    549  1.1  christos   return false;
    550  1.1  christos }
    551  1.1  christos 
    552  1.1  christos /* Print the values of the cached breakpoint/watchpoint registers.  */
    553  1.1  christos 
    554  1.1  christos void
    555  1.1  christos aarch64_show_debug_reg_state (struct aarch64_debug_reg_state *state,
    556  1.1  christos 			      const char *func, CORE_ADDR addr,
    557  1.1  christos 			      int len, enum target_hw_bp_type type)
    558  1.1  christos {
    559  1.1  christos   int i;
    560  1.1  christos 
    561  1.1  christos   debug_printf ("%s", func);
    562  1.1  christos   if (addr || len)
    563  1.1  christos     debug_printf (" (addr=0x%08lx, len=%d, type=%s)",
    564  1.1  christos 		  (unsigned long) addr, len,
    565  1.1  christos 		  type == hw_write ? "hw-write-watchpoint"
    566  1.1  christos 		  : (type == hw_read ? "hw-read-watchpoint"
    567  1.1  christos 		     : (type == hw_access ? "hw-access-watchpoint"
    568  1.1  christos 			: (type == hw_execute ? "hw-breakpoint"
    569  1.1  christos 			   : "??unknown??"))));
    570  1.1  christos   debug_printf (":\n");
    571  1.1  christos 
    572  1.1  christos   debug_printf ("\tBREAKPOINTs:\n");
    573  1.1  christos   for (i = 0; i < aarch64_num_bp_regs; i++)
    574  1.1  christos     debug_printf ("\tBP%d: addr=%s, ctrl=0x%08x, ref.count=%d\n",
    575  1.1  christos 		  i, core_addr_to_string_nz (state->dr_addr_bp[i]),
    576  1.1  christos 		  state->dr_ctrl_bp[i], state->dr_ref_count_bp[i]);
    577  1.1  christos 
    578  1.1  christos   debug_printf ("\tWATCHPOINTs:\n");
    579  1.1  christos   for (i = 0; i < aarch64_num_wp_regs; i++)
    580  1.1  christos     debug_printf ("\tWP%d: addr=%s (orig=%s), ctrl=0x%08x, ref.count=%d\n",
    581  1.1  christos 		  i, core_addr_to_string_nz (state->dr_addr_wp[i]),
    582  1.1  christos 		  core_addr_to_string_nz (state->dr_addr_orig_wp[i]),
    583  1.1  christos 		  state->dr_ctrl_wp[i], state->dr_ref_count_wp[i]);
    584  1.1  christos }
    585  1.1  christos 
    586  1.1  christos /* Return true if we can watch a memory region that starts address
    587  1.1  christos    ADDR and whose length is LEN in bytes.  */
    588  1.1  christos 
    589  1.1  christos int
    590  1.1  christos aarch64_region_ok_for_watchpoint (CORE_ADDR addr, int len)
    591  1.1  christos {
    592  1.1  christos   CORE_ADDR aligned_addr;
    593  1.1  christos 
    594  1.1  christos   /* Can not set watchpoints for zero or negative lengths.  */
    595  1.1  christos   if (len <= 0)
    596  1.1  christos     return 0;
    597  1.1  christos 
    598  1.1  christos   /* Must have hardware watchpoint debug register(s).  */
    599  1.1  christos   if (aarch64_num_wp_regs == 0)
    600  1.1  christos     return 0;
    601  1.1  christos 
    602  1.1  christos   /* We support unaligned watchpoint address and arbitrary length,
    603  1.1  christos      as long as the size of the whole watched area after alignment
    604  1.1  christos      doesn't exceed size of the total area that all watchpoint debug
    605  1.1  christos      registers can watch cooperatively.
    606  1.1  christos 
    607  1.1  christos      This is a very relaxed rule, but unfortunately there are
    608  1.1  christos      limitations, e.g. false-positive hits, due to limited support of
    609  1.1  christos      hardware debug registers in the kernel.  See comment above
    610  1.1  christos      aarch64_align_watchpoint for more information.  */
    611  1.1  christos 
    612  1.1  christos   aligned_addr = addr & ~(AARCH64_HWP_MAX_LEN_PER_REG - 1);
    613  1.1  christos   if (aligned_addr + aarch64_num_wp_regs * AARCH64_HWP_MAX_LEN_PER_REG
    614  1.1  christos       < addr + len)
    615  1.1  christos     return 0;
    616  1.1  christos 
    617  1.1  christos   /* All tests passed so we are likely to be able to set the watchpoint.
    618  1.1  christos      The reason that it is 'likely' rather than 'must' is because
    619  1.1  christos      we don't check the current usage of the watchpoint registers, and
    620  1.1  christos      there may not be enough registers available for this watchpoint.
    621  1.1  christos      Ideally we should check the cached debug register state, however
    622  1.1  christos      the checking is costly.  */
    623  1.1  christos   return 1;
    624  1.1  christos }
    625