|
|
1.1 root 1: /*
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:
31: #if MACH_KDB
32:
33: /*
34: * Miscellaneous printing.
35: */
1.1.1.3 root 36: #include <string.h>
1.1 root 37: #include <mach/port.h>
38: #include <kern/task.h>
39: #include <kern/thread.h>
40: #include <kern/queue.h>
41: #include <ipc/ipc_port.h>
42: #include <ipc/ipc_space.h>
43:
1.1.1.3 root 44: #include <machine/db_interface.h>
1.1 root 45: #include <machine/db_machdep.h>
46: #include <machine/thread.h>
47:
1.1.1.3 root 48: #include <ddb/db_command.h>
49: #include <ddb/db_output.h>
1.1 root 50: #include <ddb/db_lex.h>
51: #include <ddb/db_variables.h>
52: #include <ddb/db_sym.h>
53: #include <ddb/db_task_thread.h>
1.1.1.3 root 54: #include <ddb/db_print.h>
1.1 root 55:
1.1.1.4 ! root 56: extern unsigned long db_maxoff;
1.1 root 57:
58: /* ARGSUSED */
59: void
1.1.1.4 ! root 60: db_show_regs(
! 61: db_expr_t addr,
! 62: boolean_t have_addr,
! 63: db_expr_t count,
! 64: char *modif)
1.1 root 65: {
1.1.1.4 ! root 66: struct db_variable *regp;
1.1 root 67: db_expr_t value;
68: db_addr_t offset;
69: char * name;
1.1.1.4 ! root 70: int i;
1.1 root 71: struct db_var_aux_param aux_param;
72: task_t task = TASK_NULL;
73:
74: aux_param.modif = modif;
75: aux_param.thread = THREAD_NULL;
76: if (db_option(modif, 't')) {
77: if (have_addr) {
78: if (!db_check_thread_address_valid((thread_t)addr))
79: return;
80: aux_param.thread = (thread_t)addr;
81: } else
82: aux_param.thread = db_default_thread;
83: if (aux_param.thread != THREAD_NULL)
84: task = aux_param.thread->task;
85: }
86: for (regp = db_regs; regp < db_eregs; regp++) {
87: if (regp->max_level > 1) {
88: db_printf("bad multi-suffixed register %s\n", regp->name);
89: continue;
90: }
91: aux_param.level = regp->max_level;
92: for (i = regp->low; i <= regp->high; i++) {
93: aux_param.suffix[0] = i;
94: db_read_write_variable(regp, &value, DB_VAR_GET, &aux_param);
95: if (regp->max_level > 0)
1.1.1.2 root 96: db_printf("%s%d%*s", regp->name, i,
1.1 root 97: 12-strlen(regp->name)-((i<10)?1:2), "");
98: else
99: db_printf("%-12s", regp->name);
100: db_printf("%#*N", 2+2*sizeof(vm_offset_t), value);
1.1.1.2 root 101: db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name,
1.1 root 102: &offset, task);
103: if (name != 0 && offset <= db_maxoff && offset != value) {
104: db_printf("\t%s", name);
105: if (offset != 0)
106: db_printf("+%#r", offset);
107: }
108: db_printf("\n");
109: }
110: }
111: }
112:
113: #define OPTION_LONG 0x001 /* long print option */
114: #define OPTION_USER 0x002 /* print ps-like stuff */
115: #define OPTION_INDENT 0x100 /* print with indent */
116: #define OPTION_THREAD_TITLE 0x200 /* print thread title */
117: #define OPTION_TASK_TITLE 0x400 /* print thread title */
118:
119: #ifndef DB_TASK_NAME
120: #define DB_TASK_NAME(task) /* no task name */
121: #define DB_TASK_NAME_TITLE "" /* no task name */
1.1.1.2 root 122: #endif /* DB_TASK_NAME */
1.1 root 123:
124: #ifndef db_thread_fp_used
125: #define db_thread_fp_used(thread) FALSE
126: #endif
127:
128: char *
129: db_thread_stat(thread, status)
1.1.1.4 ! root 130: const thread_t thread;
! 131: char *status;
1.1 root 132: {
1.1.1.4 ! root 133: char *p = status;
1.1.1.2 root 134:
1.1 root 135: *p++ = (thread->state & TH_RUN) ? 'R' : '.';
136: *p++ = (thread->state & TH_WAIT) ? 'W' : '.';
137: *p++ = (thread->state & TH_SUSP) ? 'S' : '.';
138: *p++ = (thread->state & TH_SWAPPED) ? 'O' : '.';
139: *p++ = (thread->state & TH_UNINT) ? 'N' : '.';
140: /* show if the FPU has been used */
141: *p++ = db_thread_fp_used(thread) ? 'F' : '.';
142: *p++ = 0;
143: return(status);
144: }
145:
146: void
1.1.1.4 ! root 147: db_print_thread(
! 148: thread_t thread,
! 149: int thread_id,
! 150: int flag)
1.1 root 151: {
152: if (flag & OPTION_USER) {
153: char status[8];
154: char *indent = "";
155:
156: if (flag & OPTION_LONG) {
157: if (flag & OPTION_INDENT)
158: indent = " ";
159: if (flag & OPTION_THREAD_TITLE) {
160: db_printf("%s ID: THREAD STAT STACK PCB", indent);
161: db_printf(" SUS PRI CONTINUE,WAIT_FUNC\n");
162: }
163: db_printf("%s%3d%c %0*X %s %0*X %0*X %3d %3d ",
164: indent, thread_id,
165: (thread == current_thread())? '#': ':',
166: 2*sizeof(vm_offset_t), thread,
167: db_thread_stat(thread, status),
168: 2*sizeof(vm_offset_t), thread->kernel_stack,
169: 2*sizeof(vm_offset_t), thread->pcb,
170: thread->suspend_count, thread->sched_pri);
171: if ((thread->state & TH_SWAPPED) && thread->swap_func) {
172: db_task_printsym((db_addr_t)thread->swap_func,
173: DB_STGY_ANY, kernel_task);
174: db_printf(", ");
175: }
176: if (thread->state & TH_WAIT)
177: db_task_printsym((db_addr_t)thread->wait_event,
178: DB_STGY_ANY, kernel_task);
179: db_printf("\n");
180: } else {
181: if (thread_id % 3 == 0) {
182: if (flag & OPTION_INDENT)
183: db_printf("\n ");
184: } else
185: db_printf(" ");
1.1.1.2 root 186: db_printf("%3d%c(%0*X,%s)", thread_id,
1.1 root 187: (thread == current_thread())? '#': ':',
188: 2*sizeof(vm_offset_t), thread,
189: db_thread_stat(thread, status));
190: }
191: } else {
192: if (flag & OPTION_INDENT)
193: db_printf(" %3d (%0*X) ", thread_id,
194: 2*sizeof(vm_offset_t), thread);
195: else
196: db_printf("(%0*X) ", 2*sizeof(vm_offset_t), thread);
1.1.1.4 ! root 197: char status[8];
! 198: db_printf("%s", db_thread_stat(thread, status));
1.1 root 199: if (thread->state & TH_SWAPPED) {
200: if (thread->swap_func) {
201: db_printf("(");
1.1.1.2 root 202: db_task_printsym((db_addr_t)thread->swap_func,
1.1 root 203: DB_STGY_ANY, kernel_task);
204: db_printf(")");
205: } else {
206: db_printf("(swapped)");
207: }
208: }
209: if (thread->state & TH_WAIT) {
210: db_printf(" ");
1.1.1.2 root 211: db_task_printsym((db_addr_t)thread->wait_event,
1.1 root 212: DB_STGY_ANY, kernel_task);
213: }
214: db_printf("\n");
215: }
216: }
217:
218: void
1.1.1.4 ! root 219: db_print_task(
! 220: task_t task,
! 221: int task_id,
! 222: int flag)
1.1 root 223: {
224: thread_t thread;
225: int thread_id;
226:
227: if (flag & OPTION_USER) {
228: if (flag & OPTION_TASK_TITLE) {
1.1.1.2 root 229: db_printf(" ID: TASK MAP THD SUS PR %s",
1.1 root 230: DB_TASK_NAME_TITLE);
231: if ((flag & OPTION_LONG) == 0)
232: db_printf(" THREADS");
233: db_printf("\n");
234: }
235: db_printf("%3d: %0*X %0*X %3d %3d %2d ",
236: task_id, 2*sizeof(vm_offset_t), task,
237: 2*sizeof(vm_offset_t), task->map, task->thread_count,
238: task->suspend_count, task->priority);
239: DB_TASK_NAME(task);
240: if (flag & OPTION_LONG) {
241: if (flag & OPTION_TASK_TITLE)
242: flag |= OPTION_THREAD_TITLE;
243: db_printf("\n");
244: } else if (task->thread_count <= 1)
245: flag &= ~OPTION_INDENT;
246: thread_id = 0;
247: queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
248: db_print_thread(thread, thread_id, flag);
249: flag &= ~OPTION_THREAD_TITLE;
250: thread_id++;
251: }
252: if ((flag & OPTION_LONG) == 0)
253: db_printf("\n");
254: } else {
255: if (flag & OPTION_TASK_TITLE)
256: db_printf(" TASK THREADS\n");
1.1.1.4 ! root 257: if (task->name[0])
! 258: db_printf("%3d %s (%0*X): ", task_id, task->name,
! 259: 2*sizeof(vm_offset_t), task);
! 260: else
! 261: db_printf("%3d (%0*X): ", task_id,
! 262: 2*sizeof(vm_offset_t), task);
1.1 root 263: if (task->thread_count == 0) {
264: db_printf("no threads\n");
265: } else {
266: if (task->thread_count > 1) {
267: db_printf("%d threads: \n", task->thread_count);
268: flag |= OPTION_INDENT;
269: } else
270: flag &= ~OPTION_INDENT;
271: thread_id = 0;
272: queue_iterate(&task->thread_list, thread,
273: thread_t, thread_list)
274: db_print_thread(thread, thread_id++, flag);
275: }
276: }
277: }
278:
1.1.1.4 ! root 279: void
! 280: db_show_all_tasks(db_expr_t addr,
! 281: boolean_t have_addr,
! 282: db_expr_t count,
! 283: const char *modif)
! 284: {
! 285: task_t task;
! 286: int task_id = 0;
! 287: processor_set_t pset;
! 288:
! 289: db_printf(" ID %-*s NAME [THREADS]\n", 2*sizeof(vm_offset_t), "TASK");
! 290:
! 291: queue_iterate(&all_psets, pset, processor_set_t, all_psets)
! 292: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
! 293: db_printf("%3d %0*X %s [%d]\n",
! 294: task_id,
! 295: 2*sizeof(vm_offset_t),
! 296: task,
! 297: task->name,
! 298: task->thread_count);
! 299: task_id++;
! 300: }
! 301: }
! 302:
1.1 root 303: /*ARGSUSED*/
304: void
305: db_show_all_threads(addr, have_addr, count, modif)
306: db_expr_t addr;
307: boolean_t have_addr;
308: db_expr_t count;
1.1.1.4 ! root 309: const char * modif;
1.1 root 310: {
311: task_t task;
312: int task_id;
313: int flag;
314: processor_set_t pset;
315:
316: flag = OPTION_TASK_TITLE|OPTION_INDENT;
317: if (db_option(modif, 'u'))
318: flag |= OPTION_USER;
319: if (db_option(modif, 'l'))
320: flag |= OPTION_LONG;
321:
322: task_id = 0;
323: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
324: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
325: db_print_task(task, task_id, flag);
326: flag &= ~OPTION_TASK_TITLE;
327: task_id++;
328: }
329: }
330: }
331:
332: db_addr_t
333: db_task_from_space(
334: ipc_space_t space,
335: int *task_id)
336: {
337: task_t task;
338: int tid = 0;
339: processor_set_t pset;
340:
341: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
342: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
343: if (task->itk_space == space) {
344: *task_id = tid;
345: return (db_addr_t)task;
346: }
347: tid++;
348: }
349: }
350: *task_id = 0;
351: return (0);
352: }
353:
354: /*ARGSUSED*/
355: void
356: db_show_one_thread(addr, have_addr, count, modif)
357: db_expr_t addr;
358: boolean_t have_addr;
359: db_expr_t count;
1.1.1.4 ! root 360: const char * modif;
1.1 root 361: {
362: int flag;
363: int thread_id;
364: thread_t thread;
365:
366: flag = OPTION_THREAD_TITLE;
367: if (db_option(modif, 'u'))
368: flag |= OPTION_USER;
369: if (db_option(modif, 'l'))
370: flag |= OPTION_LONG;
371:
372: if (!have_addr) {
373: thread = current_thread();
374: if (thread == THREAD_NULL) {
375: db_error("No thread\n");
376: /*NOTREACHED*/
377: }
378: } else
379: thread = (thread_t) addr;
380:
381: if ((thread_id = db_lookup_thread(thread)) < 0) {
382: db_printf("bad thread address %#X\n", addr);
383: db_error(0);
384: /*NOTREACHED*/
385: }
386:
387: if (flag & OPTION_USER) {
388: db_printf("TASK%d(%0*X):\n",
389: db_lookup_task(thread->task),
390: 2*sizeof(vm_offset_t), thread->task);
391: db_print_thread(thread, thread_id, flag);
392: } else {
393: db_printf("task %d(%0*X): thread %d",
394: db_lookup_task(thread->task),
395: 2*sizeof(vm_offset_t), thread->task, thread_id);
396: db_print_thread(thread, thread_id, flag);
397: }
398: }
399:
400: /*ARGSUSED*/
401: void
402: db_show_one_task(addr, have_addr, count, modif)
403: db_expr_t addr;
404: boolean_t have_addr;
405: db_expr_t count;
1.1.1.4 ! root 406: const char * modif;
1.1 root 407: {
408: int flag;
409: int task_id;
410: task_t task;
411:
412: flag = OPTION_TASK_TITLE;
413: if (db_option(modif, 'u'))
414: flag |= OPTION_USER;
415: if (db_option(modif, 'l'))
416: flag |= OPTION_LONG;
417:
418: if (!have_addr) {
419: task = db_current_task();
420: if (task == TASK_NULL) {
421: db_error("No task\n");
422: /*NOTREACHED*/
423: }
424: } else
425: task = (task_t) addr;
426:
427: if ((task_id = db_lookup_task(task)) < 0) {
428: db_printf("bad task address %#X\n", addr);
429: db_error(0);
430: /*NOTREACHED*/
431: }
432:
433: db_print_task(task, task_id, flag);
434: }
435:
436: int
437: db_port_iterate(thread, func)
1.1.1.4 ! root 438: const thread_t thread;
1.1 root 439: void (*func)();
440: {
441: ipc_entry_t entry;
442: int index;
443: int n = 0;
444: int size;
445: ipc_space_t space;
446:
447: space = thread->task->itk_space;
448: entry = space->is_table;
449: size = space->is_table_size;
450: for (index = 0; index < size; index++, entry++) {
451: if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
452: (*func)(index, (ipc_port_t) entry->ie_object,
453: entry->ie_bits, n++);
454: }
455: return(n);
456: }
457:
458: ipc_port_t
1.1.1.4 ! root 459: db_lookup_port(
! 460: thread_t thread,
! 461: int id)
1.1 root 462: {
1.1.1.4 ! root 463: ipc_space_t space;
! 464: ipc_entry_t entry;
1.1 root 465:
466: if (thread == THREAD_NULL)
467: return(0);
468: space = thread->task->itk_space;
469: if (id < 0 || id >= space->is_table_size)
470: return(0);
471: entry = &space->is_table[id];
472: if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
473: return((ipc_port_t)entry->ie_object);
474: return(0);
475: }
476:
477: static void
478: db_print_port_id(id, port, bits, n)
479: int id;
1.1.1.4 ! root 480: const ipc_port_t port;
1.1 root 481: unsigned bits;
482: int n;
483: {
484: if (n != 0 && n % 3 == 0)
485: db_printf("\n");
486: db_printf("\tport%d(%s,%x)", id,
487: (bits & MACH_PORT_TYPE_RECEIVE)? "r":
488: (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
489: }
490:
491: static void
492: db_print_port_id_long(
493: int id,
1.1.1.4 ! root 494: const ipc_port_t port,
1.1 root 495: unsigned bits,
496: int n)
497: {
498: if (n != 0)
499: db_printf("\n");
500: db_printf("\tport%d(%s, port=0x%x", id,
501: (bits & MACH_PORT_TYPE_RECEIVE)? "r":
502: (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
503: db_printf(", receiver_name=0x%x)", port->ip_receiver_name);
504: }
505:
506: /* ARGSUSED */
507: void
508: db_show_port_id(addr, have_addr, count, modif)
509: db_expr_t addr;
510: boolean_t have_addr;
511: db_expr_t count;
1.1.1.4 ! root 512: const char * modif;
1.1 root 513: {
514: thread_t thread;
515:
516: if (!have_addr) {
517: thread = current_thread();
518: if (thread == THREAD_NULL) {
519: db_error("No thread\n");
520: /*NOTREACHED*/
521: }
522: } else
523: thread = (thread_t) addr;
524: if (db_lookup_thread(thread) < 0) {
525: db_printf("Bad thread address %#X\n", addr);
526: db_error(0);
527: /*NOTREACHED*/
528: }
529: if (db_option(modif, 'l'))
530: {
531: if (db_port_iterate(thread, db_print_port_id_long))
532: db_printf("\n");
533: return;
534: }
535: if (db_port_iterate(thread, db_print_port_id))
536: db_printf("\n");
537: }
538:
1.1.1.2 root 539: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.