MinGW build fixes
[fw/openocd] / 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 }