BSD 4_3 release
[unix-history] / usr / src / bin / adb / setup.c
index c1f9133..51f4aff 100644 (file)
@@ -1,9 +1,13 @@
-static char sccsid[] = "@(#)setup.c    4.6 82/10/28";
+static char sccsid[] = "@(#)setup.c    4.10 (Berkeley) 85/05/09";
 /*
  * adb - routines to read a.out+core at startup
  */
 #include "defs.h"
 /*
  * adb - routines to read a.out+core at startup
  */
 #include "defs.h"
+#include <frame.h>
+#include <ctype.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
+#include <sys/file.h>
+#include <vax/rpb.h>
 
 off_t  datbas;                 /* offset of the base of the data segment */
 off_t  stksiz;                 /* stack size in the core image */
 
 off_t  datbas;                 /* offset of the base of the data segment */
 off_t  stksiz;                 /* stack size in the core image */
@@ -51,7 +55,7 @@ setsym()
        esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)];
        if (symtab == NULL)
                goto nospac;
        esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)];
        if (symtab == NULL)
                goto nospac;
-       lseek(fsym, loc, 0);
+       lseek(fsym, loc, L_SET);
        if (filhdr.a_syms == 0)
                goto nosymt;
        /* SHOULD SQUISH OUT STABS HERE!!! */
        if (filhdr.a_syms == 0)
                goto nosymt;
        /* SHOULD SQUISH OUT STABS HERE!!! */
@@ -106,11 +110,12 @@ setcor()
                sbr = cursym->n_value;
                lookup("_Syssize");
                slr = cursym->n_value;
                sbr = cursym->n_value;
                lookup("_Syssize");
                slr = cursym->n_value;
-               printf("sbr %X slr %X\n", sbr, slr);
+               printf("sbr %x slr %x\n", sbr, slr);
                lookup("_masterpaddr");
                lookup("_masterpaddr");
-               physrw(fcor, cursym->n_value&0x7fffffff, &masterpcbb, 1);
-               masterpcbb = (masterpcbb&PG_PFNUM)*512;
+               physrw(fcor, KVTOPH(cursym->n_value), &masterpcbb, 1);
+               masterpcbb = (masterpcbb&PG_PFNUM)*NBPG;
                getpcb();
                getpcb();
+               findstackframe();
                return;
        }
        if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) ||
                return;
        }
        if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) ||
@@ -142,21 +147,161 @@ setcor()
        datmap.f1 = ctob(UPAGES);
        datmap.b2 = MAXSTOR - stksiz;
        datmap.e2 = MAXSTOR;
        datmap.f1 = ctob(UPAGES);
        datmap.b2 = MAXSTOR - stksiz;
        datmap.e2 = MAXSTOR;
