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 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_DEBUG("Duplicate Breakpoint address: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
64 address
, breakpoint
->unique_id
);
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 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_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
128 asid
, breakpoint
->unique_id
);
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 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_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32
" (BP %" PRIu32
")",
180 asid
, breakpoint
->unique_id
);
182 } else if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0)) {
183 LOG_DEBUG("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT
" (BP %" PRIu32
")",
184 address
, breakpoint
->unique_id
);
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
);
244 int context_breakpoint_add(struct target
*target
,
247 enum breakpoint_type type
)
249 int retval
= ERROR_OK
;
251 struct target_list
*head
;
254 while (head
!= (struct target_list
*)NULL
) {
256 retval
= context_breakpoint_add_internal(curr
, asid
, length
, type
);
257 if (retval
!= ERROR_OK
)
263 return context_breakpoint_add_internal(target
, asid
, length
, type
);
265 int hybrid_breakpoint_add(struct target
*target
,
266 target_addr_t address
,
269 enum breakpoint_type type
)
271 int retval
= ERROR_OK
;
273 struct target_list
*head
;
276 while (head
!= (struct target_list
*)NULL
) {
278 retval
= hybrid_breakpoint_add_internal(curr
, address
, asid
, length
, type
);
279 if (retval
!= ERROR_OK
)
285 return hybrid_breakpoint_add_internal(target
, address
, asid
, length
, type
);
288 /* free up a breakpoint */
289 static void breakpoint_free(struct target
*target
, struct breakpoint
*breakpoint_to_remove
)
291 struct breakpoint
*breakpoint
= target
->breakpoints
;
292 struct breakpoint
**breakpoint_p
= &target
->breakpoints
;
296 if (breakpoint
== breakpoint_to_remove
)
298 breakpoint_p
= &breakpoint
->next
;
299 breakpoint
= breakpoint
->next
;
302 if (breakpoint
== NULL
)
305 retval
= target_remove_breakpoint(target
, breakpoint
);
307 LOG_DEBUG("free BPID: %" PRIu32
" --> %d", breakpoint
->unique_id
, retval
);
308 (*breakpoint_p
) = breakpoint
->next
;
309 free(breakpoint
->orig_instr
);
313 int breakpoint_remove_internal(struct target
*target
, target_addr_t address
)
315 struct breakpoint
*breakpoint
= target
->breakpoints
;
318 if ((breakpoint
->address
== address
) && (breakpoint
->asid
== 0))
320 else if ((breakpoint
->address
== 0) && (breakpoint
->asid
== address
))
322 else if ((breakpoint
->address
== address
) && (breakpoint
->asid
!= 0))
324 breakpoint
= breakpoint
->next
;
328 breakpoint_free(target
, breakpoint
);
332 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
336 void breakpoint_remove(struct target
*target
, target_addr_t address
)
340 struct target_list
*head
;
343 while (head
!= (struct target_list
*)NULL
) {
345 found
+= breakpoint_remove_internal(curr
, address
);
349 LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT
" found", address
);
351 breakpoint_remove_internal(target
, address
);
354 void breakpoint_clear_target_internal(struct target
*target
)
356 LOG_DEBUG("Delete all breakpoints for target: %s",
357 target_name(target
));
358 while (target
->breakpoints
!= NULL
)
359 breakpoint_free(target
, target
->breakpoints
);
362 void breakpoint_clear_target(struct target
*target
)
365 struct target_list
*head
;
368 while (head
!= (struct target_list
*)NULL
) {
370 breakpoint_clear_target_internal(curr
);
374 breakpoint_clear_target_internal(target
);
378 struct breakpoint
*breakpoint_find(struct target
*target
, target_addr_t address
)
380 struct breakpoint
*breakpoint
= target
->breakpoints
;
383 if (breakpoint
->address
== address
)
385 breakpoint
= breakpoint
->next
;
391 int watchpoint_add(struct target
*target
, target_addr_t address
, uint32_t length
,
392 enum watchpoint_rw rw
, uint32_t value
, uint32_t mask
)
394 struct watchpoint
*watchpoint
= target
->watchpoints
;
395 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
400 if (watchpoint
->address
== address
) {
401 if (watchpoint
->length
!= length
402 || watchpoint
->value
!= value
403 || watchpoint
->mask
!= mask
404 || watchpoint
->rw
!= rw
) {
405 LOG_ERROR("address " TARGET_ADDR_FMT
406 " already has watchpoint %d",
407 address
, watchpoint
->unique_id
);
411 /* ignore duplicate watchpoint */
414 watchpoint_p
= &watchpoint
->next
;
415 watchpoint
= watchpoint
->next
;
418 (*watchpoint_p
) = calloc(1, sizeof(struct watchpoint
));
419 (*watchpoint_p
)->address
= address
;
420 (*watchpoint_p
)->length
= length
;
421 (*watchpoint_p
)->value
= value
;
422 (*watchpoint_p
)->mask
= mask
;
423 (*watchpoint_p
)->rw
= rw
;
424 (*watchpoint_p
)->unique_id
= bpwp_unique_id
++;
426 retval
= target_add_watchpoint(target
, *watchpoint_p
);
430 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
431 reason
= "resource not available";
433 case ERROR_TARGET_NOT_HALTED
:
434 reason
= "target running";
437 reason
= "unrecognized error";
439 LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT
", %s",
440 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
443 *watchpoint_p
= NULL
;
447 LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT
448 " of length 0x%8.8" PRIx32
" (WPID: %d)",
449 watchpoint_rw_strings
[(*watchpoint_p
)->rw
],
450 (*watchpoint_p
)->address
,
451 (*watchpoint_p
)->length
,
452 (*watchpoint_p
)->unique_id
);
457 static void watchpoint_free(struct target
*target
, struct watchpoint
*watchpoint_to_remove
)
459 struct watchpoint
*watchpoint
= target
->watchpoints
;
460 struct watchpoint
**watchpoint_p
= &target
->watchpoints
;
464 if (watchpoint
== watchpoint_to_remove
)
466 watchpoint_p
= &watchpoint
->next
;
467 watchpoint
= watchpoint
->next
;
470 if (watchpoint
== NULL
)
472 retval
= target_remove_watchpoint(target
, watchpoint
);
473 LOG_DEBUG("free WPID: %d --> %d", watchpoint
->unique_id
, retval
);
474 (*watchpoint_p
) = watchpoint
->next
;
478 void watchpoint_remove(struct target
*target
, target_addr_t address
)
480 struct watchpoint
*watchpoint
= target
->watchpoints
;
483 if (watchpoint
->address
== address
)
485 watchpoint
= watchpoint
->next
;
489 watchpoint_free(target
, watchpoint
);
491 LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT
" found", address
);
494 void watchpoint_clear_target(struct target
*target
)
496 LOG_DEBUG("Delete all watchpoints for target: %s",
497 target_name(target
));
498 while (target
->watchpoints
!= NULL
)
499 watchpoint_free(target
, target
->watchpoints
);
502 int watchpoint_hit(struct target
*target
, enum watchpoint_rw
*rw
,
503 target_addr_t
*address
)
506 struct watchpoint
*hit_watchpoint
;
508 retval
= target_hit_watchpoint(target
, &hit_watchpoint
);
509 if (retval
!= ERROR_OK
)
512 *rw
= hit_watchpoint
->rw
;
513 *address
= hit_watchpoint
->address
;
515 LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT
" (WPID: %d)",
516 hit_watchpoint
->address
,
517 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)