]> git.sur5r.net Git - openocd/blob - src/target/breakpoints.c
breakpoint_t -> struct breakpoint
[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 "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         struct breakpoint *breakpoint = target->breakpoints;
48         struct breakpoint **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(struct breakpoint));
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, struct breakpoint *breakpoint_remove)
111 {
112         struct breakpoint *breakpoint = target->breakpoints;
113         struct breakpoint **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         struct breakpoint *breakpoint = target->breakpoints;
137         struct breakpoint **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         struct breakpoint *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 struct breakpoint* breakpoint_find(target_t *target, uint32_t address)
168 {
169         struct breakpoint *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 }