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