80f98dc1101d72df063558e898b14bced1cb68f7
[openocd.git] / src / target / breakpoints.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) ST-Ericsson SA 2011 *
6 * michel.jaouen@stericsson.com : smp minimum support *
7 * *
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. *
12 * *
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. *
17 * *
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 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "target.h"
28 #include <helper/log.h>
29 #include "breakpoints.h"
30
31
32 static char *breakpoint_type_strings[] =
33 {
34 "hardware",
35 "software"
36 };
37
38 static char *watchpoint_rw_strings[] =
39 {
40 "read",
41 "write",
42 "access"
43 };
44
45 // monotonic counter/id-number for breakpoints and watch points
46 static int bpwp_unique_id;
47
48 int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
49 {
50 struct breakpoint *breakpoint = target->breakpoints;
51 struct breakpoint **breakpoint_p = &target->breakpoints;
52 char *reason;
53 int retval;
54 int n;
55
56 n = 0;
57 while (breakpoint)
58 {
59 n++;
60 if (breakpoint->address == address) {
61 /* FIXME don't assume "same address" means "same
62 * breakpoint" ... check all the parameters before
63 * succeeding.
64 */
65 LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
66 address, breakpoint->unique_id );
67 return ERROR_OK;
68 }
69 breakpoint_p = &breakpoint->next;
70 breakpoint = breakpoint->next;
71 }
72
73 (*breakpoint_p) = malloc(sizeof(struct breakpoint));
74 (*breakpoint_p)->address = address;
75 (*breakpoint_p)->length = length;
76 (*breakpoint_p)->type = type;
77 (*breakpoint_p)->set = 0;
78 (*breakpoint_p)->orig_instr = malloc(length);
79 (*breakpoint_p)->next = NULL;
80 (*breakpoint_p)->unique_id = bpwp_unique_id++;
81
82 retval = target_add_breakpoint(target, *breakpoint_p);
83 switch (retval) {
84 case ERROR_OK:
85 break;
86 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
87 reason = "resource not available";
88 goto fail;
89 case ERROR_TARGET_NOT_HALTED:
90 reason = "target running";
91 goto fail;
92 default:
93 reason = "unknown reason";
94 fail:
95 LOG_ERROR("can't add breakpoint: %s", reason);
96 free((*breakpoint_p)->orig_instr);
97 free(*breakpoint_p);
98 *breakpoint_p = NULL;
99 return retval;
100 }
101
102 LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
103 breakpoint_type_strings[(*breakpoint_p)->type],
104 (*breakpoint_p)->address, (*breakpoint_p)->length,
105 (*breakpoint_p)->unique_id );
106
107 return ERROR_OK;
108 }
109
110 int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
111 {
112
113 int retval = ERROR_OK;
114 if (target->smp)
115 {
116 struct target_list *head;
117 struct target *curr;
118 head = target->head;
119 while(head != (struct target_list*)NULL)
120 {
121 curr = head->target;
122 retval = breakpoint_add_internal(curr, address,length, type);
123 if (retval != ERROR_OK) return retval;
124 head = head->next;
125 }
126 return retval;
127 }
128 else
129 return(breakpoint_add_internal(target, address, length, type));
130
131 }
132
133 /* free up a breakpoint */
134 static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
135 {
136 struct breakpoint *breakpoint = target->breakpoints;
137 struct breakpoint **breakpoint_p = &target->breakpoints;
138 int retval;
139
140 while (breakpoint)
141 {
142 if (breakpoint == breakpoint_to_remove)
143 break;
144 breakpoint_p = &breakpoint->next;
145 breakpoint = breakpoint->next;
146 }
147
148 if (breakpoint == NULL)
149 return;
150
151 retval = target_remove_breakpoint(target, breakpoint);
152
153 LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
154 (*breakpoint_p) = breakpoint->next;
155 free(breakpoint->orig_instr);
156 free(breakpoint);
157 }
158
159 void breakpoint_remove_internal(struct target *target, uint32_t address)
160 {
161 struct breakpoint *breakpoint = target->breakpoints;
162 struct breakpoint **breakpoint_p = &target->breakpoints;
163
164 while (breakpoint)
165 {
166 if (breakpoint->address == address)
167 break;
168 breakpoint_p = &breakpoint->next;
169 breakpoint = breakpoint->next;
170 }
171
172 if (breakpoint)
173 {
174 breakpoint_free(target, breakpoint);
175 }
176 else
177 {
178 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
179 }
180 }
181 void breakpoint_remove(struct target *target, uint32_t address)
182 {
183 if ((target->smp))
184 {
185 struct target_list *head;
186 struct target *curr;
187 head = target->head;
188 while(head != (struct target_list*)NULL)
189 {
190 curr = head->target;
191 breakpoint_remove_internal(curr, address);
192 head = head->next;
193 }
194 }
195 else breakpoint_remove_internal(target, address);
196 }
197
198 void breakpoint_clear_target_internal(struct target *target)
199 {
200 struct breakpoint *breakpoint;
201
202 LOG_DEBUG("Delete all breakpoints for target: %s",
203 target_name(target));
204 while ((breakpoint = target->breakpoints) != NULL)
205 {
206 breakpoint_free(target, breakpoint);
207 }
208 }
209
210 void breakpoint_clear_target(struct target *target)
211 {
212 if (target->smp)
213 {
214 struct target_list *head;
215 struct target *curr;
216 head = target->head;
217 while(head != (struct target_list*)NULL)
218 {
219 curr = head->target;
220 breakpoint_clear_target_internal(curr);
221 head = head->next;
222 }
223 }
224 else breakpoint_clear_target_internal(target);
225
226 }
227
228
229 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
230 {
231 struct breakpoint *breakpoint = target->breakpoints;
232
233 while (breakpoint)
234 {
235 if (breakpoint->address == address)
236 return breakpoint;
237 breakpoint = breakpoint->next;
238 }
239
240 return NULL;
241 }
242
243 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
244 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
245 {
246 struct watchpoint *watchpoint = target->watchpoints;
247 struct watchpoint **watchpoint_p = &target->watchpoints;
248 int retval;
249 char *reason;
250
251 while (watchpoint)
252 {
253 if (watchpoint->address == address) {
254 if (watchpoint->length != length
255 || watchpoint->value != value
256 || watchpoint->mask != mask
257 || watchpoint->rw != rw) {
258 LOG_ERROR("address 0x%8.8" PRIx32
259 "already has watchpoint %d",
260 address, watchpoint->unique_id);
261 return ERROR_FAIL;
262 }
263
264 /* ignore duplicate watchpoint */
265 return ERROR_OK;
266 }
267 watchpoint_p = &watchpoint->next;
268 watchpoint = watchpoint->next;
269 }
270
271 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
272 (*watchpoint_p)->address = address;
273 (*watchpoint_p)->length = length;
274 (*watchpoint_p)->value = value;
275 (*watchpoint_p)->mask = mask;
276 (*watchpoint_p)->rw = rw;
277 (*watchpoint_p)->unique_id = bpwp_unique_id++;
278
279 retval = target_add_watchpoint(target, *watchpoint_p);
280 switch (retval) {
281 case ERROR_OK:
282 break;
283 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
284 reason = "resource not available";
285 goto bye;
286 case ERROR_TARGET_NOT_HALTED:
287 reason = "target running";
288 goto bye;
289 default:
290 reason = "unrecognized error";
291 bye:
292 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
293 watchpoint_rw_strings[(*watchpoint_p)->rw],
294 address, reason);
295 free (*watchpoint_p);
296 *watchpoint_p = NULL;
297 return retval;
298 }
299
300 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
301 " of length 0x%8.8" PRIx32 " (WPID: %d)",
302 watchpoint_rw_strings[(*watchpoint_p)->rw],
303 (*watchpoint_p)->address,
304 (*watchpoint_p)->length,
305 (*watchpoint_p)->unique_id );
306
307 return ERROR_OK;
308 }
309
310 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
311 {
312 struct watchpoint *watchpoint = target->watchpoints;
313 struct watchpoint **watchpoint_p = &target->watchpoints;
314 int retval;
315
316 while (watchpoint)
317 {
318 if (watchpoint == watchpoint_to_remove)
319 break;
320 watchpoint_p = &watchpoint->next;
321 watchpoint = watchpoint->next;
322 }
323
324 if (watchpoint == NULL)
325 return;
326 retval = target_remove_watchpoint(target, watchpoint);
327 LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
328 (*watchpoint_p) = watchpoint->next;
329 free(watchpoint);
330 }
331
332 void watchpoint_remove(struct target *target, uint32_t address)
333 {
334 struct watchpoint *watchpoint = target->watchpoints;
335 struct watchpoint **watchpoint_p = &target->watchpoints;
336
337 while (watchpoint)
338 {
339 if (watchpoint->address == address)
340 break;
341 watchpoint_p = &watchpoint->next;
342 watchpoint = watchpoint->next;
343 }
344
345 if (watchpoint)
346 {
347 watchpoint_free(target, watchpoint);
348 }
349 else
350 {
351 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
352 }
353 }
354
355 void watchpoint_clear_target(struct target *target)
356 {
357 struct watchpoint *watchpoint;
358
359 LOG_DEBUG("Delete all watchpoints for target: %s",
360 target_name(target));
361 while ((watchpoint = target->watchpoints) != NULL)
362 {
363 watchpoint_free(target, watchpoint);
364 }
365 }

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)