1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) ST-Ericsson SA 2011 *
6 * michel.jaouen@stericsson.com : smp minimum support *
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. *
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. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
27 #include <helper/log.h>
28 #include "breakpoints.h"
30 static const char * const breakpoint_type_strings
[] = {
35 static const char * const watchpoint_rw_strings
[] = {
41 /* monotonic counter/id-number for breakpoints and watch points */
42 static int bpwp_unique_id
;
44 static int breakpoint_add_internal(struct target
*target
,
45 target_addr_t address
,
47 enum breakpoint_type type
)
49 struct breakpoint
*breakpoint
= target
->breakpoints
;
50 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
55 if (breakpoint
->address
== address
) {
56 /* FIXME don't assume "same address" means "same
57 * breakpoint" ... check all the parameters before
60 LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
61 address
, breakpoint
->unique_id
);
62 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
64 breakpoint_p
= &breakpoint
->next
;
65 breakpoint
= breakpoint
->next
;
68 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
69 (*breakpoint_p
)->address
= address
;
70 (*breakpoint_p
)->asid
= 0;
71 (*breakpoint_p
)->length
= length
;
72 (*breakpoint_p
)->type
= type
;
73 (*breakpoint_p
)->set
= 0;
74 (*breakpoint_p
)->orig_instr
= malloc(length
);
75 (*breakpoint_p
)->next
= NULL
;
76 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
78 retval
= target_add_breakpoint(target
, *breakpoint_p
);
82 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
83 reason
= "resource not available";
85 case ERROR_TARGET_NOT_HALTED
:
86 reason
= "target running";
89 reason
= "unknown reason";
91 LOG_ERROR("can't add breakpoint: %s", reason
);
92 free((*breakpoint_p
)->orig_instr
);
98 LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT
99 " of length 0x%8.8x, (BPID: %" PRIu32
")",
101 breakpoint_type_strings
[(*breakpoint_p
)->type
],
102 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
103 (*breakpoint_p
)->unique_id
);
108 static int context_breakpoint_add_internal(struct target
*target
,
111 enum breakpoint_type type
)
113 struct breakpoint
*breakpoint
= target
->breakpoints
;
114 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
118 if (breakpoint
->asid
== asid
) {
119 /* FIXME don't assume "same address" means "same
120 * breakpoint" ... check all the parameters before
123 LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
124 asid
, breakpoint
->unique_id
);
125 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
127 breakpoint_p
= &breakpoint
->next
;
128 breakpoint
= breakpoint
->next
;
131 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
132 (*breakpoint_p
)->address
= 0;
133 (*breakpoint_p
)->asid
= asid
;
134 (*breakpoint_p
)->length
= length
;
135 (*breakpoint_p
)->type
= type
;
136 (*breakpoint_p
)->set
= 0;
137 (*breakpoint_p
)->orig_instr
= malloc(length
);
138 (*breakpoint_p
)->next
= NULL
;
139 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
140 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
141 if (retval
!= ERROR_OK
) {
142 LOG_ERROR("could not add breakpoint");
143 free((*breakpoint_p
)->orig_instr
);
145 *breakpoint_p
= NULL
;
149 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %" PRIu32
")",
150 breakpoint_type_strings
[(*breakpoint_p
)->type
],
151 (*breakpoint_p
)->asid
, (*breakpoint_p
)->length
,
152 (*breakpoint_p
)->unique_id
);
157 static int hybrid_breakpoint_add_internal(struct target
*target
,
158 target_addr_t address
,
161 enum breakpoint_type type
)
163 struct breakpoint
*breakpoint
= target
->breakpoints
;
164 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
168 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
169 /* FIXME don't assume "same address" means "same
170 * breakpoint" ... check all the parameters before
173 LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
174 asid
, breakpoint
->unique_id
);
175 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
176 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
177 LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
178 address
, breakpoint
->unique_id
);
179 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
182 breakpoint_p
= &breakpoint
->next
;
183 breakpoint
= breakpoint
->next
;
185 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
186 (*breakpoint_p
)->address
= address
;
187 (*breakpoint_p
)->asid
= asid
;
188 (*breakpoint_p
)->length
= length
;
189 (*breakpoint_p
)->type
= type
;
190 (*breakpoint_p
)->set
= 0;
191 (*breakpoint_p
)->orig_instr
= malloc(length
);
192 (*breakpoint_p
)->next
= NULL
;
193 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
196 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
197 if (retval
!= ERROR_OK
) {
198 LOG_ERROR("could not add breakpoint");
199 free((*breakpoint_p
)->orig_instr
);
201 *breakpoint_p
= NULL
;
205 "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
206 breakpoint_type_strings
[(*breakpoint_p
)->type
],
207 (*breakpoint_p
)->address
,
208 (*breakpoint_p
)->length
,
209 (*breakpoint_p
)->unique_id
);
214 int breakpoint_add(struct target
*target
,
215 target_addr_t address
,
217 enum breakpoint_type type
)
219 int retval
= ERROR_OK
;
221 struct target_list
*head
;
224 if (type
== BKPT_SOFT
)
225 return breakpoint_add_internal(head
->target
, address
, length
, type
);
229 retval
= breakpoint_add_internal(curr
, address
, length
, type
);
230 if (retval
!= ERROR_OK
)
236 return breakpoint_add_internal(target
, address
, length
, type
);
240 int context_breakpoint_add(struct target
*target
,
243 enum breakpoint_type type
)
245 int retval
= ERROR_OK
;
247 struct target_list
*head
;
252 retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
253 if (retval
!= ERROR_OK
)
259 return context_breakpoint_add_internal(target
, asid
, length
, type
);
263 int hybrid_breakpoint_add(struct target
*target
,
264 target_addr_t address
,
267 enum breakpoint_type type
)
269 int retval
= ERROR_OK
;
271 struct target_list
*head
;
276 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
277 if (retval
!= ERROR_OK
)
283 return hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
);
286 /* free up a breakpoint */
287 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
289 struct breakpoint
*breakpoint
= target
->breakpoints
;
290 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
294 if (breakpoint
== breakpoint_to_remove
)
296 breakpoint_p
= &breakpoint
->next
;
297 breakpoint
= breakpoint
->next
;
303 retval
= target_remove_breakpoint(target
, breakpoint
);
305 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
306 (*breakpoint_p
) = breakpoint
->next
;
307 free(breakpoint
->orig_instr
);
311 static int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
313 struct breakpoint
*breakpoint
= target
->breakpoints
;
316 if ((breakpoint
->address
== address
) ||
317 (breakpoint
->address
== 0 && breakpoint
->asid
== address
))
319 breakpoint
= breakpoint
->next
;
323 breakpoint_free(target
, breakpoint
);
327 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
332 static void breakpoint_remove_all_internal(struct target
*target
)
334 struct breakpoint
*breakpoint
= target
->breakpoints
;
337 struct breakpoint
*tmp
= breakpoint
;
338 breakpoint
= breakpoint
->next
;
339 breakpoint_free(target
, tmp
);
343 void breakpoint_remove(struct target
*target
, target_addr_t address
)
346 unsigned int num_breakpoints
= 0;
347 struct target_list
*head
;
352 num_breakpoints
+= breakpoint_remove_internal(curr
, address
);
355 if (!num_breakpoints
)
356 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
358 breakpoint_remove_internal(target
, address
);
362 void breakpoint_remove_all(struct target
*target
)
365 struct target_list
*head
;
370 breakpoint_remove_all_internal(curr
);
374 breakpoint_remove_all_internal(target
);
378 static void breakpoint_clear_target_internal(struct target
*target
)
380 LOG_DEBUG("Delete all breakpoints for target: %s",
381 target_name(target
));
382 while (target
->breakpoints
)
383 breakpoint_free(target
, target
->breakpoints
);
386 void breakpoint_clear_target(struct target
*target
)
389 struct target_list
*head
;
394 breakpoint_clear_target_internal(curr
);
398 breakpoint_clear_target_internal(target
);
402 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
404 struct breakpoint
*breakpoint
= target
->breakpoints
;
407 if (breakpoint
->address
== address
)
409 breakpoint
= breakpoint
->next
;
415 int watchpoint_add_internal(struct target
*target
, target_addr_t address
,
416 uint32_t length
, enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
418 struct watchpoint
*watchpoint
= target
->watchpoints
;
419 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
424 if (watchpoint
->address
== address
) {
425 if (watchpoint
->length
!= length
426 || watchpoint
->value
!= value
427 || watchpoint
->mask
!= mask
428 || watchpoint
->rw
!= rw
) {
429 LOG_ERROR("address " TARGET_ADDR_FMT
430 " already has watchpoint %d",
431 address
, watchpoint
->unique_id
);
435 /* ignore duplicate watchpoint */
438 watchpoint_p
= &watchpoint
->next
;
439 watchpoint
= watchpoint
->next
;
442 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
443 (*watchpoint_p
)->address
= address
;
444 (*watchpoint_p
)->length
= length
;
445 (*watchpoint_p
)->value
= value
;
446 (*watchpoint_p
)->mask
= mask
;
447 (*watchpoint_p
)->rw
= rw
;
448 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
450 retval
= target_add_watchpoint(target
, *watchpoint_p
);
454 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
455 reason
= "resource not available";
457 case ERROR_TARGET_NOT_HALTED
:
458 reason
= "target running";
461 reason
= "unrecognized error";
463 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
464 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
467 *watchpoint_p
= NULL
;
471 LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT
472 " of length 0x%8.8" PRIx32
" (WPID: %d)",
474 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
475 (*watchpoint_p
)->address
,
476 (*watchpoint_p
)->length
,
477 (*watchpoint_p
)->unique_id
);
482 int watchpoint_add(struct target
*target
, target_addr_t address
,
483 uint32_t length
, enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
485 int retval
= ERROR_OK
;
487 struct target_list
*head
;
491 while (head
!= (struct target_list
*)NULL
) {
493 retval
= watchpoint_add_internal(curr
, address
, length
, rw
, value
,
495 if (retval
!= ERROR_OK
)
501 return watchpoint_add_internal(target
, address
, length
, rw
, value
,
506 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
508 struct watchpoint
*watchpoint
= target
->watchpoints
;
509 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
513 if (watchpoint
== watchpoint_to_remove
)
515 watchpoint_p
= &watchpoint
->next
;
516 watchpoint
= watchpoint
->next
;
521 retval
= target_remove_watchpoint(target
, watchpoint
);
522 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
523 (*watchpoint_p
) = watchpoint
->next
;
527 int watchpoint_remove_internal(struct target
*target
, target_addr_t address
)
529 struct watchpoint
*watchpoint
= target
->watchpoints
;
532 if (watchpoint
->address
== address
)
534 watchpoint
= watchpoint
->next
;
538 watchpoint_free(target
, watchpoint
);
542 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
547 void watchpoint_remove(struct target
*target
, target_addr_t address
)
550 unsigned int num_watchpoints
= 0;
551 struct target_list
*head
;
556 num_watchpoints
+= watchpoint_remove_internal(curr
, address
);
559 if (num_watchpoints
== 0)
560 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" num_watchpoints", address
);
562 watchpoint_remove_internal(target
, address
);
566 void watchpoint_clear_target(struct target
*target
)
568 LOG_DEBUG("Delete all watchpoints for target: %s",
569 target_name(target
));
570 while (target
->watchpoints
)
571 watchpoint_free(target
, target
->watchpoints
);
574 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
575 target_addr_t
*address
)
578 struct watchpoint
*hit_watchpoint
;
580 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
581 if (retval
!= ERROR_OK
)
584 *rw
= hit_watchpoint
->rw
;
585 *address
= hit_watchpoint
->address
;
587 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
588 hit_watchpoint
->address
,
589 hit_watchpoint
->unique_id
);
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)