home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / unix / amiga / 2393 < prev    next >
Encoding:
Text File  |  1992-11-11  |  7.6 KB  |  381 lines

  1. 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
  2. From: ag@cogsci.Berkeley.EDU (Keith Gabryelski)
  3. Newsgroups: comp.unix.amiga
  4. Subject: Symbolic Kernel Backtrace Code
  5. Date: 12 Nov 1992 03:34:31 GMT
  6. Organization: Institute of Cognitive Studies, U.C. Berkeley
  7. Lines: 370
  8. Message-ID: <1dsjc7INNevv@agate.berkeley.edu>
  9. NNTP-Posting-Host: cogsci.berkeley.edu
  10.  
  11. I hacked together some kernel backtrace code that will show a
  12. symbolic backtrace with arguments if the kernel panics.
  13.  
  14. This should make it infinately easier to look at backtraces and
  15. see if they are interesting or not.
  16.  
  17. The file `syms.c' should go in /usr/sys/amiga/drivers with
  18. an entry placed in cdevsw in master.d/kernel.c.  The node should
  19. be called `/dev/syms'.
  20.  
  21. The file `stuffsyms' is a shell script that will `nm' /stand/unix
  22. sedding the interesting information and write it to /dev/syms.
  23. This can be run from /etc/sysinit to initialize the kernel symbol
  24. table.
  25.  
  26. The only trick to getting this stuff to work is to modify the
  27. symbol `backtrace' from /usr/sys/os/exp.  To do this you will need
  28. a binary editor (like emacs) or write your own program.
  29.  
  30. Change the sequence of characters:
  31.  
  32.     b a c k t r a c e ^@
  33.  
  34. in os/exp to:
  35.  
  36.     B A C K T R A C E ^@
  37.  
  38. This will modify the symbol `backtrace' so the kernel will use the
  39. one in `syms.c' instead of the one in os/exp.
  40.  
  41. In emacs you can  accomplish this by edditing /usr/sys/os/exp and
  42. typing:
  43.  
  44.     ^S b a c k t r a c e ^[ ^[ - ^[ u ^X ^S ^X ^C
  45.  
  46. Pax, Keith
  47.  
  48. # This is a shell archive.  Remove anything before this line,
  49. # then unpack it by saving it in a file and typing "sh file".
  50. #
  51. # This archive contains:
  52. #    syms.c        stuffsyms    
  53. #
  54.  
  55. echo x - syms.c
  56. cat >syms.c <<'@EOF'
  57. #include "sys/types.h"
  58. #include "sys/file.h"
  59. #include "sys/param.h"
  60. #include "sys/uio.h"
  61. #include "sys/errno.h"
  62. #include "sys/inline.h"
  63. #include "sys/sysmacros.h"
  64. #include "sys/immu.h"
  65. #include "sys/kmem.h"
  66. #include "sys/cred.h"
  67. #include "sys/utsname.h"
  68.  
  69. static boolean_t symline(char *buf, int length);
  70. static int symsprocess(char *buf, int index);
  71.  
  72. static boolean_t symsopenned;        /* openned semaphore */
  73. static char *syms;            /* symbol table */
  74. static size_t symslength;        /* length of table */
  75. static size_t symssize;            /* size of alloced memory for table */
  76.  
  77. int symsopen(dev_t *devp, int mode, int type, cred_t *credp)
  78. {
  79.     int s = spl1();
  80.  
  81.     if (symsopenned)
  82.     {
  83.     splx(s);
  84.     return EBUSY;
  85.     }
  86.  
  87.     symsopenned = B_TRUE;
  88.  
  89.     splx(s);
  90.  
  91.  
  92.     return 0;
  93. }
  94.  
  95. int symsclose(dev_t dev, int mode, cred_t *credp)
  96. {
  97.     symsopenned = B_FALSE;
  98.     return 0;
  99. }
  100.  
  101. char _symsbuf[1024];
  102. int _symslength;
  103.  
  104. int symswrite(dev_t dev, uio_t *uiop, cred_t *credp)
  105. {
  106.     while (uiop->uio_resid)
  107.     {
  108.     int error, count, n;
  109.  
  110.     count = min(sizeof _symsbuf - _symslength, uiop->uio_resid);
  111.  
  112.     error = uiomove(_symsbuf + _symslength, count, UIO_WRITE, uiop);
  113.     if (error)
  114.         return error;
  115.  
  116.     n = symsprocess(_symsbuf, _symslength + count);
  117.     if (n < 0 || n == sizeof _symsbuf)
  118.     {
  119.         _symslength = 0;
  120.         if (n < 0)
  121.         return -n;
  122.  
  123.         return EINVAL;
  124.     }
  125.     _symslength = n;
  126.     }
  127.  
  128.     return 0;
  129. }
  130.  
  131. static boolean_t symline(char *buf, int length)
  132. {
  133.     while (length && *buf != '\n')
  134.     {
  135.     ++buf;
  136.     --length;
  137.     }
  138.  
  139.     return length;
  140. }
  141.  
  142. static boolean_t symsadd(unsigned long addr, char *symbol, size_t length)
  143. {
  144.     if (!addr || !length)
  145.     return B_TRUE;
  146.  
  147.     if (symssize - symslength < sizeof addr + length)
  148.     {
  149.     size_t size = symssize + 1024;
  150.     char *ptr;
  151.  
  152.     ptr = kmem_alloc(size, 0);
  153.     if (!ptr)
  154.         return B_FALSE;
  155.  
  156.     if (syms)
  157.     {
  158.         char *old = syms;
  159.  
  160.         bcopy(old, ptr, symslength);
  161.         syms = ptr;
  162.         kmem_free(old, symssize);
  163.     }
  164.     else
  165.         syms = ptr;
  166.  
  167.     symssize = size;
  168.     }
  169.  
  170.     *(unsigned long *)&syms[symslength] = addr;
  171.     symslength += sizeof (unsigned long);
  172.  
  173.     bcopy(symbol, &syms[symslength], length);
  174.     symslength += length;
  175.  
  176.     return B_TRUE;
  177. }
  178.  
  179. static int symsprocess(char *buf, int length)
  180. {
  181.     int index;
  182.     unsigned long addr;
  183.     char symbol[1024], *s, *bufp;
  184.  
  185.     index = 0;
  186.     bufp = buf;
  187.     while (symline(bufp, length - index))
  188.     {
  189.     int c;
  190.  
  191.     if (*bufp++ != '0' || *bufp++ != 'x')
  192.         return -EINVAL;
  193.  
  194.     index += 2;
  195.  
  196.     addr = 0;
  197.     while ((c = *bufp) != ' ')
  198.     {
  199.         addr *= 16;
  200.         if (c < '0' || (c > '9' && c < 'a') || (c > 'f'))
  201.         return -EINVAL;
  202.  
  203.         if (c > '9')
  204.         c -= ('a' - 10);
  205.         else
  206.         c -= '0';
  207.         addr += c;
  208.  
  209.         ++bufp;
  210.         ++index;
  211.     }
  212.     ++bufp;
  213.     ++index;
  214.  
  215.     s = symbol;
  216.     while (*bufp != '\n')
  217.     {
  218.         *s++ = *bufp++;
  219.         ++index;
  220.     }
  221.     *s++ = '\0';
  222.     ++bufp;
  223.     ++index;
  224.  
  225.     if (!symsadd(addr, symbol, s - symbol))
  226.         return -ENOMEM;
  227.     }
  228.  
  229.     length -= index;
  230.     if (length)
  231.     ovbcopy(bufp, buf, length);
  232.  
  233.     return length;
  234. }
  235.  
  236. static void strhex(char *buf, long num)
  237. {
  238.     int i;
  239.     int digits[8];
  240.  
  241.     for (i = 0; i < sizeof digits; i++)
  242.     {
  243.     digits[i] = num % 16;
  244.     num = num / 16;
  245.     if (!num)
  246.         break;
  247.     }
  248.     if (i == sizeof digits)
  249.     --i;
  250.     *buf++ = '0';
  251.     *buf++ = 'x';
  252.     for (; i >= 0; i--)
  253.     *buf++ = "0123456789abcdef"[digits[i]];
  254.     *buf = '\0';
  255. }
  256.  
  257. char *findsym(unsigned long addr)
  258. {
  259.     if (addr && syms)
  260.     {
  261.     char *ptr = syms, *lsym = 0;
  262.     unsigned long laddr;
  263.  
  264.     while (ptr - syms < symslength)
  265.     {
  266.         if (*(unsigned long *)ptr == addr)
  267.         return ptr + sizeof (unsigned long);
  268.  
  269.         if (*(unsigned long *)ptr > addr)
  270.         {
  271.         if (lsym)
  272.         {
  273.             for (ptr = _symsbuf; *lsym; )
  274.             *ptr++ = *lsym++;
  275.             *ptr++ = '+';
  276.             strhex(ptr, addr - laddr);
  277.             return _symsbuf;
  278.         }
  279.         else
  280.             break;
  281.         }
  282.  
  283.         laddr = *(unsigned long *)ptr;
  284.         ptr += sizeof (unsigned long);
  285.         lsym = ptr;
  286.         while (*ptr++)
  287.         ;
  288.     }
  289.     }
  290.  
  291.     strhex(_symsbuf, addr);                   
  292.     return _symsbuf;
  293. }
  294.  
  295. /*
  296.  * Particular instructions looked for in stack backtrace.
  297.  */
  298. #define JSRAnMASK 0xFFF0
  299. #define JSRAn     0x4E90        /* jsr (%a0) */
  300. #define CALLMASK 0xFFFF
  301. #define JSRL     0x4EB9        /* jsr <adr> */
  302. #define JSRLpc     0x4EBB        /* jsr off.l(%pc) */
  303. #define JSRWpc     0x4EBA        /* jsr off.w(%pc) */
  304. #define BSRLpc     0x61FF        /* bsr off.l(%pc) */
  305. #define BSRWpc     0x6100        /* bsr off.w(%pc) */
  306. #define BSRBMASK 0xFF00
  307. #define BSRB     0x6100        /* bsr off.b(%pc) */
  308.  
  309. void backtrace(int dummy)
  310. {
  311.     int *fp;
  312.     short *pc;
  313.     long calladdr = 0;
  314.     static int crashflag;
  315.  
  316.     if (crashflag++)
  317.     return;
  318.  
  319.     printf("%s %s Backtrace:\n", utsname.release, utsname.version);
  320.  
  321.     for (fp = &dummy - 2;
  322.      printf("%x: ", fp), fp >= (int *)0x40000000 && fp < (int *)0x40010000;
  323.      printf("(%x, %x, %x)\n",((int*)*fp)[2],((int*)*fp)[3],((int*)*fp)[4]),
  324.      fp = (int *)*fp)
  325.     {
  326.     pc = (short *)(fp[1]-6);
  327.  
  328.     if ((*pc & CALLMASK) == JSRL)
  329.         calladdr = *(long *)(pc+1);
  330.     else if ((*pc & CALLMASK) == JSRLpc || (*pc & CALLMASK) == BSRLpc)
  331.         calladdr = (long)(pc+1) + *(long *)(pc+1);
  332.     else
  333.     {
  334.         ++pc;
  335.         if ((*pc & CALLMASK) == JSRWpc || (*pc & CALLMASK) == BSRWpc)
  336.         calladdr = (long)(pc+1) + pc[1];
  337.         else
  338.         {
  339.         ++pc;
  340.         if ((*pc & BSRBMASK) == BSRB)
  341.             calladdr = (long)pc + (signed char)pc[1];
  342.         else
  343.         {
  344.             if ((*pc & JSRAnMASK) == JSRAn)
  345.             printf("%s->indir", findsym((unsigned long)pc));
  346.             else
  347.             printf("%s->???", findsym((unsigned long)pc));
  348.             continue;
  349.         }
  350.         }
  351.     }
  352.  
  353.     printf("%s->", findsym((unsigned long)pc));
  354.     printf("%s", findsym(calladdr));
  355.     }
  356.     printf("\n");
  357.  
  358. #if EXTRA_DEBUG
  359.     {
  360.     extern sde_t cpuroot, userroot;
  361.  
  362.     printf("Kernel Root Ptr:%x  User Root Ptr:%x\n",
  363.            cpuroot.wd2.address,userroot.wd2.address);
  364.     }
  365. #endif
  366. }
  367. @EOF
  368.  
  369. chmod 644 syms.c
  370.  
  371. echo x - stuffsyms
  372. cat >stuffsyms <<'@EOF'
  373. /usr/ccs/bin/nm -xvph /stand/unix |
  374. /usr/bin/sed -n 's/^\(.*\) . \([a-zA-Z_0-9][a-zA-Z_0-9]*\)$/\1 \2/p' >/dev/syms
  375. @EOF
  376.  
  377. chmod 755 stuffsyms
  378.  
  379. exit 0
  380.  
  381.