home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / ktrace / kdump / kdump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-17  |  9.7 KB  |  425 lines

  1. /*-
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)kdump.c    5.3 (Berkeley) 1/17/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/errno.h>
  46. #include <sys/time.h>
  47. #include <sys/uio.h>
  48. #include <sys/ktrace.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/ptrace.h>
  51. #define KERNEL
  52. #include <sys/errno.h>
  53. #undef KERNEL
  54. #include <vis.h>
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include "ktrace.h"
  59.  
  60. int timestamp, decimal, fancy = 1, tail, maxdata;
  61. char *tracefile = DEF_TRACEFILE;
  62. struct ktr_header ktr_header;
  63.  
  64. #define eqs(s1, s2)    (strcmp((s1), (s2)) == 0)
  65.  
  66. main(argc, argv)
  67.     int argc;
  68.     char *argv[];
  69. {
  70.     extern int optind;
  71.     extern char *optarg;
  72.     int ch, ktrlen, size;
  73.     register void *m;
  74.     int trpoints = ALL_POINTS;
  75.  
  76.     while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != EOF)
  77.         switch((char)ch) {
  78.         case 'f':
  79.             tracefile = optarg;
  80.             break;
  81.         case 'd':
  82.             decimal = 1;
  83.             break;
  84.         case 'l':
  85.             tail = 1;
  86.             break;
  87.         case 'm':
  88.             maxdata = atoi(optarg);
  89.             break;
  90.         case 'n':
  91.             fancy = 0;
  92.             break;
  93.         case 'R':
  94.             timestamp = 2;    /* relative timestamp */
  95.             break;
  96.         case 'T':
  97.             timestamp = 1;
  98.             break;
  99.         case 't':
  100.             trpoints = getpoints(optarg);
  101.             if (trpoints < 0) {
  102.                 (void)fprintf(stderr,
  103.                     "kdump: unknown trace point in %s\n",
  104.                     optarg);
  105.                 exit(1);
  106.             }
  107.             break;
  108.         default:
  109.             usage();
  110.         }
  111.     argv += optind;
  112.     argc -= optind;
  113.  
  114.     if (argc > 1)
  115.         usage();
  116.  
  117.     m = (void *)malloc(size = 1025);
  118.     if (m == NULL) {
  119.         (void)fprintf(stderr, "kdump: %s.\n", strerror(ENOMEM));
  120.         exit(1);
  121.     }
  122.     if (!freopen(tracefile, "r", stdin)) {
  123.         (void)fprintf(stderr,
  124.             "kdump: %s: %s.\n", tracefile, strerror(errno));
  125.         exit(1);
  126.     }
  127.     while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
  128.         if (trpoints & (1<<ktr_header.ktr_type))
  129.             dumpheader(&ktr_header);
  130.         if ((ktrlen = ktr_header.ktr_len) < 0) {
  131.             (void)fprintf(stderr,
  132.                 "kdump: bogus length 0x%x\n", ktrlen);
  133.             exit(1);
  134.         }
  135.         if (ktrlen > size) {
  136.             m = (void *)realloc(m, ktrlen+1);
  137.             if (m == NULL) {
  138.                 (void)fprintf(stderr,
  139.                     "kdump: %s.\n", strerror(ENOMEM));
  140.                 exit(1);
  141.             }
  142.             size = ktrlen;
  143.         }
  144.         if (ktrlen && fread_tail(m, ktrlen, 1) == 0) {
  145.             (void)fprintf(stderr, "kdump: data too short.\n");
  146.             exit(1);
  147.         }
  148.         if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
  149.             continue;
  150.         switch (ktr_header.ktr_type) {
  151.         case KTR_SYSCALL:
  152.             ktrsyscall((struct ktr_syscall *)m);
  153.             break;
  154.         case KTR_SYSRET:
  155.             ktrsysret((struct ktr_sysret *)m);
  156.             break;
  157.         case KTR_NAMEI:
  158.             ktrnamei(m, ktrlen);
  159.             break;
  160.         case KTR_GENIO:
  161.             ktrgenio((struct ktr_genio *)m, ktrlen);
  162.             break;
  163.         case KTR_PSIG:
  164.             ktrpsig((struct ktr_psig *)m);
  165.             break;
  166.         }
  167.         if (tail)
  168.             (void)fflush(stdout);
  169.     }
  170. }
  171.  
  172. fread_tail(buf, size, num)
  173.     char *buf;
  174.     int num, size;
  175. {
  176.     int i;
  177.  
  178.     while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
  179.         (void)sleep(1);
  180.         clearerr(stdin);
  181.     }
  182.     return (i);
  183. }
  184.  
  185. dumpheader(kth)
  186.     struct ktr_header *kth;
  187. {
  188.     static char unknown[64];
  189.     static struct timeval prevtime, temp;
  190.     char *type;
  191.  
  192.     switch (kth->ktr_type) {
  193.     case KTR_SYSCALL:
  194.         type = "CALL";
  195.         break;
  196.     case KTR_SYSRET:
  197.         type = "RET ";
  198.         break;
  199.     case KTR_NAMEI:
  200.         type = "NAMI";
  201.         break;
  202.     case KTR_GENIO:
  203.         type = "GIO ";
  204.         break;
  205.     case KTR_PSIG:
  206.         type = "PSIG";
  207.         break;
  208.     default:
  209.         (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
  210.         type = unknown;
  211.     }
  212.  
  213.     (void)printf("%6d %-8s ", kth->ktr_pid, kth->ktr_comm);
  214.     if (timestamp) {
  215.         if (timestamp == 2) {
  216.             temp = kth->ktr_time;
  217.             timevalsub(&kth->ktr_time, &prevtime);
  218.             prevtime = temp;
  219.         }
  220.         (void)printf("%ld.%06ld ",
  221.             kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
  222.     }
  223.     (void)printf("%s  ", type);
  224. }
  225.  
  226. #include <sys/syscall.h>
  227. #define KTRACE
  228. #include "/sys/kern/syscalls.c"
  229. #undef KTRACE
  230. int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
  231.  
  232. static char *ptrace_ops[] = {
  233.     "PT_TRACE_ME",    "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
  234.     "PT_WRITE_I",    "PT_WRITE_D",    "PT_WRITE_U",    "PT_CONTINUE",
  235.     "PT_KILL",    "PT_STEP",
  236. };
  237.  
  238. ktrsyscall(ktr)
  239.     register struct ktr_syscall *ktr;
  240. {
  241.     register narg = ktr->ktr_narg;
  242.     register int *ip;
  243.     char *ioctlname();
  244.  
  245.     if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
  246.         (void)printf("[%d]", ktr->ktr_code);
  247.     else
  248.         (void)printf("%s", syscallnames[ktr->ktr_code]);
  249.     ip = (int *)((char *)ktr + sizeof(struct ktr_syscall));
  250.     if (narg) {
  251.         char c = '(';
  252.         if (fancy) {
  253.             if (ktr->ktr_code == SYS_ioctl) {
  254.                 char *cp;
  255.                 if (decimal)
  256.                     (void)printf("(%d", *ip);
  257.                 else
  258.                     (void)printf("(%#x", *ip);
  259.                 ip++;
  260.                 narg--;
  261.                 if ((cp = ioctlname(*ip)) != NULL)
  262.                     (void)printf(",%s", cp);
  263.                 else {
  264.                     if (decimal)
  265.                         (void)printf(",%d", *ip);
  266.                     else
  267.                         (void)printf(",%#x ", *ip);
  268.                 }
  269.                 c = ',';
  270.                 ip++;
  271.                 narg--;
  272.             } else if (ktr->ktr_code == SYS_ptrace) {
  273.                 if (*ip <= PT_STEP && *ip >= 0)
  274.                     (void)printf("(%s", ptrace_ops[*ip]);
  275.                 else
  276.                     (void)printf("(%d", *ip);
  277.                 c = ',';
  278.                 ip++;
  279.                 narg--;
  280.             }
  281.         }
  282.         while (narg) {
  283.             if (decimal)
  284.                 (void)printf("%c%d", c, *ip);
  285.             else
  286.                 (void)printf("%c%#x", c, *ip);
  287.             c = ',';
  288.             ip++;
  289.             narg--;
  290.         }
  291.         (void)putchar(')');
  292.     }
  293.     (void)putchar('\n');
  294. }
  295.  
  296. ktrsysret(ktr)
  297.     struct ktr_sysret *ktr;
  298. {
  299.     register int ret = ktr->ktr_retval;
  300.     register int error = ktr->ktr_error;
  301.     register int code = ktr->ktr_code;
  302.  
  303.     if (code >= nsyscalls || code < 0)
  304.         (void)printf("[%d] ", code);
  305.     else
  306.         (void)printf("%s ", syscallnames[code]);
  307.  
  308.     if (error == 0) {
  309.         if (fancy) {
  310.             (void)printf("%d", ret);
  311.             if (ret < 0 || ret > 9)
  312.                 (void)printf("/%#x", ret);
  313.         } else {
  314.             if (decimal)
  315.                 (void)printf("%d", ret);
  316.             else
  317.                 (void)printf("%#x", ret);
  318.         }
  319.     } else if (error == ERESTART)
  320.         (void)printf("RESTART");
  321.     else if (error == EJUSTRETURN)
  322.         (void)printf("JUSTRETURN");
  323.     else {
  324.         (void)printf("-1 errno %d", ktr->ktr_error);
  325.         if (fancy)
  326.             (void)printf(" %s", strerror(ktr->ktr_error));
  327.     }
  328.     (void)putchar('\n');
  329. }
  330.  
  331. ktrnamei(cp, len) 
  332.     char *cp;
  333. {
  334.     (void)printf("\"%.*s\"\n", len, cp);
  335. }
  336.  
  337. ktrgenio(ktr, len)
  338.     struct ktr_genio *ktr;
  339. {
  340.     register int datalen = len - sizeof (struct ktr_genio);
  341.     register char *dp = (char *)ktr + sizeof (struct ktr_genio);
  342.     register char *cp;
  343.     register int col = 0;
  344.     register width;
  345.     char visbuf[5];
  346.     static screenwidth = 0;
  347.  
  348.     if (screenwidth == 0) {
  349.         struct winsize ws;
  350.  
  351.         if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
  352.             ws.ws_col > 8)
  353.             screenwidth = ws.ws_col;
  354.         else
  355.             screenwidth = 80;
  356.     }
  357.     printf("fd %d %s %d bytes\n", ktr->ktr_fd,
  358.         ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
  359.     if (maxdata && datalen > maxdata)
  360.         datalen = maxdata;
  361.     (void)printf("       \"");
  362.     col = 8;
  363.     for (;datalen > 0; datalen--, dp++) {
  364.         (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
  365.         cp = visbuf;
  366.         /*
  367.          * Keep track of printables and
  368.          * space chars (like fold(1)).
  369.          */
  370.         if (col == 0) {
  371.             (void)putchar('\t');
  372.             col = 8;
  373.         }
  374.         switch(*cp) {
  375.         case '\n':
  376.             col = 0;
  377.             (void)putchar('\n');
  378.             continue;
  379.         case '\t':
  380.             width = 8 - (col&07);
  381.             break;
  382.         default:
  383.             width = strlen(cp);
  384.         }
  385.         if (col + width > (screenwidth-2)) {
  386.             (void)printf("\\\n\t");
  387.             col = 8;
  388.         }
  389.         col += width;
  390.         do {
  391.             (void)putchar(*cp++);
  392.         } while (*cp);
  393.     }
  394.     if (col == 0)
  395.         (void)printf("       ");
  396.     (void)printf("\"\n");
  397. }
  398.  
  399. char *signames[] = {
  400.     "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",    /*  1 - 6  */
  401.     "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  402.     "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  403.     "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  404.     "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",    /* 25 - 30 */
  405.     "USR2", NULL,                        /* 31 - 32 */
  406. };
  407.  
  408. ktrpsig(psig)
  409.     struct ktr_psig *psig;
  410. {
  411.     (void)printf("SIG%s ", signames[psig->signo]);
  412.     if (psig->action == SIG_DFL)
  413.         (void)printf("SIG_DFL\n");
  414.     else
  415.         (void)printf("caught handler=0x%x mask=0x%x code=0x%x\n",
  416.             (u_int)psig->action, psig->mask, psig->code);
  417. }
  418.  
  419. usage()
  420. {
  421.     (void)fprintf(stderr,
  422.         "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnis]]\n");
  423.     exit(1);
  424. }
  425.