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