|
|
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 "AS IS"
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 Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Author: Richard P. Draves, Carnegie Mellon University
28: * Date: 10/90
29: */
30:
31: #include "mach_kdb.h"
32: #if MACH_KDB
33:
34: #include <mach/boolean.h>
35: #include <mach/vm_param.h>
36: #include <mach/machine/vm_types.h>
37: #include <mach/machine/vm_param.h>
38: #include <vm/vm_map.h>
39:
40: #include <machine/db_machdep.h>
41: #include <ddb/db_lex.h>
42: #include <ddb/db_watch.h>
43: #include <ddb/db_access.h>
44: #include <ddb/db_sym.h>
45: #include <ddb/db_task_thread.h>
46:
47:
48:
49: /*
50: * Watchpoints.
51: */
52:
53: boolean_t db_watchpoints_inserted = TRUE;
54:
55: #define NWATCHPOINTS 100
56: struct db_watchpoint db_watch_table[NWATCHPOINTS];
57: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
58: db_watchpoint_t db_free_watchpoints = 0;
59: db_watchpoint_t db_watchpoint_list = 0;
60:
61: extern vm_map_t kernel_map;
62:
63: db_watchpoint_t
64: db_watchpoint_alloc()
65: {
66: register db_watchpoint_t watch;
67:
68: if ((watch = db_free_watchpoints) != 0) {
69: db_free_watchpoints = watch->link;
70: return (watch);
71: }
72: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
73: db_printf("All watchpoints used.\n");
74: return (0);
75: }
76: watch = db_next_free_watchpoint;
77: db_next_free_watchpoint++;
78:
79: return (watch);
80: }
81:
82: void
83: db_watchpoint_free(watch)
84: register db_watchpoint_t watch;
85: {
86: watch->link = db_free_watchpoints;
87: db_free_watchpoints = watch;
88: }
89:
90: void
91: db_set_watchpoint(task, addr, size)
92: task_t task;
93: db_addr_t addr;
94: vm_size_t size;
95: {
96: register db_watchpoint_t watch;
97:
98: /*
99: * Should we do anything fancy with overlapping regions?
100: */
101:
102: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
103: if (watch->task == task &&
104: (watch->loaddr == addr) &&
105: (watch->hiaddr == addr+size)) {
106: db_printf("Already set.\n");
107: return;
108: }
109: }
110:
111: watch = db_watchpoint_alloc();
112: if (watch == 0) {
113: db_printf("Too many watchpoints.\n");
114: return;
115: }
116:
117: watch->task = task;
118: watch->loaddr = addr;
119: watch->hiaddr = addr+size;
120:
121: watch->link = db_watchpoint_list;
122: db_watchpoint_list = watch;
123:
124: db_watchpoints_inserted = FALSE;
125: }
126:
127: void
128: db_delete_watchpoint(task, addr)
129: task_t task;
130: db_addr_t addr;
131: {
132: register db_watchpoint_t watch;
133: register db_watchpoint_t *prev;
134:
135: for (prev = &db_watchpoint_list; (watch = *prev) != 0;
136: prev = &watch->link) {
137: if (watch->task == task &&
138: (watch->loaddr <= addr) &&
139: (addr < watch->hiaddr)) {
140: *prev = watch->link;
141: db_watchpoint_free(watch);
142: return;
143: }
144: }
145:
146: db_printf("Not set.\n");
147: }
148:
149: void
150: db_list_watchpoints()
151: {
152: register db_watchpoint_t watch;
153: int task_id;
154:
155: if (db_watchpoint_list == 0) {
156: db_printf("No watchpoints set\n");
157: return;
158: }
159:
160: db_printf("Space Address Size\n");
161: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
162: if (watch->task == TASK_NULL)
163: db_printf("kernel ");
164: else {
165: task_id = db_lookup_task(watch->task);
166: if (task_id < 0)
167: db_printf("%*X", 2*sizeof(vm_offset_t), watch->task);
168: else
169: db_printf("task%-3d ", task_id);
170: }
171: db_printf(" %*X %X\n", 2*sizeof(vm_offset_t), watch->loaddr,
172: watch->hiaddr - watch->loaddr);
173: }
174: }
175:
176: static int
177: db_get_task(modif, taskp, addr)
178: char *modif;
179: task_t *taskp;
180: db_addr_t addr;
181: {
182: task_t task = TASK_NULL;
183: db_expr_t value;
184: boolean_t user_space;
185:
186: user_space = db_option(modif, 'T');
187: if (user_space) {
188: if (db_expression(&value)) {
189: task = (task_t)value;
190: if (db_lookup_task(task) < 0) {
191: db_printf("bad task address %X\n", task);
192: return(-1);
193: }
194: } else {
195: task = db_default_task;
196: if (task == TASK_NULL) {
197: if ((task = db_current_task()) == TASK_NULL) {
198: db_printf("no task\n");
199: return(-1);
200: }
201: }
202: }
203: }
204: if (!DB_VALID_ADDRESS(addr, user_space)) {
205: db_printf("Address %#X is not in %s space\n", addr,
206: (user_space)? "user": "kernel");
207: return(-1);
208: }
209: *taskp = task;
210: return(0);
211: }
212:
213: /* Delete watchpoint */
214: /*ARGSUSED*/
215: void
216: db_deletewatch_cmd(addr, have_addr, count, modif)
217: db_expr_t addr;
218: int have_addr;
219: db_expr_t count;
220: char * modif;
221: {
222: task_t task;
223:
224: if (db_get_task(modif, &task, addr) < 0)
225: return;
226: db_delete_watchpoint(task, addr);
227: }
228:
229: /* Set watchpoint */
230: /*ARGSUSED*/
231: void
232: db_watchpoint_cmd(addr, have_addr, count, modif)
233: db_expr_t addr;
234: int have_addr;
235: db_expr_t count;
236: char * modif;
237: {
238: vm_size_t size;
239: db_expr_t value;
240: task_t task;
241: boolean_t db_option();
242:
243: if (db_get_task(modif, &task, addr) < 0)
244: return;
245: if (db_expression(&value))
246: size = (vm_size_t) value;
247: else
248: size = sizeof(int);
249: db_set_watchpoint(task, addr, size);
250: }
251:
252: /* list watchpoints */
253: void
254: db_listwatch_cmd()
255: {
256: db_list_watchpoints();
257: }
258:
259: void
260: db_set_watchpoints()
261: {
262: register db_watchpoint_t watch;
263: vm_map_t map;
264:
265: if (!db_watchpoints_inserted) {
266: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
267: map = (watch->task)? watch->task->map: kernel_map;
268: pmap_protect(map->pmap,
269: trunc_page(watch->loaddr),
270: round_page(watch->hiaddr),
271: VM_PROT_READ);
272: }
273: db_watchpoints_inserted = TRUE;
274: }
275: }
276:
277: void
278: db_clear_watchpoints()
279: {
280: db_watchpoints_inserted = FALSE;
281: }
282:
283: boolean_t
284: db_find_watchpoint(map, addr, regs)
285: vm_map_t map;
286: db_addr_t addr;
287: db_regs_t *regs;
288: {
289: register db_watchpoint_t watch;
290: db_watchpoint_t found = 0;
291: register task_t task_space;
292:
293: task_space = (map == kernel_map)? TASK_NULL: db_current_task();
294: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
295: if (watch->task == task_space) {
296: if ((watch->loaddr <= addr) && (addr < watch->hiaddr))
297: return (TRUE);
298: else if ((trunc_page(watch->loaddr) <= addr) &&
299: (addr < round_page(watch->hiaddr)))
300: found = watch;
301: }
302: }
303:
304: /*
305: * We didn't hit exactly on a watchpoint, but we are
306: * in a protected region. We want to single-step
307: * and then re-protect.
308: */
309:
310: if (found) {
311: db_watchpoints_inserted = FALSE;
312: db_single_step(regs, task_space);
313: }
314:
315: return (FALSE);
316: }
317:
318: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.