1 /* Memory breakpoint operations for the remote server for GDB.
2 Copyright (C) 2002, 2003, 2005, 2007, 2008, 2009
3 Free Software Foundation, Inc.
5 Contributed by MontaVista Software.
7 This file is part of GDB.
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
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 const unsigned char *breakpoint_data
;
27 #define MAX_BREAKPOINT_LEN 8
31 struct breakpoint
*next
;
33 unsigned char old_data
[MAX_BREAKPOINT_LEN
];
35 /* Non-zero iff we are stepping over this breakpoint. */
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
;
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
46 int (*handler
) (CORE_ADDR
);
49 struct breakpoint
*breakpoints
;
52 set_breakpoint_at (CORE_ADDR where
, int (*handler
) (CORE_ADDR
))
54 struct breakpoint
*bp
;
56 if (breakpoint_data
== NULL
)
57 error ("Target does not support breakpoints.");
59 bp
= xmalloc (sizeof (struct breakpoint
));
60 memset (bp
, 0, sizeof (struct breakpoint
));
62 (*the_target
->read_memory
) (where
, bp
->old_data
,
64 (*the_target
->write_memory
) (where
, breakpoint_data
,
68 bp
->handler
= handler
;
70 bp
->next
= breakpoints
;
75 delete_breakpoint (struct breakpoint
*bp
)
77 struct breakpoint
*cur
;
79 if (breakpoints
== bp
)
81 breakpoints
= bp
->next
;
82 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
93 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
99 warning ("Could not find breakpoint in list.");
102 static struct breakpoint
*
103 find_breakpoint_at (CORE_ADDR where
)
105 struct breakpoint
*bp
= breakpoints
;
118 delete_breakpoint_at (CORE_ADDR addr
)
120 struct breakpoint
*bp
= find_breakpoint_at (addr
);
122 delete_breakpoint (bp
);
126 reinsert_breakpoint_handler (CORE_ADDR stop_pc
)
128 struct breakpoint
*stop_bp
, *orig_bp
;
130 stop_bp
= find_breakpoint_at (stop_pc
);
132 error ("lost the stopping breakpoint.");
134 orig_bp
= stop_bp
->breakpoint_to_reinsert
;
136 error ("no breakpoint to reinsert");
138 (*the_target
->write_memory
) (orig_bp
->pc
, breakpoint_data
,
140 orig_bp
->reinserting
= 0;
145 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc
, CORE_ADDR stop_at
)
147 struct breakpoint
*bp
, *orig_bp
;
149 orig_bp
= find_breakpoint_at (stop_pc
);
151 error ("Could not find original breakpoint in list.");
153 set_breakpoint_at (stop_at
, reinsert_breakpoint_handler
);
155 bp
= find_breakpoint_at (stop_at
);
157 error ("Could not find breakpoint in list (reinserting by breakpoint).");
158 bp
->breakpoint_to_reinsert
= orig_bp
;
160 (*the_target
->write_memory
) (orig_bp
->pc
, orig_bp
->old_data
,
162 orig_bp
->reinserting
= 1;
166 uninsert_breakpoint (CORE_ADDR stopped_at
)
168 struct breakpoint
*bp
;
170 bp
= find_breakpoint_at (stopped_at
);
172 error ("Could not find breakpoint in list (uninserting).");
174 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
180 reinsert_breakpoint (CORE_ADDR stopped_at
)
182 struct breakpoint
*bp
;
184 bp
= find_breakpoint_at (stopped_at
);
186 error ("Could not find breakpoint in list (uninserting).");
187 if (! bp
->reinserting
)
188 error ("Breakpoint already inserted at reinsert time.");
190 (*the_target
->write_memory
) (bp
->pc
, breakpoint_data
,
196 check_breakpoints (CORE_ADDR stop_pc
)
198 struct breakpoint
*bp
;
200 bp
= find_breakpoint_at (stop_pc
);
205 warning ("Hit a removed breakpoint?");
209 if ((*bp
->handler
) (bp
->pc
))
211 delete_breakpoint (bp
);
219 set_breakpoint_data (const unsigned char *bp_data
, int bp_len
)
221 breakpoint_data
= bp_data
;
222 breakpoint_len
= bp_len
;
226 check_mem_read (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
228 struct breakpoint
*bp
= breakpoints
;
229 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
231 for (; bp
!= NULL
; bp
= bp
->next
)
233 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
234 CORE_ADDR start
, end
;
235 int copy_offset
, copy_len
, buf_offset
;
237 if (mem_addr
>= bp_end
)
239 if (bp
->pc
>= mem_end
)
243 if (mem_addr
> start
)
250 copy_len
= end
- start
;
251 copy_offset
= start
- bp
->pc
;
252 buf_offset
= start
- mem_addr
;
254 memcpy (buf
+ buf_offset
, bp
->old_data
+ copy_offset
, copy_len
);
259 check_mem_write (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
261 struct breakpoint
*bp
= breakpoints
;
262 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
264 for (; bp
!= NULL
; bp
= bp
->next
)
266 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
267 CORE_ADDR start
, end
;
268 int copy_offset
, copy_len
, buf_offset
;
270 if (mem_addr
>= bp_end
)
272 if (bp
->pc
>= mem_end
)
276 if (mem_addr
> start
)
283 copy_len
= end
- start
;
284 copy_offset
= start
- bp
->pc
;
285 buf_offset
= start
- mem_addr
;
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
);
293 /* Delete all breakpoints. */
296 delete_all_breakpoints (void)
299 delete_breakpoint (breakpoints
);