install correct aliases file
[unix-history] / usr / src / usr.sbin / kgmon / kgmon.c
index 28cc86c..4025fb4 100644 (file)
@@ -1,28 +1,45 @@
-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
 
 #ifndef lint
 
 #ifndef lint
-static char sccsid[] = "@(#)kgmon.c    4.2 82/12/24";
-#endif
+static char sccsid[] = "@(#)kgmon.c    5.5 (Berkeley) %G%";
+#endif /* not lint */
 
 #include <sys/param.h>
 #include <machine/pte.h>
 
 #include <sys/param.h>
 #include <machine/pte.h>
+#include <sys/file.h>
+#include <sys/vm.h>
 #include <stdio.h>
 #include <nlist.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <nlist.h>
 #include <ctype.h>
-#include <sys/crt0.h>
+#include <sys/gprof.h>
 
 #define        PROFILING_ON    0
 
 #define        PROFILING_ON    0
-#define PROFILING_OFF  3
+#define        PROFILING_OFF   3
 
 
-/*
- * froms is actually a bunch of unsigned shorts indexing tos
- */
-u_short        *froms;
-struct tostruct *tos;
-char   *s_lowpc;
 u_long s_textsize;
 u_long s_textsize;
+off_t  sbuf, klseek(), lseek();
 int    ssiz;
 int    ssiz;
