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("added %s breakpoint at " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
99 breakpoint_type_strings
[(*breakpoint_p
)->type
],
100 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
101 (*breakpoint_p
)->unique_id
);
106 static int context_breakpoint_add_internal(struct target
*target
,
109 enum breakpoint_type type
)
111 struct breakpoint
*breakpoint
= target
->breakpoints
;
112 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
116 if (breakpoint
->asid
== asid
) {
117 /* FIXME don't assume "same address" means "same
118 * breakpoint" ... check all the parameters before
121 LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
122 asid
, breakpoint
->unique_id
);
123 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
125 breakpoint_p
= &breakpoint
->next
;
126 breakpoint
= breakpoint
->next
;
129 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
130 (*breakpoint_p
)->address
= 0;
131 (*breakpoint_p
)->asid
= asid
;
132 (*breakpoint_p
)->length
= length
;
133 (*breakpoint_p
)->type
= type
;
134 (*breakpoint_p
)->set
= 0;
135 (*breakpoint_p
)->orig_instr
= malloc(length
);
136 (*breakpoint_p
)->next
= NULL
;
137 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
138 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
139 if (retval
!= ERROR_OK
) {
140 LOG_ERROR("could not add breakpoint");
141 free((*breakpoint_p
)->orig_instr
);
143 *breakpoint_p
= NULL
;
147 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %" PRIu32
")",
148 breakpoint_type_strings
[(*breakpoint_p
)->type
],
149 (*breakpoint_p
)->asid
, (*breakpoint_p
)->length
,
150 (*breakpoint_p
)->unique_id
);
155 static int hybrid_breakpoint_add_internal(struct target
*target
,
156 target_addr_t address
,
159 enum breakpoint_type type
)
161 struct breakpoint
*breakpoint
= target
->breakpoints
;
162 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
166 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
167 /* FIXME don't assume "same address" means "same
168 * breakpoint" ... check all the parameters before
171 LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
172 asid
, breakpoint
->unique_id
);
173 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
174 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
175 LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
176 address
, breakpoint
->unique_id
);
177 return ERROR_TARGET_DUPLICATE_BREAKPOINT
;
180 breakpoint_p
= &breakpoint
->next
;
181 breakpoint
= breakpoint
->next
;
183 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
184 (*breakpoint_p
)->address
= address
;
185 (*breakpoint_p
)->asid
= asid
;
186 (*breakpoint_p
)->length
= length
;
187 (*breakpoint_p
)->type
= type
;
188 (*breakpoint_p
)->set
= 0;
189 (*breakpoint_p
)->orig_instr
= malloc(length
);
190 (*breakpoint_p
)->next
= NULL
;
191 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
194 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
195 if (retval
!= ERROR_OK
) {
196 LOG_ERROR("could not add breakpoint");
197 free((*breakpoint_p
)->orig_instr
);
199 *breakpoint_p
= NULL
;
203 "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT
" of length 0x%8.8x, (BPID: %" PRIu32
")",
204 breakpoint_type_strings
[(*breakpoint_p
)->type
],
205 (*breakpoint_p
)->address
,
206 (*breakpoint_p
)->length
,
207 (*breakpoint_p
)->unique_id
);
212 int breakpoint_add(struct target
*target
,
213 target_addr_t address
,
215 enum breakpoint_type type
)
217 int retval
= ERROR_OK
;
219 struct target_list
*head
;
222 if (type
== BKPT_SOFT
)
223 return breakpoint_add_internal(head
->target
, address
, length
, type
);
225 while (head
!= (struct target_list
*)NULL
) {
227 retval
= breakpoint_add_internal(curr
, address
, length
, type
);
228 if (retval
!= ERROR_OK
)
234 return breakpoint_add_internal(target
, address
, length
, type
);
238 int context_breakpoint_add(struct target
*target
,
241 enum breakpoint_type type
)
243 int retval
= ERROR_OK
;
245 struct target_list
*head
;
248 while (head
!= (struct target_list
*)NULL
) {
250 retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
251 if (retval
!= ERROR_OK
)
257 return context_breakpoint_add_internal(target
, asid
, length
, type
);
261 int hybrid_breakpoint_add(struct target
*target
,
262 target_addr_t address
,
265 enum breakpoint_type type
)
267 int retval
= ERROR_OK
;
269 struct target_list
*head
;
272 while (head
!= (struct target_list
*)NULL
) {
274 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
275 if (retval
!= ERROR_OK
)
281 return hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
);
284 /* free up a breakpoint */
285 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
287 struct breakpoint
*breakpoint
= target
->breakpoints
;
288 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
292 if (breakpoint
== breakpoint_to_remove
)
294 breakpoint_p
= &breakpoint
->next
;
295 breakpoint
= breakpoint
->next
;
301 retval
= target_remove_breakpoint(target
, breakpoint
);
303 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
304 (*breakpoint_p
) = breakpoint
->next
;
305 free(breakpoint
->orig_instr
);
309 static int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
311 struct breakpoint
*breakpoint
= target
->breakpoints
;
314 if ((breakpoint
->address
== address
) ||
315 (breakpoint
->address
== 0 && breakpoint
->asid
== address
))
317 breakpoint
= breakpoint
->next
;
321 breakpoint_free(target
, breakpoint
);
325 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
330 static void breakpoint_remove_all_internal(struct target
*target
)
332 struct breakpoint
*breakpoint
= target
->breakpoints
;
335 struct breakpoint
*tmp
= breakpoint
;
336 breakpoint
= breakpoint
->next
;
337 breakpoint_free(target
, tmp
);
341 void breakpoint_remove(struct target
*target
, target_addr_t address
)
344 unsigned int num_breakpoints
= 0;
345 struct target_list
*head
;
348 while (head
!= (struct target_list
*)NULL
) {
350 num_breakpoints
+= breakpoint_remove_internal(curr
, address
);
353 if (!num_breakpoints
)
354 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
356 breakpoint_remove_internal(target
, address
);
360 void breakpoint_remove_all(struct target
*target
)
363 struct target_list
*head
;
366 while (head
!= (struct target_list
*)NULL
) {
368 breakpoint_remove_all_internal(curr
);
372 breakpoint_remove_all_internal(target
);
376 static void breakpoint_clear_target_internal(struct target
*target
)
378 LOG_DEBUG("Delete all breakpoints for target: %s",
379 target_name(target
));
380 while (target
->breakpoints
)
381 breakpoint_free(target
, target
->breakpoints
);
384 void breakpoint_clear_target(struct target
*target
)
387 struct target_list
*head
;
390 while (head
!= (struct target_list
*)NULL
) {
392 breakpoint_clear_target_internal(curr
);
396 breakpoint_clear_target_internal(target
);
400 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
402 struct breakpoint
*breakpoint
= target
->breakpoints
;
405 if (breakpoint
->address
== address
)
407 breakpoint
= breakpoint
->next
;
413 int watchpoint_add(struct target
*target
, target_addr_t address
, uint32_t length
,
414 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
416 struct watchpoint
*watchpoint
= target
->watchpoints
;
417 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
422 if (watchpoint
->address
== address
) {
423 if (watchpoint
->length
!= length
424 || watchpoint
->value
!= value
425 || watchpoint
->mask
!= mask
426 || watchpoint
->rw
!= rw
) {
427 LOG_ERROR("address " TARGET_ADDR_FMT
428 " already has watchpoint %d",
429 address
, watchpoint
->unique_id
);
433 /* ignore duplicate watchpoint */
436 watchpoint_p
= &watchpoint
->next
;
437 watchpoint
= watchpoint
->next
;
440 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
441 (*watchpoint_p
)->address
= address
;
442 (*watchpoint_p
)->length
= length
;
443 (*watchpoint_p
)->value
= value
;
444 (*watchpoint_p
)->mask
= mask
;
445 (*watchpoint_p
)->rw
= rw
;
446 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
448 retval
= target_add_watchpoint(target
, *watchpoint_p
);
452 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
453 reason
= "resource not available";
455 case ERROR_TARGET_NOT_HALTED
:
456 reason
= "target running";
459 reason
= "unrecognized error";
461 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
462 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
465 *watchpoint_p
= NULL
;
469 LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT
470 " of length 0x%8.8" PRIx32
" (WPID: %d)",
471 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
472 (*watchpoint_p
)->address
,
473 (*watchpoint_p
)->length
,
474 (*watchpoint_p
)->unique_id
);
479 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
481 struct watchpoint
*watchpoint
= target
->watchpoints
;
482 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
486 if (watchpoint
== watchpoint_to_remove
)
488 watchpoint_p
= &watchpoint
->next
;
489 watchpoint
= watchpoint
->next
;
494 retval
= target_remove_watchpoint(target
, watchpoint
);
495 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
496 (*watchpoint_p
) = watchpoint
->next
;
500 void watchpoint_remove(struct target
*target
, target_addr_t address
)
502 struct watchpoint
*watchpoint
= target
->watchpoints
;
505 if (watchpoint
->address
== address
)
507 watchpoint
= watchpoint
->next
;
511 watchpoint_free(target
, watchpoint
);
513 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
516 void watchpoint_clear_target(struct target
*target
)
518 LOG_DEBUG("Delete all watchpoints for target: %s",
519 target_name(target
));
520 while (target
->watchpoints
)
521 watchpoint_free(target
, target
->watchpoints
);
524 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
525 target_addr_t
*address
)
528 struct watchpoint
*hit_watchpoint
;
530 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
531 if (retval
!= ERROR_OK
)
534 *rw
= hit_watchpoint
->rw
;
535 *address
= hit_watchpoint
->address
;
537 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
538 hit_watchpoint
->address
,
539 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)