daily update
[deliverable/binutils-gdb.git] / gdb / gdbserver / mem-break.c
CommitLineData
611cb4a5 1/* Memory breakpoint operations for the remote server for GDB.
6aba47ca 2 Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
611cb4a5
DJ
3
4 Contributed by MontaVista Software.
5
6 This file is part of GDB.
7
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 2 of the License, or
11 (at your option) any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
6f0f660e
EZ
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
611cb4a5
DJ
22
23#include "server.h"
24
f450004a 25const unsigned char *breakpoint_data;
611cb4a5
DJ
26int breakpoint_len;
27
28#define MAX_BREAKPOINT_LEN 8
29
30struct breakpoint
31{
32 struct breakpoint *next;
33 CORE_ADDR pc;
34 unsigned char old_data[MAX_BREAKPOINT_LEN];
35
36 /* Non-zero iff we are stepping over this breakpoint. */
37 int reinserting;
38
39 /* Non-NULL iff this breakpoint was inserted to step over
40 another one. Points to the other breakpoint (which is also
41 in the *next chain somewhere). */
42 struct breakpoint *breakpoint_to_reinsert;
43
44 /* Function to call when we hit this breakpoint. */
45 void (*handler) (CORE_ADDR);
46};
47
48struct breakpoint *breakpoints;
49
50void
51set_breakpoint_at (CORE_ADDR where, void (*handler) (CORE_ADDR))
52{
53 struct breakpoint *bp;
54
55 if (breakpoint_data == NULL)
56 error ("Target does not support breakpoints.");
57
58 bp = malloc (sizeof (struct breakpoint));
59 memset (bp, 0, sizeof (struct breakpoint));
60
61 (*the_target->read_memory) (where, bp->old_data,
62 breakpoint_len);
63 (*the_target->write_memory) (where, breakpoint_data,
64 breakpoint_len);
65
66 bp->pc = where;
67 bp->handler = handler;
68
69 bp->next = breakpoints;
70 breakpoints = bp;
71}
72
73static void
74delete_breakpoint (struct breakpoint *bp)
75{
76 struct breakpoint *cur;
77
78 if (breakpoints == bp)
79 {
80 breakpoints = bp->next;
81 (*the_target->write_memory) (bp->pc, bp->old_data,
82 breakpoint_len);
83 free (bp);
84 return;
85 }
86 cur = breakpoints;
87 while (cur->next)
88 {
89 if (cur->next == bp)
90 {
91 cur->next = bp->next;
92 (*the_target->write_memory) (bp->pc, bp->old_data,
93 breakpoint_len);
94 free (bp);
95 return;
96 }
97 }
98 warning ("Could not find breakpoint in list.");
99}
100
101static struct breakpoint *
102find_breakpoint_at (CORE_ADDR where)
103{
104 struct breakpoint *bp = breakpoints;
105
106 while (bp != NULL)
107 {
108 if (bp->pc == where)
109 return bp;
110 bp = bp->next;
111 }
112
113 return NULL;
114}
115
116static void
117reinsert_breakpoint_handler (CORE_ADDR stop_pc)
118{
119 struct breakpoint *stop_bp, *orig_bp;
120
121 stop_bp = find_breakpoint_at (stop_pc);
122 if (stop_bp == NULL)
123 error ("lost the stopping breakpoint.");
124
125 orig_bp = stop_bp->breakpoint_to_reinsert;
126 if (orig_bp == NULL)
127 error ("no breakpoint to reinsert");
128
129 (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
130 breakpoint_len);
131 orig_bp->reinserting = 0;
132 delete_breakpoint (stop_bp);
133}
134
135void
136reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
137{
138 struct breakpoint *bp, *orig_bp;
139
140 set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
141
fd3a5ca1 142 orig_bp = find_breakpoint_at (stop_pc);
611cb4a5
DJ
143 if (orig_bp == NULL)
144 error ("Could not find original breakpoint in list.");
145
146 bp = find_breakpoint_at (stop_at);
147 if (bp == NULL)
148 error ("Could not find breakpoint in list (reinserting by breakpoint).");
149 bp->breakpoint_to_reinsert = orig_bp;
150
151 (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
152 breakpoint_len);
153 orig_bp->reinserting = 1;
154}
155
156void
157uninsert_breakpoint (CORE_ADDR stopped_at)
158{
159 struct breakpoint *bp;
160
161 bp = find_breakpoint_at (stopped_at);
162 if (bp == NULL)
163 error ("Could not find breakpoint in list (uninserting).");
164
165 (*the_target->write_memory) (bp->pc, bp->old_data,
166 breakpoint_len);
167 bp->reinserting = 1;
168}
169
170void
171reinsert_breakpoint (CORE_ADDR stopped_at)
172{
173 struct breakpoint *bp;
174
175 bp = find_breakpoint_at (stopped_at);
176 if (bp == NULL)
177 error ("Could not find breakpoint in list (uninserting).");
178 if (! bp->reinserting)
179 error ("Breakpoint already inserted at reinsert time.");
180
181 (*the_target->write_memory) (bp->pc, breakpoint_data,
182 breakpoint_len);
183 bp->reinserting = 0;
184}
185
186int
187check_breakpoints (CORE_ADDR stop_pc)
188{
189 struct breakpoint *bp;
190
191 bp = find_breakpoint_at (stop_pc);
192 if (bp == NULL)
193 return 0;
194 if (bp->reinserting)
195 {
196 warning ("Hit a removed breakpoint?");
197 return 0;
198 }
199
200 (*bp->handler) (bp->pc);
201 return 1;
202}
203
204void
f450004a 205set_breakpoint_data (const unsigned char *bp_data, int bp_len)
611cb4a5
DJ
206{
207 breakpoint_data = bp_data;
208 breakpoint_len = bp_len;
209}
210
211void
f450004a 212check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
213{
214 struct breakpoint *bp = breakpoints;
215 CORE_ADDR mem_end = mem_addr + mem_len;
216
217 for (; bp != NULL; bp = bp->next)
218 {
219 CORE_ADDR bp_end = bp->pc + breakpoint_len;
220 CORE_ADDR start, end;
221 int copy_offset, copy_len, buf_offset;
222
223 if (mem_addr >= bp_end)
224 continue;
225 if (bp->pc >= mem_end)
226 continue;
227
228 start = bp->pc;
229 if (mem_addr > start)
230 start = mem_addr;
231
232 end = bp_end;
233 if (end > mem_end)
234 end = mem_end;
235
236 copy_len = end - start;
237 copy_offset = start - bp->pc;
238 buf_offset = start - mem_addr;
239
240 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
241 }
242}
243
244void
f450004a 245check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
246{
247 struct breakpoint *bp = breakpoints;
248 CORE_ADDR mem_end = mem_addr + mem_len;
249
250 for (; bp != NULL; bp = bp->next)
251 {
252 CORE_ADDR bp_end = bp->pc + breakpoint_len;
253 CORE_ADDR start, end;
254 int copy_offset, copy_len, buf_offset;
255
256 if (mem_addr >= bp_end)
257 continue;
258 if (bp->pc >= mem_end)
259 continue;
260
261 start = bp->pc;
262 if (mem_addr > start)
263 start = mem_addr;
264
265 end = bp_end;
266 if (end > mem_end)
267 end = mem_end;
268
269 copy_len = end - start;
270 copy_offset = start - bp->pc;
271 buf_offset = start - mem_addr;
272
273 memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
274 if (bp->reinserting == 0)
275 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
276 }
277}
This page took 0.436242 seconds and 4 git commands to generate.