oocd_trace_t -> struct oocd_trace
[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(target_t *target, uint32_t address, uint32_t length, enum breakpoint_type type)
46 {
47 breakpoint_t *breakpoint = target->breakpoints;
48 breakpoint_t **breakpoint_p = &target->breakpoints;
49 int retval;
50 int n;
51
52 n = 0;
53 while (breakpoint)
54 {
55 n++;
56 if (breakpoint->address == address){
57 LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
58 address, breakpoint->unique_id );
59 return ERROR_OK;
60 }
61 breakpoint_p = &breakpoint->next;
62 breakpoint = breakpoint->next;
63 }
64
65 (*breakpoint_p) = malloc(sizeof(breakpoint_t));
66 (*breakpoint_p)->address = address;
67 (*breakpoint_p)->length = length;
68 (*breakpoint_p)->type = type;
69 (*breakpoint_p)->set = 0;
70 (*breakpoint_p)->orig_instr = malloc(length);
71 (*breakpoint_p)->next = NULL;
72 (*breakpoint_p)->unique_id = bpwp_unique_id++;
73
74 if ((retval = target_add_breakpoint(target, *breakpoint_p)) != ERROR_OK)
75 {
76 switch (retval)
77 {
78 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
79 LOG_INFO("can't add %s breakpoint, resource not available (BPID=%d)",
80 breakpoint_type_strings[(*breakpoint_p)->type],
81 (*breakpoint_p)->unique_id );
82
83 free((*breakpoint_p)->orig_instr);
84 free(*breakpoint_p);
85 *breakpoint_p = NULL;
86 return retval;
87 break;
88 case ERROR_TARGET_NOT_HALTED:
89 LOG_INFO("can't add breakpoint while target is running (BPID: %d)",
90 (*breakpoint_p)->unique_id );
91 free((*breakpoint_p)->orig_instr);
92 free(*breakpoint_p);
93 *breakpoint_p = NULL;
94 return retval;
95 break;
96 default:
97 break;
98 }
99 }
100
101 LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
102 breakpoint_type_strings[(*breakpoint_p)->type],
103 (*breakpoint_p)->address, (*breakpoint_p)->length,
104 (*breakpoint_p)->unique_id );
105
106 return ERROR_OK;
107 }
108
109 /* free up a breakpoint */
110 static void breakpoint_free(target_t *target, breakpoint_t *breakpoint_remove)
111 {
112 breakpoint_t *breakpoint = target->breakpoints;
113 breakpoint_t **breakpoint_p = &target->breakpoints;
114
115 while (breakpoint)
116 {
117 if (breakpoint == breakpoint_remove)
118 break;
119 breakpoint_p = &breakpoint->next;
120 breakpoint = breakpoint->next;
121 }
122
123 if (breakpoint == NULL)
124 return;
125
126 target_remove_breakpoint(target, breakpoint);
127
128 LOG_DEBUG("BPID: %d", breakpoint->unique_id );
129 (*breakpoint_p) = breakpoint->next;
130 free(breakpoint->orig_instr);
131 free(breakpoint);
132 }
133
134 void breakpoint_remove(target_t *target, uint32_t address)
135 {
136 breakpoint_t *breakpoint = target->breakpoints;
137 breakpoint_t **breakpoint_p = &target->breakpoints;
138
139 while (breakpoint)
140 {
141 if (breakpoint->address == address)
142 break;
143 breakpoint_p = &breakpoint->next;
144 breakpoint = breakpoint->next;
145 }
146
147 if (breakpoint)
148 {
149 breakpoint_free(target, breakpoint);
150 }
151 else
152 {
153 LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
154 }
155 }
156
157 void breakpoint_clear_target(target_t *target)
158 {
159 breakpoint_t *breakpoint;
160 LOG_DEBUG("Delete all breakpoints for target: %s", target_get_name( target ));
161 while ((breakpoint = target->breakpoints) != NULL)
162 {
163 breakpoint_free(target, breakpoint);
164 }
165 }
166
167 breakpoint_t* breakpoint_find(target_t *target, uint32_t address)
168 {
169 breakpoint_t *breakpoint = target->breakpoints;
170
171 while (breakpoint)
172 {
173 if (breakpoint->address == address)
174 return breakpoint;
175 breakpoint = breakpoint->next;
176 }
177
178 return NULL;
179 }
180
181 int watchpoint_add(target_t *target, uint32_t address, uint32_t length,
182 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
183 {
184 struct watchpoint *watchpoint = target->watchpoints;
185 struct watchpoint **watchpoint_p = &target->watchpoints;
186 int retval;
187 char *reason;
188
189 while (watchpoint)
190 {
191 if (watchpoint->address == address) {
192 if (watchpoint->length != length
193 || watchpoint->value != value
194 || watchpoint->mask != mask
195 || watchpoint->rw != rw) {
196 LOG_ERROR("address 0x%8.8" PRIx32
197 "already has watchpoint %d",
198 address, watchpoint->unique_id);
199 return ERROR_FAIL;
200 }
201
202 /* ignore duplicate watchpoint */
203 return ERROR_OK;
204 }
205 watchpoint_p = &watchpoint->next;
206 watchpoint = watchpoint->next;
207 }
208
209 (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
210 (*watchpoint_p)->address = address;
211 (*watchpoint_p)->length = length;
212 (*watchpoint_p)->value = value;
213 (*watchpoint_p)->mask = mask;
214 (*watchpoint_p)->rw = rw;
215 (*watchpoint_p)->unique_id = bpwp_unique_id++;
216
217 retval = target_add_watchpoint(target, *watchpoint_p);
218 switch (retval) {
219 case ERROR_OK:
220 break;
221 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
222 reason = "resource not available";
223 goto bye;
224 case ERROR_TARGET_NOT_HALTED:
225 reason = "target running";
226 goto bye;
227 default:
228 reason = "unrecognized error";
229 bye:
230 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
231 watchpoint_rw_strings[(*watchpoint_p)->rw],
232 address, reason);
233 free (*watchpoint_p);
234 *watchpoint_p = NULL;
235 return retval;
236 }
237
238 LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 " of length 0x%8.8x (WPID: %d)",
239 watchpoint_rw_strings[(*watchpoint_p)->rw],
240 (*watchpoint_p)->address,
241 (*watchpoint_p)->length,
242 (*watchpoint_p)->unique_id );
243
244 return ERROR_OK;
245 }
246
247 static void watchpoint_free(target_t *target, struct watchpoint *watchpoint_remove)
248 {
249 struct watchpoint *watchpoint = target->watchpoints;
250 struct watchpoint **watchpoint_p = &target->watchpoints;
251
252 while (watchpoint)
253 {
254 if (watchpoint == watchpoint_remove)
255 break;
256 watchpoint_p = &watchpoint->next;
257 watchpoint = watchpoint->next;
258 }
259
260 if (watchpoint == NULL)
261 return;
262 target_remove_watchpoint(target, watchpoint);
263 LOG_DEBUG("WPID: %d", watchpoint->unique_id );
264 (*watchpoint_p) = watchpoint->next;
265 free(watchpoint);
266 }
267
268 void watchpoint_remove(target_t *target, uint32_t address)
269 {
270 struct watchpoint *watchpoint = target->watchpoints;
271 struct watchpoint **watchpoint_p = &target->watchpoints;
272
273 while (watchpoint)
274 {
275 if (watchpoint->address == address)
276 break;
277 watchpoint_p = &watchpoint->next;
278 watchpoint = watchpoint->next;
279 }
280
281 if (watchpoint)
282 {
283 watchpoint_free(target, watchpoint);
284 }
285 else
286 {
287 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
288 }
289 }
290
291 void watchpoint_clear_target(target_t *target)
292 {
293 struct watchpoint *watchpoint;
294 LOG_DEBUG("Delete all watchpoints for target: %s", target_get_name( target ));
295 while ((watchpoint = target->watchpoints) != NULL)
296 {
297 watchpoint_free(target, watchpoint);
298 }
299 }

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)