-off_t  sbuf;
 
 struct nlist nl[] = {
 #define        N_SYSMAP        0
 
 struct nlist nl[] = {
 #define        N_SYSMAP        0
@@ -48,66 +65,119 @@ struct nlist nl[] = {
 
 struct pte *Sysmap;
 
 
 struct pte *Sysmap;
 
-char   *system = "/vmunix";
-char   *kmemf = "/dev/kmem";
 int    kmem;
 int    kmem;
-int    kflg;
+int    bflag, hflag, kflag, rflag, pflag;
+int    debug = 0;
 
 main(argc, argv)
        int argc;
        char *argv[];
 {
 
 main(argc, argv)
        int argc;
        char *argv[];
 {
-       int i, j, k;
-       char *cp;
-       long conptr;
-       int fd;
-       int fromindex;
-       u_long frompc;
-       int toindex;
-       struct rawarc rawarc;
-       off_t kfroms, ktos;
-       char buf[BUFSIZ];
-       int debug = 0;
+       extern char *optarg;
+       extern int optind;
+       int ch, mode, disp, openmode;
+       char *system, *kmemf, *malloc();
+
+       while ((ch = getopt(argc, argv, "bhpr")) != EOF)
+               switch((char)ch) {
+               case 'b':
+                       bflag++;
+                       break;
+               case 'h':
+                       hflag++;
+                       break;
+               case 'p':
+                       pflag++;
+                       break;
+               case 'r':
+                       rflag++;
+                       break;
+               default:
+                       fputs("usage: kgmon [-bhrp] [system [core]]\n", stderr);
+                       exit(1);
+               }
 
 
-       argc--, argv++;
+       openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
+
+       kmemf = "/dev/kmem";
        if (argc > 0) {
                system = *argv;
                argv++, argc--;
        if (argc > 0) {
                system = *argv;
                argv++, argc--;
+               if (argc > 0) {
+                       kmemf = *argv;
+                       kflag++;
+               }
        }
        }
-       nlist(system, nl);
-       if (nl[0].n_type == 0) {
+       else
+               system = "/vmunix";
+
+       if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
                fprintf(stderr, "%s: no namelist\n", system);
                fprintf(stderr, "%s: no namelist\n", system);
-               exit(1);
+               exit(2);
        }
        }
-       if (argc > 0) {
-               kmemf = *argv;
-               kflg++;
+       if (!nl[N_PROFILING].n_value) {
+               fputs("profiling: not defined in kernel.\n", stderr);
+               exit(10);
        }
        }
-       kmem = open(kmemf, 2);
+       kmem = open(kmemf, openmode);
        if (kmem < 0) {
        if (kmem < 0) {
-               kmem = open(kmemf, 0);
+               openmode = O_RDONLY;
+               kmem = open(kmemf, openmode);
                if (kmem < 0) {
                if (kmem < 0) {
-                       fprintf(stderr, "cannot open ");
                        perror(kmemf);
                        perror(kmemf);
-                       exit(1);
+                       exit(3);
                }
                }
-               fprintf(stderr,
-                   "%s opened read-only, data may be inconsistent\n",
-                   kmemf);
+               fprintf(stderr, "%s opened read-only\n", kmemf);
+               if (rflag)
+                       fprintf(stderr, "-r supressed\n");
+               if (bflag)
+                       fprintf(stderr, "-b supressed\n");
+               if (hflag)
+                       fprintf(stderr, "-h supressed\n");
+               rflag = bflag = hflag = 0;
        }
        }
-       if (kflg) {
+       if (kflag) {
                off_t off;
 
                off_t off;
 
-               off = nl[N_SYSMAP].n_value & 0x7fffffff;
-               lseek(kmem, off, 0);
-               nl[N_SYSSIZE].n_value *= 4;
-               Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value);
-               if (Sysmap == 0) {
-                       perror("Sysmap");
+               Sysmap = (struct pte *)
+                  malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
+               if (!Sysmap) {
+                       fputs("arp: can't get memory for Sysmap.\n", stderr);
                        exit(1);
                }
                        exit(1);
                }
-               read(kmem, Sysmap, nl[N_SYSSIZE].n_value);
+               off = nl[N_SYSMAP].n_value & ~KERNBASE;
+               (void)lseek(kmem, off, L_SET);
+               (void)read(kmem, (char *)Sysmap,
+                   (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
        }
        }
+       mode = kfetch(N_PROFILING);
+       if (hflag)
+               disp = PROFILING_OFF;
+       else if (bflag)
+               disp = PROFILING_ON;
+       else
+               disp = mode;
+       if (pflag) {
+               if (openmode == O_RDONLY && mode == PROFILING_ON)
+                       fprintf(stderr, "data may be inconsistent\n");
+               dumpstate();
+       }
+       if (rflag)
+               resetstate();
+       turnonoff(disp);
+       fprintf(stdout, "kernel profiling is %s.\n", disp ? "off" : "running");
+}
+
+dumpstate()
+{
+       struct rawarc rawarc;
+       struct tostruct *tos;
+       u_long frompc;
+       off_t kfroms, ktos;
+       u_short *froms;         /* froms is a bunch of u_shorts indexing tos */
+       int i, fd, fromindex, endfrom, fromssize, tossize, toindex;
+       char buf[BUFSIZ], *s_lowpc, *malloc();
+
        turnonoff(PROFILING_OFF);
        fd = creat("gmon.out", 0666);
        if (fd < 0) {
        turnonoff(PROFILING_OFF);
        fd = creat("gmon.out", 0666);
        if (fd < 0) {
@@ -116,50 +186,42 @@ main(argc, argv)
        }
        ssiz = kfetch(N_SSIZ);
        sbuf = kfetch(N_SBUF);
        }
        ssiz = kfetch(N_SSIZ);
        sbuf = kfetch(N_SBUF);
-       klseek(kmem, (off_t)sbuf, 0);
+       (void)klseek(kmem, (off_t)sbuf, L_SET);
        for (i = ssiz; i > 0; i -= BUFSIZ) {
                read(kmem, buf, i < BUFSIZ ? i : BUFSIZ);
                write(fd, buf, i < BUFSIZ ? i : BUFSIZ);
        }
        s_textsize = kfetch(N_S_TEXTSIZE);
        for (i = ssiz; i > 0; i -= BUFSIZ) {
                read(kmem, buf, i < BUFSIZ ? i : BUFSIZ);
                write(fd, buf, i < BUFSIZ ? i : BUFSIZ);
        }
        s_textsize = kfetch(N_S_TEXTSIZE);
-       froms = (u_short *)malloc(s_textsize);
+       fromssize = s_textsize / HASHFRACTION;
+       froms = (u_short *)malloc((u_int)fromssize);
        kfroms = kfetch(N_FROMS);
        kfroms = kfetch(N_FROMS);
-       klseek(kmem, kfroms, 0);
-       for (i = 0; i < s_textsize; i += BUFSIZ) {
-               j = s_textsize - i;
-               if (j > BUFSIZ)
-                       j = BUFSIZ;
-               k = read(kmem, ((char *)(froms)) + i, j);
-               if (j != k) {
-                       fprintf(stderr, "read tos: loc %d, request %d, got %d",
-                           i, j, k);
-                       perror("");
-                       exit(5);
-               }
+       (void)klseek(kmem, kfroms, L_SET);
+       i = read(kmem, ((char *)(froms)), fromssize);
+       if (i != fromssize) {
+               fprintf(stderr, "read froms: request %d, got %d", fromssize, i);
+               perror((char *)NULL);
+               exit(5);
        }
        }
-       tos = (struct tostruct *)malloc(s_textsize);
+       tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
+       tos = (struct tostruct *)malloc((u_int)tossize);
        ktos = kfetch(N_TOS);
        ktos = kfetch(N_TOS);
-       klseek(kmem, ktos, 0);
-       for (i = 0; i < s_textsize; i += BUFSIZ) {
-               j = s_textsize - i;
-               if (j > BUFSIZ)
-                       j = BUFSIZ;
-               k = read(kmem, ((char *)(tos)) + i, j);
-               if (j != k) {
-                       fprintf(stderr, "read tos: loc %d, request %d, got %d",
-                           i, j, k);
-                       perror("");
-                       exit(6);
-               }
+       (void)klseek(kmem, ktos, L_SET);
+       i = read(kmem, ((char *)(tos)), tossize);
+       if (i != tossize) {
+               fprintf(stderr, "read tos: request %d, got %d", tossize, i);
+               perror((char *)NULL);
+               exit(6);
        }
        s_lowpc = (char *)kfetch(N_S_LOWPC);
        if (debug)
                fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n",
                    s_lowpc, s_textsize);
        }
        s_lowpc = (char *)kfetch(N_S_LOWPC);
        if (debug)
                fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n",
                    s_lowpc, s_textsize);
-       for (fromindex = 0; fromindex < s_textsize>>1; fromindex++) {
+       endfrom = fromssize / sizeof(*froms);
+       for (fromindex = 0; fromindex < endfrom; fromindex++) {
                if (froms[fromindex] == 0)
                        continue;
                if (froms[fromindex] == 0)
                        continue;
-               frompc = (u_long)s_lowpc + (fromindex<<1);
+               frompc = (u_long)s_lowpc +
+                   (fromindex * HASHFRACTION * sizeof(*froms));
                for (toindex = froms[fromindex]; toindex != 0;
                   toindex = tos[toindex].link) {
                        if (debug)
                for (toindex = froms[fromindex]; toindex != 0;
                   toindex = tos[toindex].link) {
                        if (debug)
@@ -169,24 +231,54 @@ main(argc, argv)
                        rawarc.raw_frompc = frompc;
                        rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
                        rawarc.raw_count = tos[toindex].count;
                        rawarc.raw_frompc = frompc;
                        rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
                        rawarc.raw_count = tos[toindex].count;
-                       write(fd, &rawarc, sizeof (rawarc));
+                       write(fd, (char *)&rawarc, sizeof (rawarc));
                }
        }
        close(fd);
                }
        }
        close(fd);
-       turnonoff(PROFILING_ON);
+}
+
+resetstate()
+{
+       off_t kfroms, ktos;
+       int i, fromssize, tossize;
+       char buf[BUFSIZ];
+
+       turnonoff(PROFILING_OFF);
+       bzero(buf, BUFSIZ);
+       ssiz = kfetch(N_SSIZ);
+       sbuf = kfetch(N_SBUF);
+       ssiz -= sizeof(struct phdr);
+       sbuf += sizeof(struct phdr);
+       (void)klseek(kmem, (off_t)sbuf, L_SET);
+       for (i = ssiz; i > 0; i -= BUFSIZ)
+               if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
+                       perror("sbuf write");
+                       exit(7);
+               }
+       s_textsize = kfetch(N_S_TEXTSIZE);
+       fromssize = s_textsize / HASHFRACTION;
+       kfroms = kfetch(N_FROMS);
+       (void)klseek(kmem, kfroms, L_SET);
+       for (i = fromssize; i > 0; i -= BUFSIZ)
+               if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
+                       perror("kforms write");
+                       exit(8);
+               }
+       tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
+       ktos = kfetch(N_TOS);
+       (void)klseek(kmem, ktos, L_SET);
+       for (i = tossize; i > 0; i -= BUFSIZ)
+               if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
+                       perror("ktos write");
+                       exit(9);
+               }
 }
 
 turnonoff(onoff)
        int onoff;
 {
 }
 
 turnonoff(onoff)
        int onoff;
 {
-       off_t off;
-
-       if ((off = nl[N_PROFILING].n_value) == 0) {
-               printf("profiling: not defined in kernel\n");
-               exit(1);
-       }
-       klseek(kmem, off, 0);
-       write(kmem, (char *)&onoff, sizeof (onoff));
+       (void)klseek(kmem, (long)nl[N_PROFILING].n_value, L_SET);
+       (void)write(kmem, (char *)&onoff, sizeof (onoff));
 }
 
 kfetch(index)
 }
 
 kfetch(index)
