|
|
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: David B. Golub, Carnegie Mellon University ! 28: * Date: 7/90 ! 29: */ ! 30: #include "mach_kdb.h" ! 31: #if MACH_KDB ! 32: ! 33: ! 34: /* ! 35: * Breakpoints. ! 36: */ ! 37: #include <mach/boolean.h> ! 38: #include <machine/db_machdep.h> ! 39: #include <ddb/db_lex.h> ! 40: #include <ddb/db_break.h> ! 41: #include <ddb/db_access.h> ! 42: #include <ddb/db_sym.h> ! 43: #include <ddb/db_variables.h> ! 44: #include <ddb/db_command.h> ! 45: #include <ddb/db_task_thread.h> ! 46: ! 47: #define NBREAKPOINTS 100 ! 48: #define NTHREAD_LIST (NBREAKPOINTS*3) ! 49: ! 50: struct db_breakpoint db_break_table[NBREAKPOINTS]; ! 51: db_breakpoint_t db_next_free_breakpoint = &db_break_table[0]; ! 52: db_breakpoint_t db_free_breakpoints = 0; ! 53: db_breakpoint_t db_breakpoint_list = 0; ! 54: ! 55: static struct db_thread_breakpoint db_thread_break_list[NTHREAD_LIST]; ! 56: static db_thread_breakpoint_t db_free_thread_break_list = 0; ! 57: static boolean_t db_thread_break_init = FALSE; ! 58: static int db_breakpoint_number = 0; ! 59: ! 60: db_breakpoint_t ! 61: db_breakpoint_alloc() ! 62: { ! 63: register db_breakpoint_t bkpt; ! 64: ! 65: if ((bkpt = db_free_breakpoints) != 0) { ! 66: db_free_breakpoints = bkpt->link; ! 67: return (bkpt); ! 68: } ! 69: if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) { ! 70: db_printf("All breakpoints used.\n"); ! 71: return (0); ! 72: } ! 73: bkpt = db_next_free_breakpoint; ! 74: db_next_free_breakpoint++; ! 75: ! 76: return (bkpt); ! 77: } ! 78: ! 79: void ! 80: db_breakpoint_free(bkpt) ! 81: register db_breakpoint_t bkpt; ! 82: { ! 83: bkpt->link = db_free_breakpoints; ! 84: db_free_breakpoints = bkpt; ! 85: } ! 86: ! 87: static int ! 88: db_add_thread_breakpoint(bkpt, task_thd, count, task_bpt) ! 89: register db_breakpoint_t bkpt; ! 90: vm_offset_t task_thd; ! 91: boolean_t task_bpt; ! 92: { ! 93: register db_thread_breakpoint_t tp; ! 94: ! 95: if (db_thread_break_init == FALSE) { ! 96: for (tp = db_thread_break_list; ! 97: tp < &db_thread_break_list[NTHREAD_LIST-1]; tp++) ! 98: tp->tb_next = tp+1; ! 99: tp->tb_next = 0; ! 100: db_free_thread_break_list = db_thread_break_list; ! 101: db_thread_break_init = TRUE; ! 102: } ! 103: if (db_free_thread_break_list == 0) ! 104: return (-1); ! 105: tp = db_free_thread_break_list; ! 106: db_free_thread_break_list = tp->tb_next; ! 107: tp->tb_is_task = task_bpt; ! 108: tp->tb_task_thd = task_thd; ! 109: tp->tb_count = count; ! 110: tp->tb_init_count = count; ! 111: tp->tb_cond = 0; ! 112: tp->tb_number = ++db_breakpoint_number; ! 113: tp->tb_next = bkpt->threads; ! 114: bkpt->threads = tp; ! 115: return(0); ! 116: } ! 117: ! 118: static int ! 119: db_delete_thread_breakpoint(bkpt, task_thd) ! 120: register db_breakpoint_t bkpt; ! 121: vm_offset_t task_thd; ! 122: { ! 123: register db_thread_breakpoint_t tp; ! 124: register db_thread_breakpoint_t *tpp; ! 125: void db_cond_free(); ! 126: ! 127: if (task_thd == 0) { ! 128: /* delete all the thread-breakpoints */ ! 129: ! 130: for (tpp = &bkpt->threads; (tp = *tpp) != 0; tpp = &tp->tb_next) ! 131: db_cond_free(tp); ! 132: ! 133: *tpp = db_free_thread_break_list; ! 134: db_free_thread_break_list = bkpt->threads; ! 135: bkpt->threads = 0; ! 136: return 0; ! 137: } else { ! 138: /* delete the specified thread-breakpoint */ ! 139: ! 140: for (tpp = &bkpt->threads; (tp = *tpp) != 0; tpp = &tp->tb_next) ! 141: if (tp->tb_task_thd == task_thd) { ! 142: db_cond_free(tp); ! 143: *tpp = tp->tb_next; ! 144: tp->tb_next = db_free_thread_break_list; ! 145: db_free_thread_break_list = tp; ! 146: return 0; ! 147: } ! 148: ! 149: return -1; /* not found */ ! 150: } ! 151: } ! 152: ! 153: static db_thread_breakpoint_t ! 154: db_find_thread_breakpoint(bkpt, thread) ! 155: db_breakpoint_t bkpt; ! 156: thread_t thread; ! 157: { ! 158: register db_thread_breakpoint_t tp; ! 159: register task_t task = (thread == THREAD_NULL)? TASK_NULL: thread->task; ! 160: ! 161: for (tp = bkpt->threads; tp; tp = tp->tb_next) { ! 162: if (tp->tb_is_task) { ! 163: if (tp->tb_task_thd == (vm_offset_t)task) ! 164: break; ! 165: continue; ! 166: } ! 167: if (tp->tb_task_thd == (vm_offset_t)thread || tp->tb_task_thd == 0) ! 168: break; ! 169: } ! 170: return(tp); ! 171: } ! 172: ! 173: db_thread_breakpoint_t ! 174: db_find_thread_breakpoint_here(task, addr) ! 175: task_t task; ! 176: db_addr_t addr; ! 177: { ! 178: db_breakpoint_t bkpt; ! 179: ! 180: bkpt = db_find_breakpoint(task, (db_addr_t)addr); ! 181: if (bkpt == 0) ! 182: return(0); ! 183: return(db_find_thread_breakpoint(bkpt, current_thread())); ! 184: } ! 185: ! 186: db_thread_breakpoint_t ! 187: db_find_breakpoint_number(num, bkptp) ! 188: int num; ! 189: db_breakpoint_t *bkptp; ! 190: { ! 191: register db_thread_breakpoint_t tp; ! 192: register db_breakpoint_t bkpt; ! 193: ! 194: for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { ! 195: for (tp = bkpt->threads; tp; tp = tp->tb_next) { ! 196: if (tp->tb_number == num) { ! 197: if (bkptp) ! 198: *bkptp = bkpt; ! 199: return(tp); ! 200: } ! 201: } ! 202: } ! 203: return(0); ! 204: } ! 205: ! 206: static void ! 207: db_force_delete_breakpoint(bkpt, task_thd, is_task) ! 208: db_breakpoint_t bkpt; ! 209: vm_offset_t task_thd; ! 210: boolean_t is_task; ! 211: { ! 212: db_printf("deleted a stale breakpoint at "); ! 213: if (bkpt->task == TASK_NULL || db_lookup_task(bkpt->task) >= 0) ! 214: db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task); ! 215: else ! 216: db_printf("%#X", bkpt->address); ! 217: if (bkpt->task) ! 218: db_printf(" in task %X", bkpt->task); ! 219: if (task_thd) ! 220: db_printf(" for %s %X", (is_task)? "task": "thread", task_thd); ! 221: db_printf("\n"); ! 222: db_delete_thread_breakpoint(bkpt, task_thd); ! 223: } ! 224: ! 225: void ! 226: db_check_breakpoint_valid() ! 227: { ! 228: register db_thread_breakpoint_t tbp, tbp_next; ! 229: register db_breakpoint_t bkpt, *bkptp; ! 230: ! 231: bkptp = &db_breakpoint_list; ! 232: for (bkpt = *bkptp; bkpt; bkpt = *bkptp) { ! 233: if (bkpt->task != TASK_NULL) { ! 234: if (db_lookup_task(bkpt->task) < 0) { ! 235: db_force_delete_breakpoint(bkpt, 0, FALSE); ! 236: *bkptp = bkpt->link; ! 237: db_breakpoint_free(bkpt); ! 238: continue; ! 239: } ! 240: } else { ! 241: for (tbp = bkpt->threads; tbp; tbp = tbp_next) { ! 242: tbp_next = tbp->tb_next; ! 243: if (tbp->tb_task_thd == 0) ! 244: continue; ! 245: if ((tbp->tb_is_task && ! 246: db_lookup_task((task_t)(tbp->tb_task_thd)) < 0) || ! 247: (!tbp->tb_is_task && ! 248: db_lookup_thread((thread_t)(tbp->tb_task_thd)) < 0)) { ! 249: db_force_delete_breakpoint(bkpt, ! 250: tbp->tb_task_thd, tbp->tb_is_task); ! 251: } ! 252: } ! 253: if (bkpt->threads == 0) { ! 254: db_put_task_value(bkpt->address, BKPT_SIZE, ! 255: bkpt->bkpt_inst, bkpt->task); ! 256: *bkptp = bkpt->link; ! 257: db_breakpoint_free(bkpt); ! 258: continue; ! 259: } ! 260: } ! 261: bkptp = &bkpt->link; ! 262: } ! 263: } ! 264: ! 265: void ! 266: db_set_breakpoint(task, addr, count, thread, task_bpt) ! 267: task_t task; ! 268: db_addr_t addr; ! 269: int count; ! 270: thread_t thread; ! 271: boolean_t task_bpt; ! 272: { ! 273: register db_breakpoint_t bkpt; ! 274: db_breakpoint_t alloc_bkpt = 0; ! 275: vm_offset_t task_thd; ! 276: ! 277: bkpt = db_find_breakpoint(task, addr); ! 278: if (bkpt) { ! 279: if (thread == THREAD_NULL ! 280: || db_find_thread_breakpoint(bkpt, thread)) { ! 281: db_printf("Already set.\n"); ! 282: return; ! 283: } ! 284: } else { ! 285: if (!DB_CHECK_ACCESS(addr, BKPT_SIZE, task)) { ! 286: db_printf("Cannot set break point at %X\n", addr); ! 287: return; ! 288: } ! 289: alloc_bkpt = bkpt = db_breakpoint_alloc(); ! 290: if (bkpt == 0) { ! 291: db_printf("Too many breakpoints.\n"); ! 292: return; ! 293: } ! 294: bkpt->task = task; ! 295: bkpt->flags = (task && thread == THREAD_NULL)? ! 296: (BKPT_USR_GLOBAL|BKPT_1ST_SET): 0; ! 297: bkpt->address = addr; ! 298: bkpt->threads = 0; ! 299: } ! 300: if (db_breakpoint_list == 0) ! 301: db_breakpoint_number = 0; ! 302: task_thd = (task_bpt)? (vm_offset_t)(thread->task): (vm_offset_t)thread; ! 303: if (db_add_thread_breakpoint(bkpt, task_thd, count, task_bpt) < 0) { ! 304: if (alloc_bkpt) ! 305: db_breakpoint_free(alloc_bkpt); ! 306: db_printf("Too many thread_breakpoints.\n"); ! 307: } else { ! 308: db_printf("set breakpoint #%d\n", db_breakpoint_number); ! 309: if (alloc_bkpt) { ! 310: bkpt->link = db_breakpoint_list; ! 311: db_breakpoint_list = bkpt; ! 312: } ! 313: } ! 314: } ! 315: ! 316: void ! 317: db_delete_breakpoint(task, addr, task_thd) ! 318: task_t task; ! 319: db_addr_t addr; ! 320: vm_offset_t task_thd; ! 321: { ! 322: register db_breakpoint_t bkpt; ! 323: register db_breakpoint_t *prev; ! 324: ! 325: for (prev = &db_breakpoint_list; (bkpt = *prev) != 0; ! 326: prev = &bkpt->link) { ! 327: if ((bkpt->task == task ! 328: || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL))) ! 329: && bkpt->address == addr) ! 330: break; ! 331: } ! 332: if (bkpt && (bkpt->flags & BKPT_SET_IN_MEM)) { ! 333: db_printf("cannot delete it now.\n"); ! 334: return; ! 335: } ! 336: if (bkpt == 0 ! 337: || db_delete_thread_breakpoint(bkpt, task_thd) < 0) { ! 338: db_printf("Not set.\n"); ! 339: return; ! 340: } ! 341: if (bkpt->threads == 0) { ! 342: *prev = bkpt->link; ! 343: db_breakpoint_free(bkpt); ! 344: } ! 345: } ! 346: ! 347: db_breakpoint_t ! 348: db_find_breakpoint(task, addr) ! 349: task_t task; ! 350: db_addr_t addr; ! 351: { ! 352: register db_breakpoint_t bkpt; ! 353: ! 354: for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { ! 355: if ((bkpt->task == task ! 356: || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL))) ! 357: && bkpt->address == addr) ! 358: return (bkpt); ! 359: } ! 360: return (0); ! 361: } ! 362: ! 363: boolean_t ! 364: db_find_breakpoint_here(task, addr) ! 365: task_t task; ! 366: db_addr_t addr; ! 367: { ! 368: register db_breakpoint_t bkpt; ! 369: ! 370: for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { ! 371: if ((bkpt->task == task ! 372: || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL))) ! 373: && bkpt->address == addr) ! 374: return(TRUE); ! 375: if ((bkpt->flags & BKPT_USR_GLOBAL) == 0 && ! 376: DB_PHYS_EQ(task, (vm_offset_t)addr, bkpt->task, (vm_offset_t)bkpt->address)) ! 377: return (TRUE); ! 378: } ! 379: return(FALSE); ! 380: } ! 381: ! 382: boolean_t db_breakpoints_inserted = TRUE; ! 383: ! 384: void ! 385: db_set_breakpoints() ! 386: { ! 387: register db_breakpoint_t bkpt; ! 388: register task_t task; ! 389: db_expr_t inst; ! 390: task_t cur_task; ! 391: ! 392: cur_task = (current_thread())? current_thread()->task: TASK_NULL; ! 393: if (!db_breakpoints_inserted) { ! 394: for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { ! 395: if (bkpt->flags & BKPT_SET_IN_MEM) ! 396: continue; ! 397: task = bkpt->task; ! 398: if (bkpt->flags & BKPT_USR_GLOBAL) { ! 399: if ((bkpt->flags & BKPT_1ST_SET) == 0) { ! 400: if (cur_task == TASK_NULL) ! 401: continue; ! 402: task = cur_task; ! 403: } else ! 404: bkpt->flags &= ~BKPT_1ST_SET; ! 405: } ! 406: if (DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { ! 407: inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, ! 408: task); ! 409: if (inst == BKPT_SET(inst)) ! 410: continue; ! 411: bkpt->bkpt_inst = inst; ! 412: db_put_task_value(bkpt->address, ! 413: BKPT_SIZE, ! 414: BKPT_SET(bkpt->bkpt_inst), task); ! 415: bkpt->flags |= BKPT_SET_IN_MEM; ! 416: } else { ! 417: db_printf("Warning: cannot set breakpoint at %X ", ! 418: bkpt->address); ! 419: if (task) ! 420: db_printf("in task %X\n", task); ! 421: else ! 422: db_printf("in kernel space\n"); ! 423: } ! 424: } ! 425: db_breakpoints_inserted = TRUE; ! 426: } ! 427: } ! 428: ! 429: void ! 430: db_clear_breakpoints() ! 431: { ! 432: register db_breakpoint_t bkpt, *bkptp; ! 433: register task_t task; ! 434: task_t cur_task; ! 435: db_expr_t inst; ! 436: ! 437: cur_task = (current_thread())? current_thread()->task: TASK_NULL; ! 438: if (db_breakpoints_inserted) { ! 439: bkptp = &db_breakpoint_list; ! 440: for (bkpt = *bkptp; bkpt; bkpt = *bkptp) { ! 441: task = bkpt->task; ! 442: if (bkpt->flags & BKPT_USR_GLOBAL) { ! 443: if (cur_task == TASK_NULL) { ! 444: bkptp = &bkpt->link; ! 445: continue; ! 446: } ! 447: task = cur_task; ! 448: } ! 449: if ((bkpt->flags & BKPT_SET_IN_MEM) ! 450: && DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { ! 451: inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, ! 452: task); ! 453: if (inst != BKPT_SET(inst)) { ! 454: if (bkpt->flags & BKPT_USR_GLOBAL) { ! 455: bkptp = &bkpt->link; ! 456: continue; ! 457: } ! 458: db_force_delete_breakpoint(bkpt, 0, FALSE); ! 459: *bkptp = bkpt->link; ! 460: db_breakpoint_free(bkpt); ! 461: continue; ! 462: } ! 463: db_put_task_value(bkpt->address, BKPT_SIZE, ! 464: bkpt->bkpt_inst, task); ! 465: bkpt->flags &= ~BKPT_SET_IN_MEM; ! 466: } ! 467: bkptp = &bkpt->link; ! 468: } ! 469: db_breakpoints_inserted = FALSE; ! 470: } ! 471: } ! 472: ! 473: /* ! 474: * Set a temporary breakpoint. ! 475: * The instruction is changed immediately, ! 476: * so the breakpoint does not have to be on the breakpoint list. ! 477: */ ! 478: db_breakpoint_t ! 479: db_set_temp_breakpoint(task, addr) ! 480: task_t task; ! 481: db_addr_t addr; ! 482: { ! 483: register db_breakpoint_t bkpt; ! 484: ! 485: bkpt = db_breakpoint_alloc(); ! 486: if (bkpt == 0) { ! 487: db_printf("Too many breakpoints.\n"); ! 488: return 0; ! 489: } ! 490: bkpt->task = task; ! 491: bkpt->address = addr; ! 492: bkpt->flags = BKPT_TEMP; ! 493: bkpt->threads = 0; ! 494: if (db_add_thread_breakpoint(bkpt, 0, 1, FALSE) < 0) { ! 495: if (bkpt) ! 496: db_breakpoint_free(bkpt); ! 497: db_printf("Too many thread_breakpoints.\n"); ! 498: return 0; ! 499: } ! 500: bkpt->bkpt_inst = db_get_task_value(bkpt->address, BKPT_SIZE, ! 501: FALSE, task); ! 502: db_put_task_value(bkpt->address, BKPT_SIZE, ! 503: BKPT_SET(bkpt->bkpt_inst), task); ! 504: return bkpt; ! 505: } ! 506: ! 507: void ! 508: db_delete_temp_breakpoint(task, bkpt) ! 509: task_t task; ! 510: db_breakpoint_t bkpt; ! 511: { ! 512: db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, task); ! 513: db_delete_thread_breakpoint(bkpt, 0); ! 514: db_breakpoint_free(bkpt); ! 515: } ! 516: ! 517: /* ! 518: * List breakpoints. ! 519: */ ! 520: void ! 521: db_list_breakpoints() ! 522: { ! 523: register db_breakpoint_t bkpt; ! 524: ! 525: if (db_breakpoint_list == 0) { ! 526: db_printf("No breakpoints set\n"); ! 527: return; ! 528: } ! 529: ! 530: db_printf(" No Space Thread Cnt Address(Cond)\n"); ! 531: for (bkpt = db_breakpoint_list; ! 532: bkpt != 0; ! 533: bkpt = bkpt->link) ! 534: { ! 535: register db_thread_breakpoint_t tp; ! 536: int task_id; ! 537: int thread_id; ! 538: ! 539: if (bkpt->threads) { ! 540: for (tp = bkpt->threads; tp; tp = tp->tb_next) { ! 541: db_printf("%3d ", tp->tb_number); ! 542: if (bkpt->flags & BKPT_USR_GLOBAL) ! 543: db_printf("user "); ! 544: else if (bkpt->task == TASK_NULL) ! 545: db_printf("kernel "); ! 546: else if ((task_id = db_lookup_task(bkpt->task)) < 0) ! 547: db_printf("%0*X ", 2*sizeof(vm_offset_t), bkpt->task); ! 548: else ! 549: db_printf("task%-3d ", task_id); ! 550: if (tp->tb_task_thd == 0) { ! 551: db_printf("all "); ! 552: } else { ! 553: if (tp->tb_is_task) { ! 554: task_id = db_lookup_task((task_t)(tp->tb_task_thd)); ! 555: if (task_id < 0) ! 556: db_printf("%0*X ", 2*sizeof(vm_offset_t), ! 557: tp->tb_task_thd); ! 558: else ! 559: db_printf("task%03d ", task_id); ! 560: } else { ! 561: thread_t thd = (thread_t)(tp->tb_task_thd); ! 562: task_id = db_lookup_task(thd->task); ! 563: thread_id = db_lookup_task_thread(thd->task, thd); ! 564: if (task_id < 0 || thread_id < 0) ! 565: db_printf("%0*X ", 2*sizeof(vm_offset_t), ! 566: tp->tb_task_thd); ! 567: else ! 568: db_printf("task%03d.%-3d ", task_id, thread_id); ! 569: } ! 570: } ! 571: db_printf("%3d ", tp->tb_init_count); ! 572: db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task); ! 573: if (tp->tb_cond > 0) { ! 574: db_printf("("); ! 575: db_cond_print(tp); ! 576: db_printf(")"); ! 577: } ! 578: db_printf("\n"); ! 579: } ! 580: } else { ! 581: if (bkpt->task == TASK_NULL) ! 582: db_printf(" ? kernel "); ! 583: else ! 584: db_printf("%*X ", 2*sizeof(vm_offset_t), bkpt->task); ! 585: db_printf("(?) "); ! 586: db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task); ! 587: db_printf("\n"); ! 588: } ! 589: } ! 590: } ! 591: ! 592: /* Delete breakpoint */ ! 593: /*ARGSUSED*/ ! 594: void ! 595: db_delete_cmd() ! 596: { ! 597: register n; ! 598: thread_t thread; ! 599: vm_offset_t task_thd; ! 600: boolean_t user_global = FALSE; ! 601: boolean_t task_bpt = FALSE; ! 602: boolean_t user_space = FALSE; ! 603: boolean_t thd_bpt = FALSE; ! 604: db_expr_t addr; ! 605: int t; ! 606: ! 607: t = db_read_token(); ! 608: if (t == tSLASH) { ! 609: t = db_read_token(); ! 610: if (t != tIDENT) { ! 611: db_printf("Bad modifier \"%s\"\n", db_tok_string); ! 612: db_error(0); ! 613: } ! 614: user_global = db_option(db_tok_string, 'U'); ! 615: user_space = (user_global)? TRUE: db_option(db_tok_string, 'u'); ! 616: task_bpt = db_option(db_tok_string, 'T'); ! 617: thd_bpt = db_option(db_tok_string, 't'); ! 618: if (task_bpt && user_global) ! 619: db_error("Cannot specify both 'T' and 'U' option\n"); ! 620: t = db_read_token(); ! 621: } ! 622: if (t == tHASH) { ! 623: db_thread_breakpoint_t tbp; ! 624: db_breakpoint_t bkpt; ! 625: ! 626: if (db_read_token() != tNUMBER) { ! 627: db_printf("Bad break point number #%s\n", db_tok_string); ! 628: db_error(0); ! 629: } ! 630: if ((tbp = db_find_breakpoint_number(db_tok_number, &bkpt)) == 0) { ! 631: db_printf("No such break point #%d\n", db_tok_number); ! 632: db_error(0); ! 633: } ! 634: db_delete_breakpoint(bkpt->task, bkpt->address, tbp->tb_task_thd); ! 635: return; ! 636: } ! 637: db_unread_token(t); ! 638: if (!db_expression(&addr)) { ! 639: /* ! 640: * We attempt to pick up the user_space indication from db_dot, ! 641: * so that a plain "d" always works. ! 642: */ ! 643: addr = (db_expr_t)db_dot; ! 644: if (!user_space && !DB_VALID_ADDRESS((vm_offset_t)addr, FALSE)) ! 645: user_space = TRUE; ! 646: } ! 647: if (!DB_VALID_ADDRESS((vm_offset_t) addr, user_space)) { ! 648: db_printf("Address %#X is not in %s space\n", addr, ! 649: (user_space)? "user": "kernel"); ! 650: db_error(0); ! 651: } ! 652: if (thd_bpt || task_bpt) { ! 653: for (n = 0; db_get_next_thread(&thread, n); n++) { ! 654: if (thread == THREAD_NULL) ! 655: db_error("No active thread\n"); ! 656: if (task_bpt) { ! 657: if (thread->task == TASK_NULL) ! 658: db_error("No task\n"); ! 659: task_thd = (vm_offset_t) (thread->task); ! 660: } else ! 661: task_thd = (user_global)? 0: (vm_offset_t) thread; ! 662: db_delete_breakpoint(db_target_space(thread, user_space), ! 663: (db_addr_t)addr, task_thd); ! 664: } ! 665: } else { ! 666: db_delete_breakpoint(db_target_space(THREAD_NULL, user_space), ! 667: (db_addr_t)addr, 0); ! 668: } ! 669: } ! 670: ! 671: /* Set breakpoint with skip count */ ! 672: /*ARGSUSED*/ ! 673: void ! 674: db_breakpoint_cmd(addr, have_addr, count, modif) ! 675: db_expr_t addr; ! 676: int have_addr; ! 677: db_expr_t count; ! 678: char * modif; ! 679: { ! 680: register n; ! 681: thread_t thread; ! 682: boolean_t user_global = db_option(modif, 'U'); ! 683: boolean_t task_bpt = db_option(modif, 'T'); ! 684: boolean_t user_space; ! 685: ! 686: if (count == -1) ! 687: count = 1; ! 688: ! 689: if (!task_bpt && db_option(modif,'t')) ! 690: task_bpt = TRUE; ! 691: ! 692: if (task_bpt && user_global) ! 693: db_error("Cannot specify both 'T' and 'U'\n"); ! 694: user_space = (user_global)? TRUE: db_option(modif, 'u'); ! 695: if (user_space && db_access_level < DB_ACCESS_CURRENT) ! 696: db_error("User space break point is not supported\n"); ! 697: if (!task_bpt && !DB_VALID_ADDRESS((vm_offset_t)addr, user_space)) { ! 698: /* if the user has explicitly specified user space, ! 699: do not insert a breakpoint into the kernel */ ! 700: if (user_space) ! 701: db_error("Invalid user space address\n"); ! 702: user_space = TRUE; ! 703: db_printf("%#X is in user space\n", addr); ! 704: } ! 705: if (db_option(modif, 't') || task_bpt) { ! 706: for (n = 0; db_get_next_thread(&thread, n); n++) { ! 707: if (thread == THREAD_NULL) ! 708: db_error("No active thread\n"); ! 709: if (task_bpt && thread->task == TASK_NULL) ! 710: db_error("No task\n"); ! 711: if (db_access_level <= DB_ACCESS_CURRENT && user_space ! 712: && thread->task != db_current_task()) ! 713: db_error("Cannot set break point in inactive user space\n"); ! 714: db_set_breakpoint(db_target_space(thread, user_space), ! 715: (db_addr_t)addr, count, ! 716: (user_global)? THREAD_NULL: thread, ! 717: task_bpt); ! 718: } ! 719: } else { ! 720: db_set_breakpoint(db_target_space(THREAD_NULL, user_space), ! 721: (db_addr_t)addr, ! 722: count, THREAD_NULL, FALSE); ! 723: } ! 724: } ! 725: ! 726: /* list breakpoints */ ! 727: void ! 728: db_listbreak_cmd() ! 729: { ! 730: db_list_breakpoints(); ! 731: } ! 732: ! 733: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.