1 /* Memory breakpoint operations for the remote server for GDB.
2 Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
4 Contributed by MontaVista Software.
6 This file is part of GDB.
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
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 const unsigned char *breakpoint_data;
26 #define MAX_BREAKPOINT_LEN 8
30 struct breakpoint *next;
32 unsigned char old_data[MAX_BREAKPOINT_LEN];
34 /* Non-zero iff we are stepping over this breakpoint. */
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;
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
45 int (*handler) (CORE_ADDR);
48 struct breakpoint *breakpoints;
51 set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
53 struct breakpoint *bp;
55 if (breakpoint_data == NULL)
56 error ("Target does not support breakpoints.");
58 bp = malloc (sizeof (struct breakpoint));
59 memset (bp, 0, sizeof (struct breakpoint));
61 (*the_target->read_memory) (where, bp->old_data,
63 (*the_target->write_memory) (where, breakpoint_data,
67 bp->handler = handler;
69 bp->next = breakpoints;
74 delete_breakpoint (struct breakpoint *bp)
76 struct breakpoint *cur;
78 if (breakpoints == bp)
80 breakpoints = bp->next;
81 (*the_target->write_memory) (bp->pc, bp->old_data,
92 (*the_target->write_memory) (bp->pc, bp->old_data,
98 warning ("Could not find breakpoint in list.");
101 static struct breakpoint *
102 find_breakpoint_at (CORE_ADDR where)
104 struct breakpoint *bp = breakpoints;
117 delete_breakpoint_at (CORE_ADDR addr)
119 struct breakpoint *bp = find_breakpoint_at (addr);
121 delete_breakpoint (bp);
125 reinsert_breakpoint_handler (CORE_ADDR stop_pc)
127 struct breakpoint *stop_bp, *orig_bp;
129 stop_bp = find_breakpoint_at (stop_pc);
131 error ("lost the stopping breakpoint.");
133 orig_bp = stop_bp->breakpoint_to_reinsert;
135 error ("no breakpoint to reinsert");
137 (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
139 orig_bp->reinserting = 0;
144 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
146 struct breakpoint *bp, *orig_bp;
148 orig_bp = find_breakpoint_at (stop_pc);
150 error ("Could not find original breakpoint in list.");
152 set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
154 bp = find_breakpoint_at (stop_at);
156 error ("Could not find breakpoint in list (reinserting by breakpoint).");
157 bp->breakpoint_to_reinsert = orig_bp;
159 (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
161 orig_bp->reinserting = 1;
165 uninsert_breakpoint (CORE_ADDR stopped_at)
167 struct breakpoint *bp;
169 bp = find_breakpoint_at (stopped_at);
171 error ("Could not find breakpoint in list (uninserting).");
173 (*the_target->write_memory) (bp->pc, bp->old_data,
179 reinsert_breakpoint (CORE_ADDR stopped_at)
181 struct breakpoint *bp;
183 bp = find_breakpoint_at (stopped_at);
185 error ("Could not find breakpoint in list (uninserting).");
186 if (! bp->reinserting)
187 error ("Breakpoint already inserted at reinsert time.");
189 (*the_target->write_memory) (bp->pc, breakpoint_data,
195 check_breakpoints (CORE_ADDR stop_pc)
197 struct breakpoint *bp;
199 bp = find_breakpoint_at (stop_pc);
204 warning ("Hit a removed breakpoint?");
208 if ((*bp->handler) (bp->pc))
210 delete_breakpoint (bp);
218 set_breakpoint_data (const unsigned char *bp_data, int bp_len)
220 breakpoint_data = bp_data;
221 breakpoint_len = bp_len;
225 check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
227 struct breakpoint *bp = breakpoints;
228 CORE_ADDR mem_end = mem_addr + mem_len;
230 for (; bp != NULL; bp = bp->next)
232 CORE_ADDR bp_end = bp->pc + breakpoint_len;
233 CORE_ADDR start, end;
234 int copy_offset, copy_len, buf_offset;
236 if (mem_addr >= bp_end)
238 if (bp->pc >= mem_end)
242 if (mem_addr > start)
249 copy_len = end - start;
250 copy_offset = start - bp->pc;
251 buf_offset = start - mem_addr;
253 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
258 check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
260 struct breakpoint *bp = breakpoints;
261 CORE_ADDR mem_end = mem_addr + mem_len;
263 for (; bp != NULL; bp = bp->next)
265 CORE_ADDR bp_end = bp->pc + breakpoint_len;
266 CORE_ADDR start, end;
267 int copy_offset, copy_len, buf_offset;
269 if (mem_addr >= bp_end)
271 if (bp->pc >= mem_end)
275 if (mem_addr > start)
282 copy_len = end - start;
283 copy_offset = start - bp->pc;
284 buf_offset = start - mem_addr;
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);
292 /* Delete all breakpoints. */
295 delete_all_breakpoints (void)
298 delete_breakpoint (breakpoints);