1 /* Memory breakpoint operations for the remote server for GDB.
2 Copyright (C) 2002, 2003, 2005, 2007 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 2 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, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
25 const unsigned char *breakpoint_data
;
28 #define MAX_BREAKPOINT_LEN 8
32 struct breakpoint
*next
;
34 unsigned char old_data
[MAX_BREAKPOINT_LEN
];
36 /* Non-zero iff we are stepping over this breakpoint. */
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
;
44 /* Function to call when we hit this breakpoint. */
45 void (*handler
) (CORE_ADDR
);
48 struct breakpoint
*breakpoints
;
51 set_breakpoint_at (CORE_ADDR where
, void (*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;
140 delete_breakpoint (stop_bp
);
144 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc
, CORE_ADDR stop_at
)
146 struct breakpoint
*bp
, *orig_bp
;
148 set_breakpoint_at (stop_at
, reinsert_breakpoint_handler
);
150 orig_bp
= find_breakpoint_at (stop_pc
);
152 error ("Could not find original breakpoint in list.");
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 (*bp
->handler
) (bp
->pc
);
213 set_breakpoint_data (const unsigned char *bp_data
, int bp_len
)
215 breakpoint_data
= bp_data
;
216 breakpoint_len
= bp_len
;
220 check_mem_read (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
222 struct breakpoint
*bp
= breakpoints
;
223 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
225 for (; bp
!= NULL
; bp
= bp
->next
)
227 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
228 CORE_ADDR start
, end
;
229 int copy_offset
, copy_len
, buf_offset
;
231 if (mem_addr
>= bp_end
)
233 if (bp
->pc
>= mem_end
)
237 if (mem_addr
> start
)
244 copy_len
= end
- start
;
245 copy_offset
= start
- bp
->pc
;
246 buf_offset
= start
- mem_addr
;
248 memcpy (buf
+ buf_offset
, bp
->old_data
+ copy_offset
, copy_len
);
253 check_mem_write (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
255 struct breakpoint
*bp
= breakpoints
;
256 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
258 for (; bp
!= NULL
; bp
= bp
->next
)
260 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
261 CORE_ADDR start
, end
;
262 int copy_offset
, copy_len
, buf_offset
;
264 if (mem_addr
>= bp_end
)
266 if (bp
->pc
>= mem_end
)
270 if (mem_addr
> start
)
277 copy_len
= end
- start
;
278 copy_offset
= start
- bp
->pc
;
279 buf_offset
= start
- mem_addr
;
281 memcpy (bp
->old_data
+ copy_offset
, buf
+ buf_offset
, copy_len
);
282 if (bp
->reinserting
== 0)
283 memcpy (buf
+ buf_offset
, breakpoint_data
+ copy_offset
, copy_len
);