add 'testee' target type
[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 "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
113 while (breakpoint)
114 {
115 if (breakpoint == breakpoint_remove)
116 break;
117 breakpoint_p = &breakpoint->next;
118 breakpoint = breakpoint->next;
119 }
120
121 if (breakpoint == NULL)
122 return;
123
124 target_remove_breakpoint(target, breakpoint);
125
126 LOG_DEBUG("BPID: %d", breakpoint->unique_id );
127 (*breakpoint_p) = breakpoint->next;
128 free(breakpoint->orig_instr);
129 free(breakpoint);
130 }
131
132 void breakpoint_remove(struct target *target, uint32_t address)
133 {
134 struct breakpoint *breakpoint = target->breakpoints;
135 struct breakpoint **breakpoint_p = &target->breakpoints;
136
137 while (breakpoint)
138 {
139 if (breakpoint->address == address)
140 break;
141 breakpoint_p = &breakpoint->next;
142 breakpoint = breakpoint->next;
143 }
144
145 if (breakpoint)
146 {
147 breakpoint_free(target, breakpoint);
148 }
149 else
150 {
151 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
152 }
153 }
154
155 void breakpoint_clear_target(struct target *target)
156 {
157 struct breakpoint *breakpoint;
158 LOG_DEBUG("Delete all breakpoints for target: %s", target_get_name( target ));
159 while ((breakpoint = target->breakpoints) != NULL)
160 {
161 breakpoint_free(target, breakpoint);
162 }
163 }
164
165 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
166 {
167 struct breakpoint *breakpoint = target->breakpoints;
168
169 while (breakpoint)
170 {
171 if (breakpoint->address == address)
172 return breakpoint;
173 breakpoint = breakpoint->next;
174 }
175
176 return NULL;
177 }
178
179 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
180 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
181 {
182 struct watchpoint *watchpoint = target->watchpoints;
183 struct watchpoint **watchpoint_p = &target->watchpoints;
184 int retval;
185 char *reason;
186
187 while (watchpoint)
188 {
189 if (watchpoint->address == address) {
190 if (watchpoint->length != length
191 || watchpoint->value != value
192 || watchpoint->mask != mask
193 || watchpoint->rw != rw) {
194 LOG_ERROR("address 0x%8.8" PRIx32
195 "already has watchpoint %d",
196 address, watchpoint->unique_id);
197 return ERROR_FAIL;
198 }
199
200 /* ignore duplicate watchpoint */
201 return ERROR_OK;
202 }
203 watchpoint_p = &watchpoint->next;
204 watchpoint = watchpoint->next;
205 }
206
207 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
208 (*watchpoint_p)->address = address;
209 (*watchpoint_p)->length = length;
210 (*watchpoint_p)->value = value;
211 (*watchpoint_p)->mask = mask;
212 (*watchpoint_p)->rw = rw;
213 (*watchpoint_p)->unique_id = bpwp_unique_id++;
214
215 retval = target_add_watchpoint(target, *watchpoint_p);
216 switch (retval) {
217 case ERROR_OK:
218 break;
219 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
220 reason = "resource not available";
221 goto bye;
222 case ERROR_TARGET_NOT_HALTED:
223 reason = "target running";
224 goto bye;
225 default:
226 reason = "unrecognized error";
227 bye:
228 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
229 watchpoint_rw_strings[(*watchpoint_p)->rw],
230 address, reason);
231 free (*watchpoint_p);
232 *watchpoint_p = NULL;
233 return retval;
234 }
235
236 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
237 " of length 0x%8.8" PRIx32 " (WPID: %d)",
238 watchpoint_rw_strings[(*watchpoint_p)->rw],
239 (*watchpoint_p)->address,
240 (*watchpoint_p)->length,
241 (*watchpoint_p)->unique_id );
242
243 return ERROR_OK;
244 }
245
246 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_remove)
247 {
248 struct watchpoint *watchpoint = target->watchpoints;
249 struct watchpoint **watchpoint_p = &target->watchpoints;
250
251 while (watchpoint)
252 {
253 if (watchpoint == watchpoint_remove)
254 break;
255 watchpoint_p = &watchpoint->next;
256 watchpoint = watchpoint->next;
257 }
258
259 if (watchpoint == NULL)
260 return;
261 target_remove_watchpoint(target, watchpoint);
262 LOG_DEBUG("WPID: %d", watchpoint->unique_id );
263 (*watchpoint_p) = watchpoint->next;
264 free(watchpoint);
265 }
266
267 void watchpoint_remove(struct target *target, uint32_t address)
268 {
269 struct watchpoint *watchpoint = target->watchpoints;
270 struct watchpoint **watchpoint_p = &target->watchpoints;
271
272 while (watchpoint)
273 {
274 if (watchpoint->address == address)
275 break;
276 watchpoint_p = &watchpoint->next;
277 watchpoint = watchpoint->next;
278 }
279
280 if (watchpoint)
281 {
282 watchpoint_free(target, watchpoint);
283 }
284 else
285 {
286 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
287 }
288 }
289
290 void watchpoint_clear_target(struct target *target)
291 {
292 struct watchpoint *watchpoint;
293 LOG_DEBUG("Delete all watchpoints for target: %s", target_get_name( target ));
294 while ((watchpoint = target->watchpoints) != NULL)
295 {
296 watchpoint_free(target, watchpoint);
297 }
298 }

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)