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
;
58 if (breakpoint
->address
== address
) {
59 /* FIXME don't assume "same address" means "same
60 * breakpoint" ... check all the parameters before
63 LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
64 address
, breakpoint
->unique_id
);
65 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
67 breakpoint_p
= &breakpoint
->next
;
68 breakpoint
= breakpoint
->next
;
71 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
72 (*breakpoint_p
)->address
= address
;
73 (*breakpoint_p
)->asid
= 0;
74 (*breakpoint_p
)->length
= length
;
75 (*breakpoint_p
)->type
= type
;
76 (*breakpoint_p
)->set
= 0;
77 (*breakpoint_p
)->orig_instr
= malloc(length
);
78 (*breakpoint_p
)->next
= NULL
;
79 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
81 retval
= target_add_breakpoint(target
, *breakpoint_p
);
85 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
86 reason
= "resource not available";
88 case ERROR_TARGET_NOT_HALTED
:
89 reason
= "target running";
92 reason
= "unknown reason";
94 LOG_ERROR("can't add breakpoint: %s", reason
);
95 free((*breakpoint_p
)->orig_instr
);
101 LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
102 breakpoint_type_strings
[(*breakpoint_p
)->type
],
103 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
104 (*breakpoint_p
)->unique_id
);
109 static int context_breakpoint_add_internal(struct target
*target
,
112 enum breakpoint_type type
)
114 struct breakpoint
*breakpoint
= target
->breakpoints
;
115 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
122 if (breakpoint
->asid
== asid
) {
123 /* FIXME don't assume "same address" means "same
124 * breakpoint" ... check all the parameters before
127 LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
128 asid
, breakpoint
->unique_id
);
129 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
131 breakpoint_p
= &breakpoint
->next
;
132 breakpoint
= breakpoint
->next
;
135 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
136 (*breakpoint_p
)->address
= 0;
137 (*breakpoint_p
)->asid
= asid
;
138 (*breakpoint_p
)->length
= length
;
139 (*breakpoint_p
)->type
= type
;
140 (*breakpoint_p
)->set
= 0;
141 (*breakpoint_p
)->orig_instr
= malloc(length
);
142 (*breakpoint_p
)->next
= NULL
;
143 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
144 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
145 if (retval
!= ERROR_OK
) {
146 LOG_ERROR("could not add breakpoint");
147 free((*breakpoint_p
)->orig_instr
);
149 *breakpoint_p
= NULL
;
153 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %" PRIu32
")",
154 breakpoint_type_strings
[(*breakpoint_p
)->type
],
155 (*breakpoint_p
)->asid
, (*breakpoint_p
)->length
,
156 (*breakpoint_p
)->unique_id
);
161 static int hybrid_breakpoint_add_internal(struct target
*target
,
162 target_addr_t address
,
165 enum breakpoint_type type
)
167 struct breakpoint
*breakpoint
= target
->breakpoints
;
168 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
174 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
175 /* FIXME don't assume "same address" means "same
176 * breakpoint" ... check all the parameters before
179 LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
180 asid
, breakpoint
->unique_id
);
181 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
182 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
183 LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
184 address
, breakpoint
->unique_id
);
185 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
188 breakpoint_p
= &breakpoint
->next
;
189 breakpoint
= breakpoint
->next
;
191 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
192 (*breakpoint_p
)->address
= address
;
193 (*breakpoint_p
)->asid
= asid
;
194 (*breakpoint_p
)->length
= length
;
195 (*breakpoint_p
)->type
= type
;
196 (*breakpoint_p
)->set
= 0;
197 (*breakpoint_p
)->orig_instr
= malloc(length
);
198 (*breakpoint_p
)->next
= NULL
;
199 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
202 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
203 if (retval
!= ERROR_OK
) {
204 LOG_ERROR("could not add breakpoint");
205 free((*breakpoint_p
)->orig_instr
);
207 *breakpoint_p
= NULL
;
211 "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
212 breakpoint_type_strings
[(*breakpoint_p
)->type
],
213 (*breakpoint_p
)->address
,
214 (*breakpoint_p
)->length
,
215 (*breakpoint_p
)->unique_id
);
220 int breakpoint_add(struct target
*target
,
221 target_addr_t address
,
223 enum breakpoint_type type
)
225 int retval
= ERROR_OK
;
227 struct target_list
*head
;
230 if (type
== BKPT_SOFT
)
231 return breakpoint_add_internal(head
->target
, address
, length
, type
);
233 while (head
!= (struct target_list
*)NULL
) {
235 retval
= breakpoint_add_internal(curr
, address
, length
, type
);
236 if (retval
!= ERROR_OK
)
242 return breakpoint_add_internal(target
, address
, length
, type
);
245 int context_breakpoint_add(struct target
*target
,
248 enum breakpoint_type type
)
250 int retval
= ERROR_OK
;
252 struct target_list
*head
;
255 while (head
!= (struct target_list
*)NULL
) {
257 retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
258 if (retval
!= ERROR_OK
)
264 return context_breakpoint_add_internal(target
, asid
, length
, type
);
267 int hybrid_breakpoint_add(struct target
*target
,
268 target_addr_t address
,
271 enum breakpoint_type type
)
273 int retval
= ERROR_OK
;
275 struct target_list
*head
;
278 while (head
!= (struct target_list
*)NULL
) {
280 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
281 if (retval
!= ERROR_OK
)
287 return hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
);
290 /* free up a breakpoint */
291 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
293 struct breakpoint
*breakpoint
= target
->breakpoints
;
294 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
298 if (breakpoint
== breakpoint_to_remove
)
300 breakpoint_p
= &breakpoint
->next
;
301 breakpoint
= breakpoint
->next
;
304 if (breakpoint
== NULL
)
307 retval
= target_remove_breakpoint(target
, breakpoint
);
309 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
310 (*breakpoint_p
) = breakpoint
->next
;
311 free(breakpoint
->orig_instr
);
315 static int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
317 struct breakpoint
*breakpoint
= target
->breakpoints
;
320 if ((breakpoint
->address
== address
) ||
321 (breakpoint
->address
== 0 && breakpoint
->asid
== address
))
323 breakpoint
= breakpoint
->next
;
327 breakpoint_free(target
, breakpoint
);
331 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
336 static void breakpoint_remove_all_internal(struct target
*target
)
338 struct breakpoint
*breakpoint
= target
->breakpoints
;
341 struct breakpoint
*tmp
= breakpoint
;
342 breakpoint
= breakpoint
->next
;
343 breakpoint_free(target
, tmp
);
347 void breakpoint_remove(struct target
*target
, target_addr_t address
)
351 struct target_list
*head
;
354 while (head
!= (struct target_list
*)NULL
) {
356 found
+= breakpoint_remove_internal(curr
, address
);
360 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
362 breakpoint_remove_internal(target
, address
);
365 void breakpoint_remove_all(struct target
*target
)
368 struct target_list
*head
;
371 while (head
!= (struct target_list
*)NULL
) {
373 breakpoint_remove_all_internal(curr
);
377 breakpoint_remove_all_internal(target
);
381 static void breakpoint_clear_target_internal(struct target
*target
)
383 LOG_DEBUG("Delete all breakpoints for target: %s",
384 target_name(target
));
385 while (target
->breakpoints
!= NULL
)
386 breakpoint_free(target
, target
->breakpoints
);
389 void breakpoint_clear_target(struct target
*target
)
392 struct target_list
*head
;
395 while (head
!= (struct target_list
*)NULL
) {
397 breakpoint_clear_target_internal(curr
);
401 breakpoint_clear_target_internal(target
);
405 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
407 struct breakpoint
*breakpoint
= target
->breakpoints
;
410 if (breakpoint
->address
== address
)
412 breakpoint
= breakpoint
->next
;
418 int watchpoint_add(struct target
*target
, target_addr_t address
, uint32_t length
,
419 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
421 struct watchpoint
*watchpoint
= target
->watchpoints
;
422 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
427 if (watchpoint
->address
== address
) {
428 if (watchpoint
->length
!= length
429 || watchpoint
->value
!= value
430 || watchpoint
->mask
!= mask
431 || watchpoint
->rw
!= rw
) {
432 LOG_ERROR("address " TARGET_ADDR_FMT
433 " already has watchpoint %d",
434 address
, watchpoint
->unique_id
);
438 /* ignore duplicate watchpoint */
441 watchpoint_p
= &watchpoint
->next
;
442 watchpoint
= watchpoint
->next
;
445 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
446 (*watchpoint_p
)->address
= address
;
447 (*watchpoint_p
)->length
= length
;
448 (*watchpoint_p
)->value
= value
;
449 (*watchpoint_p
)->mask
= mask
;
450 (*watchpoint_p
)->rw
= rw
;
451 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
453 retval
= target_add_watchpoint(target
, *watchpoint_p
);
457 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
458 reason
= "resource not available";
460 case ERROR_TARGET_NOT_HALTED
:
461 reason
= "target running";
464 reason
= "unrecognized error";
466 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
467 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
470 *watchpoint_p
= NULL
;
474 LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT
475 " of length 0x%8.8" PRIx32
" (WPID: %d)",
476 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
477 (*watchpoint_p
)->address
,
478 (*watchpoint_p
)->length
,
479 (*watchpoint_p
)->unique_id
);
484 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
486 struct watchpoint
*watchpoint
= target
->watchpoints
;
487 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
491 if (watchpoint
== watchpoint_to_remove
)
493 watchpoint_p
= &watchpoint
->next
;
494 watchpoint
= watchpoint
->next
;
497 if (watchpoint
== NULL
)
499 retval
= target_remove_watchpoint(target
, watchpoint
);
500 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
501 (*watchpoint_p
) = watchpoint
->next
;
505 void watchpoint_remove(struct target
*target
, target_addr_t address
)
507 struct watchpoint
*watchpoint
= target
->watchpoints
;
510 if (watchpoint
->address
== address
)
512 watchpoint
= watchpoint
->next
;
516 watchpoint_free(target
, watchpoint
);
518 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
521 void watchpoint_clear_target(struct target
*target
)
523 LOG_DEBUG("Delete all watchpoints for target: %s",
524 target_name(target
));
525 while (target
->watchpoints
!= NULL
)
526 watchpoint_free(target
, target
->watchpoints
);
529 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
530 target_addr_t
*address
)
533 struct watchpoint
*hit_watchpoint
;
535 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
536 if (retval
!= ERROR_OK
)
539 *rw
= hit_watchpoint
->rw
;
540 *address
= hit_watchpoint
->address
;
542 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
543 hit_watchpoint
->address
,
544 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)