|
|
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: #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)) { 1.1.1.2 ! root 205: db_printf("Address %#X is not in %s space\n", addr, 1.1 root 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: 1.1.1.2 ! root 318: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.