Teach linux gdbserver to step-over-breakpoints.
[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
29struct breakpoint
30{
31 struct breakpoint *next;
32 CORE_ADDR pc;
33 unsigned char old_data[MAX_BREAKPOINT_LEN];
34
d50171e4
PA
35 /* Non-zero if this breakpoint is currently inserted in the
36 inferior. */
37 int inserted;
611cb4a5 38
b65d95c5 39 /* Function to call when we hit this breakpoint. If it returns 1,
d50171e4 40 the breakpoint shall be deleted; 0, it will be left inserted. */
b65d95c5 41 int (*handler) (CORE_ADDR);
611cb4a5
DJ
42};
43
d50171e4
PA
44static struct breakpoint *
45set_raw_breakpoint_at (CORE_ADDR where)
611cb4a5 46{
95954743 47 struct process_info *proc = current_process ();
611cb4a5 48 struct breakpoint *bp;
d50171e4 49 int err;
611cb4a5
DJ
50
51 if (breakpoint_data == NULL)
52 error ("Target does not support breakpoints.");
53
d50171e4
PA
54 bp = xcalloc (1, sizeof (*bp));
55 bp->pc = where;
611cb4a5 56
d50171e4
PA
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 }
611cb4a5 69
d50171e4
PA
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
89void
90set_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));
611cb4a5
DJ
104 bp->handler = handler;
105
95954743
PA
106 bp->next = proc->breakpoints;
107 proc->breakpoints = bp;
611cb4a5
DJ
108}
109
110static void
111delete_breakpoint (struct breakpoint *bp)
112{
95954743 113 struct process_info *proc = current_process ();
611cb4a5
DJ
114 struct breakpoint *cur;
115
95954743 116 if (proc->breakpoints == bp)
611cb4a5 117 {
95954743 118 proc->breakpoints = bp->next;
611cb4a5
DJ
119 (*the_target->write_memory) (bp->pc, bp->old_data,
120 breakpoint_len);
121 free (bp);
122 return;
123 }
95954743 124 cur = proc->breakpoints;
611cb4a5
DJ
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
139static struct breakpoint *
140find_breakpoint_at (CORE_ADDR where)
141{
95954743
PA
142 struct process_info *proc = current_process ();
143 struct breakpoint *bp = proc->breakpoints;
611cb4a5
DJ
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
68070c10
PA
155void
156delete_breakpoint_at (CORE_ADDR addr)
157{
158 struct breakpoint *bp = find_breakpoint_at (addr);
159 if (bp != NULL)
160 delete_breakpoint (bp);
161}
162
d50171e4
PA
163void
164set_reinsert_breakpoint (CORE_ADDR stop_at)
611cb4a5 165{
d50171e4 166 set_breakpoint_at (stop_at, NULL);
611cb4a5
DJ
167}
168
169void
d50171e4 170delete_reinsert_breakpoints (void)
611cb4a5 171{
d50171e4
PA
172 struct process_info *proc = current_process ();
173 struct breakpoint *bp, **bp_link;
611cb4a5 174
d50171e4
PA
175 bp = proc->breakpoints;
176 bp_link = &proc->breakpoints;
611cb4a5 177
d50171e4
PA
178 while (bp)
179 {
180 *bp_link = bp->next;
181 delete_breakpoint (bp);
182 bp = *bp_link;
183 }
184}
b65d95c5 185
d50171e4
PA
186static void
187uninsert_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;
611cb4a5 199
d50171e4
PA
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 }
611cb4a5
DJ
206}
207
208void
d50171e4 209uninsert_breakpoints_at (CORE_ADDR pc)
611cb4a5
DJ
210{
211 struct breakpoint *bp;
212
d50171e4 213 bp = find_breakpoint_at (pc);
611cb4a5 214 if (bp == NULL)
d50171e4
PA
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 }
611cb4a5 225
d50171e4
PA
226 if (bp->inserted)
227 uninsert_breakpoint (bp);
611cb4a5
DJ
228}
229
d50171e4
PA
230static void
231reinsert_breakpoint (struct breakpoint *bp)
611cb4a5 232{
d50171e4 233 int err;
611cb4a5 234
d50171e4 235 if (bp->inserted)
611cb4a5
DJ
236 error ("Breakpoint already inserted at reinsert time.");
237
d50171e4
PA
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));
611cb4a5
DJ
246}
247
d50171e4
PA
248void
249reinsert_breakpoints_at (CORE_ADDR pc)
611cb4a5
DJ
250{
251 struct breakpoint *bp;
252
d50171e4 253 bp = find_breakpoint_at (pc);
611cb4a5 254 if (bp == NULL)
611cb4a5 255 {
d50171e4
PA
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;
611cb4a5
DJ
264 }
265
d50171e4
PA
266 reinsert_breakpoint (bp);
267}
268
269void
270check_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)
b65d95c5 279 {
d50171e4
PA
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;
b65d95c5 301 }
611cb4a5
DJ
302}
303
304void
f450004a 305set_breakpoint_data (const unsigned char *bp_data, int bp_len)
611cb4a5
DJ
306{
307 breakpoint_data = bp_data;
308 breakpoint_len = bp_len;
309}
310
d50171e4
PA
311int
312breakpoint_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
324int
325breakpoint_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
611cb4a5 337void
f450004a 338check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5 339{
95954743
PA
340 struct process_info *proc = current_process ();
341 struct breakpoint *bp = proc->breakpoints;
611cb4a5
DJ
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
371void
f450004a 372check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5 373{
95954743
PA
374 struct process_info *proc = current_process ();
375 struct breakpoint *bp = proc->breakpoints;
611cb4a5
DJ
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);
d50171e4 402 if (bp->inserted)
611cb4a5
DJ
403 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
404 }
405}
ae13219e 406
95954743 407/* Delete all breakpoints, and un-insert them from the inferior. */
ae13219e
DJ
408
409void
410delete_all_breakpoints (void)
411{
95954743
PA
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
421void
422free_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 }
ae13219e 432}
This page took 0.581978 seconds and 4 git commands to generate.