@@ -197,27 +289,27 @@ kfetch(index)
 
        if ((off = nl[index].n_value) == 0) {
                printf("%s: not defined in kernel\n", nl[index].n_name);
 
        if ((off = nl[index].n_value) == 0) {
                printf("%s: not defined in kernel\n", nl[index].n_name);
-               exit(1);
+               exit(11);
        }
        }
-       if (klseek(kmem, off, 0) == -1) {
+       if (klseek(kmem, off, L_SET) == -1) {
                perror("lseek");
                perror("lseek");
-               exit(2);
+               exit(12);
        }
        if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {
                perror("read");
        }
        if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {
                perror("read");
-               exit(3);
+               exit(13);
        }
        return (value);
 }
 
        }
        return (value);
 }
 
+off_t
 klseek(fd, base, off)
 klseek(fd, base, off)
-       int fd, base, off;
+       int fd, off;
+       off_t base;
 {
 {
-
-       if (kflg) {
-               /* get kernel pte */
-               base &= 0x7fffffff;
-               base = Sysmap[base >> 9].pg_pfnum * 512 + (base & 0x1ff);
+       if (kflag) {    /* get kernel pte */
+               base &= ~KERNBASE;
+               base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
        }
        return (lseek(fd, base, off));
 }
        }
        return (lseek(fd, base, off));
 }