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