]> git.sur5r.net Git - openocd/blob - src/target/breakpoints.c
SEGFAULT gaffe in dummy register handling
[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 void 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
145 void breakpoint_clear_target(target_t *target)
146 {
147         breakpoint_t *breakpoint;
148         while ((breakpoint = target->breakpoints)!=NULL)
149         {
150                 breakpoint_free(target, breakpoint);
151         }
152 }
153
154 breakpoint_t* breakpoint_find(target_t *target, u32 address)
155 {
156         breakpoint_t *breakpoint = target->breakpoints;
157         
158         while (breakpoint)
159         {
160                 if (breakpoint->address == address)
161                         return breakpoint;
162                 breakpoint = breakpoint->next;
163         }
164         
165         return NULL;
166 }
167
168 int watchpoint_add(target_t *target, u32 address, u32 length, enum watchpoint_rw rw, u32 value, u32 mask)
169 {
170         watchpoint_t *watchpoint = target->watchpoints;
171         watchpoint_t **watchpoint_p = &target->watchpoints;
172         int retval;
173                 
174         while (watchpoint)
175         {
176                 if (watchpoint->address == address)
177                         return ERROR_OK;
178                 watchpoint_p = &watchpoint->next;
179                 watchpoint = watchpoint->next;
180         }
181         
182         (*watchpoint_p) = malloc(sizeof(watchpoint_t));
183         (*watchpoint_p)->address = address;
184         (*watchpoint_p)->length = length;
185         (*watchpoint_p)->value = value;
186         (*watchpoint_p)->mask = mask;
187         (*watchpoint_p)->rw = rw;
188         (*watchpoint_p)->set = 0;
189         (*watchpoint_p)->next = NULL;
190                 
191         if ((retval = target->type->add_watchpoint(target, *watchpoint_p)) != ERROR_OK)
192         {
193                 switch (retval)
194                 {
195                         case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
196                                 LOG_INFO("can't add %s watchpoint, resource not available", watchpoint_rw_strings[(*watchpoint_p)->rw]);
197                                 free (*watchpoint_p);
198                                 *watchpoint_p = NULL;
199                                 return retval;
200                                 break;
201                         case ERROR_TARGET_NOT_HALTED:
202                                 LOG_INFO("can't add watchpoint while target is running");
203                                 free (*watchpoint_p);
204                                 *watchpoint_p = NULL;
205                                 return retval;
206                                 break;
207                         default:
208                                 LOG_ERROR("unknown error");
209                                 exit(-1);
210                                 break;
211                 }
212         }
213         
214         LOG_DEBUG("added %s watchpoint at 0x%8.8x of length 0x%8.8x",
215                 watchpoint_rw_strings[(*watchpoint_p)->rw],
216                 (*watchpoint_p)->address, (*watchpoint_p)->length);
217         
218         return ERROR_OK;
219 }
220
221 static void watchpoint_free(target_t *target, watchpoint_t *watchpoint_remove)
222 {
223         watchpoint_t *watchpoint = target->watchpoints;
224         watchpoint_t **watchpoint_p = &target->watchpoints;
225
226         while (watchpoint)
227         {
228                 if (watchpoint == watchpoint_remove)
229                         break;
230                 watchpoint_p = &watchpoint->next;
231                 watchpoint = watchpoint->next;
232         }
233         
234         if (watchpoint==NULL)
235                 return;
236         target->type->remove_watchpoint(target, watchpoint);
237         (*watchpoint_p) = watchpoint->next;
238         free(watchpoint);
239 }
240
241
242
243 void watchpoint_remove(target_t *target, u32 address)
244 {
245         watchpoint_t *watchpoint = target->watchpoints;
246         watchpoint_t **watchpoint_p = &target->watchpoints;
247         
248         while (watchpoint)
249         {
250                 if (watchpoint->address == address)
251                         break;
252                 watchpoint_p = &watchpoint->next;
253                 watchpoint = watchpoint->next;
254         }
255         
256         if (watchpoint)
257         {
258                 watchpoint_free(target, watchpoint);
259         }
260         else
261         {
262                 LOG_ERROR("no watchpoint at address 0x%8.8x found", address);
263         }
264 }
265
266
267 void watchpoint_clear_target(target_t *target)
268 {
269         watchpoint_t *watchpoint;
270         while ((watchpoint = target->watchpoints)!=NULL)
271         {
272                 watchpoint_free(target, watchpoint);
273         }
274 }