|
|
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 n = 0;
1.1.1.5 ! root 443: struct rdxtree_iter iter;
! 444: rdxtree_for_each(&thread->task->itk_space->is_map, &iter, entry) {
1.1 root 445: if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
1.1.1.5 ! root 446: (*func)(entry->ie_name, (ipc_port_t) entry->ie_object,
1.1 root 447: entry->ie_bits, n++);
448: }
449: return(n);
450: }
451:
452: ipc_port_t
1.1.1.4 root 453: db_lookup_port(
454: thread_t thread,
455: int id)
1.1 root 456: {
1.1.1.4 root 457: ipc_entry_t entry;
1.1 root 458:
459: if (thread == THREAD_NULL)
460: return(0);
1.1.1.5 ! root 461: if (id < 0)
1.1 root 462: return(0);
1.1.1.5 ! root 463: entry = ipc_entry_lookup(thread->task->itk_space, (mach_port_t) id);
! 464: if (entry && entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
1.1 root 465: return((ipc_port_t)entry->ie_object);
466: return(0);
467: }
468:
469: static void
470: db_print_port_id(id, port, bits, n)
471: int id;
1.1.1.4 root 472: const ipc_port_t port;
1.1 root 473: unsigned bits;
474: int n;
475: {
476: if (n != 0 && n % 3 == 0)
477: db_printf("\n");
478: db_printf("\tport%d(%s,%x)", id,
479: (bits & MACH_PORT_TYPE_RECEIVE)? "r":
480: (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
481: }
482:
483: static void
484: db_print_port_id_long(
485: int id,
1.1.1.4 root 486: const ipc_port_t port,
1.1 root 487: unsigned bits,
488: int n)
489: {
490: if (n != 0)
491: db_printf("\n");
492: db_printf("\tport%d(%s, port=0x%x", id,
493: (bits & MACH_PORT_TYPE_RECEIVE)? "r":
494: (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
495: db_printf(", receiver_name=0x%x)", port->ip_receiver_name);
496: }
497:
498: /* ARGSUSED */
499: void
500: db_show_port_id(addr, have_addr, count, modif)
501: db_expr_t addr;
502: boolean_t have_addr;
503: db_expr_t count;
1.1.1.4 root 504: const char * modif;
1.1 root 505: {
506: thread_t thread;
507:
508: if (!have_addr) {
509: thread = current_thread();
510: if (thread == THREAD_NULL) {
511: db_error("No thread\n");
512: /*NOTREACHED*/
513: }
514: } else
515: thread = (thread_t) addr;
516: if (db_lookup_thread(thread) < 0) {
517: db_printf("Bad thread address %#X\n", addr);
518: db_error(0);
519: /*NOTREACHED*/
520: }
521: if (db_option(modif, 'l'))
522: {
523: if (db_port_iterate(thread, db_print_port_id_long))
524: db_printf("\n");
525: return;
526: }
527: if (db_port_iterate(thread, db_print_port_id))
528: db_printf("\n");
529: }
530:
1.1.1.2 root 531: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.