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

unix.superglobalmegacorp.com

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