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