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