cfi: leave check on whether target is running to target_write_memory()
[fw/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 <helper/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         int retval;
50         int n;
51
52         n = 0;
53         while (breakpoint)
54         {
55                 n++;
56                 if (breakpoint->address == address) {
57                         /* FIXME don't assume "same address" means "same
58                          * breakpoint" ... check all the parameters before
59                          * succeeding.
60                          */
61                         LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %d)",
62                                   address, breakpoint->unique_id );
63                         return ERROR_OK;
64                 }
65                 breakpoint_p = &breakpoint->next;
66                 breakpoint = breakpoint->next;
67         }
68
69         (*breakpoint_p) = malloc(sizeof(struct breakpoint));
70         (*breakpoint_p)->address = address;
71         (*breakpoint_p)->length = length;
72         (*breakpoint_p)->type = type;
73         (*breakpoint_p)->set = 0;
74         (*breakpoint_p)->orig_instr = malloc(length);
75         (*breakpoint_p)->next = NULL;
76         (*breakpoint_p)->unique_id = bpwp_unique_id++;
77
78         retval = target_add_breakpoint(target, *breakpoint_p);
79         if (retval != ERROR_OK)
80         {
81                 LOG_ERROR("could not add breakpoint");
82                 free((*breakpoint_p)->orig_instr);
83                 free(*breakpoint_p);
84                 *breakpoint_p = NULL;
85                 return retval;
86         }
87
88         LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %d)",
89                           breakpoint_type_strings[(*breakpoint_p)->type],
90                           (*breakpoint_p)->address, (*breakpoint_p)->length,
91                           (*breakpoint_p)->unique_id  );
92
93         return ERROR_OK;
94 }
95
96 /* free up a breakpoint */
97 static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
98 {
99         struct breakpoint *breakpoint = target->breakpoints;
100         struct breakpoint **breakpoint_p = &target->breakpoints;
101         int retval;
102
103         while (breakpoint)
104         {
105                 if (breakpoint == breakpoint_to_remove)
106                         break;
107                 breakpoint_p = &breakpoint->next;
108                 breakpoint = breakpoint->next;
109         }
110
111         if (breakpoint == NULL)
112                 return;
113
114         retval = target_remove_breakpoint(target, breakpoint);
115
116         LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval);
117         (*breakpoint_p) = breakpoint->next;
118         free(breakpoint->orig_instr);
119         free(breakpoint);
120 }
121
122 void breakpoint_remove(struct target *target, uint32_t address)
123 {
124         struct breakpoint *breakpoint = target->breakpoints;
125         struct breakpoint **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.8" PRIx32 " found", address);
142         }
143 }
144
145 void breakpoint_clear_target(struct target *target)
146 {
147         struct breakpoint *breakpoint;
148
149         LOG_DEBUG("Delete all breakpoints for target: %s",
150                         target_name(target));
151         while ((breakpoint = target->breakpoints) != NULL)
152         {
153                 breakpoint_free(target, breakpoint);
154         }
155 }
156
157 struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
158 {
159         struct breakpoint *breakpoint = target->breakpoints;
160
161         while (breakpoint)
162         {
163                 if (breakpoint->address == address)
164                         return breakpoint;
165                 breakpoint = breakpoint->next;
166         }
167
168         return NULL;
169 }
170
171 int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
172                 enum watchpoint_rw rw, uint32_t value, uint32_t mask)
173 {
174         struct watchpoint *watchpoint = target->watchpoints;
175         struct watchpoint **watchpoint_p = &target->watchpoints;
176         int retval;
177
178         while (watchpoint)
179         {
180                 if (watchpoint->address == address) {
181                         if (watchpoint->length != length
182                                         || watchpoint->value != value
183                                         || watchpoint->mask != mask
184                                         || watchpoint->rw != rw) {
185                                 LOG_ERROR("address 0x%8.8" PRIx32
186                                                 "already has watchpoint %d",
187                                                 address, watchpoint->unique_id);
188                                 return ERROR_FAIL;
189                         }
190
191                         /* ignore duplicate watchpoint */
192                         return ERROR_OK;
193                 }
194                 watchpoint_p = &watchpoint->next;
195                 watchpoint = watchpoint->next;
196         }
197
198         (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
199         (*watchpoint_p)->address = address;
200         (*watchpoint_p)->length = length;
201         (*watchpoint_p)->value = value;
202         (*watchpoint_p)->mask = mask;
203         (*watchpoint_p)->rw = rw;
204         (*watchpoint_p)->unique_id = bpwp_unique_id++;
205
206         retval = target_add_watchpoint(target, *watchpoint_p);
207         if (retval != ERROR_OK)
208         {
209                 LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32,
210                          watchpoint_rw_strings[(*watchpoint_p)->rw],
211                          address);
212                 free (*watchpoint_p);
213                 *watchpoint_p = NULL;
214                 return retval;
215         }
216
217         LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
218                         " of length 0x%8.8" PRIx32 " (WPID: %d)",
219                         watchpoint_rw_strings[(*watchpoint_p)->rw],
220                         (*watchpoint_p)->address,
221                         (*watchpoint_p)->length,
222                         (*watchpoint_p)->unique_id );
223
224         return ERROR_OK;
225 }
226
227 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
228 {
229         struct watchpoint *watchpoint = target->watchpoints;
230         struct watchpoint **watchpoint_p = &target->watchpoints;
231         int retval;
232
233         while (watchpoint)
234         {
235                 if (watchpoint == watchpoint_to_remove)
236                         break;
237                 watchpoint_p = &watchpoint->next;
238                 watchpoint = watchpoint->next;
239         }
240
241         if (watchpoint == NULL)
242                 return;
243         retval = target_remove_watchpoint(target, watchpoint);
244         LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
245         (*watchpoint_p) = watchpoint->next;
246         free(watchpoint);
247 }
248
249 void watchpoint_remove(struct target *target, uint32_t address)
250 {
251         struct watchpoint *watchpoint = target->watchpoints;
252         struct watchpoint **watchpoint_p = &target->watchpoints;
253
254         while (watchpoint)
255         {
256                 if (watchpoint->address == address)
257                         break;
258                 watchpoint_p = &watchpoint->next;
259                 watchpoint = watchpoint->next;
260         }
261
262         if (watchpoint)
263         {
264                 watchpoint_free(target, watchpoint);
265         }
266         else
267         {
268                 LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
269         }
270 }
271
272 void watchpoint_clear_target(struct target *target)
273 {
274         struct watchpoint *watchpoint;
275
276         LOG_DEBUG("Delete all watchpoints for target: %s",
277                         target_name(target));
278         while ((watchpoint = target->watchpoints) != NULL)
279         {
280                 watchpoint_free(target, watchpoint);
281         }
282 }