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