Annotation of XNU/osfmk/ppc/db_trace.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.