]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/mem-break.c
Switch the license of all .c files to GPLv3.
[thirdparty/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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
611cb4a5
DJ
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
611cb4a5
DJ
20
21#include "server.h"
22
f450004a 23const unsigned char *breakpoint_data;
611cb4a5
DJ
24int breakpoint_len;
25
26#define MAX_BREAKPOINT_LEN 8
27
28struct breakpoint
29{
30 struct breakpoint *next;
31 CORE_ADDR pc;
32 unsigned char old_data[MAX_BREAKPOINT_LEN];
33
34 /* Non-zero iff we are stepping over this breakpoint. */
35 int reinserting;
36
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;
41
42 /* Function to call when we hit this breakpoint. */
43 void (*handler) (CORE_ADDR);
44};
45
46struct breakpoint *breakpoints;
47
48void
49set_breakpoint_at (CORE_ADDR where, void (*handler) (CORE_ADDR))
50{
51 struct breakpoint *bp;
52
53 if (breakpoint_data == NULL)
54 error ("Target does not support breakpoints.");
55
56 bp = malloc (sizeof (struct breakpoint));
57 memset (bp, 0, sizeof (struct breakpoint));
58
59 (*the_target->read_memory) (where, bp->old_data,
60 breakpoint_len);
61 (*the_target->write_memory) (where, breakpoint_data,
62 breakpoint_len);
63
64 bp->pc = where;
65 bp->handler = handler;
66
67 bp->next = breakpoints;
68 breakpoints = bp;
69}
70
71static void
72delete_breakpoint (struct breakpoint *bp)
73{
74 struct breakpoint *cur;
75
76 if (breakpoints == bp)
77 {
78 breakpoints = bp->next;
79 (*the_target->write_memory) (bp->pc, bp->old_data,
80 breakpoint_len);
81 free (bp);
82 return;
83 }
84 cur = breakpoints;
85 while (cur->next)
86 {
87 if (cur->next == bp)
88 {
89 cur->next = bp->next;
90 (*the_target->write_memory) (bp->pc, bp->old_data,
91 breakpoint_len);
92 free (bp);
93 return;
94 }
95 }
96 warning ("Could not find breakpoint in list.");
97}
98
99static struct breakpoint *
100find_breakpoint_at (CORE_ADDR where)
101{
102 struct breakpoint *bp = breakpoints;
103
104 while (bp != NULL)
105 {
106 if (bp->pc == where)
107 return bp;
108 bp = bp->next;
109 }
110
111 return NULL;
112}
113
68070c10
PA
114void
115delete_breakpoint_at (CORE_ADDR addr)
116{
117 struct breakpoint *bp = find_breakpoint_at (addr);
118 if (bp != NULL)
119 delete_breakpoint (bp);
120}
121
611cb4a5
DJ
122static void
123reinsert_breakpoint_handler (CORE_ADDR stop_pc)
124{
125 struct breakpoint *stop_bp, *orig_bp;
126
127 stop_bp = find_breakpoint_at (stop_pc);
128 if (stop_bp == NULL)
129 error ("lost the stopping breakpoint.");
130
131 orig_bp = stop_bp->breakpoint_to_reinsert;
132 if (orig_bp == NULL)
133 error ("no breakpoint to reinsert");
134
135 (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
136 breakpoint_len);
137 orig_bp->reinserting = 0;
138 delete_breakpoint (stop_bp);
139}
140
141void
142reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
143{
144 struct breakpoint *bp, *orig_bp;
145
146 set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
147
fd3a5ca1 148 orig_bp = find_breakpoint_at (stop_pc);
611cb4a5
DJ
149 if (orig_bp == NULL)
150 error ("Could not find original breakpoint in list.");
151
152 bp = find_breakpoint_at (stop_at);
153 if (bp == NULL)
154 error ("Could not find breakpoint in list (reinserting by breakpoint).");
155 bp->breakpoint_to_reinsert = orig_bp;
156
157 (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
158 breakpoint_len);
159 orig_bp->reinserting = 1;
160}
161
162void
163uninsert_breakpoint (CORE_ADDR stopped_at)
164{
165 struct breakpoint *bp;
166
167 bp = find_breakpoint_at (stopped_at);
168 if (bp == NULL)
169 error ("Could not find breakpoint in list (uninserting).");
170
171 (*the_target->write_memory) (bp->pc, bp->old_data,
172 breakpoint_len);
173 bp->reinserting = 1;
174}
175
176void
177reinsert_breakpoint (CORE_ADDR stopped_at)
178{
179 struct breakpoint *bp;
180
181 bp = find_breakpoint_at (stopped_at);
182 if (bp == NULL)
183 error ("Could not find breakpoint in list (uninserting).");
184 if (! bp->reinserting)
185 error ("Breakpoint already inserted at reinsert time.");
186
187 (*the_target->write_memory) (bp->pc, breakpoint_data,
188 breakpoint_len);
189 bp->reinserting = 0;
190}
191
192int
193check_breakpoints (CORE_ADDR stop_pc)
194{
195 struct breakpoint *bp;
196
197 bp = find_breakpoint_at (stop_pc);
198 if (bp == NULL)
199 return 0;
200 if (bp->reinserting)
201 {
202 warning ("Hit a removed breakpoint?");
203 return 0;
204 }
205
206 (*bp->handler) (bp->pc);
207 return 1;
208}
209
210void
f450004a 211set_breakpoint_data (const unsigned char *bp_data, int bp_len)
611cb4a5
DJ
212{
213 breakpoint_data = bp_data;
214 breakpoint_len = bp_len;
215}
216
217void
f450004a 218check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
219{
220 struct breakpoint *bp = breakpoints;
221 CORE_ADDR mem_end = mem_addr + mem_len;
222
223 for (; bp != NULL; bp = bp->next)
224 {
225 CORE_ADDR bp_end = bp->pc + breakpoint_len;
226 CORE_ADDR start, end;
227 int copy_offset, copy_len, buf_offset;
228
229 if (mem_addr >= bp_end)
230 continue;
231 if (bp->pc >= mem_end)
232 continue;
233
234 start = bp->pc;
235 if (mem_addr > start)
236 start = mem_addr;
237
238 end = bp_end;
239 if (end > mem_end)
240 end = mem_end;
241
242 copy_len = end - start;
243 copy_offset = start - bp->pc;
244 buf_offset = start - mem_addr;
245
246 memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
247 }
248}
249
250void
f450004a 251check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
611cb4a5
DJ
252{
253 struct breakpoint *bp = breakpoints;
254 CORE_ADDR mem_end = mem_addr + mem_len;
255
256 for (; bp != NULL; bp = bp->next)
257 {
258 CORE_ADDR bp_end = bp->pc + breakpoint_len;
259 CORE_ADDR start, end;
260 int copy_offset, copy_len, buf_offset;
261
262 if (mem_addr >= bp_end)
263 continue;
264 if (bp->pc >= mem_end)
265 continue;
266
267 start = bp->pc;
268 if (mem_addr > start)
269 start = mem_addr;
270
271 end = bp_end;
272 if (end > mem_end)
273 end = mem_end;
274
275 copy_len = end - start;
276 copy_offset = start - bp->pc;
277 buf_offset = start - mem_addr;
278
279 memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
280 if (bp->reinserting == 0)
281 memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
282 }
283}
ae13219e
DJ
284
285/* Delete all breakpoints. */
286
287void
288delete_all_breakpoints (void)
289{
290 while (breakpoints)
291 delete_breakpoint (breakpoints);
292}