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
);
50 set_breakpoint_at (CORE_ADDR where
, int (*handler
) (CORE_ADDR
))
52 struct process_info
*proc
= current_process ();
53 struct breakpoint
*bp
;
55 if (breakpoint_data
== NULL
)
56 error ("Target does not support breakpoints.");
58 bp
= xmalloc (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
= proc
->breakpoints
;
70 proc
->breakpoints
= bp
;
74 delete_breakpoint (struct breakpoint
*bp
)
76 struct process_info
*proc
= current_process ();
77 struct breakpoint
*cur
;
79 if (proc
->breakpoints
== bp
)
81 proc
->breakpoints
= bp
->next
;
82 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
87 cur
= proc
->breakpoints
;
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 process_info
*proc
= current_process ();
106 struct breakpoint
*bp
= proc
->breakpoints
;
119 delete_breakpoint_at (CORE_ADDR addr
)
121 struct breakpoint
*bp
= find_breakpoint_at (addr
);
123 delete_breakpoint (bp
);
127 reinsert_breakpoint_handler (CORE_ADDR stop_pc
)
129 struct breakpoint
*stop_bp
, *orig_bp
;
131 stop_bp
= find_breakpoint_at (stop_pc
);
133 error ("lost the stopping breakpoint.");
135 orig_bp
= stop_bp
->breakpoint_to_reinsert
;
137 error ("no breakpoint to reinsert");
139 (*the_target
->write_memory
) (orig_bp
->pc
, breakpoint_data
,
141 orig_bp
->reinserting
= 0;
146 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc
, CORE_ADDR stop_at
)
148 struct breakpoint
*bp
, *orig_bp
;
150 orig_bp
= find_breakpoint_at (stop_pc
);
152 error ("Could not find original breakpoint in list.");
154 set_breakpoint_at (stop_at
, reinsert_breakpoint_handler
);
156 bp
= find_breakpoint_at (stop_at
);
158 error ("Could not find breakpoint in list (reinserting by breakpoint).");
159 bp
->breakpoint_to_reinsert
= orig_bp
;
161 (*the_target
->write_memory
) (orig_bp
->pc
, orig_bp
->old_data
,
163 orig_bp
->reinserting
= 1;
167 uninsert_breakpoint (CORE_ADDR stopped_at
)
169 struct breakpoint
*bp
;
171 bp
= find_breakpoint_at (stopped_at
);
173 error ("Could not find breakpoint in list (uninserting).");
175 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
181 reinsert_breakpoint (CORE_ADDR stopped_at
)
183 struct breakpoint
*bp
;
185 bp
= find_breakpoint_at (stopped_at
);
187 error ("Could not find breakpoint in list (uninserting).");
188 if (! bp
->reinserting
)
189 error ("Breakpoint already inserted at reinsert time.");
191 (*the_target
->write_memory
) (bp
->pc
, breakpoint_data
,
197 check_breakpoints (CORE_ADDR stop_pc
)
199 struct breakpoint
*bp
;
201 bp
= find_breakpoint_at (stop_pc
);
206 warning ("Hit a removed breakpoint?");
210 if ((*bp
->handler
) (bp
->pc
))
212 delete_breakpoint (bp
);
220 set_breakpoint_data (const unsigned char *bp_data
, int bp_len
)
222 breakpoint_data
= bp_data
;
223 breakpoint_len
= bp_len
;
227 check_mem_read (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
229 struct process_info
*proc
= current_process ();
230 struct breakpoint
*bp
= proc
->breakpoints
;
231 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
233 for (; bp
!= NULL
; bp
= bp
->next
)
235 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
236 CORE_ADDR start
, end
;
237 int copy_offset
, copy_len
, buf_offset
;
239 if (mem_addr
>= bp_end
)
241 if (bp
->pc
>= mem_end
)
245 if (mem_addr
> start
)
252 copy_len
= end
- start
;
253 copy_offset
= start
- bp
->pc
;
254 buf_offset
= start
- mem_addr
;
256 memcpy (buf
+ buf_offset
, bp
->old_data
+ copy_offset
, copy_len
);
261 check_mem_write (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
263 struct process_info
*proc
= current_process ();
264 struct breakpoint
*bp
= proc
->breakpoints
;
265 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
267 for (; bp
!= NULL
; bp
= bp
->next
)
269 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
270 CORE_ADDR start
, end
;
271 int copy_offset
, copy_len
, buf_offset
;
273 if (mem_addr
>= bp_end
)
275 if (bp
->pc
>= mem_end
)
279 if (mem_addr
> start
)
286 copy_len
= end
- start
;
287 copy_offset
= start
- bp
->pc
;
288 buf_offset
= start
- mem_addr
;
290 memcpy (bp
->old_data
+ copy_offset
, buf
+ buf_offset
, copy_len
);
291 if (bp
->reinserting
== 0)
292 memcpy (buf
+ buf_offset
, breakpoint_data
+ copy_offset
, copy_len
);
296 /* Delete all breakpoints, and un-insert them from the inferior. */
299 delete_all_breakpoints (void)
301 struct process_info
*proc
= current_process ();
303 while (proc
->breakpoints
)
304 delete_breakpoint (proc
->breakpoints
);
307 /* Release all breakpoints, but do not try to un-insert them from the
311 free_all_breakpoints (struct process_info
*proc
)
313 struct breakpoint
*bp
;
315 while (proc
->breakpoints
)
317 bp
= proc
->breakpoints
;
318 proc
->breakpoints
= bp
->next
;