ARMv7-M: make DAP commands verify target is an ARMv7-M
[openocd.git] / src / target / breakpoints.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "target.h"
25 #include <helper/log.h>
26 #include "breakpoints.h"
27
28
29 static char *breakpoint_type_strings[] =
30 {
31 "hardware",
32 "software"
33 };
34
35 static char *watchpoint_rw_strings[] =
36 {
37 "read",
38 "write",
39 "access"
40 };
41
42 // monotonic counter/id-number for breakpoints and watch points
43 static int bpwp_unique_id;
44
45 int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
46 {
47 struct breakpoint *breakpoint = target->breakpoints;
48 struct breakpoint **breakpoint_p = &target->breakpoints;
49 char *reason;
50 int retval;
51 int n;
52
53 n = 0;
54 while (breakpoint)
55 {
56 n++;
57 if (breakpoint->address == address) {
58 /* FIXME don't assume "same address" means "same
59 * breakpoint" ... check all the parameters before
60 * succeeding.
61 */
62 LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
63 address, breakpoint->unique_id );
64 return ERROR_OK;
65 }
66 breakpoint_p = &breakpoint->next;
67 breakpoint = breakpoint->next;
68 }
69
70 (*breakpoint_p) = malloc(sizeof(struct breakpoint));
71 (*breakpoint_p)->address = address;
72 (*breakpoint_p)->length = length;
73 (*breakpoint_p)->type = type;
74 (*breakpoint_p)->set = 0;
75 (*breakpoint_p)->orig_instr = malloc(length);
76 (*breakpoint_p)->next = NULL;
77 (*breakpoint_p)->unique_id = bpwp_unique_id++;
78
79 retval = target_add_breakpoint(target, *breakpoint_p);
80 switch (retval) {
81 case ERROR_OK:
82 break;
83 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
84 reason = "resource not available";
85 goto fail;
86 case ERROR_TARGET_NOT_HALTED:
87 reason = "target running";
88 goto fail;
89 default:
90 reason = "unknown reason";
91 fail:
92 LOG_ERROR("can't add breakpoint: %s", reason);
93 free((*breakpoint_p)->orig_instr);
94 free(*breakpoint_p);
95 *breakpoint_p = NULL;
96 return retval;
97 }
98
99 LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
100 breakpoint_type_strings[(*breakpoint_p)->type],
101 (*breakpoint_p)->address, (*breakpoint_p)->length,
102 (*breakpoint_p)->unique_id );
103
104 return ERROR_OK;
105 }
106
107 /* free up a breakpoint */
108 static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_remove)
109 {
110 struct breakpoint *breakpoint = target->breakpoints;
111 struct breakpoint **breakpoint_p = &target->breakpoints;
112 int retval;
113
114 while (breakpoint)
115 {
116 if (breakpoint == breakpoint_remove)
117 break;
118 breakpoint_p = &breakpoint->next;
119 breakpoint = breakpoint->next;
120 }
121
122 if (breakpoint == NULL)
123 return;
124
125 retval = target_remove_breakpoint(target, breakpoint);
126
127 LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
128 (*breakpoint_p) = breakpoint->next;
129 free(breakpoint->orig_instr);
130 free(breakpoint);
131 }
132
133 void breakpoint_remove(struct target *target, uint32_t address)
134 {
135 struct breakpoint *breakpoint = target->breakpoints;
136 struct breakpoint **breakpoint_p = &target->breakpoints;
137
138 while (breakpoint)
139 {
140 if (breakpoint->address == address)
141 break;
142 breakpoint_p = &breakpoint->next;
143 breakpoint = breakpoint->next;
144 }
145
146 if (breakpoint)
147 {
148 breakpoint_free(target, breakpoint);
149 }
150 else
151 {
152 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
153 }
154 }
155
156 void breakpoint_clear_target(struct target *target)
157 {
158 struct breakpoint *breakpoint;
159
160 LOG_DEBUG("Delete all breakpoints for target: %s",
161 target_name(target));
162 while ((breakpoint = target->breakpoints) != NULL)
163 {
164 breakpoint_free(target, breakpoint);
165 }
166 }
167
168 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
169 {
170 struct breakpoint *breakpoint = target->breakpoints;
171
172 while (breakpoint)
173 {
174 if (breakpoint->address == address)
175 return breakpoint;
176 breakpoint = breakpoint->next;
177 }
178
179 return NULL;
180 }
181
182 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
183 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
184 {
185 struct watchpoint *watchpoint = target->watchpoints;
186 struct watchpoint **watchpoint_p = &target->watchpoints;
187 int retval;
188 char *reason;
189
190 while (watchpoint)
191 {
192 if (watchpoint->address == address) {
193 if (watchpoint->length != length
194 || watchpoint->value != value
195 || watchpoint->mask != mask
196 || watchpoint->rw != rw) {
197 LOG_ERROR("address 0x%8.8" PRIx32
198 "already has watchpoint %d",
199 address, watchpoint->unique_id);
200 return ERROR_FAIL;
201 }
202
203 /* ignore duplicate watchpoint */
204 return ERROR_OK;
205 }
206 watchpoint_p = &watchpoint->next;
207 watchpoint = watchpoint->next;
208 }
209
210 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
211 (*watchpoint_p)->address = address;
212 (*watchpoint_p)->length = length;
213 (*watchpoint_p)->value = value;
214 (*watchpoint_p)->mask = mask;
215 (*watchpoint_p)->rw = rw;
216 (*watchpoint_p)->unique_id = bpwp_unique_id++;
217
218 retval = target_add_watchpoint(target, *watchpoint_p);
219 switch (retval) {
220 case ERROR_OK:
221 break;
222 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
223 reason = "resource not available";
224 goto bye;
225 case ERROR_TARGET_NOT_HALTED:
226 reason = "target running";
227 goto bye;
228 default:
229 reason = "unrecognized error";
230 bye:
231 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
232 watchpoint_rw_strings[(*watchpoint_p)->rw],
233 address, reason);
234 free (*watchpoint_p);
235 *watchpoint_p = NULL;
236 return retval;
237 }
238
239 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
240 " of length 0x%8.8" PRIx32 " (WPID: %d)",
241 watchpoint_rw_strings[(*watchpoint_p)->rw],
242 (*watchpoint_p)->address,
243 (*watchpoint_p)->length,
244 (*watchpoint_p)->unique_id );
245
246 return ERROR_OK;
247 }
248
249 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_remove)
250 {
251 struct watchpoint *watchpoint = target->watchpoints;
252 struct watchpoint **watchpoint_p = &target->watchpoints;
253 int retval;
254
255 while (watchpoint)
256 {
257 if (watchpoint == watchpoint_remove)
258 break;
259 watchpoint_p = &watchpoint->next;
260 watchpoint = watchpoint->next;
261 }
262
263 if (watchpoint == NULL)
264 return;
265 retval = target_remove_watchpoint(target, watchpoint);
266 LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
267 (*watchpoint_p) = watchpoint->next;
268 free(watchpoint);
269 }
270
271 void watchpoint_remove(struct target *target, uint32_t address)
272 {
273 struct watchpoint *watchpoint = target->watchpoints;
274 struct watchpoint **watchpoint_p = &target->watchpoints;
275
276 while (watchpoint)
277 {
278 if (watchpoint->address == address)
279 break;
280 watchpoint_p = &watchpoint->next;
281 watchpoint = watchpoint->next;
282 }
283
284 if (watchpoint)
285 {
286 watchpoint_free(target, watchpoint);
287 }
288 else
289 {
290 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
291 }
292 }
293
294 void watchpoint_clear_target(struct target *target)
295 {
296 struct watchpoint *watchpoint;
297
298 LOG_DEBUG("Delete all watchpoints for target: %s",
299 target_name(target));
300 while ((watchpoint = target->watchpoints) != NULL)
301 {
302 watchpoint_free(target, watchpoint);
303 }
304 }

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)