Annotation of 43BSDReno/bin/adb/adb.vax/kstack.c, revision 1.1.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.