home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!charon.amdahl.com!pacbell.com!iggy.GW.Vitalink.COM!cs.widener.edu!hela.iti.org!usc!elroy.jpl.nasa.gov!swrinde!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!agate!cogsci.Berkeley.EDU!ag
- From: ag@cogsci.Berkeley.EDU (Keith Gabryelski)
- Newsgroups: comp.unix.amiga
- Subject: Symbolic Kernel Backtrace Code
- Date: 12 Nov 1992 03:34:31 GMT
- Organization: Institute of Cognitive Studies, U.C. Berkeley
- Lines: 370
- Message-ID: <1dsjc7INNevv@agate.berkeley.edu>
- NNTP-Posting-Host: cogsci.berkeley.edu
-
- I hacked together some kernel backtrace code that will show a
- symbolic backtrace with arguments if the kernel panics.
-
- This should make it infinately easier to look at backtraces and
- see if they are interesting or not.
-
- The file `syms.c' should go in /usr/sys/amiga/drivers with
- an entry placed in cdevsw in master.d/kernel.c. The node should
- be called `/dev/syms'.
-
- The file `stuffsyms' is a shell script that will `nm' /stand/unix
- sedding the interesting information and write it to /dev/syms.
- This can be run from /etc/sysinit to initialize the kernel symbol
- table.
-
- The only trick to getting this stuff to work is to modify the
- symbol `backtrace' from /usr/sys/os/exp. To do this you will need
- a binary editor (like emacs) or write your own program.
-
- Change the sequence of characters:
-
- b a c k t r a c e ^@
-
- in os/exp to:
-
- B A C K T R A C E ^@
-
- This will modify the symbol `backtrace' so the kernel will use the
- one in `syms.c' instead of the one in os/exp.
-
- In emacs you can accomplish this by edditing /usr/sys/os/exp and
- typing:
-
- ^S b a c k t r a c e ^[ ^[ - ^[ u ^X ^S ^X ^C
-
- Pax, Keith
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # This archive contains:
- # syms.c stuffsyms
- #
-
- echo x - syms.c
- cat >syms.c <<'@EOF'
- #include "sys/types.h"
- #include "sys/file.h"
- #include "sys/param.h"
- #include "sys/uio.h"
- #include "sys/errno.h"
- #include "sys/inline.h"
- #include "sys/sysmacros.h"
- #include "sys/immu.h"
- #include "sys/kmem.h"
- #include "sys/cred.h"
- #include "sys/utsname.h"
-
- static boolean_t symline(char *buf, int length);
- static int symsprocess(char *buf, int index);
-
- static boolean_t symsopenned; /* openned semaphore */
- static char *syms; /* symbol table */
- static size_t symslength; /* length of table */
- static size_t symssize; /* size of alloced memory for table */
-
- int symsopen(dev_t *devp, int mode, int type, cred_t *credp)
- {
- int s = spl1();
-
- if (symsopenned)
- {
- splx(s);
- return EBUSY;
- }
-
- symsopenned = B_TRUE;
-
- splx(s);
-
-
- return 0;
- }
-
- int symsclose(dev_t dev, int mode, cred_t *credp)
- {
- symsopenned = B_FALSE;
- return 0;
- }
-
- char _symsbuf[1024];
- int _symslength;
-
- int symswrite(dev_t dev, uio_t *uiop, cred_t *credp)
- {
- while (uiop->uio_resid)
- {
- int error, count, n;
-
- count = min(sizeof _symsbuf - _symslength, uiop->uio_resid);
-
- error = uiomove(_symsbuf + _symslength, count, UIO_WRITE, uiop);
- if (error)
- return error;
-
- n = symsprocess(_symsbuf, _symslength + count);
- if (n < 0 || n == sizeof _symsbuf)
- {
- _symslength = 0;
- if (n < 0)
- return -n;
-
- return EINVAL;
- }
- _symslength = n;
- }
-
- return 0;
- }
-
- static boolean_t symline(char *buf, int length)
- {
- while (length && *buf != '\n')
- {
- ++buf;
- --length;
- }
-
- return length;
- }
-
- static boolean_t symsadd(unsigned long addr, char *symbol, size_t length)
- {
- if (!addr || !length)
- return B_TRUE;
-
- if (symssize - symslength < sizeof addr + length)
- {
- size_t size = symssize + 1024;
- char *ptr;
-
- ptr = kmem_alloc(size, 0);
- if (!ptr)
- return B_FALSE;
-
- if (syms)
- {
- char *old = syms;
-
- bcopy(old, ptr, symslength);
- syms = ptr;
- kmem_free(old, symssize);
- }
- else
- syms = ptr;
-
- symssize = size;
- }
-
- *(unsigned long *)&syms[symslength] = addr;
- symslength += sizeof (unsigned long);
-
- bcopy(symbol, &syms[symslength], length);
- symslength += length;
-
- return B_TRUE;
- }
-
- static int symsprocess(char *buf, int length)
- {
- int index;
- unsigned long addr;
- char symbol[1024], *s, *bufp;
-
- index = 0;
- bufp = buf;
- while (symline(bufp, length - index))
- {
- int c;
-
- if (*bufp++ != '0' || *bufp++ != 'x')
- return -EINVAL;
-
- index += 2;
-
- addr = 0;
- while ((c = *bufp) != ' ')
- {
- addr *= 16;
- if (c < '0' || (c > '9' && c < 'a') || (c > 'f'))
- return -EINVAL;
-
- if (c > '9')
- c -= ('a' - 10);
- else
- c -= '0';
- addr += c;
-
- ++bufp;
- ++index;
- }
- ++bufp;
- ++index;
-
- s = symbol;
- while (*bufp != '\n')
- {
- *s++ = *bufp++;
- ++index;
- }
- *s++ = '\0';
- ++bufp;
- ++index;
-
- if (!symsadd(addr, symbol, s - symbol))
- return -ENOMEM;
- }
-
- length -= index;
- if (length)
- ovbcopy(bufp, buf, length);
-
- return length;
- }
-
- static void strhex(char *buf, long num)
- {
- int i;
- int digits[8];
-
- for (i = 0; i < sizeof digits; i++)
- {
- digits[i] = num % 16;
- num = num / 16;
- if (!num)
- break;
- }
- if (i == sizeof digits)
- --i;
- *buf++ = '0';
- *buf++ = 'x';
- for (; i >= 0; i--)
- *buf++ = "0123456789abcdef"[digits[i]];
- *buf = '\0';
- }
-
- char *findsym(unsigned long addr)
- {
- if (addr && syms)
- {
- char *ptr = syms, *lsym = 0;
- unsigned long laddr;
-
- while (ptr - syms < symslength)
- {
- if (*(unsigned long *)ptr == addr)
- return ptr + sizeof (unsigned long);
-
- if (*(unsigned long *)ptr > addr)
- {
- if (lsym)
- {
- for (ptr = _symsbuf; *lsym; )
- *ptr++ = *lsym++;
- *ptr++ = '+';
- strhex(ptr, addr - laddr);
- return _symsbuf;
- }
- else
- break;
- }
-
- laddr = *(unsigned long *)ptr;
- ptr += sizeof (unsigned long);
- lsym = ptr;
- while (*ptr++)
- ;
- }
- }
-
- strhex(_symsbuf, addr);
- return _symsbuf;
- }
-
- /*
- * Particular instructions looked for in stack backtrace.
- */
- #define JSRAnMASK 0xFFF0
- #define JSRAn 0x4E90 /* jsr (%a0) */
- #define CALLMASK 0xFFFF
- #define JSRL 0x4EB9 /* jsr <adr> */
- #define JSRLpc 0x4EBB /* jsr off.l(%pc) */
- #define JSRWpc 0x4EBA /* jsr off.w(%pc) */
- #define BSRLpc 0x61FF /* bsr off.l(%pc) */
- #define BSRWpc 0x6100 /* bsr off.w(%pc) */
- #define BSRBMASK 0xFF00
- #define BSRB 0x6100 /* bsr off.b(%pc) */
-
- void backtrace(int dummy)
- {
- int *fp;
- short *pc;
- long calladdr = 0;
- static int crashflag;
-
- if (crashflag++)
- return;
-
- printf("%s %s Backtrace:\n", utsname.release, utsname.version);
-
- for (fp = &dummy - 2;
- printf("%x: ", fp), fp >= (int *)0x40000000 && fp < (int *)0x40010000;
- printf("(%x, %x, %x)\n",((int*)*fp)[2],((int*)*fp)[3],((int*)*fp)[4]),
- fp = (int *)*fp)
- {
- pc = (short *)(fp[1]-6);
-
- if ((*pc & CALLMASK) == JSRL)
- calladdr = *(long *)(pc+1);
- else if ((*pc & CALLMASK) == JSRLpc || (*pc & CALLMASK) == BSRLpc)
- calladdr = (long)(pc+1) + *(long *)(pc+1);
- else
- {
- ++pc;
- if ((*pc & CALLMASK) == JSRWpc || (*pc & CALLMASK) == BSRWpc)
- calladdr = (long)(pc+1) + pc[1];
- else
- {
- ++pc;
- if ((*pc & BSRBMASK) == BSRB)
- calladdr = (long)pc + (signed char)pc[1];
- else
- {
- if ((*pc & JSRAnMASK) == JSRAn)
- printf("%s->indir", findsym((unsigned long)pc));
- else
- printf("%s->???", findsym((unsigned long)pc));
- continue;
- }
- }
- }
-
- printf("%s->", findsym((unsigned long)pc));
- printf("%s", findsym(calladdr));
- }
- printf("\n");
-
- #if EXTRA_DEBUG
- {
- extern sde_t cpuroot, userroot;
-
- printf("Kernel Root Ptr:%x User Root Ptr:%x\n",
- cpuroot.wd2.address,userroot.wd2.address);
- }
- #endif
- }
- @EOF
-
- chmod 644 syms.c
-
- echo x - stuffsyms
- cat >stuffsyms <<'@EOF'
- /usr/ccs/bin/nm -xvph /stand/unix |
- /usr/bin/sed -n 's/^\(.*\) . \([a-zA-Z_0-9][a-zA-Z_0-9]*\)$/\1 \2/p' >/dev/syms
- @EOF
-
- chmod 755 stuffsyms
-
- exit 0
-
-