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