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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /* 
        !            26:  * 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.