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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
29 #include <helper/log.h>
30 #include "breakpoints.h"
32 static const char * const breakpoint_type_strings
[] = {
37 static const char * const watchpoint_rw_strings
[] = {
43 /* monotonic counter/id-number for breakpoints and watch points */
44 static int bpwp_unique_id
;
46 int breakpoint_add_internal(struct target
*target
,
49 enum breakpoint_type type
)
51 struct breakpoint
*breakpoint
= target
->breakpoints
;
52 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 %" PRIu32
")",
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: %" PRIu32
")",
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
,
114 enum breakpoint_type type
)
116 struct breakpoint
*breakpoint
= target
->breakpoints
;
117 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
124 if (breakpoint
->asid
== asid
) {
125 /* FIXME don't assume "same address" means "same
126 * breakpoint" ... check all the parameters before
129 LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
130 asid
, breakpoint
->unique_id
);
133 breakpoint_p
= &breakpoint
->next
;
134 breakpoint
= breakpoint
->next
;
137 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
138 (*breakpoint_p
)->address
= 0;
139 (*breakpoint_p
)->asid
= asid
;
140 (*breakpoint_p
)->length
= length
;
141 (*breakpoint_p
)->type
= type
;
142 (*breakpoint_p
)->set
= 0;
143 (*breakpoint_p
)->orig_instr
= malloc(length
);
144 (*breakpoint_p
)->next
= NULL
;
145 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
146 retval
= target_add_context_breakpoint(target
, *breakpoint_p
);
147 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: %" PRIu32
")",
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
,
167 enum breakpoint_type type
)
169 struct breakpoint
*breakpoint
= target
->breakpoints
;
170 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
176 if ((breakpoint
->asid
== asid
) && (breakpoint
->address
== address
)) {
177 /* FIXME don't assume "same address" means "same
178 * breakpoint" ... check all the parameters before
181 LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
182 asid
, breakpoint
->unique_id
);
184 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
185 LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32
" (BP %" PRIu32
")",
186 address
, breakpoint
->unique_id
);
190 breakpoint_p
= &breakpoint
->next
;
191 breakpoint
= breakpoint
->next
;
193 (*breakpoint_p
) = malloc(sizeof(struct breakpoint
));
194 (*breakpoint_p
)->address
= address
;
195 (*breakpoint_p
)->asid
= asid
;
196 (*breakpoint_p
)->length
= length
;
197 (*breakpoint_p
)->type
= type
;
198 (*breakpoint_p
)->set
= 0;
199 (*breakpoint_p
)->orig_instr
= malloc(length
);
200 (*breakpoint_p
)->next
= NULL
;
201 (*breakpoint_p
)->unique_id
= bpwp_unique_id
++;
204 retval
= target_add_hybrid_breakpoint(target
, *breakpoint_p
);
205 if (retval
!= ERROR_OK
) {
206 LOG_ERROR("could not add breakpoint");
207 free((*breakpoint_p
)->orig_instr
);
209 *breakpoint_p
= NULL
;
213 "added %s Hybrid breakpoint at address 0x%8.8" PRIx32
" of length 0x%8.8x, (BPID: %" PRIu32
")",
214 breakpoint_type_strings
[(*breakpoint_p
)->type
],
215 (*breakpoint_p
)->address
,
216 (*breakpoint_p
)->length
,
217 (*breakpoint_p
)->unique_id
);
222 int breakpoint_add(struct target
*target
,
225 enum breakpoint_type type
)
227 int retval
= ERROR_OK
;
229 struct target_list
*head
;
232 if (type
== BKPT_SOFT
)
233 return breakpoint_add_internal(head
->target
, address
, length
, type
);
235 while (head
!= (struct target_list
*)NULL
) {
237 retval
= breakpoint_add_internal(curr
, address
, length
, type
);
238 if (retval
!= ERROR_OK
)
244 return breakpoint_add_internal(target
, address
, length
, type
);
246 int context_breakpoint_add(struct target
*target
,
249 enum breakpoint_type type
)
251 int retval
= ERROR_OK
;
253 struct target_list
*head
;
256 while (head
!= (struct target_list
*)NULL
) {
258 retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
259 if (retval
!= ERROR_OK
)
265 return context_breakpoint_add_internal(target
, asid
, length
, type
);
267 int hybrid_breakpoint_add(struct target
*target
,
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 int breakpoint_remove_internal(struct target
*target
, uint32_t address
)
317 struct breakpoint
*breakpoint
= target
->breakpoints
;
320 if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0))
322 else if ((breakpoint
->address
== 0) && (breakpoint
->asid
== address
))
324 else if ((breakpoint
->address
== address
) && (breakpoint
->asid
!= 0))
326 breakpoint
= breakpoint
->next
;
330 breakpoint_free(target
, breakpoint
);
334 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32
" found", address
);
338 void breakpoint_remove(struct target
*target
, uint32_t address
)
342 struct target_list
*head
;
345 while (head
!= (struct target_list
*)NULL
) {
347 found
+= breakpoint_remove_internal(curr
, address
);
351 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32
" found", address
);
353 breakpoint_remove_internal(target
, address
);
356 void breakpoint_clear_target_internal(struct target
*target
)
358 LOG_DEBUG("Delete all breakpoints for target: %s",
359 target_name(target
));
360 while (target
->breakpoints
!= NULL
)
361 breakpoint_free(target
, target
->breakpoints
);
364 void breakpoint_clear_target(struct target
*target
)
367 struct target_list
*head
;
370 while (head
!= (struct target_list
*)NULL
) {
372 breakpoint_clear_target_internal(curr
);
376 breakpoint_clear_target_internal(target
);
380 struct breakpoint
*breakpoint_find(struct target
*target
, uint32_t address
)
382 struct breakpoint
*breakpoint
= target
->breakpoints
;
385 if (breakpoint
->address
== address
)
387 breakpoint
= breakpoint
->next
;
393 int watchpoint_add(struct target
*target
, uint32_t address
, uint32_t length
,
394 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
396 struct watchpoint
*watchpoint
= target
->watchpoints
;
397 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
402 if (watchpoint
->address
== address
) {
403 if (watchpoint
->length
!= length
404 || watchpoint
->value
!= value
405 || watchpoint
->mask
!= mask
406 || watchpoint
->rw
!= rw
) {
407 LOG_ERROR("address 0x%8.8" PRIx32
408 "already has watchpoint %d",
409 address
, watchpoint
->unique_id
);
413 /* ignore duplicate watchpoint */
416 watchpoint_p
= &watchpoint
->next
;
417 watchpoint
= watchpoint
->next
;
420 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
421 (*watchpoint_p
)->address
= address
;
422 (*watchpoint_p
)->length
= length
;
423 (*watchpoint_p
)->value
= value
;
424 (*watchpoint_p
)->mask
= mask
;
425 (*watchpoint_p
)->rw
= rw
;
426 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
428 retval
= target_add_watchpoint(target
, *watchpoint_p
);
432 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
433 reason
= "resource not available";
435 case ERROR_TARGET_NOT_HALTED
:
436 reason
= "target running";
439 reason
= "unrecognized error";
441 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32
", %s",
442 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
445 *watchpoint_p
= NULL
;
449 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
450 " of length 0x%8.8" PRIx32
" (WPID: %d)",
451 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
452 (*watchpoint_p
)->address
,
453 (*watchpoint_p
)->length
,
454 (*watchpoint_p
)->unique_id
);
459 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
461 struct watchpoint
*watchpoint
= target
->watchpoints
;
462 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
466 if (watchpoint
== watchpoint_to_remove
)
468 watchpoint_p
= &watchpoint
->next
;
469 watchpoint
= watchpoint
->next
;
472 if (watchpoint
== NULL
)
474 retval
= target_remove_watchpoint(target
, watchpoint
);
475 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
476 (*watchpoint_p
) = watchpoint
->next
;
480 void watchpoint_remove(struct target
*target
, uint32_t address
)
482 struct watchpoint
*watchpoint
= target
->watchpoints
;
485 if (watchpoint
->address
== address
)
487 watchpoint
= watchpoint
->next
;
491 watchpoint_free(target
, watchpoint
);
493 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32
" found", address
);
496 void watchpoint_clear_target(struct target
*target
)
498 LOG_DEBUG("Delete all watchpoints for target: %s",
499 target_name(target
));
500 while (target
->watchpoints
!= NULL
)
501 watchpoint_free(target
, target
->watchpoints
);
504 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
, uint32_t *address
)
507 struct watchpoint
*hit_watchpoint
;
509 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
510 if (retval
!= ERROR_OK
)
513 *rw
= hit_watchpoint
->rw
;
514 *address
= hit_watchpoint
->address
;
516 LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32
" (WPID: %d)",
517 hit_watchpoint
->address
,
518 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)