Updated copyright notices for most files.
[deliverable/binutils-gdb.git] / gdb / gdbserver / mem-break.c
CommitLineData
611cb4a5 1/* Memory breakpoint operations for the remote server for GDB.
9b254dd1 2 Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
611cb4a5
DJ
3
4 Contributed by MontaVista Software.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
611cb4a5
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
611cb4a5
DJ
20
21#include "server.h"
22
f450004a 23const unsigned char *breakpoint_data;
611cb4a5
DJ
24int breakpoint_len;
25
26#define MAX_BREAKPOINT_LEN 8
27
28struct breakpoint
29{
30 struct breakpoint *next;
31 CORE_ADDR pc;
32 unsigned char old_data[MAX_BREAKPOINT_LEN];
33
34 /* Non-zero iff we are stepping over this breakpoint. */
35 int reinserting;
36
37 /* Non-NULL iff this breakpoint was inserted to step over
38 another one. Points to the other breakpoint (which is also
39 in the *next chain somewhere). */
40 struct breakpoint *breakpoint_to_reinsert;
41
b65d95c5
DJ
42 /* Function to call when we hit this breakpoint. If it returns 1,
43 the breakpoint will be deleted; 0, it will be reinserted for
44 another round. */
45 int (*handler) (CORE_ADDR);
611cb4a5
DJ
46};
47
48struct breakpoint *breakpoints;
49
50void
b65d95c5 51set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
611cb4a5
DJ
52{
53 struct breakpoint *bp;
54
55 if (breakpoint_data == NULL)
56 error ("Target does not support breakpoints.");
57
58 bp = malloc (sizeof (struct breakpoint));
59 memset (bp, 0, sizeof (struct breakpoint));
60
61 (*the_target->read_memory) (where, bp->old_data,
62 breakpoint_len);
63 (*the_target->write_memory) (where, breakpoint_data,
64 breakpoint_len);
65
66 bp->pc = where;
67 bp->handler = handler;
68
69 bp->next = breakpoints;
70 breakpoints = bp;
71}
72
73static void
74delete_breakpoint (struct breakpoint *bp)
75{
76 struct breakpoint *cur;
77
78 if (breakpoints == bp)
79 {
80 breakpoints = bp->next;
81 (*the_target->write_memory) (bp->pc, bp->old_data,
82 breakpoint_len);
83 free (bp);
84 return;
85 }
86 cur = breakpoints;
87 while (cur->next)
88 {
89 if (cur->next == bp)
90 {
91 cur->next = bp->next;
92 (*the_target->write_memory) (bp->pc, bp->old_data,
93 breakpoint_len);
94 free (bp);
95 return;
96 }
97 }
98 warning ("Could not find breakpoint in list.");
99}
100
101static struct breakpoint *
102find_breakpoint_at (CORE_ADDR where)
103{
104 struct breakpoint *bp = breakpoints;
105
106 while (bp != NULL)
107 {
108 if (bp->pc == where)
109 return bp;
110 bp = bp->next;
111 }
112
113 return NULL;
114}
115
68070c10
PA
116void
117delete_breakpoint_at (CORE_ADDR addr)
118{
119 struct breakpoint *bp = find_breakpoint_at (addr);
120 if (bp != NULL)
121 delete_breakpoint (bp);
122}
123
b65d95c5 124static int
611cb4a5
DJ
125reinsert_breakpoint_handler (CORE_ADDR stop_pc)
126{
127 struct breakpoint *stop_bp, *orig_bp;
128
129 stop_bp = find_breakpoint_at (stop_pc);
130 if (stop_bp == NULL)
131 error ("lost the stopping breakpoint.");
132
133 orig_bp = stop_bp->breakpoint_to_reinsert;
134 if (orig_bp == NULL)
135 error ("no breakpoint to reinsert");
136
137 (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
138 breakpoint_len);
139 orig_bp->reinserting = 0;
b65d95c5 140 return 1;
611cb4a5
DJ
141}
142
143void
144reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
145{
146 struct breakpoint *bp, *orig_bp;
147
fd3a5ca1 148 orig_bp = find_breakpoint_at (stop_pc);
611cb4a5
DJ
149 if (orig_bp == NULL)
150 error ("Could not find original breakpoint in list.");
151
b65d95c5
DJ
152 set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
153
611cb4a5
DJ
154 bp = find_breakpoint_at (stop_at);
155 if (bp == NULL)
156 error ("Could not find breakpoint in list (reinserting by breakpoint).");
157 bp->breakpoint_to_reinsert = orig_bp;
158
159 (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
160 breakpoint_len);
161 orig_bp->reinserting = 1;
162}
163
164void
165uninsert_breakpoint (CORE_ADDR stopped_at)
166{
167 struct breakpoint *bp;
168
169 bp = find_breakpoint_at (stopped_at);
170 if (bp == NULL)
171 error ("Could not find breakpoint in list (uninserting).");
172
173 (*the_target->write_memory) (bp->pc, bp->old_data,
174 breakpoint_len);
175 bp->reinserting = 1;
176}
177
178void
179reinsert_breakpoint (CORE_ADDR stopped_at)
180{
181 struct breakpoint *bp;
182
183 bp = find_breakpoint_at (stopped_at);
184 if (bp == NULL)
185 error ("Could not find breakpoint in list (uninserting).");
186 if (! bp->reinserting)
187 error ("Breakpoint already inserted at reinsert time.");
188
189 (*the_target->write_memory) (bp->pc, breakpoint_data,
190 breakpoint_len);
191 bp->reinserting = 0;
192}
193
194int
195check_breakpoints (CORE_ADDR stop_pc)
196{
197 struct breakpoint *bp;
198
199 bp = find_breakpoint_at (stop_pc);
200 if (bp == NULL)
201 return 0;
202 if (bp->reinserting)
203 {
204 warning ("Hit a removed breakpoint?");
205 return 0;
206 }
207
b65d95c5
DJ
208 if ((*bp->handler) (bp->pc))
209 {
210 delete_breakpoint (bp);
211 return 2;
212 }
213 else
214 return 1;
611cb4a5
DJ
215}
216
217void
f450004a 218set_breakpoint_data (const unsigned char *bp_data, int bp_len)
611cb4a5
DJ
219{
220 breakpoint_data = bp_data;
221 breakpoint_len = bp_len;
222}
223
224void
f450004a 225check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
226{
227 struct breakpoint *bp = breakpoints;
228 CORE_ADDR mem_end = mem_addr + mem_len;
229
230 for (; bp != NULL; bp = bp->next)
231 {
232 CORE_ADDR bp_end = bp->pc + breakpoint_len;
233 CORE_ADDR start, end;
234 int copy_offset, copy_len, buf_offset;
235
236 if (mem_addr >= bp_end)
237 continue;
238 if (bp->pc >= mem_end)
239 continue;
240
241 start = bp->pc;
242 if (mem_addr > start)
243 start = mem_addr;
244
245 end = bp_end;
246 if (end > mem_end)
247 end = mem_end;
248
249 copy_len = end - start;
250 copy_offset = start - bp->pc;
251 buf_offset = start - mem_addr;
252
253 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
254 }
255}
256
257void
f450004a 258check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
259{
260 struct breakpoint *bp = breakpoints;
261 CORE_ADDR mem_end = mem_addr + mem_len;
262
263 for (; bp != NULL; bp = bp->next)
264 {
265 CORE_ADDR bp_end = bp->pc + breakpoint_len;
266 CORE_ADDR start, end;
267 int copy_offset, copy_len, buf_offset;
268
269 if (mem_addr >= bp_end)
270 continue;
271 if (bp->pc >= mem_end)
272 continue;
273
274 start = bp->pc;
275 if (mem_addr > start)
276 start = mem_addr;
277
278 end = bp_end;
279 if (end > mem_end)
280 end = mem_end;
281
282 copy_len = end - start;
283 copy_offset = start - bp->pc;
284 buf_offset = start - mem_addr;
285
286 memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
287 if (bp->reinserting == 0)
288 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
289 }
290}
ae13219e
DJ
291
292/* Delete all breakpoints. */
293
294void
295delete_all_breakpoints (void)
296{
297 while (breakpoints)
298 delete_breakpoint (breakpoints);
299}
This page took 0.412695 seconds and 4 git commands to generate.