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