|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 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. 1.1.1.2 ! root 11: * 1.1 root 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. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 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) { 1.1.1.2 ! root 96: for (tp = db_thread_break_list; 1.1 root 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; 1.1.1.2 ! root 245: if ((tbp->tb_is_task && 1.1 root 246: db_lookup_task((task_t)(tbp->tb_task_thd)) < 0) || 1.1.1.2 ! root 247: (!tbp->tb_is_task && 1.1 root 248: db_lookup_thread((thread_t)(tbp->tb_task_thd)) < 0)) { 1.1.1.2 ! root 249: db_force_delete_breakpoint(bkpt, 1.1 root 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 { 1.1.1.2 ! root 417: db_printf("Warning: cannot set breakpoint at %X ", 1.1 root 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)) { 1.1.1.2 ! root 451: inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, 1.1 root 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: } 1.1.1.2 ! root 500: bkpt->bkpt_inst = db_get_task_value(bkpt->address, BKPT_SIZE, 1.1 root 501: FALSE, task); 1.1.1.2 ! root 502: db_put_task_value(bkpt->address, BKPT_SIZE, 1.1 root 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); 1.1.1.2 ! root 567: else 1.1 root 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; 1.1.1.2 ! root 606: 1.1 root 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)) { 1.1.1.2 ! root 648: db_printf("Address %#X is not in %s space\n", addr, 1.1 root 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"); 1.1.1.2 ! root 714: db_set_breakpoint(db_target_space(thread, user_space), 1.1 root 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: 1.1.1.2 ! root 733: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.