Commit | Line | Data |
---|---|---|
42a4f53d | 1 | /* Copyright (C) 2009-2019 Free Software Foundation, Inc. |
aaee2056 YQ |
2 | |
3 | This file is part of GDB. | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 3 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | ||
268a13a5 | 18 | #include "gdbsupport/common-defs.h" |
5826e159 | 19 | #include "nat/gdb_ptrace.h" |
aaee2056 | 20 | #include "mips-linux-watch.h" |
aaee2056 YQ |
21 | |
22 | /* Assuming usable watch registers REGS, return the irw_mask of | |
23 | register N. */ | |
24 | ||
25 | uint32_t | |
26 | mips_linux_watch_get_irw_mask (struct pt_watch_regs *regs, int n) | |
27 | { | |
28 | switch (regs->style) | |
29 | { | |
30 | case pt_watch_style_mips32: | |
31 | return regs->mips32.watch_masks[n] & IRW_MASK; | |
32 | case pt_watch_style_mips64: | |
33 | return regs->mips64.watch_masks[n] & IRW_MASK; | |
34 | default: | |
35 | internal_error (__FILE__, __LINE__, | |
36 | _("Unrecognized watch register style")); | |
37 | } | |
38 | } | |
39 | ||
40 | /* Assuming usable watch registers REGS, return the reg_mask of | |
41 | register N. */ | |
42 | ||
43 | static uint32_t | |
44 | get_reg_mask (struct pt_watch_regs *regs, int n) | |
45 | { | |
46 | switch (regs->style) | |
47 | { | |
48 | case pt_watch_style_mips32: | |
49 | return regs->mips32.watch_masks[n] & ~IRW_MASK; | |
50 | case pt_watch_style_mips64: | |
51 | return regs->mips64.watch_masks[n] & ~IRW_MASK; | |
52 | default: | |
53 | internal_error (__FILE__, __LINE__, | |
54 | _("Unrecognized watch register style")); | |
55 | } | |
56 | } | |
57 | ||
58 | /* Assuming usable watch registers REGS, return the num_valid. */ | |
59 | ||
60 | uint32_t | |
61 | mips_linux_watch_get_num_valid (struct pt_watch_regs *regs) | |
62 | { | |
63 | switch (regs->style) | |
64 | { | |
65 | case pt_watch_style_mips32: | |
66 | return regs->mips32.num_valid; | |
67 | case pt_watch_style_mips64: | |
68 | return regs->mips64.num_valid; | |
69 | default: | |
70 | internal_error (__FILE__, __LINE__, | |
71 | _("Unrecognized watch register style")); | |
72 | } | |
73 | } | |
74 | ||
75 | /* Assuming usable watch registers REGS, return the watchlo of | |
76 | register N. */ | |
77 | ||
78 | CORE_ADDR | |
79 | mips_linux_watch_get_watchlo (struct pt_watch_regs *regs, int n) | |
80 | { | |
81 | switch (regs->style) | |
82 | { | |
83 | case pt_watch_style_mips32: | |
84 | return regs->mips32.watchlo[n]; | |
85 | case pt_watch_style_mips64: | |
86 | return regs->mips64.watchlo[n]; | |
87 | default: | |
88 | internal_error (__FILE__, __LINE__, | |
89 | _("Unrecognized watch register style")); | |
90 | } | |
91 | } | |
92 | ||
93 | /* Assuming usable watch registers REGS, set watchlo of register N to | |
94 | VALUE. */ | |
95 | ||
96 | void | |
97 | mips_linux_watch_set_watchlo (struct pt_watch_regs *regs, int n, | |
98 | CORE_ADDR value) | |
99 | { | |
100 | switch (regs->style) | |
101 | { | |
102 | case pt_watch_style_mips32: | |
103 | /* The cast will never throw away bits as 64 bit addresses can | |
104 | never be used on a 32 bit kernel. */ | |
105 | regs->mips32.watchlo[n] = (uint32_t) value; | |
106 | break; | |
107 | case pt_watch_style_mips64: | |
108 | regs->mips64.watchlo[n] = value; | |
109 | break; | |
110 | default: | |
111 | internal_error (__FILE__, __LINE__, | |
112 | _("Unrecognized watch register style")); | |
113 | } | |
114 | } | |
115 | ||
116 | /* Assuming usable watch registers REGS, return the watchhi of | |
117 | register N. */ | |
118 | ||
119 | uint32_t | |
120 | mips_linux_watch_get_watchhi (struct pt_watch_regs *regs, int n) | |
121 | { | |
122 | switch (regs->style) | |
123 | { | |
124 | case pt_watch_style_mips32: | |
125 | return regs->mips32.watchhi[n]; | |
126 | case pt_watch_style_mips64: | |
127 | return regs->mips64.watchhi[n]; | |
128 | default: | |
129 | internal_error (__FILE__, __LINE__, | |
130 | _("Unrecognized watch register style")); | |
131 | } | |
132 | } | |
133 | ||
134 | /* Assuming usable watch registers REGS, set watchhi of register N to | |
135 | VALUE. */ | |
136 | ||
137 | void | |
138 | mips_linux_watch_set_watchhi (struct pt_watch_regs *regs, int n, | |
139 | uint16_t value) | |
140 | { | |
141 | switch (regs->style) | |
142 | { | |
143 | case pt_watch_style_mips32: | |
144 | regs->mips32.watchhi[n] = value; | |
145 | break; | |
146 | case pt_watch_style_mips64: | |
147 | regs->mips64.watchhi[n] = value; | |
148 | break; | |
149 | default: | |
150 | internal_error (__FILE__, __LINE__, | |
151 | _("Unrecognized watch register style")); | |
152 | } | |
153 | } | |
154 | ||
155 | /* Read the watch registers of process LWPID and store it in | |
156 | WATCH_READBACK. Save true to *WATCH_READBACK_VALID if watch | |
157 | registers are valid. Return 1 if watch registers are usable. | |
158 | Cached information is used unless FORCE is true. */ | |
159 | ||
160 | int | |
161 | mips_linux_read_watch_registers (long lwpid, | |
162 | struct pt_watch_regs *watch_readback, | |
163 | int *watch_readback_valid, int force) | |
164 | { | |
165 | if (force || *watch_readback_valid == 0) | |
166 | { | |
aa58a496 | 167 | if (ptrace (PTRACE_GET_WATCH_REGS, lwpid, watch_readback, NULL) == -1) |
aaee2056 YQ |
168 | { |
169 | *watch_readback_valid = -1; | |
170 | return 0; | |
171 | } | |
172 | switch (watch_readback->style) | |
173 | { | |
174 | case pt_watch_style_mips32: | |
175 | if (watch_readback->mips32.num_valid == 0) | |
176 | { | |
177 | *watch_readback_valid = -1; | |
178 | return 0; | |
179 | } | |
180 | break; | |
181 | case pt_watch_style_mips64: | |
182 | if (watch_readback->mips64.num_valid == 0) | |
183 | { | |
184 | *watch_readback_valid = -1; | |
185 | return 0; | |
186 | } | |
187 | break; | |
188 | default: | |
189 | *watch_readback_valid = -1; | |
190 | return 0; | |
191 | } | |
192 | /* Watch registers appear to be usable. */ | |
193 | *watch_readback_valid = 1; | |
194 | } | |
195 | return (*watch_readback_valid == 1) ? 1 : 0; | |
196 | } | |
197 | ||
198 | /* Convert GDB's TYPE to an IRW mask. */ | |
199 | ||
200 | uint32_t | |
f486487f | 201 | mips_linux_watch_type_to_irw (enum target_hw_bp_type type) |
aaee2056 YQ |
202 | { |
203 | switch (type) | |
204 | { | |
205 | case hw_write: | |
206 | return W_MASK; | |
207 | case hw_read: | |
208 | return R_MASK; | |
209 | case hw_access: | |
210 | return (W_MASK | R_MASK); | |
211 | default: | |
212 | return 0; | |
213 | } | |
214 | } | |
215 | ||
216 | /* Set any low order bits in MASK that are not set. */ | |
217 | ||
218 | static CORE_ADDR | |
219 | fill_mask (CORE_ADDR mask) | |
220 | { | |
221 | CORE_ADDR f = 1; | |
222 | ||
223 | while (f && f < mask) | |
224 | { | |
225 | mask |= f; | |
226 | f <<= 1; | |
227 | } | |
228 | return mask; | |
229 | } | |
230 | ||
231 | /* Try to add a single watch to the specified registers REGS. The | |
232 | address of added watch is ADDR, the length is LEN, and the mask | |
233 | is IRW. Return 1 on success, 0 on failure. */ | |
234 | ||
235 | int | |
236 | mips_linux_watch_try_one_watch (struct pt_watch_regs *regs, | |
237 | CORE_ADDR addr, int len, uint32_t irw) | |
238 | { | |
239 | CORE_ADDR base_addr, last_byte, break_addr, segment_len; | |
240 | CORE_ADDR mask_bits, t_low; | |
241 | uint16_t t_hi; | |
242 | int i, free_watches; | |
243 | struct pt_watch_regs regs_copy; | |
244 | ||
245 | if (len <= 0) | |
246 | return 0; | |
247 | ||
248 | last_byte = addr + len - 1; | |
249 | mask_bits = fill_mask (addr ^ last_byte) | IRW_MASK; | |
250 | base_addr = addr & ~mask_bits; | |
251 | ||
252 | /* Check to see if it is covered by current registers. */ | |
253 | for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++) | |
254 | { | |
255 | t_low = mips_linux_watch_get_watchlo (regs, i); | |
256 | if (t_low != 0 && irw == ((uint32_t) t_low & irw)) | |
257 | { | |
258 | t_hi = mips_linux_watch_get_watchhi (regs, i) | IRW_MASK; | |
259 | t_low &= ~(CORE_ADDR) t_hi; | |
260 | if (addr >= t_low && last_byte <= (t_low + t_hi)) | |
261 | return 1; | |
262 | } | |
263 | } | |
264 | /* Try to find an empty register. */ | |
265 | free_watches = 0; | |
266 | for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++) | |
267 | { | |
268 | t_low = mips_linux_watch_get_watchlo (regs, i); | |
269 | if (t_low == 0 | |
270 | && irw == (mips_linux_watch_get_irw_mask (regs, i) & irw)) | |
271 | { | |
272 | if (mask_bits <= (get_reg_mask (regs, i) | IRW_MASK)) | |
273 | { | |
274 | /* It fits, we'll take it. */ | |
275 | mips_linux_watch_set_watchlo (regs, i, base_addr | irw); | |
276 | mips_linux_watch_set_watchhi (regs, i, mask_bits & ~IRW_MASK); | |
277 | return 1; | |
278 | } | |
279 | else | |
280 | { | |
281 | /* It doesn't fit, but has the proper IRW capabilities. */ | |
282 | free_watches++; | |
283 | } | |
284 | } | |
285 | } | |
286 | if (free_watches > 1) | |
287 | { | |
288 | /* Try to split it across several registers. */ | |
289 | regs_copy = *regs; | |
290 | for (i = 0; i < mips_linux_watch_get_num_valid (®s_copy); i++) | |
291 | { | |
292 | t_low = mips_linux_watch_get_watchlo (®s_copy, i); | |
293 | t_hi = get_reg_mask (®s_copy, i) | IRW_MASK; | |
294 | if (t_low == 0 && irw == (t_hi & irw)) | |
295 | { | |
296 | t_low = addr & ~(CORE_ADDR) t_hi; | |
297 | break_addr = t_low + t_hi + 1; | |
298 | if (break_addr >= addr + len) | |
299 | segment_len = len; | |
300 | else | |
301 | segment_len = break_addr - addr; | |
302 | mask_bits = fill_mask (addr ^ (addr + segment_len - 1)); | |
303 | mips_linux_watch_set_watchlo (®s_copy, i, | |
304 | (addr & ~mask_bits) | irw); | |
305 | mips_linux_watch_set_watchhi (®s_copy, i, | |
306 | mask_bits & ~IRW_MASK); | |
307 | if (break_addr >= addr + len) | |
308 | { | |
309 | *regs = regs_copy; | |
310 | return 1; | |
311 | } | |
312 | len = addr + len - break_addr; | |
313 | addr = break_addr; | |
314 | } | |
315 | } | |
316 | } | |
317 | /* It didn't fit anywhere, we failed. */ | |
318 | return 0; | |
319 | } | |
320 | ||
321 | /* Fill in the watch registers REGS with the currently cached | |
322 | watches CURRENT_WATCHES. */ | |
323 | ||
324 | void | |
325 | mips_linux_watch_populate_regs (struct mips_watchpoint *current_watches, | |
326 | struct pt_watch_regs *regs) | |
327 | { | |
328 | struct mips_watchpoint *w; | |
329 | int i; | |
330 | ||
331 | /* Clear them out. */ | |
332 | for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++) | |
333 | { | |
334 | mips_linux_watch_set_watchlo (regs, i, 0); | |
335 | mips_linux_watch_set_watchhi (regs, i, 0); | |
336 | } | |
337 | ||
338 | w = current_watches; | |
339 | while (w) | |
340 | { | |
341 | uint32_t irw = mips_linux_watch_type_to_irw (w->type); | |
342 | ||
343 | i = mips_linux_watch_try_one_watch (regs, w->addr, w->len, irw); | |
344 | /* They must all fit, because we previously calculated that they | |
345 | would. */ | |
346 | gdb_assert (i); | |
347 | w = w->next; | |
348 | } | |
349 | } |