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.3 (Berkeley) 10/13/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 #if defined(tahoe) 65 #define clear(x) ((x) &~ 0xc0000000) 66 #endif 67 68 struct pte *Sysmap; 69 70 char *system = "/vmunix"; 71 char *kmemf = "/dev/kmem"; 72 int kmem; 73 int bflag, hflag, kflag, rflag, pflag; 74 int debug = 0; 75 76 main(argc, argv) 77 int argc; 78 char *argv[]; 79 { 80 int mode, disp, openmode = O_RDONLY; 81 82 argc--, argv++; 83 while (argc > 0 && argv[0][0] == '-') { 84 switch (argv[0][1]) { 85 case 'b': 86 bflag++; 87 openmode = O_RDWR; 88 break; 89 case 'h': 90 hflag++; 91 openmode = O_RDWR; 92 break; 93 case 'r': 94 rflag++; 95 openmode = O_RDWR; 96 break; 97 case 'p': 98 pflag++; 99 openmode = O_RDWR; 100 break; 101 default: 102 printf("Usage: kgmon [ -b -h -r -p system memory ]\n"); 103 exit(1); 104 } 105 argc--, argv++; 106 } 107 if (argc > 0) { 108 system = *argv; 109 argv++, argc--; 110 } 111 nlist(system, nl); 112 if (nl[0].n_type == 0) { 113 fprintf(stderr, "%s: no namelist\n", system); 114 exit(2); 115 } 116 if (argc > 0) { 117 kmemf = *argv; 118 kflag++; 119 } 120 kmem = open(kmemf, openmode); 121 if (kmem < 0) { 122 openmode = O_RDONLY; 123 kmem = open(kmemf, openmode); 124 if (kmem < 0) { 125 fprintf(stderr, "cannot open "); 126 perror(kmemf); 127 exit(3); 128 } 129 fprintf(stderr, "%s opened read-only\n", kmemf); 130 if (rflag) 131 fprintf(stderr, "-r supressed\n"); 132 if (bflag) 133 fprintf(stderr, "-b supressed\n"); 134 if (hflag) 135 fprintf(stderr, "-h supressed\n"); 136 rflag = 0; 137 bflag = 0; 138 hflag = 0; 139 } 140 if (kflag) { 141 off_t off; 142 143 off = clear(nl[N_SYSMAP].n_value); 144 lseek(kmem, off, L_SET); 145 nl[N_SYSSIZE].n_value *= 4; 146 Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value); 147 if (Sysmap == 0) { 148 perror("Sysmap"); 149 exit(4); 150 } 151 read(kmem, Sysmap, nl[N_SYSSIZE].n_value); 152 } 153 mode = kfetch(N_PROFILING); 154 if (hflag) 155 disp = PROFILING_OFF; 156 else if (bflag) 157 disp = PROFILING_ON; 158 else 159 disp = mode; 160 if (pflag) { 161 if (openmode == O_RDONLY && mode == PROFILING_ON) 162 fprintf(stderr, "data may be inconsistent\n"); 163 dumpstate(); 164 } 165 if (rflag) 166 resetstate(); 167 turnonoff(disp); 168 fprintf(stdout, "kernel profiling is %s.\n", disp ? "off" : "running"); 169 } 170 171 dumpstate() 172 { 173 int i; 174 int fd; 175 off_t kfroms, ktos; 176 int fromindex, endfrom, fromssize, tossize; 177 u_long frompc; 178 int toindex; 179 struct rawarc rawarc; 180 char buf[BUFSIZ]; 181 182 turnonoff(PROFILING_OFF); 183 fd = creat("gmon.out", 0666); 184 if (fd < 0) { 185 perror("gmon.out"); 186 return; 187 } 188 ssiz = kfetch(N_SSIZ); 189 sbuf = kfetch(N_SBUF); 190 klseek(kmem, (off_t)sbuf, L_SET); 191 for (i = ssiz; i > 0; i -= BUFSIZ) { 192 read(kmem, buf, i < BUFSIZ ? i : BUFSIZ); 193 write(fd, buf, i < BUFSIZ ? i : BUFSIZ); 194 } 195 s_textsize = kfetch(N_S_TEXTSIZE); 196 fromssize = s_textsize / HASHFRACTION; 197 froms = (u_short *)malloc(fromssize); 198 kfroms = kfetch(N_FROMS); 199 klseek(kmem, kfroms, L_SET); 200 i = read(kmem, ((char *)(froms)), fromssize); 201 if (i != fromssize) { 202 fprintf(stderr, "read froms: request %d, got %d", fromssize, i); 203 perror(""); 204 exit(5); 205 } 206 tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct); 207 tos = (struct tostruct *)malloc(tossize); 208 ktos = kfetch(N_TOS); 209 klseek(kmem, ktos, L_SET); 210 i = read(kmem, ((char *)(tos)), tossize); 211 if (i != tossize) { 212 fprintf(stderr, "read tos: request %d, got %d", tossize, i); 213 perror(""); 214 exit(6); 215 } 216 s_lowpc = (char *)kfetch(N_S_LOWPC); 217 if (debug) 218 fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n", 219 s_lowpc, s_textsize); 220 endfrom = fromssize / sizeof(*froms); 221 for (fromindex = 0; fromindex < endfrom; fromindex++) { 222 if (froms[fromindex] == 0) 223 continue; 224 frompc = (u_long)s_lowpc + 225 (fromindex * HASHFRACTION * sizeof(*froms)); 226 for (toindex = froms[fromindex]; toindex != 0; 227 toindex = tos[toindex].link) { 228 if (debug) 229 fprintf(stderr, 230 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , 231 frompc, tos[toindex].selfpc, tos[toindex].count); 232 rawarc.raw_frompc = frompc; 233 rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; 234 rawarc.raw_count = tos[toindex].count; 235 write(fd, &rawarc, sizeof (rawarc)); 236 } 237 } 238 close(fd); 239 } 240 241 resetstate() 242 { 243 int i; 244 off_t kfroms, ktos; 245 int fromssize, tossize; 246 char buf[BUFSIZ]; 247 248 turnonoff(PROFILING_OFF); 249 bzero(buf, BUFSIZ); 250 ssiz = kfetch(N_SSIZ); 251 sbuf = kfetch(N_SBUF); 252 ssiz -= sizeof(struct phdr); 253 sbuf += sizeof(struct phdr); 254 klseek(kmem, (off_t)sbuf, L_SET); 255 for (i = ssiz; i > 0; i -= BUFSIZ) 256 if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 257 perror("sbuf write"); 258 exit(7); 259 } 260 s_textsize = kfetch(N_S_TEXTSIZE); 261 fromssize = s_textsize / HASHFRACTION; 262 kfroms = kfetch(N_FROMS); 263 klseek(kmem, kfroms, L_SET); 264 for (i = fromssize; i > 0; i -= BUFSIZ) 265 if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 266 perror("kforms write"); 267 exit(8); 268 } 269 tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct); 270 ktos = kfetch(N_TOS); 271 klseek(kmem, ktos, L_SET); 272 for (i = tossize; i > 0; i -= BUFSIZ) 273 if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) { 274 perror("ktos write"); 275 exit(9); 276 } 277 } 278 279 turnonoff(onoff) 280 int onoff; 281 { 282 off_t off; 283 284 if ((off = nl[N_PROFILING].n_value) == 0) { 285 printf("profiling: not defined in kernel\n"); 286 exit(10); 287 } 288 klseek(kmem, off, L_SET); 289 write(kmem, (char *)&onoff, sizeof (onoff)); 290 } 291 292 kfetch(index) 293 int index; 294 { 295 off_t off; 296 int value; 297 298 if ((off = nl[index].n_value) == 0) { 299 printf("%s: not defined in kernel\n", nl[index].n_name); 300 exit(11); 301 } 302 if (klseek(kmem, off, L_SET) == -1) { 303 perror("lseek"); 304 exit(12); 305 } 306 if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) { 307 perror("read"); 308 exit(13); 309 } 310 return (value); 311 } 312 313 klseek(fd, base, off) 314 int fd, base, off; 315 { 316 317 if (kflag) { 318 /* get kernel pte */ 319 base = clear(base); 320 base = ((int)ptob(Sysmap[btop(base)].pg_pfnum))+(base&(NBPG-1)); 321 } 322 return (lseek(fd, base, off)); 323 } 324