|
|
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_break.c,v $ ! 29: * Revision 1.1 1992/03/25 21:44:57 pace ! 30: * Initial revision ! 31: * ! 32: * Revision 2.7 91/02/05 17:06:00 mrt ! 33: * Changed to new Mach copyright ! 34: * [91/01/31 16:17:01 mrt] ! 35: * ! 36: * Revision 2.6 91/01/08 15:09:03 rpd ! 37: * Added db_map_equal, db_map_current, db_map_addr. ! 38: * [90/11/10 rpd] ! 39: * ! 40: * Revision 2.5 90/11/05 14:26:32 rpd ! 41: * Initialize db_breakpoints_inserted to TRUE. ! 42: * [90/11/04 rpd] ! 43: * ! 44: * Revision 2.4 90/10/25 14:43:33 rwd ! 45: * Added map field to breakpoints. ! 46: * Added map argument to db_set_breakpoint, db_delete_breakpoint, ! 47: * db_find_breakpoint. Added db_find_breakpoint_here. ! 48: * [90/10/18 rpd] ! 49: * ! 50: * Revision 2.3 90/09/28 16:57:07 jsb ! 51: * Fixed db_breakpoint_free. ! 52: * [90/09/18 rpd] ! 53: * ! 54: * Revision 2.2 90/08/27 21:49:53 dbg ! 55: * Reflected changes in db_printsym()'s calling seq. ! 56: * [90/08/20 af] ! 57: * Clear breakpoints only if inserted. ! 58: * Reduce lint. ! 59: * [90/08/07 dbg] ! 60: * Created. ! 61: * [90/07/25 dbg] ! 62: * ! 63: */ ! 64: /* ! 65: * Author: David B. Golub, Carnegie Mellon University ! 66: * Date: 7/90 ! 67: */ ! 68: /* ! 69: * Breakpoints. ! 70: */ ! 71: #include "param.h" ! 72: #include "proc.h" ! 73: #include <machine/db_machdep.h> /* type definitions */ ! 74: ! 75: #include <ddb/db_lex.h> ! 76: #include <ddb/db_break.h> ! 77: #include <ddb/db_access.h> ! 78: #include <ddb/db_sym.h> ! 79: #include <ddb/db_break.h> ! 80: ! 81: extern boolean_t db_map_equal(); ! 82: extern boolean_t db_map_current(); ! 83: extern vm_map_t db_map_addr(); ! 84: ! 85: #define NBREAKPOINTS 100 ! 86: struct db_breakpoint db_break_table[NBREAKPOINTS]; ! 87: db_breakpoint_t db_next_free_breakpoint = &db_break_table[0]; ! 88: db_breakpoint_t db_free_breakpoints = 0; ! 89: db_breakpoint_t db_breakpoint_list = 0; ! 90: ! 91: db_breakpoint_t ! 92: db_breakpoint_alloc() ! 93: { ! 94: register db_breakpoint_t bkpt; ! 95: ! 96: if ((bkpt = db_free_breakpoints) != 0) { ! 97: db_free_breakpoints = bkpt->link; ! 98: return (bkpt); ! 99: } ! 100: if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) { ! 101: db_printf("All breakpoints used.\n"); ! 102: return (0); ! 103: } ! 104: bkpt = db_next_free_breakpoint; ! 105: db_next_free_breakpoint++; ! 106: ! 107: return (bkpt); ! 108: } ! 109: ! 110: void ! 111: db_breakpoint_free(bkpt) ! 112: register db_breakpoint_t bkpt; ! 113: { ! 114: bkpt->link = db_free_breakpoints; ! 115: db_free_breakpoints = bkpt; ! 116: } ! 117: ! 118: void ! 119: db_set_breakpoint(map, addr, count) ! 120: vm_map_t map; ! 121: db_addr_t addr; ! 122: int count; ! 123: { ! 124: register db_breakpoint_t bkpt; ! 125: ! 126: if (db_find_breakpoint(map, addr)) { ! 127: db_printf("Already set.\n"); ! 128: return; ! 129: } ! 130: ! 131: bkpt = db_breakpoint_alloc(); ! 132: if (bkpt == 0) { ! 133: db_printf("Too many breakpoints.\n"); ! 134: return; ! 135: } ! 136: ! 137: bkpt->map = map; ! 138: bkpt->address = addr; ! 139: bkpt->flags = 0; ! 140: bkpt->init_count = count; ! 141: bkpt->count = count; ! 142: ! 143: bkpt->link = db_breakpoint_list; ! 144: db_breakpoint_list = bkpt; ! 145: } ! 146: ! 147: void ! 148: db_delete_breakpoint(map, addr) ! 149: vm_map_t map; ! 150: db_addr_t addr; ! 151: { ! 152: register db_breakpoint_t bkpt; ! 153: register db_breakpoint_t *prev; ! 154: ! 155: for (prev = &db_breakpoint_list; ! 156: (bkpt = *prev) != 0; ! 157: prev = &bkpt->link) { ! 158: if (db_map_equal(bkpt->map, map) && ! 159: (bkpt->address == addr)) { ! 160: *prev = bkpt->link; ! 161: break; ! 162: } ! 163: } ! 164: if (bkpt == 0) { ! 165: db_printf("Not set.\n"); ! 166: return; ! 167: } ! 168: ! 169: db_breakpoint_free(bkpt); ! 170: } ! 171: ! 172: db_breakpoint_t ! 173: db_find_breakpoint(map, addr) ! 174: vm_map_t map; ! 175: db_addr_t addr; ! 176: { ! 177: register db_breakpoint_t bkpt; ! 178: ! 179: for (bkpt = db_breakpoint_list; ! 180: bkpt != 0; ! 181: bkpt = bkpt->link) ! 182: { ! 183: if (db_map_equal(bkpt->map, map) && ! 184: (bkpt->address == addr)) ! 185: return (bkpt); ! 186: } ! 187: return (0); ! 188: } ! 189: ! 190: db_breakpoint_t ! 191: db_find_breakpoint_here(addr) ! 192: db_addr_t addr; ! 193: { ! 194: return db_find_breakpoint(db_map_addr(addr), addr); ! 195: } ! 196: ! 197: boolean_t db_breakpoints_inserted = TRUE; ! 198: ! 199: void ! 200: db_set_breakpoints() ! 201: { ! 202: register db_breakpoint_t bkpt; ! 203: ! 204: if (!db_breakpoints_inserted) { ! 205: ! 206: for (bkpt = db_breakpoint_list; ! 207: bkpt != 0; ! 208: bkpt = bkpt->link) ! 209: if (db_map_current(bkpt->map)) { ! 210: bkpt->bkpt_inst = db_get_value(bkpt->address, ! 211: BKPT_SIZE, ! 212: FALSE); ! 213: db_put_value(bkpt->address, ! 214: BKPT_SIZE, ! 215: BKPT_SET(bkpt->bkpt_inst)); ! 216: } ! 217: db_breakpoints_inserted = TRUE; ! 218: } ! 219: } ! 220: ! 221: void ! 222: db_clear_breakpoints() ! 223: { ! 224: register db_breakpoint_t bkpt; ! 225: ! 226: if (db_breakpoints_inserted) { ! 227: ! 228: for (bkpt = db_breakpoint_list; ! 229: bkpt != 0; ! 230: bkpt = bkpt->link) ! 231: if (db_map_current(bkpt->map)) { ! 232: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); ! 233: } ! 234: db_breakpoints_inserted = FALSE; ! 235: } ! 236: } ! 237: ! 238: /* ! 239: * Set a temporary breakpoint. ! 240: * The instruction is changed immediately, ! 241: * so the breakpoint does not have to be on the breakpoint list. ! 242: */ ! 243: db_breakpoint_t ! 244: db_set_temp_breakpoint(addr) ! 245: db_addr_t addr; ! 246: { ! 247: register db_breakpoint_t bkpt; ! 248: ! 249: bkpt = db_breakpoint_alloc(); ! 250: if (bkpt == 0) { ! 251: db_printf("Too many breakpoints.\n"); ! 252: return 0; ! 253: } ! 254: ! 255: bkpt->map = NULL; ! 256: bkpt->address = addr; ! 257: bkpt->flags = BKPT_TEMP; ! 258: bkpt->init_count = 1; ! 259: bkpt->count = 1; ! 260: ! 261: bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE); ! 262: db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst)); ! 263: return bkpt; ! 264: } ! 265: ! 266: void ! 267: db_delete_temp_breakpoint(bkpt) ! 268: db_breakpoint_t bkpt; ! 269: { ! 270: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); ! 271: db_breakpoint_free(bkpt); ! 272: } ! 273: ! 274: /* ! 275: * List breakpoints. ! 276: */ ! 277: void ! 278: db_list_breakpoints() ! 279: { ! 280: register db_breakpoint_t bkpt; ! 281: ! 282: if (db_breakpoint_list == 0) { ! 283: db_printf("No breakpoints set\n"); ! 284: return; ! 285: } ! 286: ! 287: db_printf(" Map Count Address\n"); ! 288: for (bkpt = db_breakpoint_list; ! 289: bkpt != 0; ! 290: bkpt = bkpt->link) ! 291: { ! 292: db_printf("%s%8x %5d ", ! 293: db_map_current(bkpt->map) ? "*" : " ", ! 294: bkpt->map, bkpt->init_count); ! 295: db_printsym(bkpt->address, DB_STGY_PROC); ! 296: db_printf("\n"); ! 297: } ! 298: } ! 299: ! 300: /* Delete breakpoint */ ! 301: /*ARGSUSED*/ ! 302: void ! 303: db_delete_cmd(addr, have_addr, count, modif) ! 304: db_expr_t addr; ! 305: int have_addr; ! 306: db_expr_t count; ! 307: char * modif; ! 308: { ! 309: db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr); ! 310: } ! 311: ! 312: /* Set breakpoint with skip count */ ! 313: /*ARGSUSED*/ ! 314: void ! 315: db_breakpoint_cmd(addr, have_addr, count, modif) ! 316: db_expr_t addr; ! 317: int have_addr; ! 318: db_expr_t count; ! 319: char * modif; ! 320: { ! 321: if (count == -1) ! 322: count = 1; ! 323: ! 324: db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count); ! 325: } ! 326: ! 327: /* list breakpoints */ ! 328: void ! 329: db_listbreak_cmd() ! 330: { ! 331: db_list_breakpoints(); ! 332: } ! 333: ! 334: #include <vm/vm_kern.h> ! 335: ! 336: /* ! 337: * We want ddb to be usable before most of the kernel has been ! 338: * initialized. In particular, current_thread() or kernel_map ! 339: * (or both) may be null. ! 340: */ ! 341: ! 342: boolean_t ! 343: db_map_equal(map1, map2) ! 344: vm_map_t map1, map2; ! 345: { ! 346: return ((map1 == map2) || ! 347: ((map1 == NULL) && (map2 == kernel_map)) || ! 348: ((map1 == kernel_map) && (map2 == NULL))); ! 349: } ! 350: ! 351: boolean_t ! 352: db_map_current(map) ! 353: vm_map_t map; ! 354: { ! 355: #if 0 ! 356: thread_t thread; ! 357: ! 358: return ((map == NULL) || ! 359: (map == kernel_map) || ! 360: (((thread = current_thread()) != NULL) && ! 361: (map == thread->task->map))); ! 362: #else ! 363: return (1); ! 364: #endif ! 365: } ! 366: ! 367: vm_map_t ! 368: db_map_addr(addr) ! 369: vm_offset_t addr; ! 370: { ! 371: #if 0 ! 372: thread_t thread; ! 373: ! 374: /* ! 375: * We want to return kernel_map for all ! 376: * non-user addresses, even when debugging ! 377: * kernel tasks with their own maps. ! 378: */ ! 379: ! 380: if ((VM_MIN_ADDRESS <= addr) && ! 381: (addr < VM_MAX_ADDRESS) && ! 382: ((thread = current_thread()) != NULL)) ! 383: return thread->task->map; ! 384: else ! 385: #endif ! 386: return kernel_map; ! 387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.