Annotation of XNU/osfmk/ppc/db_trace.c, revision 1.1.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.