|
|
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: ! 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) ! 93: db_printf("%s%d%*s", regp->name, i, ! 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); ! 98: db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name, ! 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 */ ! 119: #endif DB_TASK_NAME ! 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; ! 131: ! 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(" "); ! 183: db_printf("%3d%c(%0*X,%s)", thread_id, ! 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("("); ! 203: db_task_printsym((db_addr_t)thread->swap_func, ! 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(" "); ! 212: db_task_printsym((db_addr_t)thread->wait_event, ! 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) { ! 230: db_printf(" ID: TASK MAP THD SUS PR %s", ! 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: ! 511: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.