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 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. */
43 void (*handler
) (CORE_ADDR
);
46 struct breakpoint
*breakpoints
;
49 set_breakpoint_at (CORE_ADDR where
, void (*handler
) (CORE_ADDR
))
51 struct breakpoint
*bp
;
53 if (breakpoint_data
== NULL
)
54 error ("Target does not support breakpoints.");
56 bp
= malloc (sizeof (struct breakpoint
));
57 memset (bp
, 0, sizeof (struct breakpoint
));
59 (*the_target
->read_memory
) (where
, bp
->old_data
,
61 (*the_target
->write_memory
) (where
, breakpoint_data
,
65 bp
->handler
= handler
;
67 bp
->next
= breakpoints
;
72 delete_breakpoint (struct breakpoint
*bp
)
74 struct breakpoint
*cur
;
76 if (breakpoints
== bp
)
78 breakpoints
= bp
->next
;
79 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
90 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
96 warning ("Could not find breakpoint in list.");
99 static struct breakpoint
*
100 find_breakpoint_at (CORE_ADDR where
)
102 struct breakpoint
*bp
= breakpoints
;
115 delete_breakpoint_at (CORE_ADDR addr
)
117 struct breakpoint
*bp
= find_breakpoint_at (addr
);
119 delete_breakpoint (bp
);
123 reinsert_breakpoint_handler (CORE_ADDR stop_pc
)
125 struct breakpoint
*stop_bp
, *orig_bp
;
127 stop_bp
= find_breakpoint_at (stop_pc
);
129 error ("lost the stopping breakpoint.");
131 orig_bp
= stop_bp
->breakpoint_to_reinsert
;
133 error ("no breakpoint to reinsert");
135 (*the_target
->write_memory
) (orig_bp
->pc
, breakpoint_data
,
137 orig_bp
->reinserting
= 0;
138 delete_breakpoint (stop_bp
);
142 reinsert_breakpoint_by_bp (CORE_ADDR stop_pc
, CORE_ADDR stop_at
)
144 struct breakpoint
*bp
, *orig_bp
;
146 set_breakpoint_at (stop_at
, reinsert_breakpoint_handler
);
148 orig_bp
= find_breakpoint_at (stop_pc
);
150 error ("Could not find original breakpoint in list.");
152 bp
= find_breakpoint_at (stop_at
);
154 error ("Could not find breakpoint in list (reinserting by breakpoint).");
155 bp
->breakpoint_to_reinsert
= orig_bp
;
157 (*the_target
->write_memory
) (orig_bp
->pc
, orig_bp
->old_data
,
159 orig_bp
->reinserting
= 1;
163 uninsert_breakpoint (CORE_ADDR stopped_at
)
165 struct breakpoint
*bp
;
167 bp
= find_breakpoint_at (stopped_at
);
169 error ("Could not find breakpoint in list (uninserting).");
171 (*the_target
->write_memory
) (bp
->pc
, bp
->old_data
,
177 reinsert_breakpoint (CORE_ADDR stopped_at
)
179 struct breakpoint
*bp
;
181 bp
= find_breakpoint_at (stopped_at
);
183 error ("Could not find breakpoint in list (uninserting).");
184 if (! bp
->reinserting
)
185 error ("Breakpoint already inserted at reinsert time.");
187 (*the_target
->write_memory
) (bp
->pc
, breakpoint_data
,
193 check_breakpoints (CORE_ADDR stop_pc
)
195 struct breakpoint
*bp
;
197 bp
= find_breakpoint_at (stop_pc
);
202 warning ("Hit a removed breakpoint?");
206 (*bp
->handler
) (bp
->pc
);
211 set_breakpoint_data (const unsigned char *bp_data
, int bp_len
)
213 breakpoint_data
= bp_data
;
214 breakpoint_len
= bp_len
;
218 check_mem_read (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
220 struct breakpoint
*bp
= breakpoints
;
221 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
223 for (; bp
!= NULL
; bp
= bp
->next
)
225 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
226 CORE_ADDR start
, end
;
227 int copy_offset
, copy_len
, buf_offset
;
229 if (mem_addr
>= bp_end
)
231 if (bp
->pc
>= mem_end
)
235 if (mem_addr
> start
)
242 copy_len
= end
- start
;
243 copy_offset
= start
- bp
->pc
;
244 buf_offset
= start
- mem_addr
;
246 memcpy (buf
+ buf_offset
, bp
->old_data
+ copy_offset
, copy_len
);
251 check_mem_write (CORE_ADDR mem_addr
, unsigned char *buf
, int mem_len
)
253 struct breakpoint
*bp
= breakpoints
;
254 CORE_ADDR mem_end
= mem_addr
+ mem_len
;
256 for (; bp
!= NULL
; bp
= bp
->next
)
258 CORE_ADDR bp_end
= bp
->pc
+ breakpoint_len
;
259 CORE_ADDR start
, end
;
260 int copy_offset
, copy_len
, buf_offset
;
262 if (mem_addr
>= bp_end
)
264 if (bp
->pc
>= mem_end
)
268 if (mem_addr
> start
)
275 copy_len
= end
- start
;
276 copy_offset
= start
- bp
->pc
;
277 buf_offset
= start
- mem_addr
;
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
);
285 /* Delete all breakpoints. */
288 delete_all_breakpoints (void)
291 delete_breakpoint (breakpoints
);