]> git.sur5r.net Git - openocd/blob - src/target/breakpoints.c
target: create and use target_name()
[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(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
159         LOG_DEBUG("Delete all breakpoints for target: %s",
160                         target_name(target));
161         while ((breakpoint = target->breakpoints) != NULL)
162         {
163                 breakpoint_free(target, breakpoint);
164         }
165 }
166
167 struct breakpoint* breakpoint_find(struct target *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(struct target *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
239                         " of length 0x%8.8" PRIx32 " (WPID: %d)",
240                         watchpoint_rw_strings[(*watchpoint_p)->rw],
241                         (*watchpoint_p)->address,
242                         (*watchpoint_p)->length,
243                         (*watchpoint_p)->unique_id );
244
245         return ERROR_OK;
246 }
247
248 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_remove)
249 {
250         struct watchpoint *watchpoint = target->watchpoints;
251         struct watchpoint **watchpoint_p = &target->watchpoints;
252
253         while (watchpoint)
254         {
255                 if (watchpoint == watchpoint_remove)
256                         break;
257                 watchpoint_p = &watchpoint->next;
258                 watchpoint = watchpoint->next;
259         }
260
261         if (watchpoint == NULL)
262                 return;
263         target_remove_watchpoint(target, watchpoint);
264         LOG_DEBUG("WPID: %d", watchpoint->unique_id );
265         (*watchpoint_p) = watchpoint->next;
266         free(watchpoint);
267 }
268
269 void watchpoint_remove(struct target *target, uint32_t address)
270 {
271         struct watchpoint *watchpoint = target->watchpoints;
272         struct watchpoint **watchpoint_p = &target->watchpoints;
273
274         while (watchpoint)
275         {
276                 if (watchpoint->address == address)
277                         break;
278                 watchpoint_p = &watchpoint->next;
279                 watchpoint = watchpoint->next;
280         }
281
282         if (watchpoint)
283         {
284                 watchpoint_free(target, watchpoint);
285         }
286         else
287         {
288                 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
289         }
290 }
291
292 void watchpoint_clear_target(struct target *target)
293 {
294         struct watchpoint *watchpoint;
295
296         LOG_DEBUG("Delete all watchpoints for target: %s",
297                         target_name(target));
298         while ((watchpoint = target->watchpoints) != NULL)
299         {
300                 watchpoint_free(target, watchpoint);
301         }
302 }