home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / kgmon / kgmon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  8.9 KB  |  363 lines

  1. /*
  2.  * Copyright (c) 1983 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) 1983 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[] = "@(#)kgmon.c    5.12 (Berkeley) 7/1/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #if BSD >= 199103
  46. #define NEWVM
  47. #endif
  48. #include <sys/file.h>
  49. #ifndef NEWVM
  50. #include <machine/pte.h>
  51. #include <sys/vm.h>
  52. #endif
  53. #include <sys/gprof.h>
  54. #include <stdio.h>
  55. #include <nlist.h>
  56. #include <ctype.h>
  57. #include <paths.h>
  58.  
  59. #define    PROFILING_ON    0
  60. #define    PROFILING_OFF    3
  61.  
  62. u_long    s_textsize;
  63. off_t    sbuf, klseek(), lseek();
  64. int    ssiz;
  65.  
  66. struct nlist nl[] = {
  67. #define    N_SYSMAP    0
  68.     { "_Sysmap" },
  69. #define    N_SYSSIZE    1
  70.     { "_Syssize" },
  71. #define N_FROMS        2
  72.     { "_froms" },
  73. #define    N_PROFILING    3
  74.     { "_profiling" },
  75. #define    N_S_LOWPC    4
  76.     { "_s_lowpc" },
  77. #define    N_S_TEXTSIZE    5
  78.     { "_s_textsize" },
  79. #define    N_SBUF        6
  80.     { "_sbuf" },
  81. #define N_SSIZ        7
  82.     { "_ssiz" },
  83. #define    N_TOS        8
  84.     { "_tos" },
  85.     0,
  86. };
  87.  
  88. struct    pte *Sysmap;
  89.  
  90. int    kmem;
  91. int    bflag, hflag, kflag, rflag, pflag;
  92. int    debug = 0;
  93.  
  94. main(argc, argv)
  95.     int argc;
  96.     char **argv;
  97. {
  98.     extern char *optarg;
  99.     extern int optind;
  100.     int ch, mode, disp, openmode;
  101.     char *system, *kmemf, *malloc();
  102.  
  103.     kmemf = _PATH_KMEM;
  104.     system = _PATH_UNIX;
  105.     while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF)
  106.         switch((char)ch) {
  107.         case 'M':
  108.             kmemf = optarg;
  109.             kflag = 1;
  110.             break;
  111.         case 'N':
  112.             system = optarg;
  113.             break;
  114.         case 'b':
  115.             bflag = 1;
  116.             break;
  117.         case 'h':
  118.             hflag = 1;
  119.             break;
  120.         case 'p':
  121.             pflag = 1;
  122.             break;
  123.         case 'r':
  124.             rflag = 1;
  125.             break;
  126.         default:
  127.             (void)fprintf(stderr,
  128.                 "usage: kgmon [-bhrp] [-M core] [-N system]\n");
  129.             exit(1);
  130.         }
  131.     argc -= optind;
  132.     argv += optind;
  133.  
  134. #define BACKWARD_COMPATIBILITY
  135. #ifdef    BACKWARD_COMPATIBILITY
  136.     if (*argv) {
  137.         system = *argv;
  138.         if (*++argv) {
  139.             kmemf = *argv;
  140.             ++kflag;
  141.         }
  142.     }
  143. #endif
  144.  
  145.     if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
  146.         (void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
  147.         exit(2);
  148.     }
  149.     if (!nl[N_PROFILING].n_value) {
  150.         (void)fprintf(stderr,
  151.             "kgmon: profiling: not defined in kernel.\n");
  152.         exit(10);
  153.     }
  154.  
  155.     openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
  156.     kmem = open(kmemf, openmode);
  157.     if (kmem < 0) {
  158.         openmode = O_RDONLY;
  159.         kmem = open(kmemf, openmode);
  160.         if (kmem < 0) {
  161.             perror(kmemf);
  162.             exit(3);
  163.         }
  164.         (void)fprintf(stderr, "%s opened read-only\n", kmemf);
  165.         if (rflag)
  166.             (void)fprintf(stderr, "-r supressed\n");
  167.         if (bflag)
  168.             (void)fprintf(stderr, "-b supressed\n");
  169.         if (hflag)
  170.             (void)fprintf(stderr, "-h supressed\n");
  171.         rflag = bflag = hflag = 0;
  172.     }
  173.     if (kflag) {
  174. #ifdef NEWVM
  175.         (void)fprintf(stderr,
  176.             "kgmon: can't do core files yet\n");
  177.         exit(1);
  178. #else
  179.         off_t off;
  180.  
  181.         Sysmap = (struct pte *)
  182.            malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
  183.         if (!Sysmap) {
  184.             (void)fprintf(stderr,
  185.                 "kgmon: can't get memory for Sysmap.\n");
  186.             exit(1);
  187.         }
  188.         off = nl[N_SYSMAP].n_value & ~KERNBASE;
  189.         (void)lseek(kmem, off, L_SET);
  190.         (void)read(kmem, (char *)Sysmap,
  191.             (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
  192. #endif
  193.     }
  194.     mode = kfetch(N_PROFILING);
  195.     if (hflag)
  196.         disp = PROFILING_OFF;
  197.     else if (bflag)
  198.         disp = PROFILING_ON;
  199.     else
  200.         disp = mode;
  201.     if (pflag) {
  202.         if (openmode == O_RDONLY && mode == PROFILING_ON)
  203.             (void)fprintf(stderr, "data may be inconsistent\n");
  204.         dumpstate();
  205.     }
  206.     if (rflag)
  207.         resetstate();
  208.     turnonoff(disp);
  209.     (void)fprintf(stdout,
  210.         "kernel profiling is %s.\n", disp ? "off" : "running");
  211.     exit(0);
  212. }
  213.  
  214. dumpstate()
  215. {
  216.     extern int errno;
  217.     struct rawarc rawarc;
  218.     struct tostruct *tos;
  219.     u_long frompc;
  220.     off_t kfroms, ktos;
  221.     u_short *froms;        /* froms is a bunch of u_shorts indexing tos */
  222.     int i, fd, fromindex, endfrom, fromssize, tossize, toindex;
  223.     char buf[BUFSIZ], *s_lowpc, *malloc(), *strerror();
  224.  
  225.     turnonoff(PROFILING_OFF);
  226.     fd = creat("gmon.out", 0666);
  227.     if (fd < 0) {
  228.         perror("gmon.out");
  229.         return;
  230.     }
  231.     ssiz = kfetch(N_SSIZ);
  232.     sbuf = kfetch(N_SBUF);
  233.     (void)klseek(kmem, (off_t)sbuf, L_SET);
  234.     for (i = ssiz; i > 0; i -= BUFSIZ) {
  235.         read(kmem, buf, i < BUFSIZ ? i : BUFSIZ);
  236.         write(fd, buf, i < BUFSIZ ? i : BUFSIZ);
  237.     }
  238.     s_textsize = kfetch(N_S_TEXTSIZE);
  239.     fromssize = s_textsize / HASHFRACTION;
  240.     froms = (u_short *)malloc((u_int)fromssize);
  241.     kfroms = kfetch(N_FROMS);
  242.     (void)klseek(kmem, kfroms, L_SET);
  243.     i = read(kmem, ((char *)(froms)), fromssize);
  244.     if (i != fromssize) {
  245.         (void)fprintf(stderr, "read kmem: request %d, got %d: %s",
  246.             fromssize, i, strerror(errno));
  247.         exit(5);
  248.     }
  249.     tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
  250.     tos = (struct tostruct *)malloc((u_int)tossize);
  251.     ktos = kfetch(N_TOS);
  252.     (void)klseek(kmem, ktos, L_SET);
  253.     i = read(kmem, ((char *)(tos)), tossize);
  254.     if (i != tossize) {
  255.         (void)fprintf(stderr, "read kmem: request %d, got %d: %s",
  256.             tossize, i, strerror(errno));
  257.         exit(6);
  258.     }
  259.     s_lowpc = (char *)kfetch(N_S_LOWPC);
  260.     if (debug)
  261.         (void)fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n",
  262.             s_lowpc, s_textsize);
  263.     endfrom = fromssize / sizeof(*froms);
  264.     for (fromindex = 0; fromindex < endfrom; fromindex++) {
  265.         if (froms[fromindex] == 0)
  266.             continue;
  267.         frompc = (u_long)s_lowpc +
  268.             (fromindex * HASHFRACTION * sizeof(*froms));
  269.         for (toindex = froms[fromindex]; toindex != 0;
  270.            toindex = tos[toindex].link) {
  271.             if (debug)
  272.                 (void)fprintf(stderr,
  273.                 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
  274.                 frompc, tos[toindex].selfpc, tos[toindex].count);
  275.             rawarc.raw_frompc = frompc;
  276.             rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
  277.             rawarc.raw_count = tos[toindex].count;
  278.             write(fd, (char *)&rawarc, sizeof (rawarc));
  279.         }
  280.     }
  281.     close(fd);
  282. }
  283.  
  284. resetstate()
  285. {
  286.     off_t kfroms, ktos;
  287.     int i, fromssize, tossize;
  288.     char buf[BUFSIZ];
  289.  
  290.     turnonoff(PROFILING_OFF);
  291.     bzero(buf, BUFSIZ);
  292.     ssiz = kfetch(N_SSIZ);
  293.     sbuf = kfetch(N_SBUF);
  294.     ssiz -= sizeof(struct phdr);
  295.     sbuf += sizeof(struct phdr);
  296.     (void)klseek(kmem, (off_t)sbuf, L_SET);
  297.     for (i = ssiz; i > 0; i -= BUFSIZ)
  298.         if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
  299.             perror("sbuf write");
  300.             exit(7);
  301.         }
  302.     s_textsize = kfetch(N_S_TEXTSIZE);
  303.     fromssize = s_textsize / HASHFRACTION;
  304.     kfroms = kfetch(N_FROMS);
  305.     (void)klseek(kmem, kfroms, L_SET);
  306.     for (i = fromssize; i > 0; i -= BUFSIZ)
  307.         if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
  308.             perror("kforms write");
  309.             exit(8);
  310.         }
  311.     tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
  312.     ktos = kfetch(N_TOS);
  313.     (void)klseek(kmem, ktos, L_SET);
  314.     for (i = tossize; i > 0; i -= BUFSIZ)
  315.         if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
  316.             perror("ktos write");
  317.             exit(9);
  318.         }
  319. }
  320.  
  321. turnonoff(onoff)
  322.     int onoff;
  323. {
  324.     (void)klseek(kmem, (long)nl[N_PROFILING].n_value, L_SET);
  325.     (void)write(kmem, (char *)&onoff, sizeof (onoff));
  326. }
  327.  
  328. kfetch(index)
  329.     int index;
  330. {
  331.     off_t off;
  332.     int value;
  333.  
  334.     if ((off = nl[index].n_value) == 0) {
  335.         printf("%s: not defined in kernel\n", nl[index].n_name);
  336.         exit(11);
  337.     }
  338.     if (klseek(kmem, off, L_SET) == -1) {
  339.         perror("lseek");
  340.         exit(12);
  341.     }
  342.     if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {
  343.         perror("read");
  344.         exit(13);
  345.     }
  346.     return (value);
  347. }
  348.  
  349. off_t
  350. klseek(fd, base, off)
  351.     int fd, off;
  352.     off_t base;
  353. {
  354.  
  355. #ifndef NEWVM
  356.     if (kflag) {    /* get kernel pte */
  357.         base &= ~KERNBASE;
  358.         base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
  359.     }
  360. #endif
  361.     return (lseek(fd, base, off));
  362. }
  363.