Annotation of sys/ddb/db_watch.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_watch.c,v 1.9 2006/03/13 06:23:20 jsg Exp $ */
! 2: /* $NetBSD: db_watch.c,v 1.9 1996/03/30 22:30:12 christos Exp $ */
! 3:
! 4: /*
! 5: * Mach Operating System
! 6: * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
! 7: * All Rights Reserved.
! 8: *
! 9: * Permission to use, copy, modify and distribute this software and its
! 10: * documentation is hereby granted, provided that both the copyright
! 11: * notice and this permission notice appear in all copies of the
! 12: * software, derivative works or modified versions, and any portions
! 13: * thereof, and that both notices appear in supporting documentation.
! 14: *
! 15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
! 17: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 18: *
! 19: * Carnegie Mellon requests users of this software to return to
! 20: *
! 21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 22: * School of Computer Science
! 23: * Carnegie Mellon University
! 24: * Pittsburgh PA 15213-3890
! 25: *
! 26: * any improvements or extensions that they make and grant Carnegie Mellon
! 27: * the rights to redistribute these changes.
! 28: *
! 29: * Author: Richard P. Draves, Carnegie Mellon University
! 30: * Date: 10/90
! 31: */
! 32:
! 33: #include <sys/param.h>
! 34: #include <sys/proc.h>
! 35:
! 36: #include <machine/db_machdep.h>
! 37:
! 38: #include <ddb/db_break.h>
! 39: #include <ddb/db_watch.h>
! 40: #include <ddb/db_lex.h>
! 41: #include <ddb/db_access.h>
! 42: #include <ddb/db_run.h>
! 43: #include <ddb/db_sym.h>
! 44: #include <ddb/db_output.h>
! 45: #include <ddb/db_command.h>
! 46: #include <ddb/db_extern.h>
! 47:
! 48: /*
! 49: * Watchpoints.
! 50: */
! 51:
! 52: boolean_t db_watchpoints_inserted = TRUE;
! 53:
! 54: #define NWATCHPOINTS 100
! 55: struct db_watchpoint db_watch_table[NWATCHPOINTS];
! 56: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
! 57: db_watchpoint_t db_free_watchpoints = 0;
! 58: db_watchpoint_t db_watchpoint_list = 0;
! 59:
! 60: db_watchpoint_t
! 61: db_watchpoint_alloc(void)
! 62: {
! 63: db_watchpoint_t watch;
! 64:
! 65: if ((watch = db_free_watchpoints) != 0) {
! 66: db_free_watchpoints = watch->link;
! 67: return (watch);
! 68: }
! 69: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
! 70: db_printf("All watchpoints used.\n");
! 71: return (0);
! 72: }
! 73: watch = db_next_free_watchpoint;
! 74: db_next_free_watchpoint++;
! 75:
! 76: return (watch);
! 77: }
! 78:
! 79: void
! 80: db_watchpoint_free(db_watchpoint_t watch)
! 81: {
! 82: watch->link = db_free_watchpoints;
! 83: db_free_watchpoints = watch;
! 84: }
! 85:
! 86: void
! 87: db_set_watchpoint(struct vm_map *map, db_addr_t addr, vsize_t size)
! 88: {
! 89: db_watchpoint_t watch;
! 90:
! 91: if (map == NULL) {
! 92: db_printf("No map.\n");
! 93: return;
! 94: }
! 95:
! 96: /*
! 97: * Should we do anything fancy with overlapping regions?
! 98: */
! 99:
! 100: for (watch = db_watchpoint_list;
! 101: watch != 0;
! 102: watch = watch->link)
! 103: if (db_map_equal(watch->map, map) &&
! 104: (watch->loaddr == addr) &&
! 105: (watch->hiaddr == addr+size)) {
! 106: db_printf("Already set.\n");
! 107: return;
! 108: }
! 109:
! 110: watch = db_watchpoint_alloc();
! 111: if (watch == 0) {
! 112: db_printf("Too many watchpoints.\n");
! 113: return;
! 114: }
! 115:
! 116: watch->map = map;
! 117: watch->loaddr = addr;
! 118: watch->hiaddr = addr+size;
! 119:
! 120: watch->link = db_watchpoint_list;
! 121: db_watchpoint_list = watch;
! 122:
! 123: db_watchpoints_inserted = FALSE;
! 124: }
! 125:
! 126: void
! 127: db_delete_watchpoint(struct vm_map *map, db_addr_t addr)
! 128: {
! 129: db_watchpoint_t watch;
! 130: db_watchpoint_t *prev;
! 131:
! 132: for (prev = &db_watchpoint_list;
! 133: (watch = *prev) != 0;
! 134: prev = &watch->link)
! 135: if (db_map_equal(watch->map, map) &&
! 136: (watch->loaddr <= addr) &&
! 137: (addr < watch->hiaddr)) {
! 138: *prev = watch->link;
! 139: db_watchpoint_free(watch);
! 140: return;
! 141: }
! 142:
! 143: db_printf("Not set.\n");
! 144: }
! 145:
! 146: void
! 147: db_list_watchpoints(void)
! 148: {
! 149: db_watchpoint_t watch;
! 150:
! 151: if (db_watchpoint_list == 0) {
! 152: db_printf("No watchpoints set\n");
! 153: return;
! 154: }
! 155:
! 156: db_printf(" Map Address Size\n");
! 157: for (watch = db_watchpoint_list;
! 158: watch != 0;
! 159: watch = watch->link)
! 160: db_printf("%s%p %8lx %lx\n",
! 161: db_map_current(watch->map) ? "*" : " ",
! 162: watch->map, watch->loaddr,
! 163: watch->hiaddr - watch->loaddr);
! 164: }
! 165:
! 166: /* Delete watchpoint */
! 167: /*ARGSUSED*/
! 168: void
! 169: db_deletewatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 170: {
! 171: db_delete_watchpoint(db_map_addr(addr), addr);
! 172: }
! 173:
! 174: /* Set watchpoint */
! 175: /*ARGSUSED*/
! 176: void
! 177: db_watchpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 178: {
! 179: vsize_t size;
! 180: db_expr_t value;
! 181:
! 182: if (db_expression(&value))
! 183: size = (vsize_t) value;
! 184: else
! 185: size = 4;
! 186: db_skip_to_eol();
! 187:
! 188: db_set_watchpoint(db_map_addr(addr), addr, size);
! 189: }
! 190:
! 191: /* list watchpoints */
! 192: /*ARGSUSED*/
! 193: void
! 194: db_listwatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 195: {
! 196: db_list_watchpoints();
! 197: }
! 198:
! 199: void
! 200: db_set_watchpoints(void)
! 201: {
! 202: db_watchpoint_t watch;
! 203:
! 204: if (!db_watchpoints_inserted && db_watchpoint_list != NULL) {
! 205: for (watch = db_watchpoint_list;
! 206: watch != 0;
! 207: watch = watch->link)
! 208: pmap_protect(watch->map->pmap,
! 209: trunc_page(watch->loaddr),
! 210: round_page(watch->hiaddr),
! 211: VM_PROT_READ);
! 212: pmap_update(watch->map->pmap);
! 213: db_watchpoints_inserted = TRUE;
! 214: }
! 215: }
! 216:
! 217: void
! 218: db_clear_watchpoints(void)
! 219: {
! 220: db_watchpoints_inserted = FALSE;
! 221: }
! 222:
! 223: boolean_t
! 224: db_find_watchpoint(struct vm_map *map, db_addr_t addr, db_regs_t *regs)
! 225: {
! 226: db_watchpoint_t watch;
! 227: db_watchpoint_t found = 0;
! 228:
! 229: for (watch = db_watchpoint_list;
! 230: watch != 0;
! 231: watch = watch->link)
! 232: if (db_map_equal(watch->map, map)) {
! 233: if ((watch->loaddr <= addr) &&
! 234: (addr < watch->hiaddr))
! 235: return (TRUE);
! 236: else if ((trunc_page(watch->loaddr) <= addr) &&
! 237: (addr < round_page(watch->hiaddr)))
! 238: found = watch;
! 239: }
! 240:
! 241: /*
! 242: * We didn't hit exactly on a watchpoint, but we are
! 243: * in a protected region. We want to single-step
! 244: * and then re-protect.
! 245: */
! 246:
! 247: if (found) {
! 248: db_watchpoints_inserted = FALSE;
! 249: db_single_step(regs);
! 250: }
! 251:
! 252: return (FALSE);
! 253: }
CVSweb