40d421c122f6bb3c411e2979ed2476dd77400753
[deliverable/binutils-gdb.git] / gdb / gdbserver / mem-break.c
1 /* Memory breakpoint operations for the remote server for GDB.
2 Copyright (C) 2002, 2003, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
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
11 the Free Software Foundation; either version 3 of the License, or
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "server.h"
23
24 const unsigned char *breakpoint_data;
25 int breakpoint_len;
26
27 #define MAX_BREAKPOINT_LEN 8
28
29 struct breakpoint
30 {
31 struct breakpoint *next;
32 CORE_ADDR pc;
33 unsigned char old_data[MAX_BREAKPOINT_LEN];
34
35 /* Non-zero if this breakpoint is currently inserted in the
36 inferior. */
37 int inserted;
38
39 /* Function to call when we hit this breakpoint. If it returns 1,
40 the breakpoint shall be deleted; 0, it will be left inserted. */
41 int (*handler) (CORE_ADDR);
42 };
43
44 static struct breakpoint *
45 set_raw_breakpoint_at (CORE_ADDR where)
46 {
47 struct process_info *proc = current_process ();
48 struct breakpoint *bp;
49 int err;
50
51 if (breakpoint_data == NULL)
52 error ("Target does not support breakpoints.");
53
54 bp = xcalloc (1, sizeof (*bp));
55 bp->pc = where;
56
57 err = (*the_target->read_memory) (where, bp->old_data,
58 breakpoint_len);
59 if (err != 0)
60 {
61 if (debug_threads)
62 fprintf (stderr,
63 "Failed to read shadow memory of"
64 " breakpoint at 0x%s (%s).\n",
65 paddress (where), strerror (err));
66 free (bp);
67 return NULL;
68 }
69
70 err = (*the_target->write_memory) (where, breakpoint_data,
71 breakpoint_len);
72 if (err != 0)
73 {
74 if (debug_threads)
75 fprintf (stderr,
76 "Failed to insert breakpoint at 0x%s (%s).\n",
77 paddress (where), strerror (err));
78 free (bp);
79 return NULL;
80 }
81
82 /* Link the breakpoint in. */
83 bp->inserted = 1;
84 bp->next = proc->breakpoints;
85 proc->breakpoints = bp;
86 return bp;
87 }
88
89 void
90 set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
91 {
92 struct process_info *proc = current_process ();
93 struct breakpoint *bp;
94
95 bp = set_raw_breakpoint_at (where);
96
97 if (bp == NULL)
98 {
99 /* warn? */
100 return;
101 }
102
103 bp = xcalloc (1, sizeof (struct breakpoint));
104 bp->handler = handler;
105
106 bp->next = proc->breakpoints;
107 proc->breakpoints = bp;
108 }
109
110 static void
111 delete_breakpoint (struct breakpoint *bp)
112 {
113 struct process_info *proc = current_process ();
114 struct breakpoint *cur;
115
116 if (proc->breakpoints == bp)
117 {
118 proc->breakpoints = bp->next;
119 (*the_target->write_memory) (bp->pc, bp->old_data,
120 breakpoint_len);
121 free (bp);
122 return;
123 }
124 cur = proc->breakpoints;
125 while (cur->next)
126 {
127 if (cur->next == bp)
128 {
129 cur->next = bp->next;
130 (*the_target->write_memory) (bp->pc, bp->old_data,
131 breakpoint_len);
132 free (bp);
133 return;
134 }
135 }
136 warning ("Could not find breakpoint in list.");
137 }
138
139 static struct breakpoint *
140 find_breakpoint_at (CORE_ADDR where)
141 {
142 struct process_info *proc = current_process ();
143 struct breakpoint *bp = proc->breakpoints;
144
145 while (bp != NULL)
146 {
147 if (bp->pc == where)
148 return bp;
149 bp = bp->next;
150 }
151
152 return NULL;
153 }
154
155 void
156 delete_breakpoint_at (CORE_ADDR addr)
157 {
158 struct breakpoint *bp = find_breakpoint_at (addr);
159 if (bp != NULL)
160 delete_breakpoint (bp);
161 }
162
163 void
164 set_reinsert_breakpoint (CORE_ADDR stop_at)
165 {
166 set_breakpoint_at (stop_at, NULL);
167 }
168
169 void
170 delete_reinsert_breakpoints (void)
171 {
172 struct process_info *proc = current_process ();
173 struct breakpoint *bp, **bp_link;
174
175 bp = proc->breakpoints;
176 bp_link = &proc->breakpoints;
177
178 while (bp)
179 {
180 *bp_link = bp->next;
181 delete_breakpoint (bp);
182 bp = *bp_link;
183 }
184 }
185
186 static void
187 uninsert_breakpoint (struct breakpoint *bp)
188 {
189 if (bp->inserted)
190 {
191 int err;
192
193 bp->inserted = 0;
194 err = (*the_target->write_memory) (bp->pc, bp->old_data,
195 breakpoint_len);
196 if (err != 0)
197 {
198 bp->inserted = 1;
199
200 if (debug_threads)
201 fprintf (stderr,
202 "Failed to uninsert raw breakpoint at 0x%s (%s).\n",
203 paddress (bp->pc), strerror (err));
204 }
205 }
206 }
207
208 void
209 uninsert_breakpoints_at (CORE_ADDR pc)
210 {
211 struct breakpoint *bp;
212
213 bp = find_breakpoint_at (pc);
214 if (bp == NULL)
215 {
216 /* This can happen when we remove all breakpoints while handling
217 a step-over. */
218 if (debug_threads)
219 fprintf (stderr,
220 "Could not find breakpoint at 0x%s "
221 "in list (uninserting).\n",
222 paddress (pc));
223 return;
224 }
225
226 if (bp->inserted)
227 uninsert_breakpoint (bp);
228 }
229
230 static void
231 reinsert_breakpoint (struct breakpoint *bp)
232 {
233 int err;
234
235 if (bp->inserted)
236 error ("Breakpoint already inserted at reinsert time.");
237
238 err = (*the_target->write_memory) (bp->pc, breakpoint_data,
239 breakpoint_len);
240 if (err == 0)
241 bp->inserted = 1;
242 else if (debug_threads)
243 fprintf (stderr,
244 "Failed to reinsert breakpoint at 0x%s (%s).\n",
245 paddress (bp->pc), strerror (err));
246 }
247
248 void
249 reinsert_breakpoints_at (CORE_ADDR pc)
250 {
251 struct breakpoint *bp;
252
253 bp = find_breakpoint_at (pc);
254 if (bp == NULL)
255 {
256 /* This can happen when we remove all breakpoints while handling
257 a step-over. */
258 if (debug_threads)
259 fprintf (stderr,
260 "Could not find breakpoint at 0x%s "
261 "in list (reinserting).\n",
262 paddress (pc));
263 return;
264 }
265
266 reinsert_breakpoint (bp);
267 }
268
269 void
270 check_breakpoints (CORE_ADDR stop_pc)
271 {
272 struct process_info *proc = current_process ();
273 struct breakpoint *bp, **bp_link;
274
275 bp = proc->breakpoints;
276 bp_link = &proc->breakpoints;
277
278 while (bp)
279 {
280 if (bp->pc == stop_pc)
281 {
282 if (!bp->inserted)
283 {
284 warning ("Hit a removed breakpoint?");
285 return;
286 }
287
288 if (bp->handler != NULL && (*bp->handler) (stop_pc))
289 {
290 *bp_link = bp->next;
291
292 delete_breakpoint (bp);
293
294 bp = *bp_link;
295 continue;
296 }
297 }
298
299 bp_link = &bp->next;
300 bp = *bp_link;
301 }
302 }
303
304 void
305 set_breakpoint_data (const unsigned char *bp_data, int bp_len)
306 {
307 breakpoint_data = bp_data;
308 breakpoint_len = bp_len;
309 }
310
311 int
312 breakpoint_here (CORE_ADDR addr)
313 {
314 struct process_info *proc = current_process ();
315 struct breakpoint *bp;
316
317 for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
318 if (bp->pc == addr)
319 return 1;
320
321 return 0;
322 }
323
324 int
325 breakpoint_inserted_here (CORE_ADDR addr)
326 {
327 struct process_info *proc = current_process ();
328 struct breakpoint *bp;
329
330 for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
331 if (bp->pc == addr && bp->inserted)
332 return 1;
333
334 return 0;
335 }
336
337 void
338 check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
339 {
340 struct process_info *proc = current_process ();
341 struct breakpoint *bp = proc->breakpoints;
342 CORE_ADDR mem_end = mem_addr + mem_len;
343
344 for (; bp != NULL; bp = bp->next)
345 {
346 CORE_ADDR bp_end = bp->pc + breakpoint_len;
347 CORE_ADDR start, end;
348 int copy_offset, copy_len, buf_offset;
349
350 if (mem_addr >= bp_end)
351 continue;
352 if (bp->pc >= mem_end)
353 continue;
354
355 start = bp->pc;
356 if (mem_addr > start)
357 start = mem_addr;
358
359 end = bp_end;
360 if (end > mem_end)
361 end = mem_end;
362
363 copy_len = end - start;
364 copy_offset = start - bp->pc;
365 buf_offset = start - mem_addr;
366
367 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
368 }
369 }
370
371 void
372 check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
373 {
374 struct process_info *proc = current_process ();
375 struct breakpoint *bp = proc->breakpoints;
376 CORE_ADDR mem_end = mem_addr + mem_len;
377
378 for (; bp != NULL; bp = bp->next)
379 {
380 CORE_ADDR bp_end = bp->pc + breakpoint_len;
381 CORE_ADDR start, end;
382 int copy_offset, copy_len, buf_offset;
383
384 if (mem_addr >= bp_end)
385 continue;
386 if (bp->pc >= mem_end)
387 continue;
388
389 start = bp->pc;
390 if (mem_addr > start)
391 start = mem_addr;
392
393 end = bp_end;
394 if (end > mem_end)
395 end = mem_end;
396
397 copy_len = end - start;
398 copy_offset = start - bp->pc;
399 buf_offset = start - mem_addr;
400
401 memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
402 if (bp->inserted)
403 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
404 }
405 }
406
407 /* Delete all breakpoints, and un-insert them from the inferior. */
408
409 void
410 delete_all_breakpoints (void)
411 {
412 struct process_info *proc = current_process ();
413
414 while (proc->breakpoints)
415 delete_breakpoint (proc->breakpoints);
416 }
417
418 /* Release all breakpoints, but do not try to un-insert them from the
419 inferior. */
420
421 void
422 free_all_breakpoints (struct process_info *proc)
423 {
424 struct breakpoint *bp;
425
426 while (proc->breakpoints)
427 {
428 bp = proc->breakpoints;
429 proc->breakpoints = bp->next;
430 free (bp);
431 }
432 }
This page took 0.041527 seconds and 4 git commands to generate.