Annotation of 43BSDReno/bin/adb/adb.tahoe/kstack.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)kstack.c   5.1 (Berkeley) 1/16/89";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * adb - routines to probe the kernel stack when debugging post-mortem
        !             7:  * crash dumps.
        !             8:  */
        !             9: 
        !            10: #include "defs.h"
        !            11: #include <ctype.h>
        !            12: #include <machine/pte.h>
        !            13: #include <machine/frame.h>
        !            14: #include <machine/rpb.h>
        !            15: 
        !            16: struct pte *sbr;
        !            17: int    slr;
        !            18: struct pcb pcb;
        !            19: 
        !            20: static caddr_t rpb, erpb;
        !            21: static caddr_t intstack, eintstack;
        !            22: static caddr_t ustack, eustack;
        !            23: 
        !            24: char   *malloc();
        !            25: 
        !            26: /*
        !            27:  * Convert a kernel virtual address to an (off_t) physical offset.
        !            28:  */
        !            29: #define        kvtooff(a)      ((off_t)(a) & ~KERNBASE)
        !            30: 
        !            31: /*
        !            32:  * Check if an address is in one of the kernel's stacks:
        !            33:  * interrupt stack, rpb stack (during restart sequence),
        !            34:  * or u. stack.
        !            35:  */
        !            36: #define        within(a, b, e) \
        !            37:        ((addr_t)(a) >= (addr_t)(b) && (addr_t)(a) < (addr_t)(e))
        !            38: #define        kstackaddr(a) \
        !            39:        (within(a, intstack, eintstack) || \
        !            40:         within(a, rpb + sizeof(struct rpb), erpb) || \
        !            41:         within(a, ustack, eustack))
        !            42: 
        !            43: /*
        !            44:  * Determine whether we are looking at a kernel core dump, and if so,
        !            45:  * set sbr and slr and the current pcb.
        !            46:  */
        !            47: getkcore() {
        !            48:        struct nlist *sm, *ss, *mp;
        !            49: 
        !            50:        if ((sm = lookup("_Sysmap")) == NULL ||
        !            51:            (ss = lookup("_Syssize")) == NULL ||
        !            52:            (mp = lookup("_masterpaddr")) == NULL)
        !            53:                return (0);     /* a.out is not a vmunix */
        !            54:        datmap.m1.b = 0;
        !            55:        datmap.m1.e = -1L;
        !            56:        /* must set sbr, slr before setpcb() */
        !            57:        sbr = (struct pte *)sm->n_value;
        !            58:        slr = ss->n_value;
        !            59:        adbprintf("sbr %X slr %X\n", sbr, slr);
        !            60:        setpcb((addr_t)mp->n_value);
        !            61:        getpcb();
        !            62:        findstackframe();
        !            63:        return (1);
        !            64: }
        !            65: 
        !            66: /*
        !            67:  * A version of lookup that never returns failure, and which returns
        !            68:  * the n_value field of the symbol found.
        !            69:  */
        !            70: static caddr_t
        !            71: xlookup(sym)
        !            72:        char *sym;
        !            73: {
        !            74:        struct nlist *sp;
        !            75: 
        !            76:        if ((sp = lookup(sym)) == NULL) {
        !            77:                adbprintf("symbol %s not found ... bad kernel core?\n", sym);
        !            78:                exit(1);
        !            79:        }
        !            80:        return ((caddr_t)sp->n_value);
        !            81: }
        !            82: 
        !            83: /*
        !            84:  * Find the current stack frame when debugging the kernel.
        !            85:  * If we're looking at a crash dump and this was not a ``clean''
        !            86:  * crash, then we must search the interrupt stack carefully
        !            87:  * looking for a valid frame.
        !            88:  */
        !            89: findstackframe()
        !            90: {
        !            91:        register char *cp;
        !            92:        register int n;
        !            93:        caddr_t addr;
        !            94:        struct frame fr;
        !            95:        char buf[256];
        !            96: 
        !            97:        if (readcore(kvtooff(xlookup("_panicstr")), (caddr_t)&addr,
        !            98:                        sizeof(addr)) != sizeof(addr) || addr == 0)
        !            99:                return;
        !           100:        n = readcore(kvtooff(addr), buf, sizeof(buf));
        !           101:        for (cp = buf; --n > 0 && *cp != 0; cp++)
        !           102:                if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
        !           103:                        *cp = '?';
        !           104:        *cp = '\0';
        !           105:        adbprintf("panic: %s\n", buf);
        !           106: 
        !           107:        /*
        !           108:         * After a panic, look at the top of the rpb stack to find a stack
        !           109:         * frame.  If this was a clean crash, i.e. one which left the
        !           110:         * interrupt and kernel stacks in a reasonable state, then we should
        !           111:         * find a pointer to the proper stack frame here (at location
        !           112:         * intstack-8).  If we don't find a reasonable frame here, then we
        !           113:         * must search down through the interrupt stack.
        !           114:         */
        !           115:        intstack = xlookup("_intstack");
        !           116:        eintstack = xlookup("_Xdoadump");               /* XXX */
        !           117:        rpb = xlookup("_rsstk");                        /* XXX */
        !           118:        erpb = rpb + NBPG - 2 * sizeof(long);
        !           119:        ustack = xlookup("_u");
        !           120:        eustack = ustack + ctob(UPAGES);
        !           121:        ustack += (int)((struct user *)0)->u_stack;
        !           122:        (void) readcore(kvtooff(intstack - 8), (caddr_t)&addr, sizeof(addr));
        !           123:        if (!getframe(addr, &fr) && !checkintstack(&addr, &fr)) {
        !           124:                /* search kernel stack? */
        !           125:                prints("can't locate stack frame\n");
        !           126:                return;
        !           127:        }
        !           128:        /* probably shouldn't clobber pcb, but for now this is easy */
        !           129:        pcb.pcb_fp = (int)addr;
        !           130:        pcb.pcb_pc = fr.fr_savpc;
        !           131: }
        !           132: 
        !           133: /*
        !           134:  * Search interrupt stack for a valid frame.  Return 1 if found,
        !           135:  * also setting *addr to the kernel address of the frame, and *frame
        !           136:  * to the frame at that address.
        !           137:  */
        !           138: checkintstack(addr, frame)
        !           139:        caddr_t *addr;
        !           140:        struct frame *frame;
        !           141: {
        !           142:        register int ssize;
        !           143:        register char *stack;
        !           144: 
        !           145:        ssize = eintstack - intstack;
        !           146:        if ((stack = malloc((u_int)ssize)) == NULL)
        !           147:                return (0);
        !           148:        if (readcore(kvtooff(intstack), stack, ssize) != ssize) {
        !           149:                free(stack);
        !           150:                return (0);
        !           151:        }
        !           152:        for (ssize -= sizeof(*frame); ssize >= 0; ssize -= 4) {
        !           153:                if (goodframe((struct frame *)&stack[ssize])) {
        !           154:                        *addr = &intstack[ssize] + FRAMEOFF;
        !           155:                        *frame = *(struct frame *)&stack[ssize];
        !           156:                        free(stack);
        !           157:                        return (1);
        !           158:                }
        !           159:        }
        !           160:        free(stack);
        !           161:        return (0);
        !           162: }
        !           163: 
        !           164: /*
        !           165:  * Get a stack frame and verify that it looks like
        !           166:  * something which might be on a kernel stack.  Return 1 if OK.
        !           167:  */
        !           168: getframe(addr, fp)
        !           169:        caddr_t addr;
        !           170:        struct frame *fp;
        !           171: {
        !           172:        off_t off;
        !           173:        char *err = NULL;
        !           174: 
        !           175:        if (!kstackaddr(addr))
        !           176:                return (0);
        !           177:        off = vtophys((addr_t)(addr - FRAMEOFF), &err);
        !           178:        if (err || readcore(off, (caddr_t)fp, sizeof(*fp)) != sizeof(*fp))
        !           179:                return (0);
        !           180:        return (goodframe(fp));
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * Check a call frame to see if it's ok as a kernel stack frame.
        !           185:  * It should have its parent frame in the kernel stack, and should
        !           186:  * return to kernel code.
        !           187:  */
        !           188: goodframe(fr)
        !           189:        register struct frame *fr;
        !           190: {
        !           191: 
        !           192:        return (kstackaddr(fr->fr_savfp) &&
        !           193:                within(fr->fr_savpc, txtmap.m1.b, txtmap.m1.e));
        !           194: }

unix.superglobalmegacorp.com

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