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