1 /* Memory breakpoint operations for the remote server for GDB.
2 Copyright (C) 2002, 2003, 2005, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>. */
23 const unsigned char *breakpoint_data
;
26 #define MAX_BREAKPOINT_LEN 8
30 struct breakpoint
*next
;
32 unsigned char old_data
[MAX_BREAKPOINT_LEN
];
34 /* Non-zero iff we are stepping over this breakpoint. */
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
;
42 /* Function to call when we hit this breakpoint. If it returns 1,
43 the breakpoint will be deleted; 0, it will be reinserted for
45 int (*handler
) (CORE_ADDR
);
48 struct breakpoint
*breakpoints
;
51 set_breakpoint_at (CORE_ADDR where
, int (*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;
144 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc
, CORE_ADDR stop_at
)
146 struct breakpoint
*bp
, *orig_bp
;
148 orig_bp
= find_breakpoint_at (stop_pc
);
150 error ("Could not find original breakpoint in list.");
152 set_breakpoint_at (stop_at
, reinsert_breakpoint_handler
);
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 if ((*bp
->handler
) (bp
->pc
))
210 delete_breakpoint (bp
);
218 set_breakpoint_data (const unsigned char *bp_data
, int bp_len
)
220 breakpoint_data
= bp_data
;
221 breakpoint_len
= bp_len
;
225 check_mem_read (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
227 struct breakpoint
*bp
= breakpoints
;
228 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
230 for (; bp
!= NULL
; bp
= bp
->next
)
232 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
233 CORE_ADDR start
, end
;
234 int copy_offset
, copy_len
, buf_offset
;
236 if (mem_addr
>= bp_end
)
238 if (bp
->pc
>= mem_end
)
242 if (mem_addr
> start
)
249 copy_len
= end
- start
;
250 copy_offset
= start
- bp
->pc
;
251 buf_offset
= start
- mem_addr
;
253 memcpy (buf
+ buf_offset
, bp
->old_data
+ copy_offset
, copy_len
);
258 check_mem_write (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
260 struct breakpoint
*bp
= breakpoints
;
261 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
263 for (; bp
!= NULL
; bp
= bp
->next
)
265 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
266 CORE_ADDR start
, end
;
267 int copy_offset
, copy_len
, buf_offset
;
269 if (mem_addr
>= bp_end
)
271 if (bp
->pc
>= mem_end
)
275 if (mem_addr
> start
)
282 copy_len
= end
- start
;
283 copy_offset
= start
- bp
->pc
;
284 buf_offset
= start
- mem_addr
;
286 memcpy (bp
->old_data
+ copy_offset
, buf
+ buf_offset
, copy_len
);
287 if (bp
->reinserting
== 0)
288 memcpy (buf
+ buf_offset
, breakpoint_data
+ copy_offset
, copy_len
);
292 /* Delete all breakpoints. */
295 delete_all_breakpoints (void)
298 delete_breakpoint (breakpoints
);