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