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