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