Annotation of XNU/osfmk/i386/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:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: 
                     53: #include <string.h>
                     54: 
                     55: #include <mach/boolean.h>
                     56: #include <vm/vm_map.h>
                     57: #include <kern/thread.h>
                     58: #include <kern/task.h>
                     59: 
                     60: #include <machine/asm.h>
                     61: #include <machine/db_machdep.h>
                     62: #include <machine/setjmp.h>
                     63: #include <mach/machine.h>
                     64: 
                     65: #include <ddb/db_access.h>
                     66: #include <ddb/db_sym.h>
                     67: #include <ddb/db_variables.h>
                     68: #include <ddb/db_command.h>
                     69: #include <ddb/db_task_thread.h>
                     70: #include <ddb/db_output.h>
                     71: 
                     72: extern jmp_buf_t *db_recover;
                     73: extern struct i386_saved_state *saved_state[];
                     74: 
                     75: struct i386_kernel_state ddb_null_kregs;
                     76: 
                     77: /*
                     78:  * Stack trace.
                     79:  */
                     80: 
                     81: extern vm_offset_t vm_min_inks_addr;   /* set by db_clone_symtabXXX */
                     82: #define INKSERVER(va)  (((vm_offset_t)(va)) >= vm_min_inks_addr)
                     83: 
                     84: #if    NCPUS > 1
                     85: extern vm_offset_t interrupt_stack[];
                     86: #define        ININTSTACK(va)                                          \
                     87:        (((vm_offset_t)(va)) >= interrupt_stack[cpu_number()] &&\
                     88:         (((vm_offset_t)(va)) < interrupt_stack[cpu_number()] + \
                     89:                                INTSTACK_SIZE))
                     90: #else  /* NCPUS > 1 */
                     91: extern  char intstack[];
                     92: #define        ININTSTACK(va)                                          \
                     93:        (((vm_offset_t)(va)) >= (vm_offset_t)intstack &&        \
                     94:         (((vm_offset_t)(va)) < ((vm_offset_t)&intstack) +      \
                     95:                                INTSTACK_SIZE))
                     96: #endif /* NCPUS > 1 */
                     97: 
                     98: #define        INKERNELSTACK(va, th)                                   \
                     99:        (th == THR_ACT_NULL ||                          \
                    100:         (((vm_offset_t)(va)) >= th->thread->kernel_stack &&    \
                    101:          (((vm_offset_t)(va)) < th->thread->kernel_stack +     \
                    102:                                 KERNEL_STACK_SIZE)) ||         \
                    103:          ININTSTACK(va))
                    104: 
                    105: struct i386_frame {
                    106:        struct i386_frame       *f_frame;
                    107:        int                     f_retaddr;
                    108:        int                     f_arg0;
                    109: };
                    110: 
                    111: #define        TRAP            1
                    112: #define        INTERRUPT       2
                    113: #define SYSCALL                3
                    114: 
                    115: db_addr_t      db_user_trap_symbol_value = 0;
                    116: db_addr_t      db_kernel_trap_symbol_value = 0;
                    117: db_addr_t      db_interrupt_symbol_value = 0;
                    118: db_addr_t      db_return_to_iret_symbol_value = 0;
                    119: db_addr_t      db_syscall_symbol_value = 0;
                    120: boolean_t      db_trace_symbols_found = FALSE;
                    121: 
                    122: struct i386_kregs {
                    123:        char    *name;
                    124:        int     offset;
                    125: } i386_kregs[] = {
                    126:        { "ebx", (int)(&((struct i386_kernel_state *)0)->k_ebx) },
                    127:        { "esp", (int)(&((struct i386_kernel_state *)0)->k_esp) },
                    128:        { "ebp", (int)(&((struct i386_kernel_state *)0)->k_ebp) },
                    129:        { "edi", (int)(&((struct i386_kernel_state *)0)->k_edi) },
                    130:        { "esi", (int)(&((struct i386_kernel_state *)0)->k_esi) },
                    131:        { "eip", (int)(&((struct i386_kernel_state *)0)->k_eip) },
                    132:        { 0 },
                    133: };
                    134: 
                    135: /* Forward */
                    136: 
                    137: extern int *   db_lookup_i386_kreg(
                    138:                        char                    *name,
                    139:                        int                     *kregp);
                    140: extern int     db_i386_reg_value(
                    141:                        struct db_variable      * vp,
                    142:                        db_expr_t               * val,
                    143:                        int                     flag,
                    144:                        db_var_aux_param_t      ap);
                    145: extern void    db_find_trace_symbols(void);
                    146: extern int     db_numargs(
                    147:                        struct i386_frame       *fp,
                    148:                        task_t                  task);
                    149: extern void    db_nextframe(
                    150:                        struct i386_frame       **lfp,
                    151:                        struct i386_frame       **fp,
                    152:                        db_addr_t               *ip,
                    153:                        int                     frame_type,
                    154:                        thread_act_t            thr_act);
                    155: extern int     _setjmp(
                    156:                        jmp_buf_t               * jb);
                    157: 
                    158: /*
                    159:  * Machine register set.
                    160:  */
                    161: struct db_variable db_regs[] = {
                    162:        { "cs", (int *)&ddb_regs.cs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    163:        { "ds", (int *)&ddb_regs.ds,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    164:        { "es", (int *)&ddb_regs.es,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    165:        { "fs", (int *)&ddb_regs.fs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    166:        { "gs", (int *)&ddb_regs.gs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    167:        { "ss", (int *)&ddb_regs.ss,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    168:        { "eax",(int *)&ddb_regs.eax, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    169:        { "ecx",(int *)&ddb_regs.ecx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    170:        { "edx",(int *)&ddb_regs.edx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    171:        { "ebx",(int *)&ddb_regs.ebx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    172:        { "esp",(int *)&ddb_regs.uesp,db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    173:        { "ebp",(int *)&ddb_regs.ebp, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    174:        { "esi",(int *)&ddb_regs.esi, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    175:        { "edi",(int *)&ddb_regs.edi, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    176:        { "eip",(int *)&ddb_regs.eip, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    177:        { "efl",(int *)&ddb_regs.efl, db_i386_reg_value, 0, 0, 0, 0, TRUE },
                    178: };
                    179: struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
                    180: 
                    181: int *
                    182: db_lookup_i386_kreg(
                    183:        char    *name,
                    184:        int     *kregp)
                    185: {
                    186:        register struct i386_kregs *kp;
                    187: 
                    188:        for (kp = i386_kregs; kp->name; kp++) {
                    189:            if (strcmp(name, kp->name) == 0)
                    190:                return((int *)((int)kregp + kp->offset));
                    191:        }
                    192:        return(0);
                    193: }
                    194:        
                    195: int
                    196: db_i386_reg_value(
                    197:        struct  db_variable     *vp,
                    198:        db_expr_t               *valuep,
                    199:        int                     flag,
                    200:        db_var_aux_param_t      ap)
                    201: {
                    202:        extern char             etext;
                    203:        int                     *dp = 0;
                    204:        db_expr_t               null_reg = 0;
                    205:        register thread_act_t   thr_act = ap->thr_act;
                    206:        extern unsigned         int_stack_high;
                    207:        int                     cpu;
                    208: 
                    209:        if (db_option(ap->modif, 'u')) {
                    210:            if (thr_act == THR_ACT_NULL) {
                    211:                if ((thr_act = current_act()) == THR_ACT_NULL)
                    212:                    db_error("no user registers\n");
                    213:            }
                    214:            if (thr_act == current_act()) {
                    215:                if (IS_USER_TRAP(&ddb_regs, &etext))
                    216:                    dp = vp->valuep;
                    217:                else if (ddb_regs.ebp < int_stack_high)
                    218:                    db_error("cannot get/set user registers in nested interrupt\n");
                    219:            }
                    220:        } else {
                    221:            if (thr_act == THR_ACT_NULL || thr_act == current_act()) {
                    222:                dp = vp->valuep;
                    223:            } else {
                    224:              if (thr_act->thread &&
                    225:                  !(thr_act->thread->state & TH_STACK_HANDOFF) && 
                    226:                        thr_act->thread->kernel_stack) {
                    227:                int cpu;
                    228: 
                    229:                for (cpu = 0; cpu < NCPUS; cpu++) {
                    230:                    if (machine_slot[cpu].running == TRUE &&
                    231:                        cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
                    232:                        dp = (int *) (((int)saved_state[cpu]) +
                    233:                                      (((int) vp->valuep) -
                    234:                                       (int) &ddb_regs));
                    235:                        break;
                    236:                    }
                    237:                }
                    238:                if (dp == 0 && thr_act && thr_act->thread)
                    239:                    dp = db_lookup_i386_kreg(vp->name,
                    240:                         (int *)(STACK_IKS(thr_act->thread->kernel_stack)));
                    241:                if (dp == 0)
                    242:                    dp = &null_reg;
                    243:              } else if (thr_act->thread &&
                    244:                         (thr_act->thread->state&TH_STACK_HANDOFF)){
                    245:                /* only EIP is valid */
                    246:                if (vp->valuep == (int *) &ddb_regs.eip) {
                    247:                    dp = (int *)(&thr_act->thread->continuation);
                    248:                } else {
                    249:                    dp = &null_reg;
                    250:                }
                    251:              }
                    252:            }
                    253:        }
                    254:        if (dp == 0) {
                    255:            int cpu;
                    256: 
                    257:            if (!db_option(ap->modif, 'u')) {
                    258:                for (cpu = 0; cpu < NCPUS; cpu++) {
                    259:                    if (machine_slot[cpu].running == TRUE &&
                    260:                        cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
                    261:                            dp = (int *) (((int)saved_state[cpu]) +
                    262:                                          (((int) vp->valuep) -
                    263:                                           (int) &ddb_regs));
                    264:                            break;
                    265:                    }
                    266:                }
                    267:            }
                    268:            if (dp == 0) {
                    269:                if (!thr_act || thr_act->mact.pcb == 0)
                    270:                    db_error("no pcb\n");
                    271:                dp = (int *)((int)(&thr_act->mact.pcb->iss) + 
                    272:                             ((int)vp->valuep - (int)&ddb_regs));
                    273:            }
                    274:        }
                    275:        if (flag == DB_VAR_SET)
                    276:            *dp = *valuep;
                    277:        else
                    278:            *valuep = *dp;
                    279:        return(0);
                    280: }
                    281: 
                    282: void
                    283: db_find_trace_symbols(void)
                    284: {
                    285:        db_expr_t       value;
                    286:        boolean_t       found_some;
                    287: 
                    288:        found_some = FALSE;
                    289:        if (db_value_of_name(CC_SYM_PREFIX "user_trap", &value)) {
                    290:            db_user_trap_symbol_value = (db_addr_t) value;
                    291:            found_some = TRUE;
                    292:        }
                    293:        if (db_value_of_name(CC_SYM_PREFIX "kernel_trap", &value)) {
                    294:            db_kernel_trap_symbol_value = (db_addr_t) value;
                    295:            found_some = TRUE;
                    296:        }
                    297:        if (db_value_of_name(CC_SYM_PREFIX "interrupt", &value)) {
                    298:            db_interrupt_symbol_value = (db_addr_t) value;
                    299:            found_some = TRUE;
                    300:        }
                    301:        if (db_value_of_name(CC_SYM_PREFIX "return_to_iret", &value)) {
                    302:            db_return_to_iret_symbol_value = (db_addr_t) value;
                    303:            found_some = TRUE;
                    304:        }
                    305:        if (db_value_of_name(CC_SYM_PREFIX "syscall", &value)) {
                    306:            db_syscall_symbol_value = (db_addr_t) value;
                    307:            found_some = TRUE;
                    308:        }
                    309:        if (found_some) 
                    310:            db_trace_symbols_found = TRUE;
                    311: }
                    312: 
                    313: /*
                    314:  * Figure out how many arguments were passed into the frame at "fp".
                    315:  */
                    316: int db_numargs_default = 5;
                    317: 
                    318: int
                    319: db_numargs(
                    320:        struct i386_frame       *fp,
                    321:        task_t                  task)
                    322: {
                    323:        int     *argp;
                    324:        int     inst;
                    325:        int     args;
                    326:        extern char     etext;
                    327: 
                    328:        argp = (int *)db_get_task_value((int)&fp->f_retaddr, 4, FALSE, task);
                    329:        if (argp < (int *)VM_MIN_KERNEL_ADDRESS || (char *)argp > &etext)
                    330:            args = db_numargs_default;
                    331:        else if (!DB_CHECK_ACCESS((int)argp, 4, task))
                    332:            args = db_numargs_default;
                    333:        else {
                    334:            inst = db_get_task_value((int)argp, 4, FALSE, task);
                    335:            if ((inst & 0xff) == 0x59)  /* popl %ecx */
                    336:                args = 1;
                    337:            else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */
                    338:                args = ((inst >> 16) & 0xff) / 4;
                    339:            else
                    340:                args = db_numargs_default;
                    341:        }
                    342:        return (args);
                    343: }
                    344: 
                    345: struct interrupt_frame {
                    346:        struct i386_frame *if_frame;    /* point to next frame */
                    347:        int               if_retaddr;   /* return address to _interrupt */
                    348:        int               if_unit;      /* unit number */
                    349:        int               if_spl;       /* saved spl */
                    350:        int               if_iretaddr;  /* _return_to_{iret,iret_i} */
                    351:        int               if_edx;       /* old sp(iret) or saved edx(iret_i) */
                    352:        int               if_ecx;       /* saved ecx(iret_i) */
                    353:        int               if_eax;       /* saved eax(iret_i) */
                    354:        int               if_eip;       /* saved eip(iret_i) */
                    355:        int               if_cs;        /* saved cs(iret_i) */
                    356:        int               if_efl;       /* saved efl(iret_i) */
                    357: };
                    358: 
                    359: /* 
                    360:  * Figure out the next frame up in the call stack.  
                    361:  * For trap(), we print the address of the faulting instruction and 
                    362:  *   proceed with the calling frame.  We return the ip that faulted.
                    363:  *   If the trap was caused by jumping through a bogus pointer, then
                    364:  *   the next line in the backtrace will list some random function as 
                    365:  *   being called.  It should get the argument list correct, though.  
                    366:  *   It might be possible to dig out from the next frame up the name
                    367:  *   of the function that faulted, but that could get hairy.
                    368:  */
                    369: void
                    370: db_nextframe(
                    371:        struct i386_frame       **lfp,          /* in/out */
                    372:        struct i386_frame       **fp,           /* in/out */
                    373:        db_addr_t               *ip,            /* out */
                    374:        int                     frame_type,     /* in */
                    375:        thread_act_t            thr_act)        /* in */
                    376: {
                    377:        extern char *   trap_type[];
                    378:        extern int      TRAP_TYPES;
                    379: 
                    380:        struct i386_saved_state *saved_regs;
                    381:        struct interrupt_frame *ifp;
                    382:        struct i386_interrupt_state *isp;
                    383:        task_t task = (thr_act != THR_ACT_NULL)? thr_act->task: TASK_NULL;
                    384: 
                    385:        switch(frame_type) {
                    386:        case TRAP:
                    387:            /*
                    388:             * We know that trap() has 1 argument and we know that
                    389:             * it is an (strcut i386_saved_state *).
                    390:             */
                    391:            saved_regs = (struct i386_saved_state *)
                    392:                        db_get_task_value((int)&((*fp)->f_arg0),4,FALSE,task);
                    393:            if (saved_regs->trapno >= 0 && saved_regs->trapno < TRAP_TYPES) {
                    394:                db_printf(">>>>> %s trap at ",
                    395:                        trap_type[saved_regs->trapno]);
                    396:            } else {
                    397:                db_printf(">>>>> trap (number %d) at ",
                    398:                        saved_regs->trapno & 0xffff);
                    399:            }
                    400:            db_task_printsym(saved_regs->eip, DB_STGY_PROC, task);
                    401:            db_printf(" <<<<<\n");
                    402:            *fp = (struct i386_frame *)saved_regs->ebp;
                    403:            *ip = (db_addr_t)saved_regs->eip;
                    404:            break;
                    405:        case INTERRUPT:
                    406:            if (*lfp == 0) {
                    407:                db_printf(">>>>> interrupt <<<<<\n");
                    408:                goto miss_frame;
                    409:            }
                    410:            db_printf(">>>>> interrupt at "); 
                    411:            ifp = (struct interrupt_frame *)(*lfp);
                    412:            *fp = ifp->if_frame;
                    413:            if (ifp->if_iretaddr == db_return_to_iret_symbol_value)
                    414:                *ip = ((struct i386_interrupt_state *) ifp->if_edx)->eip;
                    415:            else
                    416:                *ip = (db_addr_t) ifp->if_eip;
                    417:            db_task_printsym(*ip, DB_STGY_PROC, task);
                    418:            db_printf(" <<<<<\n");
                    419:            break;
                    420:        case SYSCALL:
                    421:            if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) {
                    422:                *ip = (db_addr_t) thr_act->mact.pcb->iss.eip;
                    423:                *fp = (struct i386_frame *) thr_act->mact.pcb->iss.ebp;
                    424:                break;
                    425:            }
                    426:            /* falling down for unknown case */
                    427:        default:
                    428:        miss_frame:
                    429:            *ip = (db_addr_t)
                    430:                db_get_task_value((int)&(*fp)->f_retaddr, 4, FALSE, task);
                    431:            *lfp = *fp;
                    432:            *fp = (struct i386_frame *)
                    433:                db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task);
                    434:            break;
                    435:        }
                    436: }
                    437: 
                    438: void
                    439: db_stack_trace_cmd(
                    440:        db_expr_t       addr,
                    441:        boolean_t       have_addr,
                    442:        db_expr_t       count,
                    443:        char            *modif)
                    444: {
                    445:        struct i386_frame *frame, *lastframe;
                    446:        int             *argp;
                    447:        db_addr_t       callpc, lastcallpc;
                    448:        int             frame_type;
                    449:        boolean_t       kernel_only = TRUE;
                    450:        boolean_t       trace_thread = FALSE;
                    451:        boolean_t       trace_all_threads = FALSE;
                    452:        int             thcount = 0;
                    453:        char            *filename;
                    454:        int             linenum;
                    455:        task_t          task;
                    456:        thread_act_t    th, top_act;
                    457:        int             user_frame;
                    458:        int             frame_count;
                    459:        jmp_buf_t       *prev;
                    460:        jmp_buf_t       db_jmp_buf;
                    461:        queue_entry_t   act_list;
                    462: 
                    463:        if (!db_trace_symbols_found)
                    464:            db_find_trace_symbols();
                    465: 
                    466:        {
                    467:            register char *cp = modif;
                    468:            register char c;
                    469: 
                    470:            while ((c = *cp++) != 0) {
                    471:                if (c == 't')
                    472:                    trace_thread = TRUE;
                    473:                if (c == 'T') {
                    474:                    trace_all_threads = TRUE;
                    475:                    trace_thread = TRUE;
                    476:                }
                    477:                if (c == 'u')
                    478:                    kernel_only = FALSE;
                    479:            }
                    480:        }
                    481: 
                    482:        if (trace_all_threads) {
                    483:            if (!have_addr && !trace_thread) {
                    484:                have_addr = TRUE;
                    485:                trace_thread = TRUE;
                    486:                act_list = &(current_task()->thr_acts);
                    487:                addr = (db_expr_t) queue_first(act_list);
                    488:            } else if (trace_thread) {
                    489:                if (have_addr) {
                    490:                    if (!db_check_act_address_valid((thread_act_t)addr)) {
                    491:                        if (db_lookup_task((task_t)addr) == -1)
                    492:                            return;
                    493:                        act_list = &(((task_t)addr)->thr_acts);
                    494:                        addr = (db_expr_t) queue_first(act_list);
                    495:                    } else {
                    496:                        act_list = &(((thread_act_t)addr)->task->thr_acts);
                    497:                        thcount = db_lookup_task_act(((thread_act_t)addr)->task,
                    498:                                                        (thread_act_t)addr);
                    499:                    }
                    500:                } else {
                    501:                    th = db_default_act;
                    502:                    if (th == THR_ACT_NULL)
                    503:                        th = current_act();
                    504:                    if (th == THR_ACT_NULL) {
                    505:                        db_printf("no active thr_act\n");
                    506:                        return;
                    507:                    }
                    508:                    have_addr = TRUE;
                    509:                    act_list = &th->task->thr_acts;
                    510:                    addr = (db_expr_t) queue_first(act_list);
                    511:                }
                    512:            }
                    513:        }
                    514: 
                    515:        if (count == -1)
                    516:            count = 65535;
                    517: 
                    518:     next_thread:
                    519:        top_act = THR_ACT_NULL;
                    520: 
                    521:        user_frame = 0;
                    522:        frame_count = count;
                    523: 
                    524:        if (!have_addr && !trace_thread) {
                    525:            frame = (struct i386_frame *)ddb_regs.ebp;
                    526:            callpc = (db_addr_t)ddb_regs.eip;
                    527:            th = current_act();
                    528:            task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
                    529:        } else if (trace_thread) {
                    530:            if (have_addr) {
                    531:                th = (thread_act_t) addr;
                    532:                if (!db_check_act_address_valid(th))
                    533:                    return;
                    534:            } else {
                    535:                th = db_default_act;
                    536:                if (th == THR_ACT_NULL)
                    537:                   th = current_act();
                    538:                if (th == THR_ACT_NULL) {
                    539:                   db_printf("no active thread\n");
                    540:                   return;
                    541:                }
                    542:            }
                    543:            if (trace_all_threads)
                    544:                db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
                    545:                      addr, thcount, th->task->thr_act_count);
                    546: 
                    547:        next_activation:
                    548:            user_frame = 0;
                    549: 
                    550:            task = th->task;
                    551:            if (th == current_act()) {
                    552:                frame = (struct i386_frame *)ddb_regs.ebp;
                    553:                callpc = (db_addr_t)ddb_regs.eip;
                    554:            } else {
                    555:                if (th->mact.pcb == 0) {
                    556:                    db_printf("thread has no pcb\n");
                    557:                    return;
                    558:                }
                    559:                if (!th->thread) {
                    560:                    register struct i386_saved_state *iss =
                    561:                                                &th->mact.pcb->iss;
                    562: 
                    563:                    db_printf("thread has no shuttle\n");
                    564: #if 0
                    565:                    frame = (struct i386_frame *) (iss->ebp);
                    566:                    callpc = (db_addr_t) (iss->eip);
                    567: #else
                    568:                    goto thread_done;
                    569: #endif
                    570:                }
                    571:                else if ((th->thread->state & TH_STACK_HANDOFF) ||
                    572:                          th->thread->kernel_stack == 0) {
                    573:                    register struct i386_saved_state *iss =
                    574:                                                &th->mact.pcb->iss;
                    575: 
                    576:                    db_printf("Continuation ");
                    577:                    db_task_printsym((db_expr_t)th->thread->continuation,
                    578:                                                        DB_STGY_PROC, task);
                    579:                    db_printf("\n");
                    580:                    frame = (struct i386_frame *) (iss->ebp);
                    581:                    callpc = (db_addr_t) (iss->eip);
                    582:                } else {
                    583:                    int cpu;
                    584: 
                    585:                    for (cpu = 0; cpu < NCPUS; cpu++) {
                    586:                        if (machine_slot[cpu].running == TRUE &&
                    587:                            cpu_data[cpu].active_thread == th->thread &&
                    588:                            saved_state[cpu]) {
                    589:                            break;
                    590:                        }
                    591:                    }
                    592:                    if (top_act != THR_ACT_NULL) {
                    593:                            /*
                    594:                             * Trying to get the backtrace of an activation
                    595:                             * which is not the top_most one in the RPC chain:
                    596:                             * use the activation's pcb.
                    597:                             */
                    598:                            register struct i386_saved_state *iss =
                    599:                                &th->mact.pcb->iss;
                    600:                            frame = (struct i386_frame *) (iss->ebp);
                    601:                            callpc = (db_addr_t) (iss->eip);
                    602:                    } else {
                    603:                        if (cpu == NCPUS) {
                    604:                            register struct i386_kernel_state *iks;
                    605:                            int r;
                    606: 
                    607:                            iks = STACK_IKS(th->thread->kernel_stack);
                    608:                            prev = db_recover;
                    609:                            if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
                    610:                                frame = (struct i386_frame *) (iks->k_ebp);
                    611:                                callpc = (db_addr_t) (iks->k_eip);
                    612:                            } else {
                    613:                                /*
                    614:                                 * The kernel stack has probably been
                    615:                                 * paged out (swapped out activation).
                    616:                                 */
                    617:                                db_recover = prev;
                    618:                                if (r == 2)     /* 'q' from db_more() */
                    619:                                    db_error(0);
                    620:                                db_printf("<kernel stack (0x%x) error "
                    621:                                          "(probably swapped out)>\n",
                    622:                                          iks);
                    623:                                goto thread_done;
                    624:                            }
                    625:                            db_recover = prev;
                    626:                        } else {
                    627:                            db_printf(">>>>> active on cpu %d <<<<<\n",
                    628:                                      cpu);
                    629:                            frame = (struct i386_frame *)
                    630:                                saved_state[cpu]->ebp;
                    631:                            callpc = (db_addr_t) saved_state[cpu]->eip;
                    632:                        }
                    633:                    }
                    634:                }
                    635:            }
                    636:        } else {
                    637:            frame = (struct i386_frame *)addr;
                    638:            th = (db_default_act)? db_default_act: current_act();
                    639:            task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
                    640:            callpc = (db_addr_t)db_get_task_value((int)&frame->f_retaddr,
                    641:                                                  4, 
                    642:                                                  FALSE, 
                    643:                                                  (user_frame) ? task : 0);
                    644:        }
                    645: 
                    646:        if (!INKERNELSTACK((unsigned)frame, th)) {
                    647:            db_printf(">>>>> user space <<<<<\n");
                    648:            if (kernel_only)
                    649:                goto thread_done;
                    650:            user_frame++;
                    651:        } else if (INKSERVER(callpc) && INKSERVER(frame)) {
                    652:            db_printf(">>>>> INKserver space <<<<<\n");
                    653:        }
                    654: 
                    655:        lastframe = 0;
                    656:        lastcallpc = (db_addr_t) 0;
                    657:        while (frame_count-- && frame != 0) {
                    658:            int narg;
                    659:            char *      name;
                    660:            db_expr_t   offset;
                    661:            db_addr_t call_func = 0;
                    662:            int r;
                    663: 
                    664:            db_symbol_values(NULL,
                    665:                             db_search_task_symbol_and_line(
                    666:                                        callpc,
                    667:                                        DB_STGY_XTRN, 
                    668:                                        &offset,
                    669:                                        &filename,
                    670:                                        &linenum,
                    671:                                        (user_frame) ? task : 0,
                    672:                                        &narg),
                    673:                             &name, (db_expr_t *)&call_func);
                    674:            if (user_frame == 0) {
                    675:                if (call_func == db_user_trap_symbol_value ||
                    676:                    call_func == db_kernel_trap_symbol_value) {
                    677:                    frame_type = TRAP;
                    678:                    narg = 1;
                    679:                } else if (call_func == db_interrupt_symbol_value) {
                    680:                    frame_type = INTERRUPT;
                    681:                    goto next_frame;
                    682:                } else if (call_func == db_syscall_symbol_value) {
                    683:                    frame_type = SYSCALL;
                    684:                    goto next_frame;
                    685:                } else {
                    686:                    frame_type = 0;
                    687:                    prev = db_recover;
                    688:                    if ((r = _setjmp(db_recover = &db_jmp_buf)) == 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 thread_done;
                    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 thread_done;
                    709:                }
                    710:            }
                    711: 
                    712:            if (name == 0 || offset > db_maxoff) {
                    713:                db_printf("0x%x 0x%x(", frame, callpc);
                    714:                offset = 0;
                    715:            } else
                    716:                db_printf("0x%x %s(", frame, name);
                    717: 
                    718:            argp = &frame->f_arg0;
                    719:            while (narg > 0) {
                    720:                int value;
                    721: 
                    722:                prev = db_recover;
                    723:                if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
                    724:                    value = db_get_task_value((int)argp,
                    725:                                              4,
                    726:                                              FALSE,
                    727:                                              (user_frame) ? task : 0);
                    728:                } else {
                    729:                    db_recover = prev;
                    730:                    if (r == 2)         /* 'q' from db_more() */
                    731:                        db_error(0);
                    732:                    db_printf("... <stack error>)");
                    733:                    if (offset)
                    734:                        db_printf("+%x", offset);
                    735:                    if (filename) {
                    736:                        db_printf(" [%s", filename);
                    737:                        if (linenum > 0)
                    738:                            db_printf(":%d", linenum);
                    739:                        db_printf("]");
                    740:                    }
                    741:                    db_printf("\n");
                    742:                    goto thread_done;
                    743:                }
                    744:                db_recover = prev;
                    745:                db_printf("%x", value);
                    746:                argp++;
                    747:                if (--narg != 0)
                    748:                    db_printf(",");
                    749:            }
                    750:            if (narg < 0)
                    751:                db_printf("...");
                    752:            db_printf(")");
                    753:            if (offset) {
                    754:                db_printf("+%x", offset);
                    755:             }
                    756:            if (filename) {
                    757:                db_printf(" [%s", filename);
                    758:                if (linenum > 0)
                    759:                    db_printf(":%d", linenum);
                    760:                db_printf("]");
                    761:            }
                    762:            db_printf("\n");
                    763: 
                    764:        next_frame:
                    765:            lastcallpc = callpc;
                    766:            db_nextframe(&lastframe, &frame, &callpc, frame_type,
                    767:                         (user_frame) ? th : THR_ACT_NULL);
                    768: 
                    769:            if (frame == 0) {
                    770:                if (th->lower != THR_ACT_NULL) {
                    771:                    if (top_act == THR_ACT_NULL)
                    772:                        top_act = th;
                    773:                    th = th->lower;
                    774:                    db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
                    775:                              th,
                    776:                              db_lookup_task(th->task),
                    777:                              db_lookup_task_act(th->task, th));
                    778:                    goto next_activation;
                    779:                }
                    780:                /* end of chain */
                    781:                break;
                    782:            }
                    783:            if (!INKERNELSTACK(lastframe, th) ||
                    784:                !INKERNELSTACK((unsigned)frame, th))
                    785:                user_frame++;
                    786:            if (user_frame == 1) {
                    787:                db_printf(">>>>> user space <<<<<\n");
                    788:                if (kernel_only)
                    789:                    break;
                    790:            } else if ((!INKSERVER(lastframe) || !INKSERVER(lastcallpc)) &&
                    791:                        (INKSERVER(callpc) && INKSERVER(frame))) {
                    792:                db_printf(">>>>> inkserver space <<<<<\n");
                    793:            }
                    794:            if (frame <= lastframe) {
                    795:                if ((INKERNELSTACK(lastframe, th) &&
                    796:                     !INKERNELSTACK(frame, th)) ||
                    797:                    (INKSERVER(lastframe) ^ INKSERVER(frame)))
                    798:                    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.