1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) ST-Ericsson SA 2011 *
8 * michel.jaouen@stericsson.com : smp minimum support *
9 ***************************************************************************/
16 #include <helper/log.h>
17 #include "breakpoints.h"
20 static const char * const breakpoint_type_strings
[] = {
25 static const char * const watchpoint_rw_strings
[] = {
31 /* monotonic counter/id-number for breakpoints and watch points */
32 static int bpwp_unique_id
;
34 static int breakpoint_add_internal(struct target
*target
,
35 target_addr_t address
,
37 enum breakpoint_type type
)
39 struct breakpoint
*breakpoint
= target
->breakpoints
;
40 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
45 if (breakpoint
->address
== address
) {
46 /* FIXME don't assume "same address" means "same
47 * breakpoint" ... check all the parameters before
50 LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
51 address
, breakpoint
->unique_id
);
52 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
54 breakpoint_p
= &breakpoint
->next
;
55 breakpoint
= breakpoint
->next
;
58 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
59 (*breakpoint_p
)->address
= address
;
60 (*breakpoint_p
)->asid
= 0;
61 (*breakpoint_p
)->length
= length
;
62 (*breakpoint_p
)->type
= type
;
63 (*breakpoint_p
)->is_set
= false;
64 (*breakpoint_p
)->orig_instr
= malloc(length
);
65 (*breakpoint_p
)->next
= NULL
;
66 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
68 retval
= target_add_breakpoint(target
, *breakpoint_p
);
72 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
73 reason
= "resource not available";
75 case ERROR_TARGET_NOT_HALTED
:
76 reason
= "target running";
79 reason
= "unknown reason";
81 LOG_ERROR("can't add breakpoint: %s", reason
);
82 free((*breakpoint_p
)->orig_instr
);
88 LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT
89 " of length 0x%8.8x, (BPID: %" PRIu32
")",
91 breakpoint_type_strings
[(*breakpoint_p
)->type
],
92 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
93 (*breakpoint_p
)->unique_id
);
98 static int context_breakpoint_add_internal(struct target
*target
,
101 enum breakpoint_type type
)
103 struct breakpoint
*breakpoint
= target
->breakpoints
;
104 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
108 if (breakpoint
->asid
== asid
) {
109 /* FIXME don't assume "same address" means "same
110 * breakpoint" ... check all the parameters before
113 LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
114 asid
, breakpoint
->unique_id
);
115 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
117 breakpoint_p
= &breakpoint
->next
;
118 breakpoint
= breakpoint
->next
;
121 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
122 (*breakpoint_p
)->address
= 0;
123 (*breakpoint_p
)->asid
= asid
;
124 (*breakpoint_p
)->length
= length
;
125 (*breakpoint_p
)->type
= type
;
126 (*breakpoint_p
)->is_set
= false;
127 (*breakpoint_p
)->orig_instr
= malloc(length
);
128 (*breakpoint_p
)->next
= NULL
;
129 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
130 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
131 if (retval
!= ERROR_OK
) {
132 LOG_ERROR("could not add breakpoint");
133 free((*breakpoint_p
)->orig_instr
);
135 *breakpoint_p
= NULL
;
139 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %" PRIu32
")",
140 breakpoint_type_strings
[(*breakpoint_p
)->type
],
141 (*breakpoint_p
)->asid
, (*breakpoint_p
)->length
,
142 (*breakpoint_p
)->unique_id
);
147 static int hybrid_breakpoint_add_internal(struct target
*target
,
148 target_addr_t address
,
151 enum breakpoint_type type
)
153 struct breakpoint
*breakpoint
= target
->breakpoints
;
154 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
158 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
159 /* FIXME don't assume "same address" means "same
160 * breakpoint" ... check all the parameters before
163 LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
164 asid
, breakpoint
->unique_id
);
165 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
166 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
167 LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
168 address
, breakpoint
->unique_id
);
169 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
172 breakpoint_p
= &breakpoint
->next
;
173 breakpoint
= breakpoint
->next
;
175 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
176 (*breakpoint_p
)->address
= address
;
177 (*breakpoint_p
)->asid
= asid
;
178 (*breakpoint_p
)->length
= length
;
179 (*breakpoint_p
)->type
= type
;
180 (*breakpoint_p
)->is_set
= false;
181 (*breakpoint_p
)->orig_instr
= malloc(length
);
182 (*breakpoint_p
)->next
= NULL
;
183 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
186 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
187 if (retval
!= ERROR_OK
) {
188 LOG_ERROR("could not add breakpoint");
189 free((*breakpoint_p
)->orig_instr
);
191 *breakpoint_p
= NULL
;
195 "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
196 breakpoint_type_strings
[(*breakpoint_p
)->type
],
197 (*breakpoint_p
)->address
,
198 (*breakpoint_p
)->length
,
199 (*breakpoint_p
)->unique_id
);
204 int breakpoint_add(struct target
*target
,
205 target_addr_t address
,
207 enum breakpoint_type type
)
210 struct target_list
*head
;
212 if (type
== BKPT_SOFT
) {
213 head
= list_first_entry(target
->smp_targets
, struct target_list
, lh
);
214 return breakpoint_add_internal(head
->target
, address
, length
, type
);
217 foreach_smp_target(head
, target
->smp_targets
) {
218 struct target
*curr
= head
->target
;
219 int retval
= breakpoint_add_internal(curr
, address
, length
, type
);
220 if (retval
!= ERROR_OK
)
226 return breakpoint_add_internal(target
, address
, length
, type
);
230 int context_breakpoint_add(struct target
*target
,
233 enum breakpoint_type type
)
236 struct target_list
*head
;
238 foreach_smp_target(head
, target
->smp_targets
) {
239 struct target
*curr
= head
->target
;
240 int retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
241 if (retval
!= ERROR_OK
)
247 return context_breakpoint_add_internal(target
, asid
, length
, type
);
251 int hybrid_breakpoint_add(struct target
*target
,
252 target_addr_t address
,
255 enum breakpoint_type type
)
258 struct target_list
*head
;
260 foreach_smp_target(head
, target
->smp_targets
) {
261 struct target
*curr
= head
->target
;
262 int retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
263 if (retval
!= ERROR_OK
)
269 return hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
);
272 /* free up a breakpoint */
273 static int breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
275 struct breakpoint
*breakpoint
= target
->breakpoints
;
276 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
280 if (breakpoint
== breakpoint_to_remove
)
282 breakpoint_p
= &breakpoint
->next
;
283 breakpoint
= breakpoint
->next
;
289 retval
= target_remove_breakpoint(target
, breakpoint
);
290 if (retval
!= ERROR_OK
) {
291 LOG_TARGET_ERROR(target
, "could not remove breakpoint #%d on this target",
296 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
297 (*breakpoint_p
) = breakpoint
->next
;
298 free(breakpoint
->orig_instr
);
304 static int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
306 struct breakpoint
*breakpoint
= target
->breakpoints
;
309 if ((breakpoint
->address
== address
) ||
310 (breakpoint
->address
== 0 && breakpoint
->asid
== address
))
312 breakpoint
= breakpoint
->next
;
316 return breakpoint_free(target
, breakpoint
);
318 return ERROR_BREAKPOINT_NOT_FOUND
;
322 static int breakpoint_remove_all_internal(struct target
*target
)
324 struct breakpoint
*breakpoint
= target
->breakpoints
;
325 int retval
= ERROR_OK
;
328 struct breakpoint
*tmp
= breakpoint
;
329 breakpoint
= breakpoint
->next
;
330 int status
= breakpoint_free(target
, tmp
);
331 if (status
!= ERROR_OK
)
338 int breakpoint_remove(struct target
*target
, target_addr_t address
)
340 int retval
= ERROR_OK
;
341 unsigned int num_found_breakpoints
= 0;
343 struct target_list
*head
;
345 foreach_smp_target(head
, target
->smp_targets
) {
346 struct target
*curr
= head
->target
;
347 int status
= breakpoint_remove_internal(curr
, address
);
349 if (status
!= ERROR_BREAKPOINT_NOT_FOUND
) {
350 num_found_breakpoints
++;
352 if (status
!= ERROR_OK
) {
353 LOG_TARGET_ERROR(curr
, "failed to remove breakpoint at address " TARGET_ADDR_FMT
, address
);
360 retval
= breakpoint_remove_internal(target
, address
);
362 if (retval
!= ERROR_BREAKPOINT_NOT_FOUND
) {
363 num_found_breakpoints
++;
365 if (retval
!= ERROR_OK
)
366 LOG_TARGET_ERROR(target
, "failed to remove breakpoint at address " TARGET_ADDR_FMT
, address
);
370 if (num_found_breakpoints
== 0)
371 LOG_TARGET_ERROR(target
, "no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
376 int breakpoint_remove_all(struct target
*target
)
378 int retval
= ERROR_OK
;
380 struct target_list
*head
;
382 foreach_smp_target(head
, target
->smp_targets
) {
383 struct target
*curr
= head
->target
;
384 int status
= breakpoint_remove_all_internal(curr
);
386 if (status
!= ERROR_OK
)
390 retval
= breakpoint_remove_all_internal(target
);
396 static int breakpoint_clear_target_internal(struct target
*target
)
398 LOG_DEBUG("Delete all breakpoints for target: %s",
399 target_name(target
));
401 int retval
= ERROR_OK
;
403 while (target
->breakpoints
) {
404 int status
= breakpoint_free(target
, target
->breakpoints
);
405 if (status
!= ERROR_OK
)
412 int breakpoint_clear_target(struct target
*target
)
414 int retval
= ERROR_OK
;
417 struct target_list
*head
;
419 foreach_smp_target(head
, target
->smp_targets
) {
420 struct target
*curr
= head
->target
;
421 int status
= breakpoint_clear_target_internal(curr
);
423 if (status
!= ERROR_OK
)
427 retval
= breakpoint_clear_target_internal(target
);
433 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
435 struct breakpoint
*breakpoint
= target
->breakpoints
;
438 if (breakpoint
->address
== address
)
440 breakpoint
= breakpoint
->next
;
446 static int watchpoint_add_internal(struct target
*target
, target_addr_t address
,
447 uint32_t length
, enum watchpoint_rw rw
, uint64_t value
, uint64_t mask
)
449 struct watchpoint
*watchpoint
= target
->watchpoints
;
450 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
455 if (watchpoint
->address
== address
) {
456 if (watchpoint
->length
!= length
457 || watchpoint
->value
!= value
458 || watchpoint
->mask
!= mask
459 || watchpoint
->rw
!= rw
) {
460 LOG_ERROR("address " TARGET_ADDR_FMT
461 " already has watchpoint %d",
462 address
, watchpoint
->unique_id
);
466 /* ignore duplicate watchpoint */
469 watchpoint_p
= &watchpoint
->next
;
470 watchpoint
= watchpoint
->next
;
473 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
474 (*watchpoint_p
)->address
= address
;
475 (*watchpoint_p
)->length
= length
;
476 (*watchpoint_p
)->value
= value
;
477 (*watchpoint_p
)->mask
= mask
;
478 (*watchpoint_p
)->rw
= rw
;
479 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
481 retval
= target_add_watchpoint(target
, *watchpoint_p
);
485 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
486 reason
= "resource not available";
488 case ERROR_TARGET_NOT_HALTED
:
489 reason
= "target running";
492 reason
= "unrecognized error";
494 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
495 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
498 *watchpoint_p
= NULL
;
502 LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT
503 " of length 0x%8.8" PRIx32
" (WPID: %d)",
505 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
506 (*watchpoint_p
)->address
,
507 (*watchpoint_p
)->length
,
508 (*watchpoint_p
)->unique_id
);
513 int watchpoint_add(struct target
*target
, target_addr_t address
,
514 uint32_t length
, enum watchpoint_rw rw
, uint64_t value
, uint64_t mask
)
517 struct target_list
*head
;
519 foreach_smp_target(head
, target
->smp_targets
) {
520 struct target
*curr
= head
->target
;
521 int retval
= watchpoint_add_internal(curr
, address
, length
, rw
, value
, mask
);
522 if (retval
!= ERROR_OK
)
528 return watchpoint_add_internal(target
, address
, length
, rw
, value
,
533 static int watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
535 struct watchpoint
*watchpoint
= target
->watchpoints
;
536 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
540 if (watchpoint
== watchpoint_to_remove
)
542 watchpoint_p
= &watchpoint
->next
;
543 watchpoint
= watchpoint
->next
;
548 retval
= target_remove_watchpoint(target
, watchpoint
);
549 if (retval
!= ERROR_OK
) {
550 LOG_TARGET_ERROR(target
, "could not remove watchpoint #%d on this target",
555 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
556 (*watchpoint_p
) = watchpoint
->next
;
562 static int watchpoint_remove_internal(struct target
*target
, target_addr_t address
)
564 struct watchpoint
*watchpoint
= target
->watchpoints
;
567 if (watchpoint
->address
== address
)
569 watchpoint
= watchpoint
->next
;
573 return watchpoint_free(target
, watchpoint
);
575 return ERROR_WATCHPOINT_NOT_FOUND
;
579 int watchpoint_remove(struct target
*target
, target_addr_t address
)
581 int retval
= ERROR_OK
;
582 unsigned int num_found_watchpoints
= 0;
584 struct target_list
*head
;
586 foreach_smp_target(head
, target
->smp_targets
) {
587 struct target
*curr
= head
->target
;
588 int status
= watchpoint_remove_internal(curr
, address
);
590 if (status
!= ERROR_WATCHPOINT_NOT_FOUND
) {
591 num_found_watchpoints
++;
593 if (status
!= ERROR_OK
) {
594 LOG_TARGET_ERROR(curr
, "failed to remove watchpoint at address" TARGET_ADDR_FMT
, address
);
600 retval
= watchpoint_remove_internal(target
, address
);
602 if (retval
!= ERROR_WATCHPOINT_NOT_FOUND
) {
603 num_found_watchpoints
++;
605 if (retval
!= ERROR_OK
)
606 LOG_TARGET_ERROR(target
, "failed to remove watchpoint at address" TARGET_ADDR_FMT
, address
);
610 if (num_found_watchpoints
== 0)
611 LOG_TARGET_ERROR(target
, "no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
616 int watchpoint_clear_target(struct target
*target
)
618 int retval
= ERROR_OK
;
620 LOG_DEBUG("Delete all watchpoints for target: %s",
621 target_name(target
));
622 while (target
->watchpoints
) {
623 int status
= watchpoint_free(target
, target
->watchpoints
);
624 if (status
!= ERROR_OK
)
631 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
632 target_addr_t
*address
)
635 struct watchpoint
*hit_watchpoint
;
637 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
638 if (retval
!= ERROR_OK
)
641 *rw
= hit_watchpoint
->rw
;
642 *address
= hit_watchpoint
->address
;
644 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
645 hit_watchpoint
->address
,
646 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)