cortex_m3: use armv7m's async algorithm implementation
[openocd.git] / src / target / breakpoints.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) ST-Ericsson SA 2011 *
6 * michel.jaouen@stericsson.com : smp minimum support *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "target.h"
28 #include <helper/log.h>
29 #include "breakpoints.h"
30
31
32 static char *breakpoint_type_strings[] =
33 {
34 "hardware",
35 "software"
36 };
37
38 static char *watchpoint_rw_strings[] =
39 {
40 "read",
41 "write",
42 "access"
43 };
44
45 // monotonic counter/id-number for breakpoints and watch points
46 static int bpwp_unique_id;
47
48 int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
49 {
50 struct breakpoint *breakpoint = target->breakpoints;
51 struct breakpoint **breakpoint_p = &target->breakpoints;
52 char *reason;
53 int retval;
54 int n;
55
56 n = 0;
57 while (breakpoint)
58 {
59 n++;
60 if (breakpoint->address == address) {
61 /* FIXME don't assume "same address" means "same
62 * breakpoint" ... check all the parameters before
63 * succeeding.
64 */
65 LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
66 address, breakpoint->unique_id );
67 return ERROR_OK;
68 }
69 breakpoint_p = &breakpoint->next;
70 breakpoint = breakpoint->next;
71 }
72
73 (*breakpoint_p) = malloc(sizeof(struct breakpoint));
74 (*breakpoint_p)->address = address;
75 (*breakpoint_p)->asid = 0;
76 (*breakpoint_p)->length = length;
77 (*breakpoint_p)->type = type;
78 (*breakpoint_p)->set = 0;
79 (*breakpoint_p)->orig_instr = malloc(length);
80 (*breakpoint_p)->next = NULL;
81 (*breakpoint_p)->unique_id = bpwp_unique_id++;
82
83 retval = target_add_breakpoint(target, *breakpoint_p);
84 switch (retval) {
85 case ERROR_OK:
86 break;
87 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
88 reason = "resource not available";
89 goto fail;
90 case ERROR_TARGET_NOT_HALTED:
91 reason = "target running";
92 goto fail;
93 default:
94 reason = "unknown reason";
95 fail:
96 LOG_ERROR("can't add breakpoint: %s", reason);
97 free((*breakpoint_p)->orig_instr);
98 free(*breakpoint_p);
99 *breakpoint_p = NULL;
100 return retval;
101 }
102
103 LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
104 breakpoint_type_strings[(*breakpoint_p)->type],
105 (*breakpoint_p)->address, (*breakpoint_p)->length,
106 (*breakpoint_p)->unique_id );
107
108 return ERROR_OK;
109 }
110
111 int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type)
112 {
113 struct breakpoint *breakpoint = target->breakpoints;
114 struct breakpoint **breakpoint_p = &target->breakpoints;
115 int retval;
116 int n;
117
118 n = 0;
119 while (breakpoint)
120 {
121 n++;
122 if (breakpoint->asid == asid)
123 {
124 /* FIXME don't assume "same address" means "same
125 * breakpoint" ... check all the parameters before
126 * succeeding.
127 */
128 LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
129 asid, breakpoint->unique_id );
130 return -1;
131 }
132 breakpoint_p = &breakpoint->next;
133 breakpoint = breakpoint->next;
134 }
135
136 (*breakpoint_p) = malloc(sizeof(struct breakpoint));
137 (*breakpoint_p)->address = 0;
138 (*breakpoint_p)->asid = asid;
139 (*breakpoint_p)->length = length;
140 (*breakpoint_p)->type = type;
141 (*breakpoint_p)->set = 0;
142 (*breakpoint_p)->orig_instr = malloc(length);
143 (*breakpoint_p)->next = NULL;
144 (*breakpoint_p)->unique_id = bpwp_unique_id++;
145 retval = target_add_context_breakpoint(target, *breakpoint_p);
146 if (retval != ERROR_OK)
147 {
148 LOG_ERROR("could not add breakpoint");
149 free((*breakpoint_p)->orig_instr);
150 free(*breakpoint_p);
151 *breakpoint_p = NULL;
152 return retval;
153 }
154
155 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
156 breakpoint_type_strings[(*breakpoint_p)->type],
157 (*breakpoint_p)->asid, (*breakpoint_p)->length,
158 (*breakpoint_p)->unique_id );
159
160 return ERROR_OK;
161 }
162
163 int hybrid_breakpoint_add_internal(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type)
164 {
165 struct breakpoint *breakpoint = target->breakpoints;
166 struct breakpoint **breakpoint_p = &target->breakpoints;
167 int retval;
168 int n;
169 n = 0;
170 while (breakpoint)
171 {
172 n++;
173 if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
174 /* FIXME don't assume "same address" means "same
175 * breakpoint" ... check all the parameters before
176 * succeeding.
177 */
178 LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %d)",
179 asid, breakpoint->unique_id );
180 return -1;
181 }
182 else if ((breakpoint->address == address) && (breakpoint->asid == 0))
183 {
184 LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %d)",
185 address, breakpoint->unique_id );
186 return -1;
187
188 }
189 breakpoint_p = &breakpoint->next;
190 breakpoint = breakpoint->next;
191 }
192 (*breakpoint_p) = malloc(sizeof(struct breakpoint));
193 (*breakpoint_p)->address = address;
194 (*breakpoint_p)->asid = asid;
195 (*breakpoint_p)->length = length;
196 (*breakpoint_p)->type = type;
197 (*breakpoint_p)->set = 0;
198 (*breakpoint_p)->orig_instr = malloc(length);
199 (*breakpoint_p)->next = NULL;
200 (*breakpoint_p)->unique_id = bpwp_unique_id++;
201
202
203 retval = target_add_hybrid_breakpoint(target, *breakpoint_p);
204 if (retval != ERROR_OK)
205 {
206 LOG_ERROR("could not add breakpoint");
207 free((*breakpoint_p)->orig_instr);
208 free(*breakpoint_p);
209 *breakpoint_p = NULL;
210 return retval;
211 }
212 LOG_DEBUG("added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
213 breakpoint_type_strings[(*breakpoint_p)->type],
214 (*breakpoint_p)->address, (*breakpoint_p)->length,
215 (*breakpoint_p)->unique_id );
216
217 return ERROR_OK;
218 }
219
220
221
222 int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
223 {
224
225 int retval = ERROR_OK;
226 if (target->smp)
227 {
228 struct target_list *head;
229 struct target *curr;
230 head = target->head;
231 while(head != (struct target_list*)NULL)
232 {
233 curr = head->target;
234 retval = breakpoint_add_internal(curr, address,length, type);
235 if (retval != ERROR_OK) return retval;
236 head = head->next;
237 }
238 return retval;
239 }
240 else
241 return(breakpoint_add_internal(target, address, length, type));
242
243 }
244 int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type)
245 {
246
247 int retval = ERROR_OK;
248 if (target->smp)
249 {
250 struct target_list *head;
251 struct target *curr;
252 head = target->head;
253 while(head != (struct target_list*)NULL)
254 {
255 curr = head->target;
256 retval = context_breakpoint_add_internal(curr, asid,length, type);
257 if (retval != ERROR_OK) return retval;
258 head = head->next;
259 }
260 return retval;
261 }
262 else
263 return(context_breakpoint_add_internal(target, asid, length, type));
264
265 }
266 int hybrid_breakpoint_add(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type)
267 {
268
269 int retval = ERROR_OK;
270 if (target->smp)
271 {
272 struct target_list *head;
273 struct target *curr;
274 head = target->head;
275 while(head != (struct target_list*)NULL)
276 {
277 curr = head->target;
278 retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
279 if (retval != ERROR_OK) return retval;
280 head = head->next;
281 }
282 return retval;
283 }
284 else
285 return(hybrid_breakpoint_add_internal(target, address, asid, length, type));
286
287 }
288
289 /* free up a breakpoint */
290 static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
291 {
292 struct breakpoint *breakpoint = target->breakpoints;
293 struct breakpoint **breakpoint_p = &target->breakpoints;
294 int retval;
295
296 while (breakpoint)
297 {
298 if (breakpoint == breakpoint_to_remove)
299 break;
300 breakpoint_p = &breakpoint->next;
301 breakpoint = breakpoint->next;
302 }
303
304 if (breakpoint == NULL)
305 return;
306
307 retval = target_remove_breakpoint(target, breakpoint);
308
309 LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
310 (*breakpoint_p) = breakpoint->next;
311 free(breakpoint->orig_instr);
312 free(breakpoint);
313 }
314
315 void breakpoint_remove_internal(struct target *target, uint32_t address)
316 {
317 struct breakpoint *breakpoint = target->breakpoints;
318
319 while (breakpoint)
320 {
321 if ((breakpoint->address == address) && (breakpoint->asid == 0))
322 break;
323 else if ((breakpoint->address == 0) && (breakpoint->asid == address))
324 break;
325 else if ((breakpoint->address == address) && (breakpoint->asid != 0))
326 break;
327 breakpoint = breakpoint->next;
328 }
329
330 if (breakpoint)
331 {
332 breakpoint_free(target, breakpoint);
333 }
334 else
335 {
336 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
337 }
338 }
339 void breakpoint_remove(struct target *target, uint32_t address)
340 {
341 if ((target->smp))
342 {
343 struct target_list *head;
344 struct target *curr;
345 head = target->head;
346 while(head != (struct target_list*)NULL)
347 {
348 curr = head->target;
349 breakpoint_remove_internal(curr, address);
350 head = head->next;
351 }
352 }
353 else breakpoint_remove_internal(target, address);
354 }
355
356 void breakpoint_clear_target_internal(struct target *target)
357 {
358 struct breakpoint *breakpoint;
359
360 LOG_DEBUG("Delete all breakpoints for target: %s",
361 target_name(target));
362 while ((breakpoint = target->breakpoints) != NULL)
363 {
364 breakpoint_free(target, breakpoint);
365 }
366 }
367
368 void breakpoint_clear_target(struct target *target)
369 {
370 if (target->smp)
371 {
372 struct target_list *head;
373 struct target *curr;
374 head = target->head;
375 while(head != (struct target_list*)NULL)
376 {
377 curr = head->target;
378 breakpoint_clear_target_internal(curr);
379 head = head->next;
380 }
381 }
382 else breakpoint_clear_target_internal(target);
383
384 }
385
386
387 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
388 {
389 struct breakpoint *breakpoint = target->breakpoints;
390
391 while (breakpoint)
392 {
393 if (breakpoint->address == address)
394 return breakpoint;
395 breakpoint = breakpoint->next;
396 }
397
398 return NULL;
399 }
400
401 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
402 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
403 {
404 struct watchpoint *watchpoint = target->watchpoints;
405 struct watchpoint **watchpoint_p = &target->watchpoints;
406 int retval;
407 char *reason;
408
409 while (watchpoint)
410 {
411 if (watchpoint->address == address) {
412 if (watchpoint->length != length
413 || watchpoint->value != value
414 || watchpoint->mask != mask
415 || watchpoint->rw != rw) {
416 LOG_ERROR("address 0x%8.8" PRIx32
417 "already has watchpoint %d",
418 address, watchpoint->unique_id);
419 return ERROR_FAIL;
420 }
421
422 /* ignore duplicate watchpoint */
423 return ERROR_OK;
424 }
425 watchpoint_p = &watchpoint->next;
426 watchpoint = watchpoint->next;
427 }
428
429 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
430 (*watchpoint_p)->address = address;
431 (*watchpoint_p)->length = length;
432 (*watchpoint_p)->value = value;
433 (*watchpoint_p)->mask = mask;
434 (*watchpoint_p)->rw = rw;
435 (*watchpoint_p)->unique_id = bpwp_unique_id++;
436
437 retval = target_add_watchpoint(target, *watchpoint_p);
438 switch (retval) {
439 case ERROR_OK:
440 break;
441 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
442 reason = "resource not available";
443 goto bye;
444 case ERROR_TARGET_NOT_HALTED:
445 reason = "target running";
446 goto bye;
447 default:
448 reason = "unrecognized error";
449 bye:
450 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
451 watchpoint_rw_strings[(*watchpoint_p)->rw],
452 address, reason);
453 free (*watchpoint_p);
454 *watchpoint_p = NULL;
455 return retval;
456 }
457
458 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
459 " of length 0x%8.8" PRIx32 " (WPID: %d)",
460 watchpoint_rw_strings[(*watchpoint_p)->rw],
461 (*watchpoint_p)->address,
462 (*watchpoint_p)->length,
463 (*watchpoint_p)->unique_id );
464
465 return ERROR_OK;
466 }
467
468 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
469 {
470 struct watchpoint *watchpoint = target->watchpoints;
471 struct watchpoint **watchpoint_p = &target->watchpoints;
472 int retval;
473
474 while (watchpoint)
475 {
476 if (watchpoint == watchpoint_to_remove)
477 break;
478 watchpoint_p = &watchpoint->next;
479 watchpoint = watchpoint->next;
480 }
481
482 if (watchpoint == NULL)
483 return;
484 retval = target_remove_watchpoint(target, watchpoint);
485 LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
486 (*watchpoint_p) = watchpoint->next;
487 free(watchpoint);
488 }
489
490 void watchpoint_remove(struct target *target, uint32_t address)
491 {
492 struct watchpoint *watchpoint = target->watchpoints;
493
494 while (watchpoint)
495 {
496 if (watchpoint->address == address)
497 break;
498 watchpoint = watchpoint->next;
499 }
500
501 if (watchpoint)
502 {
503 watchpoint_free(target, watchpoint);
504 }
505 else
506 {
507 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
508 }
509 }
510
511 void watchpoint_clear_target(struct target *target)
512 {
513 struct watchpoint *watchpoint;
514
515 LOG_DEBUG("Delete all watchpoints for target: %s",
516 target_name(target));
517 while ((watchpoint = target->watchpoints) != NULL)
518 {
519 watchpoint_free(target, watchpoint);
520 }
521 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)