]> git.sur5r.net Git - openocd/blob - src/target/breakpoints.c
- correctly enter debug state on a "soft_reset_halt" command
[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         if ((retval = target->type->add_breakpoint(target, address, length, type)) != ERROR_OK)
61         {
62                 switch (retval)
63                 {
64                         case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
65                                 INFO("can't add %s breakpoint, resource not available", breakpoint_type_strings[type]);
66                                 return retval;
67                                 break;
68                         case ERROR_TARGET_NOT_HALTED:
69                                 INFO("can't add breakpoint while target is running");
70                                 return retval;
71                                 break;
72                         default:
73                                 ERROR("unknown error");
74                                 exit(-1);
75                                 break;
76                 }
77         }
78         
79         (*breakpoint_p) = malloc(sizeof(breakpoint_t));
80         (*breakpoint_p)->address = address;
81         (*breakpoint_p)->length = length;
82         (*breakpoint_p)->type = type;
83         (*breakpoint_p)->set = 0;
84         (*breakpoint_p)->orig_instr = malloc(CEIL(length, 8));
85         (*breakpoint_p)->next = NULL;
86         
87         DEBUG("added %s breakpoint at 0x%8.8x of length 0x%8.8x", breakpoint_type_strings[type], address, length);
88         
89         return ERROR_OK;
90 }
91
92 int breakpoint_remove(target_t *target, u32 address)
93 {
94         breakpoint_t *breakpoint = target->breakpoints;
95         breakpoint_t **breakpoint_p = &target->breakpoints;
96         int retval;
97         
98         while (breakpoint)
99         {
100                 if (breakpoint->address == address)
101                         break;
102                 breakpoint_p = &breakpoint->next;
103                 breakpoint = breakpoint->next;
104         }
105         
106         if (breakpoint)
107         {
108                 if ((retval = target->type->remove_breakpoint(target, breakpoint)) != ERROR_OK)
109                 {
110                         switch (retval)
111                         {
112                                 case ERROR_TARGET_NOT_HALTED:
113                                         INFO("can't remove breakpoint while target is running");
114                                         return retval;
115                                         break;
116                                 default:
117                                         ERROR("unknown error");
118                                         exit(-1);
119                                         break;
120                         }
121                 }
122                 (*breakpoint_p) = breakpoint->next;
123                 free(breakpoint->orig_instr);
124                 free(breakpoint);
125         }
126         else
127         {
128                 ERROR("no breakpoint at address 0x%8.8x found", address);
129         }
130         
131         return ERROR_OK;
132 }
133
134 breakpoint_t* breakpoint_find(target_t *target, u32 address)
135 {
136         breakpoint_t *breakpoint = target->breakpoints;
137         
138         while (breakpoint)
139         {
140                 if (breakpoint->address == address)
141                         return breakpoint;
142                 breakpoint = breakpoint->next;
143         }
144         
145         return NULL;
146 }
147
148 int watchpoint_add(target_t *target, u32 address, u32 length, enum watchpoint_rw rw, u32 value, u32 mask)
149 {
150         watchpoint_t *watchpoint = target->watchpoints;
151         watchpoint_t **watchpoint_p = &target->watchpoints;
152         int retval;
153                 
154         while (watchpoint)
155         {
156                 if (watchpoint->address == address)
157                         return ERROR_OK;
158                 watchpoint_p = &watchpoint->next;
159                 watchpoint = watchpoint->next;
160         }
161         
162         if ((retval = target->type->add_watchpoint(target, address, length, rw)) != ERROR_OK)
163         {
164                 switch (retval)
165                 {
166                         case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
167                                 INFO("can't add %s watchpoint, resource not available", watchpoint_rw_strings[rw]);
168                                 return retval;
169                                 break;
170                         case ERROR_TARGET_NOT_HALTED:
171                                 INFO("can't add watchpoint while target is running");
172                                 return retval;
173                                 break;
174                         default:
175                                 ERROR("unknown error");
176                                 exit(-1);
177                                 break;
178                 }
179         }
180         
181         (*watchpoint_p) = malloc(sizeof(watchpoint_t));
182         (*watchpoint_p)->address = address;
183         (*watchpoint_p)->length = length;
184         (*watchpoint_p)->value = value;
185         (*watchpoint_p)->mask = mask;
186         (*watchpoint_p)->rw = rw;
187         (*watchpoint_p)->set = 0;
188         (*watchpoint_p)->next = NULL;
189         
190         DEBUG("added %s watchpoint at 0x%8.8x of length 0x%8.8x", watchpoint_rw_strings[rw], address, length);
191         
192         return ERROR_OK;
193 }
194
195 int watchpoint_remove(target_t *target, u32 address)
196 {
197         watchpoint_t *watchpoint = target->watchpoints;
198         watchpoint_t **watchpoint_p = &target->watchpoints;
199         int retval;
200         
201         while (watchpoint)
202         {
203                 if (watchpoint->address == address)
204                         break;
205                 watchpoint_p = &watchpoint->next;
206                 watchpoint = watchpoint->next;
207         }
208         
209         if (watchpoint)
210         {
211                 if ((retval = target->type->remove_watchpoint(target, watchpoint)) != ERROR_OK)
212                 {
213                         ERROR("BUG: can't remove watchpoint");
214                         exit(-1);
215                 }
216                 (*watchpoint_p) = watchpoint->next;
217                 free(watchpoint);
218         }
219         else
220         {
221                 ERROR("no watchpoint at address 0x%8.8x found", address);
222         }
223         
224         return ERROR_OK;
225 }