]> git.sur5r.net Git - openocd/blob - src/target/breakpoints.c
Clear all dangling breakpoints upon GDB connection.
[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 <stdlib.h>
25
26 #include "binarybuffer.h"
27 #include "target.h"
28 #include "log.h"
29 #include "types.h"
30
31 #include "breakpoints.h"
32
33 char *breakpoint_type_strings[] =
34 {
35         "hardware",
36         "software"
37 };
38
39 char *watchpoint_rw_strings[] =
40 {
41         "read",
42         "write",
43         "access"
44 };
45
46 int breakpoint_add(target_t *target, u32 address, u32 length, enum breakpoint_type type)
47 {
48         breakpoint_t *breakpoint = target->breakpoints;
49         breakpoint_t **breakpoint_p = &target->breakpoints;
50         int retval;
51         
52         while (breakpoint)
53         {
54                 if (breakpoint->address == address)
55                         return ERROR_OK;
56                 breakpoint_p = &breakpoint->next;
57                 breakpoint = breakpoint->next;
58         }
59                 
60         (*breakpoint_p) = malloc(sizeof(breakpoint_t));
61         (*breakpoint_p)->address = address;
62         (*breakpoint_p)->length = length;
63         (*breakpoint_p)->type = type;
64         (*breakpoint_p)->set = 0;
65         (*breakpoint_p)->orig_instr = malloc(length);
66         (*breakpoint_p)->next = NULL;
67         
68         if ((retval = target->type->add_breakpoint(target, *breakpoint_p)) != ERROR_OK)
69         {
70                 switch (retval)
71                 {
72                         case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
73                                 LOG_INFO("can't add %s breakpoint, resource not available", breakpoint_type_strings[(*breakpoint_p)->type]);
74                                 free((*breakpoint_p)->orig_instr);
75                                 free(*breakpoint_p);
76                                 *breakpoint_p = NULL;
77                                 return retval;
78                                 break;
79                         case ERROR_TARGET_NOT_HALTED:
80                                 LOG_INFO("can't add breakpoint while target is running");
81                                 free((*breakpoint_p)->orig_instr);
82                                 free(*breakpoint_p);
83                                 *breakpoint_p = NULL;
84                                 return retval;
85                                 break;
86                         default:
87                                 break;
88                 }
89         }
90         
91         LOG_DEBUG("added %s breakpoint at 0x%8.8x of length 0x%8.8x", 
92                 breakpoint_type_strings[(*breakpoint_p)->type],
93                 (*breakpoint_p)->address, (*breakpoint_p)->length);
94         
95         return ERROR_OK;
96 }
97
98 /* free up a breakpoint */
99 static void breakpoint_free(target_t *target, breakpoint_t *breakpoint_remove)
100 {
101         breakpoint_t *breakpoint = target->breakpoints;
102         breakpoint_t **breakpoint_p = &target->breakpoints;
103         
104         while (breakpoint)
105         {
106                 if (breakpoint==breakpoint_remove)
107                         break;
108                 breakpoint_p = &breakpoint->next;
109                 breakpoint = breakpoint->next;
110         }
111         
112         if (breakpoint==NULL)
113                 return;
114         
115         target->type->remove_breakpoint(target, breakpoint);
116         
117         (*breakpoint_p) = breakpoint->next;
118         free(breakpoint->orig_instr);
119         free(breakpoint);
120 }
121
122 int breakpoint_remove(target_t *target, u32 address)
123 {
124         breakpoint_t *breakpoint = target->breakpoints;
125         breakpoint_t **breakpoint_p = &target->breakpoints;
126         
127         while (breakpoint)
128         {
129                 if (breakpoint->address == address)
130                         break;
131                 breakpoint_p = &breakpoint->next;
132                 breakpoint = breakpoint->next;
133         }
134         
135         if (breakpoint)
136         {
137                 breakpoint_free(target, breakpoint);
138         }
139         else
140         {
141                 LOG_ERROR("no breakpoint at address 0x%8.8x found", address);
142         }
143         
144         return ERROR_OK;
145 }
146
147 void breakpoint_clear_target(target_t *target)
148 {
149         breakpoint_t *breakpoint;
150         while ((breakpoint = target->breakpoints)!=NULL)
151         {
152                 breakpoint_free(target, breakpoint);
153         }
154 }
155
156 breakpoint_t* breakpoint_find(target_t *target, u32 address)
157 {
158         breakpoint_t *breakpoint = target->breakpoints;
159         
160         while (breakpoint)
161         {
162                 if (breakpoint->address == address)
163                         return breakpoint;
164                 breakpoint = breakpoint->next;
165         }
166         
167         return NULL;
168 }
169
170 int watchpoint_add(target_t *target, u32 address, u32 length, enum watchpoint_rw rw, u32 value, u32 mask)
171 {
172         watchpoint_t *watchpoint = target->watchpoints;
173         watchpoint_t **watchpoint_p = &target->watchpoints;
174         int retval;
175                 
176         while (watchpoint)
177         {
178                 if (watchpoint->address == address)
179                         return ERROR_OK;
180                 watchpoint_p = &watchpoint->next;
181                 watchpoint = watchpoint->next;
182         }
183         
184         (*watchpoint_p) = malloc(sizeof(watchpoint_t));
185         (*watchpoint_p)->address = address;
186         (*watchpoint_p)->length = length;
187         (*watchpoint_p)->value = value;
188         (*watchpoint_p)->mask = mask;
189         (*watchpoint_p)->rw = rw;
190         (*watchpoint_p)->set = 0;
191         (*watchpoint_p)->next = NULL;
192                 
193         if ((retval = target->type->add_watchpoint(target, *watchpoint_p)) != ERROR_OK)
194         {
195                 switch (retval)
196                 {
197                         case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
198                                 LOG_INFO("can't add %s watchpoint, resource not available", watchpoint_rw_strings[(*watchpoint_p)->rw]);
199                                 free (*watchpoint_p);
200                                 *watchpoint_p = NULL;
201                                 return retval;
202                                 break;
203                         case ERROR_TARGET_NOT_HALTED:
204                                 LOG_INFO("can't add watchpoint while target is running");
205                                 free (*watchpoint_p);
206                                 *watchpoint_p = NULL;
207                                 return retval;
208                                 break;
209                         default:
210                                 LOG_ERROR("unknown error");
211                                 exit(-1);
212                                 break;
213                 }
214         }
215         
216         LOG_DEBUG("added %s watchpoint at 0x%8.8x of length 0x%8.8x",
217                 watchpoint_rw_strings[(*watchpoint_p)->rw],
218                 (*watchpoint_p)->address, (*watchpoint_p)->length);
219         
220         return ERROR_OK;
221 }
222
223 static void watchpoint_free(target_t *target, watchpoint_t *watchpoint_remove)
224 {
225         watchpoint_t *watchpoint = target->watchpoints;
226         watchpoint_t **watchpoint_p = &target->watchpoints;
227
228         while (watchpoint)
229         {
230                 if (watchpoint == watchpoint_remove)
231                         break;
232                 watchpoint_p = &watchpoint->next;
233                 watchpoint = watchpoint->next;
234         }
235         
236         if (watchpoint==NULL)
237                 return;
238         target->type->remove_watchpoint(target, watchpoint);
239         (*watchpoint_p) = watchpoint->next;
240         free(watchpoint);
241 }
242
243
244
245 int watchpoint_remove(target_t *target, u32 address)
246 {
247         watchpoint_t *watchpoint = target->watchpoints;
248         watchpoint_t **watchpoint_p = &target->watchpoints;
249         
250         while (watchpoint)
251         {
252                 if (watchpoint->address == address)
253                         break;
254                 watchpoint_p = &watchpoint->next;
255                 watchpoint = watchpoint->next;
256         }
257         
258         if (watchpoint)
259         {
260                 watchpoint_free(target, watchpoint);
261         }
262         else
263         {
264                 LOG_ERROR("no watchpoint at address 0x%8.8x found", address);
265         }
266         
267         return ERROR_OK;
268 }
269
270
271 void watchpoint_clear_target(target_t *target)
272 {
273         watchpoint_t *watchpoint;
274         while ((watchpoint = target->watchpoints)!=NULL)
275         {
276                 watchpoint_free(target, watchpoint);
277         }
278 }