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
);
335 void breakpoint_remove(struct target
*target
, target_addr_t address
)
339 struct target_list
*head
;
342 while (head
!= (struct target_list
*)NULL
) {
344 found
+= breakpoint_remove_internal(curr
, address
);
348 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
350 breakpoint_remove_internal(target
, address
);
353 void breakpoint_clear_target_internal(struct target
*target
)
355 LOG_DEBUG("Delete all breakpoints for target: %s",
356 target_name(target
));
357 while (target
->breakpoints
!= NULL
)
358 breakpoint_free(target
, target
->breakpoints
);
361 void breakpoint_clear_target(struct target
*target
)
364 struct target_list
*head
;
367 while (head
!= (struct target_list
*)NULL
) {
369 breakpoint_clear_target_internal(curr
);
373 breakpoint_clear_target_internal(target
);
377 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
379 struct breakpoint
*breakpoint
= target
->breakpoints
;
382 if (breakpoint
->address
== address
)
384 breakpoint
= breakpoint
->next
;
390 int watchpoint_add(struct target
*target
, target_addr_t address
, uint32_t length
,
391 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
393 struct watchpoint
*watchpoint
= target
->watchpoints
;
394 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
399 if (watchpoint
->address
== address
) {
400 if (watchpoint
->length
!= length
401 || watchpoint
->value
!= value
402 || watchpoint
->mask
!= mask
403 || watchpoint
->rw
!= rw
) {
404 LOG_ERROR("address " TARGET_ADDR_FMT
405 " already has watchpoint %d",
406 address
, watchpoint
->unique_id
);
410 /* ignore duplicate watchpoint */
413 watchpoint_p
= &watchpoint
->next
;
414 watchpoint
= watchpoint
->next
;
417 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
418 (*watchpoint_p
)->address
= address
;
419 (*watchpoint_p
)->length
= length
;
420 (*watchpoint_p
)->value
= value
;
421 (*watchpoint_p
)->mask
= mask
;
422 (*watchpoint_p
)->rw
= rw
;
423 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
425 retval
= target_add_watchpoint(target
, *watchpoint_p
);
429 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
430 reason
= "resource not available";
432 case ERROR_TARGET_NOT_HALTED
:
433 reason
= "target running";
436 reason
= "unrecognized error";
438 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
439 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
442 *watchpoint_p
= NULL
;
446 LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT
447 " of length 0x%8.8" PRIx32
" (WPID: %d)",
448 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
449 (*watchpoint_p
)->address
,
450 (*watchpoint_p
)->length
,
451 (*watchpoint_p
)->unique_id
);
456 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
458 struct watchpoint
*watchpoint
= target
->watchpoints
;
459 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
463 if (watchpoint
== watchpoint_to_remove
)
465 watchpoint_p
= &watchpoint
->next
;
466 watchpoint
= watchpoint
->next
;
469 if (watchpoint
== NULL
)
471 retval
= target_remove_watchpoint(target
, watchpoint
);
472 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
473 (*watchpoint_p
) = watchpoint
->next
;
477 void watchpoint_remove(struct target
*target
, target_addr_t address
)
479 struct watchpoint
*watchpoint
= target
->watchpoints
;
482 if (watchpoint
->address
== address
)
484 watchpoint
= watchpoint
->next
;
488 watchpoint_free(target
, watchpoint
);
490 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
493 void watchpoint_clear_target(struct target
*target
)
495 LOG_DEBUG("Delete all watchpoints for target: %s",
496 target_name(target
));
497 while (target
->watchpoints
!= NULL
)
498 watchpoint_free(target
, target
->watchpoints
);
501 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
502 target_addr_t
*address
)
505 struct watchpoint
*hit_watchpoint
;
507 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
508 if (retval
!= ERROR_OK
)
511 *rw
= hit_watchpoint
->rw
;
512 *address
= hit_watchpoint
->address
;
514 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
515 hit_watchpoint
->address
,
516 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)