|
|
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 ! 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 the ! 24: * rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * HISTORY ! 28: * $Log: db_watch.c,v $ ! 29: * Revision 1.1 1992/03/25 21:45:37 pace ! 30: * Initial revision ! 31: * ! 32: * Revision 2.5 91/02/05 17:07:27 mrt ! 33: * Changed to new Mach copyright ! 34: * [91/01/31 16:20:02 mrt] ! 35: * ! 36: * Revision 2.4 91/01/08 15:09:24 rpd ! 37: * Use db_map_equal, db_map_current, db_map_addr. ! 38: * [90/11/10 rpd] ! 39: * ! 40: * Revision 2.3 90/11/05 14:26:39 rpd ! 41: * Initialize db_watchpoints_inserted to TRUE. ! 42: * [90/11/04 rpd] ! 43: * ! 44: * Revision 2.2 90/10/25 14:44:16 rwd ! 45: * Made db_watchpoint_cmd parse a size argument. ! 46: * [90/10/17 rpd] ! 47: * Generalized the watchpoint support. ! 48: * [90/10/16 rwd] ! 49: * Created. ! 50: * [90/10/16 rpd] ! 51: * ! 52: */ ! 53: /* ! 54: * Author: Richard P. Draves, Carnegie Mellon University ! 55: * Date: 10/90 ! 56: */ ! 57: ! 58: #include "param.h" ! 59: #include "proc.h" ! 60: #include <machine/db_machdep.h> ! 61: ! 62: #include <vm/vm_map.h> ! 63: #include <ddb/db_lex.h> ! 64: #include <ddb/db_watch.h> ! 65: #include <ddb/db_access.h> ! 66: #include <ddb/db_sym.h> ! 67: #include <machine/db_machdep.h> ! 68: ! 69: /* ! 70: * Watchpoints. ! 71: */ ! 72: ! 73: extern boolean_t db_map_equal(); ! 74: extern boolean_t db_map_current(); ! 75: extern vm_map_t db_map_addr(); ! 76: ! 77: boolean_t db_watchpoints_inserted = TRUE; ! 78: ! 79: #define NWATCHPOINTS 100 ! 80: struct db_watchpoint db_watch_table[NWATCHPOINTS]; ! 81: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0]; ! 82: db_watchpoint_t db_free_watchpoints = 0; ! 83: db_watchpoint_t db_watchpoint_list = 0; ! 84: ! 85: db_watchpoint_t ! 86: db_watchpoint_alloc() ! 87: { ! 88: register db_watchpoint_t watch; ! 89: ! 90: if ((watch = db_free_watchpoints) != 0) { ! 91: db_free_watchpoints = watch->link; ! 92: return (watch); ! 93: } ! 94: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) { ! 95: db_printf("All watchpoints used.\n"); ! 96: return (0); ! 97: } ! 98: watch = db_next_free_watchpoint; ! 99: db_next_free_watchpoint++; ! 100: ! 101: return (watch); ! 102: } ! 103: ! 104: void ! 105: db_watchpoint_free(watch) ! 106: register db_watchpoint_t watch; ! 107: { ! 108: watch->link = db_free_watchpoints; ! 109: db_free_watchpoints = watch; ! 110: } ! 111: ! 112: void ! 113: db_set_watchpoint(map, addr, size) ! 114: vm_map_t map; ! 115: db_addr_t addr; ! 116: vm_size_t size; ! 117: { ! 118: register db_watchpoint_t watch; ! 119: ! 120: if (map == NULL) { ! 121: db_printf("No map.\n"); ! 122: return; ! 123: } ! 124: ! 125: /* ! 126: * Should we do anything fancy with overlapping regions? ! 127: */ ! 128: ! 129: for (watch = db_watchpoint_list; ! 130: watch != 0; ! 131: watch = watch->link) ! 132: if (db_map_equal(watch->map, map) && ! 133: (watch->loaddr == addr) && ! 134: (watch->hiaddr == addr+size)) { ! 135: db_printf("Already set.\n"); ! 136: return; ! 137: } ! 138: ! 139: watch = db_watchpoint_alloc(); ! 140: if (watch == 0) { ! 141: db_printf("Too many watchpoints.\n"); ! 142: return; ! 143: } ! 144: ! 145: watch->map = map; ! 146: watch->loaddr = addr; ! 147: watch->hiaddr = addr+size; ! 148: ! 149: watch->link = db_watchpoint_list; ! 150: db_watchpoint_list = watch; ! 151: ! 152: db_watchpoints_inserted = FALSE; ! 153: } ! 154: ! 155: void ! 156: db_delete_watchpoint(map, addr) ! 157: vm_map_t map; ! 158: db_addr_t addr; ! 159: { ! 160: register db_watchpoint_t watch; ! 161: register db_watchpoint_t *prev; ! 162: ! 163: for (prev = &db_watchpoint_list; ! 164: (watch = *prev) != 0; ! 165: prev = &watch->link) ! 166: if (db_map_equal(watch->map, map) && ! 167: (watch->loaddr <= addr) && ! 168: (addr < watch->hiaddr)) { ! 169: *prev = watch->link; ! 170: db_watchpoint_free(watch); ! 171: return; ! 172: } ! 173: ! 174: db_printf("Not set.\n"); ! 175: } ! 176: ! 177: void ! 178: db_list_watchpoints() ! 179: { ! 180: register db_watchpoint_t watch; ! 181: ! 182: if (db_watchpoint_list == 0) { ! 183: db_printf("No watchpoints set\n"); ! 184: return; ! 185: } ! 186: ! 187: db_printf(" Map Address Size\n"); ! 188: for (watch = db_watchpoint_list; ! 189: watch != 0; ! 190: watch = watch->link) ! 191: db_printf("%s%8x %8x %x\n", ! 192: db_map_current(watch->map) ? "*" : " ", ! 193: watch->map, watch->loaddr, ! 194: watch->hiaddr - watch->loaddr); ! 195: } ! 196: ! 197: /* Delete watchpoint */ ! 198: /*ARGSUSED*/ ! 199: void ! 200: db_deletewatch_cmd(addr, have_addr, count, modif) ! 201: db_expr_t addr; ! 202: int have_addr; ! 203: db_expr_t count; ! 204: char * modif; ! 205: { ! 206: db_delete_watchpoint(db_map_addr(addr), addr); ! 207: } ! 208: ! 209: /* Set watchpoint */ ! 210: /*ARGSUSED*/ ! 211: void ! 212: db_watchpoint_cmd(addr, have_addr, count, modif) ! 213: db_expr_t addr; ! 214: int have_addr; ! 215: db_expr_t count; ! 216: char * modif; ! 217: { ! 218: vm_size_t size; ! 219: db_expr_t value; ! 220: ! 221: if (db_expression(&value)) ! 222: size = (vm_size_t) value; ! 223: else ! 224: size = 4; ! 225: db_skip_to_eol(); ! 226: ! 227: db_set_watchpoint(db_map_addr(addr), addr, size); ! 228: } ! 229: ! 230: /* list watchpoints */ ! 231: void ! 232: db_listwatch_cmd() ! 233: { ! 234: db_list_watchpoints(); ! 235: } ! 236: ! 237: void ! 238: db_set_watchpoints() ! 239: { ! 240: register db_watchpoint_t watch; ! 241: ! 242: if (!db_watchpoints_inserted) { ! 243: for (watch = db_watchpoint_list; ! 244: watch != 0; ! 245: watch = watch->link) ! 246: pmap_protect(watch->map->pmap, ! 247: trunc_page(watch->loaddr), ! 248: round_page(watch->hiaddr), ! 249: VM_PROT_READ); ! 250: ! 251: db_watchpoints_inserted = TRUE; ! 252: } ! 253: } ! 254: ! 255: void ! 256: db_clear_watchpoints() ! 257: { ! 258: db_watchpoints_inserted = FALSE; ! 259: } ! 260: ! 261: boolean_t ! 262: db_find_watchpoint(map, addr, regs) ! 263: vm_map_t map; ! 264: db_addr_t addr; ! 265: db_regs_t *regs; ! 266: { ! 267: register db_watchpoint_t watch; ! 268: db_watchpoint_t found = 0; ! 269: ! 270: for (watch = db_watchpoint_list; ! 271: watch != 0; ! 272: watch = watch->link) ! 273: if (db_map_equal(watch->map, map)) { ! 274: if ((watch->loaddr <= addr) && ! 275: (addr < watch->hiaddr)) ! 276: return (TRUE); ! 277: else if ((trunc_page(watch->loaddr) <= addr) && ! 278: (addr < round_page(watch->hiaddr))) ! 279: found = watch; ! 280: } ! 281: ! 282: /* ! 283: * We didn't hit exactly on a watchpoint, but we are ! 284: * in a protected region. We want to single-step ! 285: * and then re-protect. ! 286: */ ! 287: ! 288: if (found) { ! 289: db_watchpoints_inserted = FALSE; ! 290: db_single_step(regs); ! 291: } ! 292: ! 293: return (FALSE); ! 294: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.