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, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
28 #include <helper/log.h>
29 #include "breakpoints.h"
32 static char *breakpoint_type_strings
[] =
38 static char *watchpoint_rw_strings
[] =
45 // monotonic counter/id-number for breakpoints and watch points
46 static int bpwp_unique_id
;
48 int breakpoint_add_internal(struct target
*target
, uint32_t address
, uint32_t length
, enum breakpoint_type type
)
50 struct breakpoint
*breakpoint
= target
->breakpoints
;
51 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
60 if (breakpoint
->address
== address
) {
61 /* FIXME don't assume "same address" means "same
62 * breakpoint" ... check all the parameters before
65 LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32
" (BP %d)",
66 address
, breakpoint
->unique_id
);
69 breakpoint_p
= &breakpoint
->next
;
70 breakpoint
= breakpoint
->next
;
73 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
74 (*breakpoint_p
)->address
= address
;
75 (*breakpoint_p
)->asid
= 0;
76 (*breakpoint_p
)->length
= length
;
77 (*breakpoint_p
)->type
= type
;
78 (*breakpoint_p
)->set
= 0;
79 (*breakpoint_p
)->orig_instr
= malloc(length
);
80 (*breakpoint_p
)->next
= NULL
;
81 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
83 retval
= target_add_breakpoint(target
, *breakpoint_p
);
87 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
88 reason
= "resource not available";
90 case ERROR_TARGET_NOT_HALTED
:
91 reason
= "target running";
94 reason
= "unknown reason";
96 LOG_ERROR("can't add breakpoint: %s", reason
);
97 free((*breakpoint_p
)->orig_instr
);
103 LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %d)",
104 breakpoint_type_strings
[(*breakpoint_p
)->type
],
105 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
106 (*breakpoint_p
)->unique_id
);
111 int context_breakpoint_add_internal(struct target
*target
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
113 struct breakpoint
*breakpoint
= target
->breakpoints
;
114 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
122 if (breakpoint
->asid
== asid
)
124 /* FIXME don't assume "same address" means "same
125 * breakpoint" ... check all the parameters before
128 LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %d)",
129 asid
, breakpoint
->unique_id
);
132 breakpoint_p
= &breakpoint
->next
;
133 breakpoint
= breakpoint
->next
;
136 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
137 (*breakpoint_p
)->address
= 0;
138 (*breakpoint_p
)->asid
= asid
;
139 (*breakpoint_p
)->length
= length
;
140 (*breakpoint_p
)->type
= type
;
141 (*breakpoint_p
)->set
= 0;
142 (*breakpoint_p
)->orig_instr
= malloc(length
);
143 (*breakpoint_p
)->next
= NULL
;
144 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
145 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
146 if (retval
!= ERROR_OK
)
148 LOG_ERROR("could not add breakpoint");
149 free((*breakpoint_p
)->orig_instr
);
151 *breakpoint_p
= NULL
;
155 LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %d)",
156 breakpoint_type_strings
[(*breakpoint_p
)->type
],
157 (*breakpoint_p
)->asid
, (*breakpoint_p
)->length
,
158 (*breakpoint_p
)->unique_id
);
163 int hybrid_breakpoint_add_internal(struct target
*target
, uint32_t address
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
165 struct breakpoint
*breakpoint
= target
->breakpoints
;
166 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
173 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
174 /* FIXME don't assume "same address" means "same
175 * breakpoint" ... check all the parameters before
178 LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %d)",
179 asid
, breakpoint
->unique_id
);
182 else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0))
184 LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32
" (BP %d)",
185 address
, breakpoint
->unique_id
);
189 breakpoint_p
= &breakpoint
->next
;
190 breakpoint
= breakpoint
->next
;
192 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
193 (*breakpoint_p
)->address
= address
;
194 (*breakpoint_p
)->asid
= asid
;
195 (*breakpoint_p
)->length
= length
;
196 (*breakpoint_p
)->type
= type
;
197 (*breakpoint_p
)->set
= 0;
198 (*breakpoint_p
)->orig_instr
= malloc(length
);
199 (*breakpoint_p
)->next
= NULL
;
200 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
203 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
204 if (retval
!= ERROR_OK
)
206 LOG_ERROR("could not add breakpoint");
207 free((*breakpoint_p
)->orig_instr
);
209 *breakpoint_p
= NULL
;
212 LOG_DEBUG("added %s Hybrid breakpoint at address 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %d)",
213 breakpoint_type_strings
[(*breakpoint_p
)->type
],
214 (*breakpoint_p
)->address
, (*breakpoint_p
)->length
,
215 (*breakpoint_p
)->unique_id
);
222 int breakpoint_add(struct target
*target
, uint32_t address
, uint32_t length
, enum breakpoint_type type
)
225 int retval
= ERROR_OK
;
228 struct target_list
*head
;
231 if (type
== BKPT_SOFT
)
232 return(breakpoint_add_internal(head
->target
, address
,length
, type
));
234 while(head
!= (struct target_list
*)NULL
)
237 retval
= breakpoint_add_internal(curr
, address
,length
, type
);
238 if (retval
!= ERROR_OK
) return retval
;
244 return(breakpoint_add_internal(target
, address
, length
, type
));
247 int context_breakpoint_add(struct target
*target
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
250 int retval
= ERROR_OK
;
253 struct target_list
*head
;
256 while(head
!= (struct target_list
*)NULL
)
259 retval
= context_breakpoint_add_internal(curr
, asid
,length
, type
);
260 if (retval
!= ERROR_OK
) return retval
;
266 return(context_breakpoint_add_internal(target
, asid
, length
, type
));
269 int hybrid_breakpoint_add(struct target
*target
, uint32_t address
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
272 int retval
= ERROR_OK
;
275 struct target_list
*head
;
278 while(head
!= (struct target_list
*)NULL
)
281 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
282 if (retval
!= ERROR_OK
) return retval
;
288 return(hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
));
292 /* free up a breakpoint */
293 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
295 struct breakpoint
*breakpoint
= target
->breakpoints
;
296 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
301 if (breakpoint
== breakpoint_to_remove
)
303 breakpoint_p
= &breakpoint
->next
;
304 breakpoint
= breakpoint
->next
;
307 if (breakpoint
== NULL
)
310 retval
= target_remove_breakpoint(target
, breakpoint
);
312 LOG_DEBUG("free BPID: %d --> %d", breakpoint
->unique_id
, retval
);
313 (*breakpoint_p
) = breakpoint
->next
;
314 free(breakpoint
->orig_instr
);
318 int breakpoint_remove_internal(struct target
*target
, uint32_t address
)
320 struct breakpoint
*breakpoint
= target
->breakpoints
;
324 if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0))
326 else if ((breakpoint
->address
== 0) && (breakpoint
->asid
== address
))
328 else if ((breakpoint
->address
== address
) && (breakpoint
->asid
!= 0))
330 breakpoint
= breakpoint
->next
;
335 breakpoint_free(target
, breakpoint
);
341 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32
" found", address
);
345 void breakpoint_remove(struct target
*target
, uint32_t address
)
350 struct target_list
*head
;
353 while(head
!= (struct target_list
*)NULL
)
356 found
+= breakpoint_remove_internal(curr
, address
);
360 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32
" found", address
);
362 else breakpoint_remove_internal(target
, address
);
365 void breakpoint_clear_target_internal(struct target
*target
)
367 struct breakpoint
*breakpoint
;
369 LOG_DEBUG("Delete all breakpoints for target: %s",
370 target_name(target
));
371 while ((breakpoint
= target
->breakpoints
) != NULL
)
373 breakpoint_free(target
, breakpoint
);
377 void breakpoint_clear_target(struct target
*target
)
381 struct target_list
*head
;
384 while(head
!= (struct target_list
*)NULL
)
387 breakpoint_clear_target_internal(curr
);
391 else breakpoint_clear_target_internal(target
);
396 struct breakpoint
* breakpoint_find(struct target
*target
, uint32_t address
)
398 struct breakpoint
*breakpoint
= target
->breakpoints
;
402 if (breakpoint
->address
== address
)
404 breakpoint
= breakpoint
->next
;
410 int watchpoint_add(struct target
*target
, uint32_t address
, uint32_t length
,
411 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
413 struct watchpoint
*watchpoint
= target
->watchpoints
;
414 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
420 if (watchpoint
->address
== address
) {
421 if (watchpoint
->length
!= length
422 || watchpoint
->value
!= value
423 || watchpoint
->mask
!= mask
424 || watchpoint
->rw
!= rw
) {
425 LOG_ERROR("address 0x%8.8" PRIx32
426 "already has watchpoint %d",
427 address
, watchpoint
->unique_id
);
431 /* ignore duplicate watchpoint */
434 watchpoint_p
= &watchpoint
->next
;
435 watchpoint
= watchpoint
->next
;
438 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
439 (*watchpoint_p
)->address
= address
;
440 (*watchpoint_p
)->length
= length
;
441 (*watchpoint_p
)->value
= value
;
442 (*watchpoint_p
)->mask
= mask
;
443 (*watchpoint_p
)->rw
= rw
;
444 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
446 retval
= target_add_watchpoint(target
, *watchpoint_p
);
450 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
451 reason
= "resource not available";
453 case ERROR_TARGET_NOT_HALTED
:
454 reason
= "target running";
457 reason
= "unrecognized error";
459 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32
", %s",
460 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
462 free (*watchpoint_p
);
463 *watchpoint_p
= NULL
;
467 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
468 " of length 0x%8.8" PRIx32
" (WPID: %d)",
469 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
470 (*watchpoint_p
)->address
,
471 (*watchpoint_p
)->length
,
472 (*watchpoint_p
)->unique_id
);
477 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
479 struct watchpoint
*watchpoint
= target
->watchpoints
;
480 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
485 if (watchpoint
== watchpoint_to_remove
)
487 watchpoint_p
= &watchpoint
->next
;
488 watchpoint
= watchpoint
->next
;
491 if (watchpoint
== NULL
)
493 retval
= target_remove_watchpoint(target
, watchpoint
);
494 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
495 (*watchpoint_p
) = watchpoint
->next
;
499 void watchpoint_remove(struct target
*target
, uint32_t address
)
501 struct watchpoint
*watchpoint
= target
->watchpoints
;
505 if (watchpoint
->address
== address
)
507 watchpoint
= watchpoint
->next
;
512 watchpoint_free(target
, watchpoint
);
516 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32
" found", address
);
520 void watchpoint_clear_target(struct target
*target
)
522 struct watchpoint
*watchpoint
;
524 LOG_DEBUG("Delete all watchpoints for target: %s",
525 target_name(target
));
526 while ((watchpoint
= target
->watchpoints
) != NULL
)
528 watchpoint_free(target
, watchpoint
);
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)