cleanup: rename armv4_5 to arm for readability
[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 if (type == BKPT_SOFT)
232 return(breakpoint_add_internal(head->target, address,length, type));
233
234 while(head != (struct target_list*)NULL)
235 {
236 curr = head->target;
237 retval = breakpoint_add_internal(curr, address,length, type);
238 if (retval != ERROR_OK) return retval;
239 head = head->next;
240 }
241 return retval;
242 }
243 else
244 return(breakpoint_add_internal(target, address, length, type));
245
246 }
247 int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type)
248 {
249
250 int retval = ERROR_OK;
251 if (target->smp)
252 {
253 struct target_list *head;
254 struct target *curr;
255 head = target->head;
256 while(head != (struct target_list*)NULL)
257 {
258 curr = head->target;
259 retval = context_breakpoint_add_internal(curr, asid,length, type);
260 if (retval != ERROR_OK) return retval;
261 head = head->next;
262 }
263 return retval;
264 }
265 else
266 return(context_breakpoint_add_internal(target, asid, length, type));
267
268 }
269 int hybrid_breakpoint_add(struct target *target, uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type)
270 {
271
272 int retval = ERROR_OK;
273 if (target->smp)
274 {
275 struct target_list *head;
276 struct target *curr;
277 head = target->head;
278 while(head != (struct target_list*)NULL)
279 {
280 curr = head->target;
281 retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
282 if (retval != ERROR_OK) return retval;
283 head = head->next;
284 }
285 return retval;
286 }
287 else
288 return(hybrid_breakpoint_add_internal(target, address, asid, length, type));
289
290 }
291
292 /* free up a breakpoint */
293 static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
294 {
295 struct breakpoint *breakpoint = target->breakpoints;
296 struct breakpoint **breakpoint_p = &target->breakpoints;
297 int retval;
298
299 while (breakpoint)
300 {
301 if (breakpoint == breakpoint_to_remove)
302 break;
303 breakpoint_p = &breakpoint->next;
304 breakpoint = breakpoint->next;
305 }
306
307 if (breakpoint == NULL)
308 return;
309
310 retval = target_remove_breakpoint(target, breakpoint);
311
312 LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
313 (*breakpoint_p) = breakpoint->next;
314 free(breakpoint->orig_instr);
315 free(breakpoint);
316 }
317
318 int breakpoint_remove_internal(struct target *target, uint32_t address)
319 {
320 struct breakpoint *breakpoint = target->breakpoints;
321
322 while (breakpoint)
323 {
324 if ((breakpoint->address == address) && (breakpoint->asid == 0))
325 break;
326 else if ((breakpoint->address == 0) && (breakpoint->asid == address))
327 break;
328 else if ((breakpoint->address == address) && (breakpoint->asid != 0))
329 break;
330 breakpoint = breakpoint->next;
331 }
332
333 if (breakpoint)
334 {
335 breakpoint_free(target, breakpoint);
336 return 1;
337 }
338 else
339 {
340 if (!target->smp)
341 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
342 return 0;
343 }
344 }
345 void breakpoint_remove(struct target *target, uint32_t address)
346 {
347 int found = 0;
348 if (target->smp)
349 {
350 struct target_list *head;
351 struct target *curr;
352 head = target->head;
353 while(head != (struct target_list*)NULL)
354 {
355 curr = head->target;
356 found += breakpoint_remove_internal(curr, address);
357 head = head->next;
358 }
359 if (found == 0)
360 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
361 }
362 else breakpoint_remove_internal(target, address);
363 }
364
365 void breakpoint_clear_target_internal(struct target *target)
366 {
367 struct breakpoint *breakpoint;
368
369 LOG_DEBUG("Delete all breakpoints for target: %s",
370 target_name(target));
371 while ((breakpoint = target->breakpoints) != NULL)
372 {
373 breakpoint_free(target, breakpoint);
374 }
375 }
376
377 void breakpoint_clear_target(struct target *target)
378 {
379 if (target->smp)
380 {
381 struct target_list *head;
382 struct target *curr;
383 head = target->head;
384 while(head != (struct target_list*)NULL)
385 {
386 curr = head->target;
387 breakpoint_clear_target_internal(curr);
388 head = head->next;
389 }
390 }
391 else breakpoint_clear_target_internal(target);
392
393 }
394
395
396 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
397 {
398 struct breakpoint *breakpoint = target->breakpoints;
399
400 while (breakpoint)
401 {
402 if (breakpoint->address == address)
403 return breakpoint;
404 breakpoint = breakpoint->next;
405 }
406
407 return NULL;
408 }
409
410 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
411 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
412 {
413 struct watchpoint *watchpoint = target->watchpoints;
414 struct watchpoint **watchpoint_p = &target->watchpoints;
415 int retval;
416 char *reason;
417
418 while (watchpoint)
419 {
420 if (watchpoint->address == address) {
421 if (watchpoint->length != length
422 || watchpoint->value != value
423 || watchpoint->mask != mask
424 || watchpoint->rw != rw) {
425 LOG_ERROR("address 0x%8.8" PRIx32
426 "already has watchpoint %d",
427 address, watchpoint->unique_id);
428 return ERROR_FAIL;
429 }
430
431 /* ignore duplicate watchpoint */
432 return ERROR_OK;
433 }
434 watchpoint_p = &watchpoint->next;
435 watchpoint = watchpoint->next;
436 }
437
438 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
439 (*watchpoint_p)->address = address;
440 (*watchpoint_p)->length = length;
441 (*watchpoint_p)->value = value;
442 (*watchpoint_p)->mask = mask;
443 (*watchpoint_p)->rw = rw;
444 (*watchpoint_p)->unique_id = bpwp_unique_id++;
445
446 retval = target_add_watchpoint(target, *watchpoint_p);
447 switch (retval) {
448 case ERROR_OK:
449 break;
450 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
451 reason = "resource not available";
452 goto bye;
453 case ERROR_TARGET_NOT_HALTED:
454 reason = "target running";
455 goto bye;
456 default:
457 reason = "unrecognized error";
458 bye:
459 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
460 watchpoint_rw_strings[(*watchpoint_p)->rw],
461 address, reason);
462 free (*watchpoint_p);
463 *watchpoint_p = NULL;
464 return retval;
465 }
466
467 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
468 " of length 0x%8.8" PRIx32 " (WPID: %d)",
469 watchpoint_rw_strings[(*watchpoint_p)->rw],
470 (*watchpoint_p)->address,
471 (*watchpoint_p)->length,
472 (*watchpoint_p)->unique_id);
473
474 return ERROR_OK;
475 }
476
477 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
478 {
479 struct watchpoint *watchpoint = target->watchpoints;
480 struct watchpoint **watchpoint_p = &target->watchpoints;
481 int retval;
482
483 while (watchpoint)
484 {
485 if (watchpoint == watchpoint_to_remove)
486 break;
487 watchpoint_p = &watchpoint->next;
488 watchpoint = watchpoint->next;
489 }
490
491 if (watchpoint == NULL)
492 return;
493 retval = target_remove_watchpoint(target, watchpoint);
494 LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
495 (*watchpoint_p) = watchpoint->next;
496 free(watchpoint);
497 }
498
499 void watchpoint_remove(struct target *target, uint32_t address)
500 {
501 struct watchpoint *watchpoint = target->watchpoints;
502
503 while (watchpoint)
504 {
505 if (watchpoint->address == address)
506 break;
507 watchpoint = watchpoint->next;
508 }
509
510 if (watchpoint)
511 {
512 watchpoint_free(target, watchpoint);
513 }
514 else
515 {
516 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
517 }
518 }
519
520 void watchpoint_clear_target(struct target *target)
521 {
522 struct watchpoint *watchpoint;
523
524 LOG_DEBUG("Delete all watchpoints for target: %s",
525 target_name(target));
526 while ((watchpoint = target->watchpoints) != NULL)
527 {
528 watchpoint_free(target, watchpoint);
529 }
530 }

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)