|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: ! 26: #include <string.h> ! 27: ! 28: #include <mach/boolean.h> ! 29: #include <vm/vm_map.h> ! 30: #include <kern/thread.h> ! 31: #include <kern/task.h> ! 32: ! 33: #include <machine/asm.h> ! 34: #include <machine/db_machdep.h> ! 35: #include <machine/setjmp.h> ! 36: #include <mach/machine.h> ! 37: ! 38: #include <ddb/db_access.h> ! 39: #include <ddb/db_sym.h> ! 40: #include <ddb/db_variables.h> ! 41: #include <ddb/db_command.h> ! 42: #include <ddb/db_task_thread.h> ! 43: #include <ddb/db_output.h> ! 44: ! 45: extern jmp_buf_t *db_recover; ! 46: extern struct ppc_saved_state *saved_state[]; ! 47: ! 48: struct ppc_saved_state ddb_null_kregs; ! 49: ! 50: extern vm_offset_t vm_min_inks_addr; /* set by db_clone_symtabXXX */ ! 51: ! 52: #define DB_NUMARGS_MAX 5 ! 53: ! 54: ! 55: extern char FixedStackStart[], FixedStackEnd[]; ! 56: #define INFIXEDSTACK(va) \ ! 57: ((((vm_offset_t)(va)) >= (vm_offset_t)&FixedStackStart) && \ ! 58: (((vm_offset_t)(va)) < ((vm_offset_t)&FixedStackEnd))) ! 59: ! 60: #define INKERNELSTACK(va, th) \ ! 61: (th == THR_ACT_NULL || \ ! 62: (((vm_offset_t)(va)) >= th->thread->kernel_stack && \ ! 63: (((vm_offset_t)(va)) < th->thread->kernel_stack + \ ! 64: KERNEL_STACK_SIZE)) || \ ! 65: INFIXEDSTACK(va)) ! 66: ! 67: #ifdef __MACHO__ ! 68: struct db_ppc_frame { ! 69: struct db_ppc_frame *f_frame; ! 70: int pad1; ! 71: db_addr_t f_retaddr; ! 72: int pad3; ! 73: int pad4; ! 74: int pad5; ! 75: db_addr_t f_arg[DB_NUMARGS_MAX]; ! 76: }; ! 77: #endif ! 78: ! 79: #define TRAP 1 ! 80: #define INTERRUPT 2 ! 81: #define SYSCALL 3 ! 82: ! 83: db_addr_t db_user_trap_symbol_value = 0; ! 84: db_addr_t db_kernel_trap_symbol_value = 0; ! 85: db_addr_t db_interrupt_symbol_value = 0; ! 86: db_addr_t db_return_to_iret_symbol_value = 0; ! 87: db_addr_t db_syscall_symbol_value = 0; ! 88: boolean_t db_trace_symbols_found = FALSE; ! 89: ! 90: extern int db_ppc_reg_value( ! 91: struct db_variable * vp, ! 92: db_expr_t * val, ! 93: int flag, ! 94: db_var_aux_param_t ap); ! 95: extern void db_find_trace_symbols(void); ! 96: extern int db_numargs( ! 97: struct db_ppc_frame *fp, ! 98: task_t task); ! 99: extern boolean_t db_find_arg( ! 100: struct db_ppc_frame *frame, ! 101: db_addr_t calleepc, ! 102: task_t task, ! 103: int narg, ! 104: db_addr_t *arg); ! 105: extern void db_nextframe( ! 106: struct db_ppc_frame **lfp, ! 107: struct db_ppc_frame **fp, ! 108: db_addr_t *ip, ! 109: int frame_type, ! 110: thread_act_t thr_act, ! 111: db_addr_t linkpc); ! 112: extern int _setjmp( ! 113: jmp_buf_t * jb); ! 114: ! 115: /* ! 116: * Machine register set. ! 117: */ ! 118: struct db_variable db_regs[] = { ! 119: /* XXX "pc" is an alias to "srr0"... */ ! 120: { "pc", (int *)&ddb_regs.srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 121: { "srr0", (int *)&ddb_regs.srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 122: { "srr1", (int *)&ddb_regs.srr1, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 123: { "r0", (int *)&ddb_regs.r0, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 124: { "r1", (int *)&ddb_regs.r1, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 125: { "r2", (int *)&ddb_regs.r2, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 126: { "r3", (int *)&ddb_regs.r3, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 127: { "r4", (int *)&ddb_regs.r4, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 128: { "r5", (int *)&ddb_regs.r5, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 129: { "r6", (int *)&ddb_regs.r6, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 130: { "r7", (int *)&ddb_regs.r7, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 131: { "r8", (int *)&ddb_regs.r8, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 132: { "r9", (int *)&ddb_regs.r9, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 133: { "r10", (int *)&ddb_regs.r10, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 134: { "r11", (int *)&ddb_regs.r11, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 135: { "r12", (int *)&ddb_regs.r12, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 136: { "r13", (int *)&ddb_regs.r13, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 137: { "r14", (int *)&ddb_regs.r14, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 138: { "r15", (int *)&ddb_regs.r15, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 139: { "r16", (int *)&ddb_regs.r16, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 140: { "r17", (int *)&ddb_regs.r17, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 141: { "r18", (int *)&ddb_regs.r18, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 142: { "r19", (int *)&ddb_regs.r19, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 143: { "r20", (int *)&ddb_regs.r20, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 144: { "r21", (int *)&ddb_regs.r21, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 145: { "r22", (int *)&ddb_regs.r22, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 146: { "r23", (int *)&ddb_regs.r23, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 147: { "r24", (int *)&ddb_regs.r24, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 148: { "r25", (int *)&ddb_regs.r25, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 149: { "r26", (int *)&ddb_regs.r26, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 150: { "r27", (int *)&ddb_regs.r27, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 151: { "r28", (int *)&ddb_regs.r28, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 152: { "r29", (int *)&ddb_regs.r29, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 153: { "r30", (int *)&ddb_regs.r30, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 154: { "r31", (int *)&ddb_regs.r31, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 155: { "cr", (int *)&ddb_regs.cr, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 156: { "xer", (int *)&ddb_regs.xer, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 157: { "lr", (int *)&ddb_regs.lr, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 158: { "ctr", (int *)&ddb_regs.ctr, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 159: { "mq", (int *)&ddb_regs.mq, db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 160: { "sr_copyin",(int *)&ddb_regs.sr_copyin,db_ppc_reg_value, 0, 0, 0, 0, TRUE }, ! 161: }; ! 162: struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); ! 163: ! 164: int ! 165: db_ppc_reg_value( ! 166: struct db_variable *vp, ! 167: db_expr_t *valuep, ! 168: int flag, ! 169: db_var_aux_param_t ap) ! 170: { ! 171: int *dp = 0; ! 172: db_expr_t null_reg = 0; ! 173: register thread_act_t thr_act = ap->thr_act; ! 174: int cpu; ! 175: ! 176: if (db_option(ap->modif, 'u')) { ! 177: if (thr_act == THR_ACT_NULL) { ! 178: if ((thr_act = current_act()) == THR_ACT_NULL) ! 179: db_error("no user registers\n"); ! 180: } ! 181: if (thr_act == current_act()) { ! 182: if (IS_USER_TRAP((&ddb_regs))) ! 183: dp = vp->valuep; ! 184: else if (INFIXEDSTACK(ddb_regs.r1)) ! 185: db_error("cannot get/set user registers in nested interrupt\n"); ! 186: } ! 187: } else { ! 188: if (thr_act == THR_ACT_NULL || thr_act == current_act()) { ! 189: dp = vp->valuep; ! 190: } else { ! 191: if (thr_act->thread && ! 192: !(thr_act->thread->state & TH_STACK_HANDOFF) && ! 193: thr_act->thread->kernel_stack) { ! 194: int cpu; ! 195: ! 196: for (cpu = 0; cpu < NCPUS; cpu++) { ! 197: if (machine_slot[cpu].running == TRUE && ! 198: cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) { ! 199: dp = (int *) (((int)saved_state[cpu]) + ! 200: (((int) vp->valuep) - ! 201: (int) &ddb_regs)); ! 202: break; ! 203: } ! 204: } ! 205: #if 0 ! 206: if (dp == 0 && thr_act && thr_act->thread) ! 207: dp = db_lookup_i386_kreg(vp->name, ! 208: (int *)(STACK_IKS(thr_act->thread->kernel_stack))); ! 209: #endif ! 210: if (dp == 0) ! 211: dp = &null_reg; ! 212: } else if (thr_act->thread && ! 213: (thr_act->thread->state&TH_STACK_HANDOFF)){ ! 214: /* only PC is valid */ ! 215: if (vp->valuep == (int *) &ddb_regs.srr0) { ! 216: dp = (int *)(&thr_act->thread->continuation); ! 217: } else { ! 218: dp = &null_reg; ! 219: } ! 220: } ! 221: } ! 222: } ! 223: if (dp == 0) { ! 224: int cpu; ! 225: ! 226: if (!db_option(ap->modif, 'u')) { ! 227: for (cpu = 0; cpu < NCPUS; cpu++) { ! 228: if (machine_slot[cpu].running == TRUE && ! 229: cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) { ! 230: dp = (int *) (((int)saved_state[cpu]) + ! 231: (((int) vp->valuep) - ! 232: (int) &ddb_regs)); ! 233: break; ! 234: } ! 235: } ! 236: } ! 237: if (dp == 0) { ! 238: if (!thr_act || thr_act->mact.pcb == 0) ! 239: db_error("no pcb\n"); ! 240: dp = (int *)((int)(&thr_act->mact.pcb->ss) + ! 241: ((int)vp->valuep - (int)&ddb_regs)); ! 242: } ! 243: } ! 244: if (flag == DB_VAR_SET) ! 245: *dp = *valuep; ! 246: else ! 247: *valuep = *dp; ! 248: return(0); ! 249: } ! 250: ! 251: void ! 252: db_find_trace_symbols(void) ! 253: { ! 254: db_expr_t value; ! 255: boolean_t found_some; ! 256: ! 257: found_some = FALSE; ! 258: if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) { ! 259: db_user_trap_symbol_value = (db_addr_t) value; ! 260: found_some = TRUE; ! 261: } ! 262: if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) { ! 263: db_kernel_trap_symbol_value = (db_addr_t) value; ! 264: found_some = TRUE; ! 265: } ! 266: if (db_value_of_name(CC_SYM_PREFIX "ihandler", &value)) { ! 267: db_interrupt_symbol_value = (db_addr_t) value; ! 268: found_some = TRUE; ! 269: } ! 270: #if 0 ! 271: if (db_value_of_name(CC_SYM_PREFIX "return_to_iret", &value)) { ! 272: db_return_to_iret_symbol_value = (db_addr_t) value; ! 273: found_some = TRUE; ! 274: } ! 275: #endif ! 276: if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) { ! 277: db_syscall_symbol_value = (db_addr_t) value; ! 278: found_some = TRUE; ! 279: } ! 280: if (found_some) ! 281: db_trace_symbols_found = TRUE; ! 282: } ! 283: ! 284: int ! 285: db_numargs( ! 286: struct db_ppc_frame *fp, ! 287: task_t task) ! 288: { ! 289: return (DB_NUMARGS_MAX); ! 290: } ! 291: ! 292: boolean_t ! 293: db_find_arg( ! 294: struct db_ppc_frame *fp, ! 295: db_addr_t calleepc, ! 296: task_t task, ! 297: int narg, ! 298: db_addr_t *arg) ! 299: { ! 300: db_addr_t argp; ! 301: db_addr_t calleep; ! 302: db_addr_t offset; ! 303: int i; ! 304: int inst; ! 305: char *name; ! 306: ! 307: #if XXX_BS ! 308: db_find_task_sym_and_offset(calleepc, &name, &offset, task); ! 309: calleep = calleepc-offset; ! 310: ! 311: for (i = 0; calleep < calleepc; i++, calleep++) { ! 312: if (!DB_CHECK_ACCESS((int) calleep, 4, task)) { ! 313: continue; ! 314: } ! 315: inst = db_get_task_value(calleep, 4, FALSE, task); ! 316: if ((inst & 0xffff0000) == (0x907f0000 + (narg << 21)) || ! 317: (inst & 0xffff0000) == (0x90610000 + (narg << 21))) { ! 318: argp = (db_addr_t) &(fp->f_arg[narg]); ! 319: *arg = argp; ! 320: return TRUE; ! 321: } ! 322: } ! 323: #endif ! 324: return FALSE; ! 325: } ! 326: ! 327: /* ! 328: * Figure out the next frame up in the call stack. ! 329: * For trap(), we print the address of the faulting instruction and ! 330: * proceed with the calling frame. We return the ip that faulted. ! 331: * If the trap was caused by jumping through a bogus pointer, then ! 332: * the next line in the backtrace will list some random function as ! 333: * being called. It should get the argument list correct, though. ! 334: * It might be possible to dig out from the next frame up the name ! 335: * of the function that faulted, but that could get hairy. ! 336: */ ! 337: void ! 338: db_nextframe( ! 339: struct db_ppc_frame **lfp, /* in/out */ ! 340: struct db_ppc_frame **fp, /* in/out */ ! 341: db_addr_t *ip, /* out */ ! 342: int frame_type, /* in */ ! 343: thread_act_t thr_act, ! 344: db_addr_t linkpc) /* in */ ! 345: { ! 346: extern char * trap_type[]; ! 347: extern int TRAP_TYPES; ! 348: ! 349: struct ppc_saved_state *saved_regs; ! 350: ! 351: task_t task = (thr_act != THR_ACT_NULL)? thr_act->task: TASK_NULL; ! 352: ! 353: switch(frame_type) { ! 354: case TRAP: ! 355: #if 0 ! 356: /* ! 357: * We know that trap() has 1 argument and we know that ! 358: * it is an (strcut i386_saved_state *). ! 359: */ ! 360: saved_regs = (struct i386_saved_state *) ! 361: db_get_task_value((int)&((*fp)->f_arg0),4,FALSE,task); ! 362: if (saved_regs->trapno >= 0 && saved_regs->trapno < TRAP_TYPES) { ! 363: db_printf(">>>>> %s trap at ", ! 364: trap_type[saved_regs->trapno]); ! 365: } else { ! 366: db_printf(">>>>> trap (number %d) at ", ! 367: saved_regs->trapno & 0xffff); ! 368: } ! 369: db_task_printsym(saved_regs->eip, DB_STGY_PROC, task); ! 370: db_printf(" <<<<<\n"); ! 371: *fp = (struct i386_frame *)saved_regs->ebp; ! 372: *ip = (db_addr_t)saved_regs->eip; ! 373: #else ! 374: db_printf(">>>>> trap <<<<<\n"); ! 375: goto miss_frame; ! 376: #endif ! 377: break; ! 378: case INTERRUPT: ! 379: if (*lfp == 0) { ! 380: db_printf(">>>>> interrupt <<<<<\n"); ! 381: goto miss_frame; ! 382: } ! 383: #if 0 ! 384: db_printf(">>>>> interrupt at "); ! 385: ifp = (struct interrupt_frame *)(*lfp); ! 386: *fp = ifp->if_frame; ! 387: if (ifp->if_iretaddr == db_return_to_iret_symbol_value) ! 388: *ip = ((struct i386_interrupt_state *) ifp->if_edx)->eip; ! 389: else ! 390: *ip = (db_addr_t) ifp->if_eip; ! 391: db_task_printsym(*ip, DB_STGY_PROC, task); ! 392: db_printf(" <<<<<\n"); ! 393: #else ! 394: db_printf(">>>>> interrupt <<<<<\n"); ! 395: goto miss_frame; ! 396: #endif ! 397: break; ! 398: case SYSCALL: ! 399: if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) { ! 400: *ip = (db_addr_t) thr_act->mact.pcb->ss.srr0; ! 401: *fp = (struct db_ppc_frame *) (thr_act->mact.pcb->ss.r1); ! 402: break; ! 403: } ! 404: /* falling down for unknown case */ ! 405: default: ! 406: miss_frame: ! 407: if ((*fp)->f_frame) ! 408: *ip = (db_addr_t) ! 409: db_get_task_value((int)&(*fp)->f_frame->f_retaddr, ! 410: 4, FALSE, task); ! 411: else ! 412: *ip = (db_addr_t) ! 413: db_get_task_value((int)&(*fp)->f_retaddr, ! 414: 4, FALSE, task); ! 415: ! 416: *lfp = *fp; ! 417: *fp = (struct db_ppc_frame *) ! 418: db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task); ! 419: break; ! 420: } ! 421: } ! 422: ! 423: void ! 424: db_stack_trace_cmd( ! 425: db_expr_t addr, ! 426: boolean_t have_addr, ! 427: db_expr_t count, ! 428: char *modif) ! 429: { ! 430: struct db_ppc_frame *frame, *lastframe; ! 431: db_addr_t callpc, linkpc, lastcallpc; ! 432: int frame_type; ! 433: boolean_t kernel_only = TRUE; ! 434: boolean_t trace_thread = FALSE; ! 435: boolean_t trace_all_threads = FALSE; ! 436: int thcount = 0; ! 437: char *filename; ! 438: int linenum; ! 439: task_t task; ! 440: thread_act_t th, top_act; ! 441: int user_frame; ! 442: int frame_count; ! 443: jmp_buf_t *prev; ! 444: jmp_buf_t db_jmp_buf; ! 445: queue_entry_t act_list; ! 446: ! 447: if (!db_trace_symbols_found) ! 448: db_find_trace_symbols(); ! 449: { ! 450: register char *cp = modif; ! 451: register char c; ! 452: ! 453: while ((c = *cp++) != 0) { ! 454: if (c == 't') ! 455: trace_thread = TRUE; ! 456: if (c == 'T') { ! 457: trace_all_threads = TRUE; ! 458: trace_thread = TRUE; ! 459: } ! 460: if (c == 'u') ! 461: kernel_only = FALSE; ! 462: } ! 463: } ! 464: ! 465: if (trace_all_threads) { ! 466: if (!have_addr && !trace_thread) { ! 467: have_addr = TRUE; ! 468: trace_thread = TRUE; ! 469: act_list = &(current_task()->thr_acts); ! 470: addr = (db_expr_t) queue_first(act_list); ! 471: } else if (trace_thread) { ! 472: if (have_addr) { ! 473: if (!db_check_act_address_valid((thread_act_t)addr)) { ! 474: if (db_lookup_task((task_t)addr) == -1) ! 475: return; ! 476: act_list = &(((task_t)addr)->thr_acts); ! 477: addr = (db_expr_t) queue_first(act_list); ! 478: } else { ! 479: act_list = &(((thread_act_t)addr)->task->thr_acts); ! 480: thcount = db_lookup_task_act(((thread_act_t)addr)->task, ! 481: (thread_act_t)addr); ! 482: } ! 483: } else { ! 484: th = db_default_act; ! 485: if (th == THR_ACT_NULL) ! 486: th = current_act(); ! 487: if (th == THR_ACT_NULL) { ! 488: db_printf("no active thr_act\n"); ! 489: return; ! 490: } ! 491: have_addr = TRUE; ! 492: act_list = &th->task->thr_acts; ! 493: addr = (db_expr_t) queue_first(act_list); ! 494: } ! 495: } ! 496: } ! 497: ! 498: if (count == -1) ! 499: count = 65535; ! 500: ! 501: next_thread: ! 502: top_act = THR_ACT_NULL; ! 503: ! 504: user_frame = 0; ! 505: frame_count = count; ! 506: ! 507: if (!have_addr && !trace_thread) { ! 508: frame = (struct db_ppc_frame *)(ddb_regs.r1); ! 509: callpc = (db_addr_t)ddb_regs.srr0; ! 510: linkpc = (db_addr_t)ddb_regs.lr; ! 511: th = current_act(); ! 512: task = (th != THR_ACT_NULL)? th->task: TASK_NULL; ! 513: } else if (trace_thread) { ! 514: if (have_addr) { ! 515: th = (thread_act_t) addr; ! 516: if (!db_check_act_address_valid(th)) ! 517: return; ! 518: } else { ! 519: th = db_default_act; ! 520: if (th == THR_ACT_NULL) ! 521: th = current_act(); ! 522: if (th == THR_ACT_NULL) { ! 523: db_printf("no active thread\n"); ! 524: return; ! 525: } ! 526: } ! 527: if (trace_all_threads) ! 528: db_printf("---------- Thread 0x%x (#%d of %d) ----------\n", ! 529: addr, thcount, th->task->thr_act_count); ! 530: ! 531: next_activation: ! 532: user_frame = 0; ! 533: ! 534: task = th->task; ! 535: if (th == current_act()) { ! 536: frame = (struct db_ppc_frame *)(ddb_regs.r1); ! 537: callpc = (db_addr_t)ddb_regs.srr0; ! 538: linkpc = (db_addr_t)ddb_regs.lr; ! 539: } else { ! 540: if (th->mact.pcb == 0) { ! 541: db_printf("thread has no pcb\n"); ! 542: return; ! 543: } ! 544: if (!th->thread) { ! 545: register struct ppc_saved_state *pss = ! 546: &th->mact.pcb->ss; ! 547: ! 548: db_printf("thread has no shuttle\n"); ! 549: #if 0 ! 550: frame = (struct db_ppc_frame *) (pss->r1); ! 551: callpc = (db_addr_t) (pss->srr0); ! 552: linkpc = (db_addr_t) (pss->lr); ! 553: #else ! 554: goto thread_done; ! 555: #endif ! 556: } ! 557: else if ((th->thread->state & TH_STACK_HANDOFF) || ! 558: th->thread->kernel_stack == 0) { ! 559: register struct ppc_saved_state *pss = ! 560: &th->mact.pcb->ss; ! 561: ! 562: db_printf("Continuation "); ! 563: db_task_printsym((db_expr_t)th->thread->continuation, ! 564: DB_STGY_PROC, task); ! 565: db_printf("\n"); ! 566: frame = (struct db_ppc_frame *) (pss->r1); ! 567: callpc = (db_addr_t) (pss->srr0); ! 568: linkpc = (db_addr_t) (pss->lr); ! 569: } else { ! 570: int cpu; ! 571: ! 572: for (cpu = 0; cpu < NCPUS; cpu++) { ! 573: if (machine_slot[cpu].running == TRUE && ! 574: cpu_data[cpu].active_thread == th->thread && ! 575: saved_state[cpu]) { ! 576: break; ! 577: } ! 578: } ! 579: if (top_act != THR_ACT_NULL) { ! 580: /* ! 581: * Trying to get the backtrace of an activation ! 582: * which is not the top_most one in the RPC chain: ! 583: * use the activation's pcb. ! 584: */ ! 585: struct ppc_saved_state *pss; ! 586: ! 587: pss = (struct ppc_saved_state *)th->mact.pcb; ! 588: frame = (struct db_ppc_frame *) (pss->r1); ! 589: callpc = (db_addr_t) (pss->srr0); ! 590: linkpc = (db_addr_t) (pss->lr); ! 591: } else { ! 592: if (cpu == NCPUS) { ! 593: register struct ppc_saved_state *iks; ! 594: int r; ! 595: ! 596: iks = (struct ppc_saved_state *)th->mact.pcb; ! 597: prev = db_recover; ! 598: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) { ! 599: frame = (struct db_ppc_frame *) (iks->r1); ! 600: callpc = (db_addr_t) (iks->lr); ! 601: linkpc = 0; ! 602: } else { ! 603: /* ! 604: * The kernel stack has probably been ! 605: * paged out (swapped out activation). ! 606: */ ! 607: db_recover = prev; ! 608: if (r == 2) /* 'q' from db_more() */ ! 609: db_error(0); ! 610: db_printf("<kernel stack (0x%x) error " ! 611: "(probably swapped out)>\n", ! 612: iks); ! 613: goto next_act; ! 614: } ! 615: db_recover = prev; ! 616: } else { ! 617: db_printf(">>>>> active on cpu %d <<<<<\n", ! 618: cpu); ! 619: frame = (struct db_ppc_frame *) ! 620: (saved_state[cpu]->r1); ! 621: callpc = (db_addr_t) saved_state[cpu]->srr0; ! 622: linkpc = (db_addr_t) saved_state[cpu]->lr; ! 623: } ! 624: } ! 625: } ! 626: } ! 627: } else { ! 628: frame = (struct db_ppc_frame *)addr; ! 629: th = (db_default_act)? db_default_act: current_act(); ! 630: task = (th != THR_ACT_NULL)? th->task: TASK_NULL; ! 631: if (frame->f_frame) { ! 632: callpc = (db_addr_t)db_get_task_value ! 633: ((int)&frame->f_frame->f_retaddr, ! 634: 4, FALSE, (user_frame) ? task : 0); ! 635: callpc = callpc-sizeof(callpc); ! 636: } else ! 637: callpc =0; ! 638: linkpc = 0; ! 639: } ! 640: ! 641: if (!INKERNELSTACK((unsigned)frame, th)) { ! 642: db_printf(">>>>> user space <<<<<\n"); ! 643: if (kernel_only) ! 644: goto thread_done; ! 645: user_frame++; ! 646: } ! 647: ! 648: lastframe = 0; ! 649: lastcallpc = (db_addr_t) 0; ! 650: while (frame_count-- && frame != 0) { ! 651: int narg = DB_NUMARGS_MAX; ! 652: int arg; ! 653: char * name; ! 654: db_expr_t offset; ! 655: db_addr_t call_func = 0; ! 656: int r; ! 657: db_addr_t off; ! 658: ! 659: db_symbol_values(NULL, ! 660: db_search_task_symbol_and_line( ! 661: callpc, DB_STGY_XTRN, &offset, &filename, ! 662: &linenum, (user_frame) ? task : 0, &narg), ! 663: &name, (db_expr_t *)&call_func); ! 664: if ( name == NULL) { ! 665: db_find_task_sym_and_offset(callpc, ! 666: &name, &off, (user_frame) ? task : 0); ! 667: offset = (db_expr_t) off; ! 668: } ! 669: ! 670: if (user_frame == 0) { ! 671: if (call_func && ! 672: (call_func == db_user_trap_symbol_value || ! 673: call_func == db_kernel_trap_symbol_value)) { ! 674: frame_type = TRAP; ! 675: narg = 1; ! 676: } else if (call_func && ! 677: call_func == db_interrupt_symbol_value) { ! 678: frame_type = INTERRUPT; ! 679: goto next_frame; ! 680: } else if (call_func && ! 681: call_func == db_syscall_symbol_value) { ! 682: frame_type = SYSCALL; ! 683: goto next_frame; ! 684: } else { ! 685: frame_type = 0; ! 686: prev = db_recover; ! 687: if ((r = _setjmp(db_recover = &db_jmp_buf)) ! 688: == 0) { ! 689: if (narg < 0) ! 690: narg = db_numargs(frame, ! 691: (user_frame) ? task : 0); ! 692: db_recover = prev; ! 693: } else { ! 694: db_recover = prev; ! 695: goto next_act; ! 696: } ! 697: } ! 698: } else { ! 699: frame_type = 0; ! 700: prev = db_recover; ! 701: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) { ! 702: if (narg < 0) ! 703: narg = db_numargs(frame, ! 704: (user_frame) ? task : 0); ! 705: db_recover = prev; ! 706: } else { ! 707: db_recover = prev; ! 708: goto next_act; ! 709: } ! 710: } ! 711: ! 712: if (name == 0 || offset > db_maxoff) { ! 713: db_printf("[%08X]0x%08X(", frame, callpc); ! 714: } else { ! 715: db_printf("[%08X]%s", frame, name); ! 716: if (offset) ! 717: db_printf("+%x", offset); ! 718: db_printf("("); ! 719: }; ! 720: ! 721: narg = db_numargs(frame, (user_frame) ? task : 0); ! 722: ! 723: for (arg =0; arg < narg; arg++) { ! 724: db_addr_t argp; ! 725: int value; ! 726: boolean_t found; ! 727: ! 728: prev = db_recover; ! 729: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) { ! 730: found = FALSE; ! 731: if (lastframe) ! 732: found = db_find_arg(frame, lastframe->f_retaddr, ! 733: (user_frame) ? task : 0, arg, &argp); ! 734: if (found) ! 735: value = db_get_task_value(argp, 4, FALSE, ! 736: (user_frame) ? task : 0); ! 737: } else { ! 738: db_recover = prev; ! 739: if (r == 2) /* 'q' from db_more() */ ! 740: db_error(0); ! 741: db_printf("... <stack error>)"); ! 742: db_printf("\n"); ! 743: goto next_act; ! 744: } ! 745: db_recover = prev; ! 746: if (found) ! 747: db_printf("%08X", value); ! 748: else ! 749: db_printf("??"); ! 750: argp = argp + sizeof(argp); ! 751: if (arg < narg-1) ! 752: db_printf(","); ! 753: } ! 754: if (arg != narg) ! 755: db_printf("..."); ! 756: db_printf(")"); ! 757: db_printf("\n"); ! 758: ! 759: next_frame: ! 760: lastcallpc = callpc; ! 761: prev = db_recover; ! 762: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) { ! 763: db_nextframe(&lastframe, &frame, &callpc, frame_type, ! 764: (user_frame) ? th : THR_ACT_NULL, linkpc); ! 765: callpc = callpc-sizeof(callpc); ! 766: db_recover = prev; ! 767: } else { ! 768: db_recover = prev; ! 769: frame = 0; ! 770: } ! 771: linkpc = 0; ! 772: ! 773: if (frame == 0) { ! 774: next_act: ! 775: if (th->lower != THR_ACT_NULL) { ! 776: if (top_act == THR_ACT_NULL) ! 777: top_act = th; ! 778: th = th->lower; ! 779: db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n", ! 780: th, ! 781: db_lookup_task(th->task), ! 782: db_lookup_task_act(th->task, th)); ! 783: goto next_activation; ! 784: } ! 785: /* end of chain */ ! 786: break; ! 787: } ! 788: if (!INKERNELSTACK(lastframe, th) || ! 789: !INKERNELSTACK((unsigned)frame, th)) ! 790: user_frame++; ! 791: if (user_frame == 1) { ! 792: db_printf(">>>>> user space <<<<<\n"); ! 793: if (kernel_only) ! 794: break; ! 795: } ! 796: ! 797: if (frame <= lastframe) { ! 798: if ((INKERNELSTACK(lastframe, th) && !INKERNELSTACK(frame, th))) continue; ! 799: db_printf("Bad frame pointer: 0x%x\n", frame); ! 800: break; ! 801: } ! 802: } ! 803: ! 804: thread_done: ! 805: if (trace_all_threads) { ! 806: if (top_act != THR_ACT_NULL) ! 807: th = top_act; ! 808: th = (thread_act_t) queue_next(&th->thr_acts); ! 809: if (! queue_end(act_list, (queue_entry_t) th)) { ! 810: db_printf("\n"); ! 811: addr = (db_expr_t) th; ! 812: thcount++; ! 813: goto next_thread; ! 814: ! 815: } ! 816: } ! 817: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.