|
|
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.