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