1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)kgmon.c 5.2 (Berkeley) 2/18/86"; 15: #endif not lint 16: 17: #include <sys/param.h> 18: #include <machine/pte.h> 19: #include <sys/file.h> 20: #include <sys/vm.h> 21: #include <stdio.h> 22: #include <nlist.h> 23: #include <ctype.h> 24: #include <sys/gprof.h> 25: 26: #define PROFILING_ON 0 27: #define PROFILING_OFF 3 28: 29: /* 30: * froms is actually a bunch of unsigned shorts indexing tos 31: */ 32: u_short *froms; 33: struct tostruct *tos; 34: char *s_lowpc; 35: u_long s_textsize; 36: int ssiz; 37: off_t sbuf; 38: 39: struct nlist nl[] = { 40: #define N_SYSMAP 0 41: { "_Sysmap" }, 42: #define N_SYSSIZE 1 43: { "_Syssize" }, 44: #define N_FROMS 2 45: { "_froms" }, 46: #define N_PROFILING 3 47: { "_profiling" }, 48: #define N_S_LOWPC 4 49: { "_s_lowpc" }, 50: #define N_S_TEXTSIZE 5 51: { "_s_textsize" }, 52: #define N_SBUF 6 53: { "_sbuf" }, 54: #define N_SSIZ 7 55: { "_ssiz" }, 56: #define N_TOS 8 57: { "_tos" }, 58: 0, 59: }; 60: 61: #if defined(vax) 62: #define clear(x) ((x) &~ 0x80000000) 63: #endif 64: 65: struct pte *Sysmap; 66: 67: char *system = "/vmunix"; 68: char *kmemf = "/dev/kmem"; 69: int kmem; 70: int bflag, hflag, kflag, rflag, pflag; 71: int debug = 0; 72: 73: main(argc, argv) 74: int argc; 75: char *argv[]; 76: { 77: int mode, disp, openmode = O_RDONLY; 78: 79: argc--, argv++; 80: while (argc > 0 && argv[0][0] == '-') { 81: switch (argv[0][1]) { 82: case 'b': 83: bflag++; 84: openmode = O_RDWR; 85: break; 86: case 'h': 87: hflag++; 88: openmode = O_RDWR; 89: break; 90: case 'r': 91: rflag++; 92: openmode = O_RDWR; 93: break; 94: case 'p': 95: pflag++; 96: openmode = O_RDWR; 97: break; 98: default: 99: printf("Usage: kgmon [ -b -h -r -p system memory ]\n"); 100: exit(1); 101: } 102: argc--, argv++; 103: } 104: if (argc > 0) { 105: system = *argv; 106: argv++, argc--; 107: } 108: nlist(system, nl); 109: if (nl[0].n_type == 0) { 110: fprintf(stderr, "%s: no namelist\n", system); 111: exit(2); 112: } 113: if (argc > 0) { 114: kmemf = *argv; 115: kflag++; 116: } 117: kmem = open(kmemf, openmode); 118: if (kmem < 0) { 119: openmode = O_RDONLY; 120: kmem = open(kmemf, openmode); 121: if (kmem < 0) { 122: fprintf(stderr, "cannot open "); 123: perror(kmemf); 124: exit(3); 125: } 126: fprintf(stderr, "%s opened read-only\n", kmemf); 127: if (rflag) 128: fprintf(stderr, "-r supressed\n"); 129: if (bflag) 130: fprintf(stderr, "-b supressed\n"); 131: if (hflag) 132: fprintf(stderr, "-h supressed\n"); 133: rflag = 0; 134: bflag = 0; 135: hflag = 0; 136: } 137: if (kflag) { 138: off_t off; 139: 140: off = clear(nl[N_SYSMAP].n_value); 141: lseek(kmem, off, L_SET); 142: nl[N_SYSSIZE].n_value *= 4; 143: Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value); 144: if (Sysmap == 0) { 145: perror("Sysmap"); 146: exit(4); 147: } 148: read(kmem, Sysmap, nl[N_SYSSIZE].n_value); 149: } 150: mode = kfetch(N_PROFILING); 151: if (hflag) 152: disp = PROFILING_OFF; 153: else if (bflag) 154: disp = PROFILING_ON; 155: else 156: disp = mode; 157: if (pflag) { 158: if (openmode == O_RDONLY && mode == PROFILING_ON) 159: fprintf(stderr, "data may be inconsistent\n"); 160: dumpstate(); 161: } 162: if (rflag) 163: resetstate(); 164: turnonoff(disp); 165: fprintf(stdout, "kernel profiling is %s.\n", disp ? "off" : "running"); 166: } 167: 168: dumpstate() 169: { 170: int i; 171: int fd; 172: off_t kfroms, ktos; 173: int fromindex, endfrom, fromssize, tossize; 174: u_long frompc; 175: int toindex; 176: struct rawarc rawarc; 177: char buf[BUFSIZ]; 178: 179: turnonoff(PROFILING_OFF); 180: fd = creat("gmon.out", 0666); 181: if (fd < 0) { 182: perror("gmon.out"); 183: return; 184: } 185: ssiz = kfetch(N_SSIZ); 186: sbuf = kfetch(N_SBUF); 187: klseek(kmem, (off_t)sbuf, L_SET); 188: for (i = ssiz; i > 0; i -= BUFSIZ) { 189: read(kmem, buf, i < BUFSIZ ? i : BUFSIZ); 190: write(fd, buf, i < BUFSIZ ? i : BUFSIZ); 191: } 192: s_textsize = kfetch(N_S_TEXTSIZE); 193: fromssize = s_textsize / HASHFRACTION; 194: froms = (u_short *)malloc(fromssize); 195: kfroms = kfetch(N_FROMS); 196: klseek(kmem, kfroms, L_SET); 197: i = read(kmem, ((char *)(froms)), fromssize); 198: if (i != fromssize) { 199: fprintf(stderr, "read froms: request %d, got %d", fromssize, i); 200: perror(""); 201: exit(5); 202: } 203: tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct); 204: tos = (struct tostruct *)malloc(tossize); 205: ktos = kfetch(N_TOS); 206: klseek(kmem, ktos, L_SET); 207: i = read(kmem, ((char *)(tos)), tossize); 208: if (i != tossize) { 209: fprintf(stderr, "read tos: request %d, got %d", tossize, i); 210: perror(""); 211: exit(6); 212: } 213: s_lowpc = (char *)kfetch(N_S_LOWPC); 214: if (debug) 215: fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n", 216: s_lowpc, s_textsize); 217: endfrom = fromssize / sizeof(*froms); 218: for (fromindex = 0; fromindex < endfrom; fromindex++) { 219: if (froms[fromindex] == 0) 220: continue; 221: frompc = (u_long)s_lowpc + 222: (fromindex * HASHFRACTION * sizeof(*froms)); 223: for (toindex = froms[fromindex]; toindex != 0; 224: toindex = tos[toindex].link) { 225: if (debug) 226: fprintf(stderr, 227: "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , 228: frompc, tos[toindex].selfpc, tos[toindex].count); 229: rawarc.raw_frompc = frompc; 230: rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; 231: rawarc.raw_count = tos[toindex].count; 232: write(fd, &rawarc, sizeof (rawarc)); 233: } 234: } 235: close(fd); 236: } 237: 238: resetstate() 239: { 240: int i; 241: off_t kfroms, ktos; 242: int fromssize, tossize; 243: char buf[BUFSIZ]; 244: 245: turnonoff(PROFILING_OFF); 246: bzero(buf, BUFSIZ); 247: ssiz = kfetch(N_SSIZ); 248: sbuf = kfetch(N_SBUF); 249: ssiz -= sizeof(struct phdr); 250: sbuf += sizeof(struct phdr); 251: klseek(kmem, (off_t)sbuf, L_SET); 252: for (i = ssiz; i > 0; i -= BUFSIZ) 253: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 254: perror("sbuf write"); 255: exit(7); 256: } 257: s_textsize = kfetch(N_S_TEXTSIZE); 258: fromssize = s_textsize / HASHFRACTION; 259: kfroms = kfetch(N_FROMS); 260: klseek(kmem, kfroms, L_SET); 261: for (i = fromssize; i > 0; i -= BUFSIZ) 262: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 263: perror("kforms write"); 264: exit(8); 265: } 266: tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct); 267: ktos = kfetch(N_TOS); 268: klseek(kmem, ktos, L_SET); 269: for (i = tossize; i > 0; i -= BUFSIZ) 270: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 271: perror("ktos write"); 272: exit(9); 273: } 274: } 275: 276: turnonoff(onoff) 277: int onoff; 278: { 279: off_t off; 280: 281: if ((off = nl[N_PROFILING].n_value) == 0) { 282: printf("profiling: not defined in kernel\n"); 283: exit(10); 284: } 285: klseek(kmem, off, L_SET); 286: write(kmem, (char *)&onoff, sizeof (onoff)); 287: } 288: 289: kfetch(index) 290: int index; 291: { 292: off_t off; 293: int value; 294: 295: if ((off = nl[index].n_value) == 0) { 296: printf("%s: not defined in kernel\n", nl[index].n_name); 297: exit(11); 298: } 299: if (klseek(kmem, off, L_SET) == -1) { 300: perror("lseek"); 301: exit(12); 302: } 303: if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) { 304: perror("read"); 305: exit(13); 306: } 307: return (value); 308: } 309: 310: klseek(fd, base, off) 311: int fd, base, off; 312: { 313: 314: if (kflag) { 315: /* get kernel pte */ 316: base = clear(base); 317: base = ((int)ptob(Sysmap[btop(base)].pg_pfnum))+(base&(NBPG-1)); 318: } 319: return (lseek(fd, base, off)); 320: }