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 void 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
);
291 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
292 (*breakpoint_p
) = breakpoint
->next
;
293 free(breakpoint
->orig_instr
);
297 static int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
299 struct breakpoint
*breakpoint
= target
->breakpoints
;
302 if ((breakpoint
->address
== address
) ||
303 (breakpoint
->address
== 0 && breakpoint
->asid
== address
))
305 breakpoint
= breakpoint
->next
;
309 breakpoint_free(target
, breakpoint
);
313 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
318 static void breakpoint_remove_all_internal(struct target
*target
)
320 struct breakpoint
*breakpoint
= target
->breakpoints
;
323 struct breakpoint
*tmp
= breakpoint
;
324 breakpoint
= breakpoint
->next
;
325 breakpoint_free(target
, tmp
);
329 void breakpoint_remove(struct target
*target
, target_addr_t address
)
332 unsigned int num_breakpoints
= 0;
333 struct target_list
*head
;
335 foreach_smp_target(head
, target
->smp_targets
) {
336 struct target
*curr
= head
->target
;
337 num_breakpoints
+= breakpoint_remove_internal(curr
, address
);
339 if (!num_breakpoints
)
340 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
342 breakpoint_remove_internal(target
, address
);
346 void breakpoint_remove_all(struct target
*target
)
349 struct target_list
*head
;
351 foreach_smp_target(head
, target
->smp_targets
) {
352 struct target
*curr
= head
->target
;
353 breakpoint_remove_all_internal(curr
);
356 breakpoint_remove_all_internal(target
);
360 static void breakpoint_clear_target_internal(struct target
*target
)
362 LOG_DEBUG("Delete all breakpoints for target: %s",
363 target_name(target
));
364 while (target
->breakpoints
)
365 breakpoint_free(target
, target
->breakpoints
);
368 void breakpoint_clear_target(struct target
*target
)
371 struct target_list
*head
;
373 foreach_smp_target(head
, target
->smp_targets
) {
374 struct target
*curr
= head
->target
;
375 breakpoint_clear_target_internal(curr
);
378 breakpoint_clear_target_internal(target
);
382 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
384 struct breakpoint
*breakpoint
= target
->breakpoints
;
387 if (breakpoint
->address
== address
)
389 breakpoint
= breakpoint
->next
;
395 static int watchpoint_add_internal(struct target
*target
, target_addr_t address
,
396 uint32_t length
, enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
398 struct watchpoint
*watchpoint
= target
->watchpoints
;
399 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
404 if (watchpoint
->address
== address
) {
405 if (watchpoint
->length
!= length
406 || watchpoint
->value
!= value
407 || watchpoint
->mask
!= mask
408 || watchpoint
->rw
!= rw
) {
409 LOG_ERROR("address " TARGET_ADDR_FMT
410 " already has watchpoint %d",
411 address
, watchpoint
->unique_id
);
415 /* ignore duplicate watchpoint */
418 watchpoint_p
= &watchpoint
->next
;
419 watchpoint
= watchpoint
->next
;
422 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
423 (*watchpoint_p
)->address
= address
;
424 (*watchpoint_p
)->length
= length
;
425 (*watchpoint_p
)->value
= value
;
426 (*watchpoint_p
)->mask
= mask
;
427 (*watchpoint_p
)->rw
= rw
;
428 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
430 retval
= target_add_watchpoint(target
, *watchpoint_p
);
434 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
435 reason
= "resource not available";
437 case ERROR_TARGET_NOT_HALTED
:
438 reason
= "target running";
441 reason
= "unrecognized error";
443 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
444 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
447 *watchpoint_p
= NULL
;
451 LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT
452 " of length 0x%8.8" PRIx32
" (WPID: %d)",
454 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
455 (*watchpoint_p
)->address
,
456 (*watchpoint_p
)->length
,
457 (*watchpoint_p
)->unique_id
);
462 int watchpoint_add(struct target
*target
, target_addr_t address
,
463 uint32_t length
, enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
466 struct target_list
*head
;
468 foreach_smp_target(head
, target
->smp_targets
) {
469 struct target
*curr
= head
->target
;
470 int retval
= watchpoint_add_internal(curr
, address
, length
, rw
, value
, mask
);
471 if (retval
!= ERROR_OK
)
477 return watchpoint_add_internal(target
, address
, length
, rw
, value
,
482 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
484 struct watchpoint
*watchpoint
= target
->watchpoints
;
485 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
489 if (watchpoint
== watchpoint_to_remove
)
491 watchpoint_p
= &watchpoint
->next
;
492 watchpoint
= watchpoint
->next
;
497 retval
= target_remove_watchpoint(target
, watchpoint
);
498 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
499 (*watchpoint_p
) = watchpoint
->next
;
503 static int watchpoint_remove_internal(struct target
*target
, target_addr_t address
)
505 struct watchpoint
*watchpoint
= target
->watchpoints
;
508 if (watchpoint
->address
== address
)
510 watchpoint
= watchpoint
->next
;
514 watchpoint_free(target
, watchpoint
);
518 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
523 void watchpoint_remove(struct target
*target
, target_addr_t address
)
526 unsigned int num_watchpoints
= 0;
527 struct target_list
*head
;
529 foreach_smp_target(head
, target
->smp_targets
) {
530 struct target
*curr
= head
->target
;
531 num_watchpoints
+= watchpoint_remove_internal(curr
, address
);
533 if (num_watchpoints
== 0)
534 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" num_watchpoints", address
);
536 watchpoint_remove_internal(target
, address
);
540 void watchpoint_clear_target(struct target
*target
)
542 LOG_DEBUG("Delete all watchpoints for target: %s",
543 target_name(target
));
544 while (target
->watchpoints
)
545 watchpoint_free(target
, target
->watchpoints
);
548 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
549 target_addr_t
*address
)
552 struct watchpoint
*hit_watchpoint
;
554 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
555 if (retval
!= ERROR_OK
)
558 *rw
= hit_watchpoint
->rw
;
559 *address
= hit_watchpoint
->address
;
561 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
562 hit_watchpoint
->address
,
563 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)