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