* gdb.base/macscp.exp (objfile): Move it to ${objdir}/${subdir}/.
[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
49struct breakpoint *breakpoints;
50
51void
b65d95c5 52set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
611cb4a5
DJ
53{
54 struct breakpoint *bp;
55
56 if (breakpoint_data == NULL)
57 error ("Target does not support breakpoints.");
58
bca929d3 59 bp = xmalloc (sizeof (struct breakpoint));
611cb4a5
DJ
60 memset (bp, 0, sizeof (struct breakpoint));
61
62 (*the_target->read_memory) (where, bp->old_data,
63 breakpoint_len);
64 (*the_target->write_memory) (where, breakpoint_data,
65 breakpoint_len);
66
67 bp->pc = where;
68 bp->handler = handler;
69
70 bp->next = breakpoints;
71 breakpoints = bp;
72}
73
74static void
75delete_breakpoint (struct breakpoint *bp)
76{
77 struct breakpoint *cur;
78
79 if (breakpoints == bp)
80 {
81 breakpoints = bp->next;
82 (*the_target->write_memory) (bp->pc, bp->old_data,
83 breakpoint_len);
84 free (bp);
85 return;
86 }
87 cur = breakpoints;
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{
105 struct breakpoint *bp = breakpoints;
106
107 while (bp != NULL)
108 {
109 if (bp->pc == where)
110 return bp;
111 bp = bp->next;
112 }
113
114 return NULL;
115}
116
68070c10
PA
117void
118delete_breakpoint_at (CORE_ADDR addr)
119{
120 struct breakpoint *bp = find_breakpoint_at (addr);
121 if (bp != NULL)
122 delete_breakpoint (bp);
123}
124
b65d95c5 125static int
611cb4a5
DJ
126reinsert_breakpoint_handler (CORE_ADDR stop_pc)
127{
128 struct breakpoint *stop_bp, *orig_bp;
129
130 stop_bp = find_breakpoint_at (stop_pc);
131 if (stop_bp == NULL)
132 error ("lost the stopping breakpoint.");
133
134 orig_bp = stop_bp->breakpoint_to_reinsert;
135 if (orig_bp == NULL)
136 error ("no breakpoint to reinsert");
137
138 (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
139 breakpoint_len);
140 orig_bp->reinserting = 0;
b65d95c5 141 return 1;
611cb4a5
DJ
142}
143
144void
145reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
146{
147 struct breakpoint *bp, *orig_bp;
148
fd3a5ca1 149 orig_bp = find_breakpoint_at (stop_pc);
611cb4a5
DJ
150 if (orig_bp == NULL)
151 error ("Could not find original breakpoint in list.");
152
b65d95c5
DJ
153 set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
154
611cb4a5
DJ
155 bp = find_breakpoint_at (stop_at);
156 if (bp == NULL)
157 error ("Could not find breakpoint in list (reinserting by breakpoint).");
158 bp->breakpoint_to_reinsert = orig_bp;
159
160 (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
161 breakpoint_len);
162 orig_bp->reinserting = 1;
163}
164
165void
166uninsert_breakpoint (CORE_ADDR stopped_at)
167{
168 struct breakpoint *bp;
169
170 bp = find_breakpoint_at (stopped_at);
171 if (bp == NULL)
172 error ("Could not find breakpoint in list (uninserting).");
173
174 (*the_target->write_memory) (bp->pc, bp->old_data,
175 breakpoint_len);
176 bp->reinserting = 1;
177}
178
179void
180reinsert_breakpoint (CORE_ADDR stopped_at)
181{
182 struct breakpoint *bp;
183
184 bp = find_breakpoint_at (stopped_at);
185 if (bp == NULL)
186 error ("Could not find breakpoint in list (uninserting).");
187 if (! bp->reinserting)
188 error ("Breakpoint already inserted at reinsert time.");
189
190 (*the_target->write_memory) (bp->pc, breakpoint_data,
191 breakpoint_len);
192 bp->reinserting = 0;
193}
194
195int
196check_breakpoints (CORE_ADDR stop_pc)
197{
198 struct breakpoint *bp;
199
200 bp = find_breakpoint_at (stop_pc);
201 if (bp == NULL)
202 return 0;
203 if (bp->reinserting)
204 {
205 warning ("Hit a removed breakpoint?");
206 return 0;
207 }
208
b65d95c5
DJ
209 if ((*bp->handler) (bp->pc))
210 {
211 delete_breakpoint (bp);
212 return 2;
213 }
214 else
215 return 1;
611cb4a5
DJ
216}
217
218void
f450004a 219set_breakpoint_data (const unsigned char *bp_data, int bp_len)
611cb4a5
DJ
220{
221 breakpoint_data = bp_data;
222 breakpoint_len = bp_len;
223}
224
225void
f450004a 226check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
227{
228 struct breakpoint *bp = breakpoints;
229 CORE_ADDR mem_end = mem_addr + mem_len;
230
231 for (; bp != NULL; bp = bp->next)
232 {
233 CORE_ADDR bp_end = bp->pc + breakpoint_len;
234 CORE_ADDR start, end;
235 int copy_offset, copy_len, buf_offset;
236
237 if (mem_addr >= bp_end)
238 continue;
239 if (bp->pc >= mem_end)
240 continue;
241
242 start = bp->pc;
243 if (mem_addr > start)
244 start = mem_addr;
245
246 end = bp_end;
247 if (end > mem_end)
248 end = mem_end;
249
250 copy_len = end - start;
251 copy_offset = start - bp->pc;
252 buf_offset = start - mem_addr;
253
254 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
255 }
256}
257
258void
f450004a 259check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
260{
261 struct breakpoint *bp = breakpoints;
262 CORE_ADDR mem_end = mem_addr + mem_len;
263
264 for (; bp != NULL; bp = bp->next)
265 {
266 CORE_ADDR bp_end = bp->pc + breakpoint_len;
267 CORE_ADDR start, end;
268 int copy_offset, copy_len, buf_offset;
269
270 if (mem_addr >= bp_end)
271 continue;
272 if (bp->pc >= mem_end)
273 continue;
274
275 start = bp->pc;
276 if (mem_addr > start)
277 start = mem_addr;
278
279 end = bp_end;
280 if (end > mem_end)
281 end = mem_end;
282
283 copy_len = end - start;
284 copy_offset = start - bp->pc;
285 buf_offset = start - mem_addr;
286
287 memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
288 if (bp->reinserting == 0)
289 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
290 }
291}
ae13219e
DJ
292
293/* Delete all breakpoints. */
294
295void
296delete_all_breakpoints (void)
297{
298 while (breakpoints)
299 delete_breakpoint (breakpoints);
300}
This page took 0.484343 seconds and 4 git commands to generate.