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 while(head
!= (struct target_list
*)NULL
)
234 retval
= breakpoint_add_internal(curr
, address
,length
, type
);
235 if (retval
!= ERROR_OK
) return retval
;
241 return(breakpoint_add_internal(target
, address
, length
, type
));
244 int context_breakpoint_add(struct target
*target
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
247 int retval
= ERROR_OK
;
250 struct target_list
*head
;
253 while(head
!= (struct target_list
*)NULL
)
256 retval
= context_breakpoint_add_internal(curr
, asid
,length
, type
);
257 if (retval
!= ERROR_OK
) return retval
;
263 return(context_breakpoint_add_internal(target
, asid
, length
, type
));
266 int hybrid_breakpoint_add(struct target
*target
, uint32_t address
, uint32_t asid
, uint32_t length
, enum breakpoint_type type
)
269 int retval
= ERROR_OK
;
272 struct target_list
*head
;
275 while(head
!= (struct target_list
*)NULL
)
278 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
279 if (retval
!= ERROR_OK
) return retval
;
285 return(hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
));
289 /* free up a breakpoint */
290 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
292 struct breakpoint
*breakpoint
= target
->breakpoints
;
293 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: %d --> %d", breakpoint
->unique_id
, retval
);
310 (*breakpoint_p
) = breakpoint
->next
;
311 free(breakpoint
->orig_instr
);
315 void breakpoint_remove_internal(struct target
*target
, uint32_t address
)
317 struct breakpoint
*breakpoint
= target
->breakpoints
;
321 if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0))
323 else if ((breakpoint
->address
== 0) && (breakpoint
->asid
== address
))
325 else if ((breakpoint
->address
== address
) && (breakpoint
->asid
!= 0))
327 breakpoint
= breakpoint
->next
;
332 breakpoint_free(target
, breakpoint
);
336 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32
" found", address
);
339 void breakpoint_remove(struct target
*target
, uint32_t address
)
343 struct target_list
*head
;
346 while(head
!= (struct target_list
*)NULL
)
349 breakpoint_remove_internal(curr
, address
);
353 else breakpoint_remove_internal(target
, address
);
356 void breakpoint_clear_target_internal(struct target
*target
)
358 struct breakpoint
*breakpoint
;
360 LOG_DEBUG("Delete all breakpoints for target: %s",
361 target_name(target
));
362 while ((breakpoint
= target
->breakpoints
) != NULL
)
364 breakpoint_free(target
, breakpoint
);
368 void breakpoint_clear_target(struct target
*target
)
372 struct target_list
*head
;
375 while(head
!= (struct target_list
*)NULL
)
378 breakpoint_clear_target_internal(curr
);
382 else breakpoint_clear_target_internal(target
);
387 struct breakpoint
* breakpoint_find(struct target
*target
, uint32_t address
)
389 struct breakpoint
*breakpoint
= target
->breakpoints
;
393 if (breakpoint
->address
== address
)
395 breakpoint
= breakpoint
->next
;
401 int watchpoint_add(struct target
*target
, uint32_t address
, uint32_t length
,
402 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
404 struct watchpoint
*watchpoint
= target
->watchpoints
;
405 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
411 if (watchpoint
->address
== address
) {
412 if (watchpoint
->length
!= length
413 || watchpoint
->value
!= value
414 || watchpoint
->mask
!= mask
415 || watchpoint
->rw
!= rw
) {
416 LOG_ERROR("address 0x%8.8" PRIx32
417 "already has watchpoint %d",
418 address
, watchpoint
->unique_id
);
422 /* ignore duplicate watchpoint */
425 watchpoint_p
= &watchpoint
->next
;
426 watchpoint
= watchpoint
->next
;
429 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
430 (*watchpoint_p
)->address
= address
;
431 (*watchpoint_p
)->length
= length
;
432 (*watchpoint_p
)->value
= value
;
433 (*watchpoint_p
)->mask
= mask
;
434 (*watchpoint_p
)->rw
= rw
;
435 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
437 retval
= target_add_watchpoint(target
, *watchpoint_p
);
441 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
442 reason
= "resource not available";
444 case ERROR_TARGET_NOT_HALTED
:
445 reason
= "target running";
448 reason
= "unrecognized error";
450 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32
", %s",
451 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
453 free (*watchpoint_p
);
454 *watchpoint_p
= NULL
;
458 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
459 " of length 0x%8.8" PRIx32
" (WPID: %d)",
460 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
461 (*watchpoint_p
)->address
,
462 (*watchpoint_p
)->length
,
463 (*watchpoint_p
)->unique_id
);
468 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
470 struct watchpoint
*watchpoint
= target
->watchpoints
;
471 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
476 if (watchpoint
== watchpoint_to_remove
)
478 watchpoint_p
= &watchpoint
->next
;
479 watchpoint
= watchpoint
->next
;
482 if (watchpoint
== NULL
)
484 retval
= target_remove_watchpoint(target
, watchpoint
);
485 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
486 (*watchpoint_p
) = watchpoint
->next
;
490 void watchpoint_remove(struct target
*target
, uint32_t address
)
492 struct watchpoint
*watchpoint
= target
->watchpoints
;
496 if (watchpoint
->address
== address
)
498 watchpoint
= watchpoint
->next
;
503 watchpoint_free(target
, watchpoint
);
507 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32
" found", address
);
511 void watchpoint_clear_target(struct target
*target
)
513 struct watchpoint
*watchpoint
;
515 LOG_DEBUG("Delete all watchpoints for target: %s",
516 target_name(target
));
517 while ((watchpoint
= target
->watchpoints
) != NULL
)
519 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)