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