|
|
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
68: db_watchpoint_alloc()
69: {
70: register db_watchpoint_t watch;
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)
88: register db_watchpoint_t watch;
89: {
90: watch->link = db_free_watchpoints;
91: db_free_watchpoints = watch;
92: }
93:
94: void
95: db_set_watchpoint(task, addr, size)
96: task_t task;
97: db_addr_t addr;
98: vm_size_t size;
99: {
100: register db_watchpoint_t watch;
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)
133: task_t task;
134: db_addr_t addr;
135: {
136: register db_watchpoint_t watch;
137: register db_watchpoint_t *prev;
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: {
156: register db_watchpoint_t watch;
157: int task_id;
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)
182: char *modif;
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;
224: char * modif;
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;
240: char * modif;
241: {
242: vm_size_t size;
243: db_expr_t value;
244: task_t task;
245: boolean_t db_option();
246:
247: if (db_get_task(modif, &task, addr) < 0)
248: return;
249: if (db_expression(&value))
250: size = (vm_size_t) value;
251: else
252: size = sizeof(int);
253: db_set_watchpoint(task, addr, size);
254: }
255:
256: /* list watchpoints */
257: void
258: db_listwatch_cmd()
259: {
260: db_list_watchpoints();
261: }
262:
263: void
1.1.1.3 ! root 264: db_set_watchpoints(void)
1.1 root 265: {
266: register db_watchpoint_t watch;
267: vm_map_t map;
1.1.1.3 ! root 268: unsigned hw_idx = 0;
1.1 root 269:
270: if (!db_watchpoints_inserted) {
271: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
1.1.1.3 ! root 272: if (db_set_hw_watchpoint(watch, hw_idx)) {
! 273: hw_idx++;
! 274: continue;
! 275: }
1.1 root 276: map = (watch->task)? watch->task->map: kernel_map;
277: pmap_protect(map->pmap,
278: trunc_page(watch->loaddr),
279: round_page(watch->hiaddr),
280: VM_PROT_READ);
281: }
282: db_watchpoints_inserted = TRUE;
283: }
284: }
285:
286: void
1.1.1.3 ! root 287: db_clear_watchpoints(void)
1.1 root 288: {
1.1.1.3 ! root 289: unsigned hw_idx = 0;
! 290:
! 291: while (db_clear_hw_watchpoint(hw_idx))
! 292: hw_idx++;
! 293:
1.1 root 294: db_watchpoints_inserted = FALSE;
295: }
296:
297: boolean_t
298: db_find_watchpoint(map, addr, regs)
299: vm_map_t map;
300: db_addr_t addr;
301: db_regs_t *regs;
302: {
303: register db_watchpoint_t watch;
304: db_watchpoint_t found = 0;
305: register task_t task_space;
306:
307: task_space = (map == kernel_map)? TASK_NULL: db_current_task();
308: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
309: if (watch->task == task_space) {
310: if ((watch->loaddr <= addr) && (addr < watch->hiaddr))
311: return (TRUE);
312: else if ((trunc_page(watch->loaddr) <= addr) &&
313: (addr < round_page(watch->hiaddr)))
314: found = watch;
315: }
316: }
317:
318: /*
319: * We didn't hit exactly on a watchpoint, but we are
320: * in a protected region. We want to single-step
321: * and then re-protect.
322: */
323:
324: if (found) {
325: db_watchpoints_inserted = FALSE;
326: db_single_step(regs, task_space);
327: }
328:
329: return (FALSE);
330: }
331:
1.1.1.2 root 332: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.