|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * HISTORY ! 27: * ! 28: * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez ! 29: * Import of Mac OS X kernel (~semeria) ! 30: * ! 31: * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez ! 32: * Import of OSF Mach kernel (~mburg) ! 33: * ! 34: * Revision 1.1.12.2 1995/01/06 19:11:06 devrcs ! 35: * mk6 CR668 - 1.3b26 merge ! 36: * * Revision 1.1.3.5 1994/05/06 18:40:29 tmt ! 37: * Merged osc1.3dec/shared with osc1.3b19 ! 38: * Merge Alpha changes into osc1.312b source code. ! 39: * 64bit cleanup. ! 40: * * End1.3merge ! 41: * [1994/11/04 08:50:16 dwm] ! 42: * ! 43: * Revision 1.1.12.1 1994/09/23 01:22:53 ezf ! 44: * change marker to not FREE ! 45: * [1994/09/22 21:11:33 ezf] ! 46: * ! 47: * Revision 1.1.10.1 1994/01/05 19:28:22 bolinger ! 48: * Be sure to count kernel-loaded tasks as part of kernel address space ! 49: * in locating watchpoints. ! 50: * [1994/01/04 17:43:33 bolinger] ! 51: * ! 52: * Revision 1.1.3.3 1993/07/27 18:28:31 elliston ! 53: * Add ANSI prototypes. CR #9523. ! 54: * [1993/07/27 18:13:30 elliston] ! 55: * ! 56: * Revision 1.1.3.2 1993/06/02 23:13:14 jeffc ! 57: * Added to OSF/1 R1.3 from NMK15.0. ! 58: * [1993/06/02 20:57:54 jeffc] ! 59: * ! 60: * Revision 1.1 1992/09/30 02:01:33 robert ! 61: * Initial revision ! 62: * ! 63: * $EndLog$ ! 64: */ ! 65: /* CMU_HIST */ ! 66: /* ! 67: * Revision 2.7 91/10/09 16:04:32 af ! 68: * Revision 2.6.3.1 91/10/05 13:08:50 jeffreyh ! 69: * Added user space watch point support including non current task. ! 70: * Changed "map" field of db_watchpoint structure to "task" ! 71: * for a user to easily understand the target space. ! 72: * [91/08/29 tak] ! 73: * ! 74: * Revision 2.6.3.1 91/10/05 13:08:50 jeffreyh ! 75: * Added user space watch point support including non current task. ! 76: * Changed "map" field of db_watchpoint structure to "task" ! 77: * for a user to easily understand the target space. ! 78: * [91/08/29 tak] ! 79: * ! 80: * Revision 2.6 91/05/14 15:37:30 mrt ! 81: * Correcting copyright ! 82: * ! 83: * Revision 2.5 91/02/05 17:07:27 mrt ! 84: * Changed to new Mach copyright ! 85: * [91/01/31 16:20:02 mrt] ! 86: * ! 87: * Revision 2.4 91/01/08 15:09:24 rpd ! 88: * Use db_map_equal, db_map_current, db_map_addr. ! 89: * [90/11/10 rpd] ! 90: * ! 91: * Revision 2.3 90/11/05 14:26:39 rpd ! 92: * Initialize db_watchpoints_inserted to TRUE. ! 93: * [90/11/04 rpd] ! 94: * ! 95: * Revision 2.2 90/10/25 14:44:16 rwd ! 96: * Made db_watchpoint_cmd parse a size argument. ! 97: * [90/10/17 rpd] ! 98: * Generalized the watchpoint support. ! 99: * [90/10/16 rwd] ! 100: * Created. ! 101: * [90/10/16 rpd] ! 102: * ! 103: */ ! 104: /* CMU_ENDHIST */ ! 105: /* ! 106: * Mach Operating System ! 107: * Copyright (c) 1991,1990 Carnegie Mellon University ! 108: * All Rights Reserved. ! 109: * ! 110: * Permission to use, copy, modify and distribute this software and its ! 111: * documentation is hereby granted, provided that both the copyright ! 112: * notice and this permission notice appear in all copies of the ! 113: * software, derivative works or modified versions, and any portions ! 114: * thereof, and that both notices appear in supporting documentation. ! 115: * ! 116: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 117: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 118: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 119: * ! 120: * Carnegie Mellon requests users of this software to return to ! 121: * ! 122: * Software Distribution Coordinator or [email protected] ! 123: * School of Computer Science ! 124: * Carnegie Mellon University ! 125: * Pittsburgh PA 15213-3890 ! 126: * ! 127: * any improvements or extensions that they make and grant Carnegie Mellon ! 128: * the rights to redistribute these changes. ! 129: */ ! 130: /* ! 131: */ ! 132: /* ! 133: * Author: Richard P. Draves, Carnegie Mellon University ! 134: * Date: 10/90 ! 135: */ ! 136: ! 137: #include <mach/boolean.h> ! 138: #include <mach/vm_param.h> ! 139: #include <mach/machine/vm_types.h> ! 140: #include <mach/machine/vm_param.h> ! 141: #include <vm/vm_map.h> ! 142: ! 143: #include <machine/db_machdep.h> ! 144: #include <ddb/db_lex.h> ! 145: #include <ddb/db_watch.h> ! 146: #include <ddb/db_access.h> ! 147: #include <ddb/db_sym.h> ! 148: #include <ddb/db_task_thread.h> ! 149: #include <ddb/db_command.h> ! 150: #include <ddb/db_expr.h> ! 151: #include <ddb/db_output.h> /* For db_printf() */ ! 152: #include <ddb/db_run.h> /* For db_single_step() */ ! 153: ! 154: /* ! 155: * Watchpoints. ! 156: */ ! 157: ! 158: boolean_t db_watchpoints_inserted = TRUE; ! 159: ! 160: #define NWATCHPOINTS 100 ! 161: struct db_watchpoint db_watch_table[NWATCHPOINTS]; ! 162: db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0]; ! 163: db_watchpoint_t db_free_watchpoints = 0; ! 164: db_watchpoint_t db_watchpoint_list = 0; ! 165: ! 166: extern vm_map_t kernel_map; ! 167: ! 168: ! 169: ! 170: /* Prototypes for functions local to this file. XXX -- should be static. ! 171: */ ! 172: ! 173: db_watchpoint_t db_watchpoint_alloc(void); ! 174: ! 175: void db_watchpoint_free(register db_watchpoint_t watch); ! 176: ! 177: void db_set_watchpoint( ! 178: task_t task, ! 179: db_addr_t addr, ! 180: vm_size_t size); ! 181: ! 182: void db_delete_watchpoint( ! 183: task_t task, ! 184: db_addr_t addr); ! 185: ! 186: static int db_get_task( ! 187: char *modif, ! 188: task_t *taskp, ! 189: db_addr_t addr); ! 190: ! 191: void db_list_watchpoints(void); ! 192: ! 193: ! 194: ! 195: db_watchpoint_t ! 196: db_watchpoint_alloc(void) ! 197: { ! 198: register db_watchpoint_t watch; ! 199: ! 200: if ((watch = db_free_watchpoints) != 0) { ! 201: db_free_watchpoints = watch->link; ! 202: return (watch); ! 203: } ! 204: if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) { ! 205: db_printf("All watchpoints used.\n"); ! 206: return (0); ! 207: } ! 208: watch = db_next_free_watchpoint; ! 209: db_next_free_watchpoint++; ! 210: ! 211: return (watch); ! 212: } ! 213: ! 214: void ! 215: db_watchpoint_free(register db_watchpoint_t watch) ! 216: { ! 217: watch->link = db_free_watchpoints; ! 218: db_free_watchpoints = watch; ! 219: } ! 220: ! 221: void ! 222: db_set_watchpoint( ! 223: task_t task, ! 224: db_addr_t addr, ! 225: vm_size_t size) ! 226: { ! 227: register db_watchpoint_t watch; ! 228: ! 229: /* ! 230: * Should we do anything fancy with overlapping regions? ! 231: */ ! 232: ! 233: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) { ! 234: if (watch->task == task && ! 235: (watch->loaddr == addr) && ! 236: (watch->hiaddr == addr+size)) { ! 237: db_printf("Already set.\n"); ! 238: return; ! 239: } ! 240: } ! 241: ! 242: watch = db_watchpoint_alloc(); ! 243: if (watch == 0) { ! 244: db_printf("Too many watchpoints.\n"); ! 245: return; ! 246: } ! 247: ! 248: watch->task = task; ! 249: watch->loaddr = addr; ! 250: watch->hiaddr = addr+size; ! 251: ! 252: watch->link = db_watchpoint_list; ! 253: db_watchpoint_list = watch; ! 254: ! 255: db_watchpoints_inserted = FALSE; ! 256: } ! 257: ! 258: void ! 259: db_delete_watchpoint( ! 260: task_t task, ! 261: db_addr_t addr) ! 262: { ! 263: register db_watchpoint_t watch; ! 264: register db_watchpoint_t *prev; ! 265: ! 266: for (prev = &db_watchpoint_list; (watch = *prev) != 0; ! 267: prev = &watch->link) { ! 268: if (watch->task == task && ! 269: (watch->loaddr <= addr) && ! 270: (addr < watch->hiaddr)) { ! 271: *prev = watch->link; ! 272: db_watchpoint_free(watch); ! 273: return; ! 274: } ! 275: } ! 276: ! 277: db_printf("Not set.\n"); ! 278: } ! 279: ! 280: void ! 281: db_list_watchpoints(void) ! 282: { ! 283: register db_watchpoint_t watch; ! 284: int task_id; ! 285: ! 286: if (db_watchpoint_list == 0) { ! 287: db_printf("No watchpoints set\n"); ! 288: return; ! 289: } ! 290: ! 291: db_printf("Space Address Size\n"); ! 292: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) { ! 293: if (watch->task == TASK_NULL) ! 294: db_printf("kernel "); ! 295: else { ! 296: task_id = db_lookup_task(watch->task); ! 297: if (task_id < 0) ! 298: db_printf("%*X", 2*sizeof(vm_offset_t), watch->task); ! 299: else ! 300: db_printf("task%-3d ", task_id); ! 301: } ! 302: db_printf(" %*X %X\n", 2*sizeof(vm_offset_t), watch->loaddr, ! 303: watch->hiaddr - watch->loaddr); ! 304: } ! 305: } ! 306: ! 307: static int ! 308: db_get_task( ! 309: char *modif, ! 310: task_t *taskp, ! 311: db_addr_t addr) ! 312: { ! 313: task_t task = TASK_NULL; ! 314: db_expr_t value; ! 315: boolean_t user_space; ! 316: ! 317: user_space = db_option(modif, 'T'); ! 318: if (user_space) { ! 319: if (db_expression(&value)) { ! 320: task = (task_t)value; ! 321: if (db_lookup_task(task) < 0) { ! 322: db_printf("bad task address %X\n", task); ! 323: return(-1); ! 324: } ! 325: } else { ! 326: task = db_default_task; ! 327: if (task == TASK_NULL) { ! 328: if ((task = db_current_task()) == TASK_NULL) { ! 329: db_printf("no task\n"); ! 330: return(-1); ! 331: } ! 332: } ! 333: } ! 334: } ! 335: if (!DB_VALID_ADDRESS(addr, user_space)) { ! 336: db_printf("Address %#X is not in %s space\n", addr, ! 337: (user_space)? "user": "kernel"); ! 338: return(-1); ! 339: } ! 340: *taskp = task; ! 341: return(0); ! 342: } ! 343: ! 344: /* Delete watchpoint */ ! 345: void ! 346: db_deletewatch_cmd( ! 347: db_expr_t addr, ! 348: int have_addr, ! 349: db_expr_t count, ! 350: char * modif) ! 351: { ! 352: task_t task; ! 353: ! 354: if (db_get_task(modif, &task, addr) < 0) ! 355: return; ! 356: db_delete_watchpoint(task, addr); ! 357: } ! 358: ! 359: /* Set watchpoint */ ! 360: void ! 361: db_watchpoint_cmd( ! 362: db_expr_t addr, ! 363: int have_addr, ! 364: db_expr_t count, ! 365: char * modif) ! 366: { ! 367: vm_size_t size; ! 368: db_expr_t value; ! 369: task_t task; ! 370: ! 371: if (db_get_task(modif, &task, addr) < 0) ! 372: return; ! 373: if (db_expression(&value)) ! 374: size = (vm_size_t) value; ! 375: else ! 376: size = sizeof(int); ! 377: db_set_watchpoint(task, addr, size); ! 378: } ! 379: ! 380: /* list watchpoints */ ! 381: void ! 382: db_listwatch_cmd(void) ! 383: { ! 384: db_list_watchpoints(); ! 385: } ! 386: ! 387: void ! 388: db_set_watchpoints(void) ! 389: { ! 390: register db_watchpoint_t watch; ! 391: vm_map_t map; ! 392: ! 393: if (!db_watchpoints_inserted) { ! 394: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) { ! 395: map = (watch->task)? watch->task->map: kernel_map; ! 396: pmap_protect(map->pmap, ! 397: trunc_page(watch->loaddr), ! 398: round_page(watch->hiaddr), ! 399: VM_PROT_READ); ! 400: } ! 401: db_watchpoints_inserted = TRUE; ! 402: } ! 403: } ! 404: ! 405: void ! 406: db_clear_watchpoints(void) ! 407: { ! 408: db_watchpoints_inserted = FALSE; ! 409: } ! 410: ! 411: boolean_t ! 412: db_find_watchpoint( ! 413: vm_map_t map, ! 414: db_addr_t addr, ! 415: db_regs_t *regs) ! 416: { ! 417: register db_watchpoint_t watch; ! 418: db_watchpoint_t found = 0; ! 419: register task_t task_space; ! 420: ! 421: task_space = (vm_map_pmap(map) == kernel_pmap)? ! 422: TASK_NULL: db_current_space(); ! 423: for (watch = db_watchpoint_list; watch != 0; watch = watch->link) { ! 424: if (watch->task == task_space) { ! 425: if ((watch->loaddr <= addr) && (addr < watch->hiaddr)) ! 426: return (TRUE); ! 427: else if ((trunc_page(watch->loaddr) <= addr) && ! 428: (addr < round_page(watch->hiaddr))) ! 429: found = watch; ! 430: } ! 431: } ! 432: ! 433: /* ! 434: * We didn't hit exactly on a watchpoint, but we are ! 435: * in a protected region. We want to single-step ! 436: * and then re-protect. ! 437: */ ! 438: ! 439: if (found) { ! 440: db_watchpoints_inserted = FALSE; ! 441: db_single_step(regs, task_space); ! 442: } ! 443: ! 444: return (FALSE); ! 445: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.