-       if (filhdr.a_magic && u.u_exdata.ux_mag &&
-           filhdr.a_magic != u.u_exdata.ux_mag)
-               printf("corefile not from this program");
 }
 
 getpcb()
 {
 
 }
 
 getpcb()
 {
 
-       lseek(fcor, masterpcbb&~0x80000000, 0);
+       lseek(fcor, KVTOPH(masterpcbb), L_SET);
        read(fcor, &pcb, sizeof (struct pcb));
        pcb.pcb_p0lr &= ~AST_CLR;
        read(fcor, &pcb, sizeof (struct pcb));
        pcb.pcb_p0lr &= ~AST_CLR;
-       printf("p0br %X p0lr %X p1br %X p1lr %X\n",
+       printf("p0br %x p0lr %x p1br %x p1lr %x\n",
            pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
 }
 
            pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
 }
 
+caddr_t        rpb, scb;
+caddr_t        intstack, eintstack;
+caddr_t        ustack, eustack;
+struct frame *getframe();
+struct frame *checkintstack();
+
+/*
+ * Find the current stack frame when debugging the kernel.
+ * If we're looking at a crash dump and this was not a ``clean''
+ * crash, then we must search the interrupt stack carefully
+ * looking for a valid frame.
+ */
+findstackframe()
+{
+       char *panicstr, buf[256];
+       register struct frame *fp;
+       caddr_t addr;
+       register char *cp;
+       int mask;
+
+       if (lookup("_panicstr") == 0)
+               return;
+       lseek(fcor, KVTOPH(cursym->n_value), L_SET);
+       read(fcor, &panicstr, sizeof (panicstr));
+       if (panicstr == 0)
+               return;
+       lseek(fcor, KVTOPH((off_t)panicstr), L_SET);
+       read(fcor, buf, sizeof (buf));
+       for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++)
+               if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+                       *cp = '?';
+       if (*cp)
+               *cp = '\0';
+       printf("panic: %s\n", buf);
+       /*
+        * After a panic, look at the top of the rpb stack to
+        * find a stack frame.  If this was a clean crash,
+        * i.e. one which left the interrupt and kernel stacks
+        * in a reasonable state, then we should find a pointer
+        * to the proper stack frame here (at location scb-4).
+        * If we don't find a reasonable frame here, then we
+        * must search down through the interrupt stack.
+        */
+       intstack = lookup("_intstack")->n_value;
+#define        NISP    3                       /* from locore.s */
+       eintstack = intstack + NISP*NBPG;
+       rpb = lookup("_rpb")->n_value;
+       scb = lookup("_scb")->n_value;
+       lookup("_u");
+       ustack = cursym->n_value + (int)&((struct user *)0)->u_stack[0];
+       eustack = cursym->n_value + ctob(UPAGES);
+       physrw(fcor, KVTOPH((int)scb - sizeof (caddr_t)), &addr, 1);
+       fp = getframe(fcor, addr);
+       if (fp == 0)
+               fp = checkintstack();
+       /* search kernel stack? */
+       if (fp == 0) {
+               printf("can't locate stack frame\n");
+               return;
+       }
+       /* probably shouldn't clobber pcb, but for now this is easy */
+       pcb.pcb_fp = addr;
+       pcb.pcb_pc = fp->fr_savpc;
+       pcb.pcb_ap = addr + sizeof (struct frame) + fp->fr_spa;
+       for (mask = fp->fr_mask; mask; mask >>= 1)
+               if (mask & 01)
+                       pcb.pcb_ap += sizeof (caddr_t);
+}
+
+/*
+ * Search interrupt stack for a valid frame.
+ */
+struct frame *
+checkintstack(fcor)
+{
+       char stack[NISP*NBPG];
+       off_t off = vtophys(intstack);
+       struct frame *fp;
+       register caddr_t addr;
+
+       if (off == -1 || lseek(fcor, off, L_SET) != off ||
+           read(fcor, stack, sizeof (stack)) != sizeof (stack))
+               return ((struct frame *)0);
+       addr = eintstack;
+       do {
+               addr -= sizeof (caddr_t);
+               fp = (struct frame *)&stack[addr - intstack];
+       } while (addr >= intstack + sizeof (struct frame) &&
+           !checkframe(fp));
+       return (addr < intstack+sizeof (struct frame) ? (struct frame *)0 : fp);
+}
+
+/*
+ * Get a stack frame and verify it looks like
+ * something which might be on a kernel stack.
+ */
+struct frame *
+getframe(fcor, fp)
+       int fcor;
+       caddr_t fp;
+{
+       static struct frame frame;
+       off_t off;
+
+       if (!kstackaddr(fp) || (off = vtophys(fp)) == -1)
+               return ((struct frame *)0);
+       if (lseek(fcor, off, L_SET) != off ||
+           read(fcor, &frame, sizeof (frame)) != sizeof (frame))
+               return ((struct frame *)0);
+       if (!checkframe(&frame))
+               return ((struct frame *)0);
+       return (&frame);
+}
+
+/*
+ * Check a call frame to see if it's ok as
+ * a kernel stack frame.
+ */
+checkframe(fp)
+       register struct frame *fp;
+{
+
+       if (fp->fr_handler != 0 || fp->fr_s == 0)
+               return (0);
+       if (!kstackaddr(fp->fr_savap) || !kstackaddr(fp->fr_savfp))
+               return (0);
+       return (within(fp->fr_savpc, txtmap.b1, txtmap.e1));
+}
+
+/*
+ * Check if an address is in one of the kernel's stacks:
+ * interrupt stack, rpb stack (during restart sequence),
+ * or u. stack.
+ */
+kstackaddr(addr)
+       caddr_t addr;
+{
+
+       return (within(addr, intstack, eintstack) ||
+           within(addr, rpb + sizeof (struct rpb), scb) ||
+           within(addr, ustack, eustack));
+}
+
 create(f)
        char *f;
 {
 create(f)
        char *f;
 {