|
|
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.