Annotation of sys/ddb/db_watch.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_watch.c,v 1.9 2006/03/13 06:23:20 jsg Exp $ */
2: /* $NetBSD: db_watch.c,v 1.9 1996/03/30 22:30:12 christos Exp $ */
3:
4: /*
5: * Mach Operating System
6: * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7: * All Rights Reserved.
8: *
9: * Permission to use, copy, modify and distribute this software and its
10: * documentation is hereby granted, provided that both the copyright
11: * notice and this permission notice appear in all copies of the
12: * software, derivative works or modified versions, and any portions
13: * thereof, and that both notices appear in supporting documentation.
14: *
15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: *
29: * Author: Richard P. Draves, Carnegie Mellon University
30: * Date: 10/90
31: */
32:
33: #include <sys/param.h>
34: #include <sys/proc.h>
35:
36: #include <machine/db_machdep.h>
37:
38: #include <ddb/db_break.h>
39: #include <ddb/db_watch.h>
40: #include <ddb/db_lex.h>
41: #include <ddb/db_access.h>
42: #include <ddb/db_run.h>
43: #include <ddb/db_sym.h>
44: #include <ddb/db_output.h>
45: #include <ddb/db_command.h>
46: #include <ddb/db_extern.h>
47:
48: /*
49: * Watchpoints.
50: */
51:
52: boolean_t db_watchpoints_inserted = TRUE;
53:
54: #define NWATCHPOINTS 100
55: struct db_watchpoint db_watch_table[NWATCHPOINTS];
56: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
57: db_watchpoint_t db_free_watchpoints = 0;
58: db_watchpoint_t db_watchpoint_list = 0;
59:
60: db_watchpoint_t
61: db_watchpoint_alloc(void)
62: {
63: db_watchpoint_t watch;
64:
65: if ((watch = db_free_watchpoints) != 0) {
66: db_free_watchpoints = watch->link;
67: return (watch);
68: }
69: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
70: db_printf("All watchpoints used.\n");
71: return (0);
72: }
73: watch = db_next_free_watchpoint;
74: db_next_free_watchpoint++;
75:
76: return (watch);
77: }
78:
79: void
80: db_watchpoint_free(db_watchpoint_t watch)
81: {
82: watch->link = db_free_watchpoints;
83: db_free_watchpoints = watch;
84: }
85:
86: void
87: db_set_watchpoint(struct vm_map *map, db_addr_t addr, vsize_t size)
88: {
89: db_watchpoint_t watch;
90:
91: if (map == NULL) {
92: db_printf("No map.\n");
93: return;
94: }
95:
96: /*
97: * Should we do anything fancy with overlapping regions?
98: */
99:
100: for (watch = db_watchpoint_list;
101: watch != 0;
102: watch = watch->link)
103: if (db_map_equal(watch->map, map) &&
104: (watch->loaddr == addr) &&
105: (watch->hiaddr == addr+size)) {
106: db_printf("Already set.\n");
107: return;
108: }
109:
110: watch = db_watchpoint_alloc();
111: if (watch == 0) {
112: db_printf("Too many watchpoints.\n");
113: return;
114: }
115:
116: watch->map = map;
117: watch->loaddr = addr;
118: watch->hiaddr = addr+size;
119:
120: watch->link = db_watchpoint_list;
121: db_watchpoint_list = watch;
122:
123: db_watchpoints_inserted = FALSE;
124: }
125:
126: void
127: db_delete_watchpoint(struct vm_map *map, db_addr_t addr)
128: {
129: db_watchpoint_t watch;
130: db_watchpoint_t *prev;
131:
132: for (prev = &db_watchpoint_list;
133: (watch = *prev) != 0;
134: prev = &watch->link)
135: if (db_map_equal(watch->map, map) &&
136: (watch->loaddr <= addr) &&
137: (addr < watch->hiaddr)) {
138: *prev = watch->link;
139: db_watchpoint_free(watch);
140: return;
141: }
142:
143: db_printf("Not set.\n");
144: }
145:
146: void
147: db_list_watchpoints(void)
148: {
149: db_watchpoint_t watch;
150:
151: if (db_watchpoint_list == 0) {
152: db_printf("No watchpoints set\n");
153: return;
154: }
155:
156: db_printf(" Map Address Size\n");
157: for (watch = db_watchpoint_list;
158: watch != 0;
159: watch = watch->link)
160: db_printf("%s%p %8lx %lx\n",
161: db_map_current(watch->map) ? "*" : " ",
162: watch->map, watch->loaddr,
163: watch->hiaddr - watch->loaddr);
164: }
165:
166: /* Delete watchpoint */
167: /*ARGSUSED*/
168: void
169: db_deletewatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
170: {
171: db_delete_watchpoint(db_map_addr(addr), addr);
172: }
173:
174: /* Set watchpoint */
175: /*ARGSUSED*/
176: void
177: db_watchpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
178: {
179: vsize_t size;
180: db_expr_t value;
181:
182: if (db_expression(&value))
183: size = (vsize_t) value;
184: else
185: size = 4;
186: db_skip_to_eol();
187:
188: db_set_watchpoint(db_map_addr(addr), addr, size);
189: }
190:
191: /* list watchpoints */
192: /*ARGSUSED*/
193: void
194: db_listwatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
195: {
196: db_list_watchpoints();
197: }
198:
199: void
200: db_set_watchpoints(void)
201: {
202: db_watchpoint_t watch;
203:
204: if (!db_watchpoints_inserted && db_watchpoint_list != NULL) {
205: for (watch = db_watchpoint_list;
206: watch != 0;
207: watch = watch->link)
208: pmap_protect(watch->map->pmap,
209: trunc_page(watch->loaddr),
210: round_page(watch->hiaddr),
211: VM_PROT_READ);
212: pmap_update(watch->map->pmap);
213: db_watchpoints_inserted = TRUE;
214: }
215: }
216:
217: void
218: db_clear_watchpoints(void)
219: {
220: db_watchpoints_inserted = FALSE;
221: }
222:
223: boolean_t
224: db_find_watchpoint(struct vm_map *map, db_addr_t addr, db_regs_t *regs)
225: {
226: db_watchpoint_t watch;
227: db_watchpoint_t found = 0;
228:
229: for (watch = db_watchpoint_list;
230: watch != 0;
231: watch = watch->link)
232: if (db_map_equal(watch->map, map)) {
233: if ((watch->loaddr <= addr) &&
234: (addr < watch->hiaddr))
235: return (TRUE);
236: else if ((trunc_page(watch->loaddr) <= addr) &&
237: (addr < round_page(watch->hiaddr)))
238: found = watch;
239: }
240:
241: /*
242: * We didn't hit exactly on a watchpoint, but we are
243: * in a protected region. We want to single-step
244: * and then re-protect.
245: */
246:
247: if (found) {
248: db_watchpoints_inserted = FALSE;
249: db_single_step(regs);
250: }
251:
252: return (FALSE);
253: }
CVSweb