|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie the
24: * rights to redistribute these changes.
25: */
26: /*
27: * HISTORY
28: * $Log: db_watch.c,v $
1.1.1.2 ! root 29: * Revision 1.1.1.1 1993/03/21 09:46:27 cgd
! 30: * initial import of 386bsd-0.1 sources
! 31: *
1.1 root 32: * Revision 1.1 1992/03/25 21:45:37 pace
33: * Initial revision
34: *
35: * Revision 2.5 91/02/05 17:07:27 mrt
36: * Changed to new Mach copyright
37: * [91/01/31 16:20:02 mrt]
38: *
39: * Revision 2.4 91/01/08 15:09:24 rpd
40: * Use db_map_equal, db_map_current, db_map_addr.
41: * [90/11/10 rpd]
42: *
43: * Revision 2.3 90/11/05 14:26:39 rpd
44: * Initialize db_watchpoints_inserted to TRUE.
45: * [90/11/04 rpd]
46: *
47: * Revision 2.2 90/10/25 14:44:16 rwd
48: * Made db_watchpoint_cmd parse a size argument.
49: * [90/10/17 rpd]
50: * Generalized the watchpoint support.
51: * [90/10/16 rwd]
52: * Created.
53: * [90/10/16 rpd]
54: *
55: */
56: /*
57: * Author: Richard P. Draves, Carnegie Mellon University
58: * Date: 10/90
59: */
60:
61: #include "param.h"
62: #include "proc.h"
63: #include <machine/db_machdep.h>
64:
65: #include <vm/vm_map.h>
66: #include <ddb/db_lex.h>
67: #include <ddb/db_watch.h>
68: #include <ddb/db_access.h>
69: #include <ddb/db_sym.h>
70: #include <machine/db_machdep.h>
71:
72: /*
73: * Watchpoints.
74: */
75:
76: extern boolean_t db_map_equal();
77: extern boolean_t db_map_current();
78: extern vm_map_t db_map_addr();
79:
80: boolean_t db_watchpoints_inserted = TRUE;
81:
82: #define NWATCHPOINTS 100
83: struct db_watchpoint db_watch_table[NWATCHPOINTS];
84: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
85: db_watchpoint_t db_free_watchpoints = 0;
86: db_watchpoint_t db_watchpoint_list = 0;
87:
88: db_watchpoint_t
89: db_watchpoint_alloc()
90: {
91: register db_watchpoint_t watch;
92:
93: if ((watch = db_free_watchpoints) != 0) {
94: db_free_watchpoints = watch->link;
95: return (watch);
96: }
97: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
98: db_printf("All watchpoints used.\n");
99: return (0);
100: }
101: watch = db_next_free_watchpoint;
102: db_next_free_watchpoint++;
103:
104: return (watch);
105: }
106:
107: void
108: db_watchpoint_free(watch)
109: register db_watchpoint_t watch;
110: {
111: watch->link = db_free_watchpoints;
112: db_free_watchpoints = watch;
113: }
114:
115: void
116: db_set_watchpoint(map, addr, size)
117: vm_map_t map;
118: db_addr_t addr;
119: vm_size_t size;
120: {
121: register db_watchpoint_t watch;
122:
123: if (map == NULL) {
124: db_printf("No map.\n");
125: return;
126: }
127:
128: /*
129: * Should we do anything fancy with overlapping regions?
130: */
131:
132: for (watch = db_watchpoint_list;
133: watch != 0;
134: watch = watch->link)
135: if (db_map_equal(watch->map, map) &&
136: (watch->loaddr == addr) &&
137: (watch->hiaddr == addr+size)) {
138: db_printf("Already set.\n");
139: return;
140: }
141:
142: watch = db_watchpoint_alloc();
143: if (watch == 0) {
144: db_printf("Too many watchpoints.\n");
145: return;
146: }
147:
148: watch->map = map;
149: watch->loaddr = addr;
150: watch->hiaddr = addr+size;
151:
152: watch->link = db_watchpoint_list;
153: db_watchpoint_list = watch;
154:
155: db_watchpoints_inserted = FALSE;
156: }
157:
158: void
159: db_delete_watchpoint(map, addr)
160: vm_map_t map;
161: db_addr_t addr;
162: {
163: register db_watchpoint_t watch;
164: register db_watchpoint_t *prev;
165:
166: for (prev = &db_watchpoint_list;
167: (watch = *prev) != 0;
168: prev = &watch->link)
169: if (db_map_equal(watch->map, map) &&
170: (watch->loaddr <= addr) &&
171: (addr < watch->hiaddr)) {
172: *prev = watch->link;
173: db_watchpoint_free(watch);
174: return;
175: }
176:
177: db_printf("Not set.\n");
178: }
179:
180: void
181: db_list_watchpoints()
182: {
183: register db_watchpoint_t watch;
184:
185: if (db_watchpoint_list == 0) {
186: db_printf("No watchpoints set\n");
187: return;
188: }
189:
190: db_printf(" Map Address Size\n");
191: for (watch = db_watchpoint_list;
192: watch != 0;
193: watch = watch->link)
194: db_printf("%s%8x %8x %x\n",
195: db_map_current(watch->map) ? "*" : " ",
196: watch->map, watch->loaddr,
197: watch->hiaddr - watch->loaddr);
198: }
199:
200: /* Delete watchpoint */
201: /*ARGSUSED*/
202: void
203: db_deletewatch_cmd(addr, have_addr, count, modif)
204: db_expr_t addr;
205: int have_addr;
206: db_expr_t count;
207: char * modif;
208: {
209: db_delete_watchpoint(db_map_addr(addr), addr);
210: }
211:
212: /* Set watchpoint */
213: /*ARGSUSED*/
214: void
215: db_watchpoint_cmd(addr, have_addr, count, modif)
216: db_expr_t addr;
217: int have_addr;
218: db_expr_t count;
219: char * modif;
220: {
221: vm_size_t size;
222: db_expr_t value;
223:
224: if (db_expression(&value))
225: size = (vm_size_t) value;
226: else
227: size = 4;
228: db_skip_to_eol();
229:
230: db_set_watchpoint(db_map_addr(addr), addr, size);
231: }
232:
233: /* list watchpoints */
234: void
235: db_listwatch_cmd()
236: {
237: db_list_watchpoints();
238: }
239:
240: void
241: db_set_watchpoints()
242: {
243: register db_watchpoint_t watch;
244:
245: if (!db_watchpoints_inserted) {
246: for (watch = db_watchpoint_list;
247: watch != 0;
248: watch = watch->link)
249: pmap_protect(watch->map->pmap,
250: trunc_page(watch->loaddr),
251: round_page(watch->hiaddr),
252: VM_PROT_READ);
253:
254: db_watchpoints_inserted = TRUE;
255: }
256: }
257:
258: void
259: db_clear_watchpoints()
260: {
261: db_watchpoints_inserted = FALSE;
262: }
263:
264: boolean_t
265: db_find_watchpoint(map, addr, regs)
266: vm_map_t map;
267: db_addr_t addr;
268: db_regs_t *regs;
269: {
270: register db_watchpoint_t watch;
271: db_watchpoint_t found = 0;
272:
273: for (watch = db_watchpoint_list;
274: watch != 0;
275: watch = watch->link)
276: if (db_map_equal(watch->map, map)) {
277: if ((watch->loaddr <= addr) &&
278: (addr < watch->hiaddr))
279: return (TRUE);
280: else if ((trunc_page(watch->loaddr) <= addr) &&
281: (addr < round_page(watch->hiaddr)))
282: found = watch;
283: }
284:
285: /*
286: * We didn't hit exactly on a watchpoint, but we are
287: * in a protected region. We want to single-step
288: * and then re-protect.
289: */
290:
291: if (found) {
292: db_watchpoints_inserted = FALSE;
293: db_single_step(regs);
294: }
295:
296: return (FALSE);
297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.