|
|
1.1 root 1: /*
2: * Copyright (c) 1983 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)kgmon.c 5.10 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: #include <machine/pte.h>
31:
32: #include <sys/param.h>
33: #include <sys/file.h>
34: #include <sys/vm.h>
35: #include <sys/gprof.h>
36: #include <stdio.h>
37: #include <nlist.h>
38: #include <ctype.h>
39: #include <paths.h>
40:
41: #define PROFILING_ON 0
42: #define PROFILING_OFF 3
43:
44: u_long s_textsize;
45: off_t sbuf, klseek(), lseek();
46: int ssiz;
47:
48: struct nlist nl[] = {
49: #define N_SYSMAP 0
50: { "_Sysmap" },
51: #define N_SYSSIZE 1
52: { "_Syssize" },
53: #define N_FROMS 2
54: { "_froms" },
55: #define N_PROFILING 3
56: { "_profiling" },
57: #define N_S_LOWPC 4
58: { "_s_lowpc" },
59: #define N_S_TEXTSIZE 5
60: { "_s_textsize" },
61: #define N_SBUF 6
62: { "_sbuf" },
63: #define N_SSIZ 7
64: { "_ssiz" },
65: #define N_TOS 8
66: { "_tos" },
67: 0,
68: };
69:
70: struct pte *Sysmap;
71:
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: extern char *optarg;
81: extern int optind;
82: int ch, mode, disp, openmode;
83: char *system, *kmemf, *malloc();
84:
85: while ((ch = getopt(argc, argv, "bhpr")) != EOF)
86: switch((char)ch) {
87: case 'b':
88: bflag++;
89: break;
90: case 'h':
91: hflag++;
92: break;
93: case 'p':
94: pflag++;
95: break;
96: case 'r':
97: rflag++;
98: break;
99: default:
100: (void)fprintf(stderr,
101: "usage: kgmon [-bhrp] [system [core]]\n");
102: exit(1);
103: }
104: argc -= optind;
105: argv += optind;
106:
107: kmemf = _PATH_KMEM;
108: if (*argv) {
109: system = *argv;
110: if (*++argv) {
111: kmemf = *argv;
112: ++kflag;
113: }
114: }
115: else
116: system = _PATH_UNIX;
117:
118: if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
119: (void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
120: exit(2);
121: }
122: if (!nl[N_PROFILING].n_value) {
123: (void)fprintf(stderr,
124: "kgmon: profiling: not defined in kernel.\n");
125: exit(10);
126: }
127:
128: openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
129: kmem = open(kmemf, openmode);
130: if (kmem < 0) {
131: openmode = O_RDONLY;
132: kmem = open(kmemf, openmode);
133: if (kmem < 0) {
134: perror(kmemf);
135: exit(3);
136: }
137: (void)fprintf(stderr, "%s opened read-only\n", kmemf);
138: if (rflag)
139: (void)fprintf(stderr, "-r supressed\n");
140: if (bflag)
141: (void)fprintf(stderr, "-b supressed\n");
142: if (hflag)
143: (void)fprintf(stderr, "-h supressed\n");
144: rflag = bflag = hflag = 0;
145: }
146: if (kflag) {
147: off_t off;
148:
149: Sysmap = (struct pte *)
150: malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
151: if (!Sysmap) {
152: (void)fprintf(stderr,
153: "kgmon: can't get memory for Sysmap.\n");
154: exit(1);
155: }
156: off = nl[N_SYSMAP].n_value & ~KERNBASE;
157: (void)lseek(kmem, off, L_SET);
158: (void)read(kmem, (char *)Sysmap,
159: (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
160: }
161: mode = kfetch(N_PROFILING);
162: if (hflag)
163: disp = PROFILING_OFF;
164: else if (bflag)
165: disp = PROFILING_ON;
166: else
167: disp = mode;
168: if (pflag) {
169: if (openmode == O_RDONLY && mode == PROFILING_ON)
170: (void)fprintf(stderr, "data may be inconsistent\n");
171: dumpstate();
172: }
173: if (rflag)
174: resetstate();
175: turnonoff(disp);
176: (void)fprintf(stdout,
177: "kernel profiling is %s.\n", disp ? "off" : "running");
178: }
179:
180: dumpstate()
181: {
182: extern int errno;
183: struct rawarc rawarc;
184: struct tostruct *tos;
185: u_long frompc;
186: off_t kfroms, ktos;
187: u_short *froms; /* froms is a bunch of u_shorts indexing tos */
188: int i, fd, fromindex, endfrom, fromssize, tossize, toindex;
189: char buf[BUFSIZ], *s_lowpc, *malloc(), *strerror();
190:
191: turnonoff(PROFILING_OFF);
192: fd = creat("gmon.out", 0666);
193: if (fd < 0) {
194: perror("gmon.out");
195: return;
196: }
197: ssiz = kfetch(N_SSIZ);
198: sbuf = kfetch(N_SBUF);
199: (void)klseek(kmem, (off_t)sbuf, L_SET);
200: for (i = ssiz; i > 0; i -= BUFSIZ) {
201: read(kmem, buf, i < BUFSIZ ? i : BUFSIZ);
202: write(fd, buf, i < BUFSIZ ? i : BUFSIZ);
203: }
204: s_textsize = kfetch(N_S_TEXTSIZE);
205: fromssize = s_textsize / HASHFRACTION;
206: froms = (u_short *)malloc((u_int)fromssize);
207: kfroms = kfetch(N_FROMS);
208: (void)klseek(kmem, kfroms, L_SET);
209: i = read(kmem, ((char *)(froms)), fromssize);
210: if (i != fromssize) {
211: (void)fprintf(stderr, "read kmem: request %d, got %d: %s",
212: fromssize, i, strerror(errno));
213: exit(5);
214: }
215: tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
216: tos = (struct tostruct *)malloc((u_int)tossize);
217: ktos = kfetch(N_TOS);
218: (void)klseek(kmem, ktos, L_SET);
219: i = read(kmem, ((char *)(tos)), tossize);
220: if (i != tossize) {
221: (void)fprintf(stderr, "read kmem: request %d, got %d: %s",
222: tossize, i, strerror(errno));
223: exit(6);
224: }
225: s_lowpc = (char *)kfetch(N_S_LOWPC);
226: if (debug)
227: (void)fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n",
228: s_lowpc, s_textsize);
229: endfrom = fromssize / sizeof(*froms);
230: for (fromindex = 0; fromindex < endfrom; fromindex++) {
231: if (froms[fromindex] == 0)
232: continue;
233: frompc = (u_long)s_lowpc +
234: (fromindex * HASHFRACTION * sizeof(*froms));
235: for (toindex = froms[fromindex]; toindex != 0;
236: toindex = tos[toindex].link) {
237: if (debug)
238: (void)fprintf(stderr,
239: "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
240: frompc, tos[toindex].selfpc, tos[toindex].count);
241: rawarc.raw_frompc = frompc;
242: rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
243: rawarc.raw_count = tos[toindex].count;
244: write(fd, (char *)&rawarc, sizeof (rawarc));
245: }
246: }
247: close(fd);
248: }
249:
250: resetstate()
251: {
252: off_t kfroms, ktos;
253: int i, fromssize, tossize;
254: char buf[BUFSIZ];
255:
256: turnonoff(PROFILING_OFF);
257: bzero(buf, BUFSIZ);
258: ssiz = kfetch(N_SSIZ);
259: sbuf = kfetch(N_SBUF);
260: ssiz -= sizeof(struct phdr);
261: sbuf += sizeof(struct phdr);
262: (void)klseek(kmem, (off_t)sbuf, L_SET);
263: for (i = ssiz; i > 0; i -= BUFSIZ)
264: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
265: perror("sbuf write");
266: exit(7);
267: }
268: s_textsize = kfetch(N_S_TEXTSIZE);
269: fromssize = s_textsize / HASHFRACTION;
270: kfroms = kfetch(N_FROMS);
271: (void)klseek(kmem, kfroms, L_SET);
272: for (i = fromssize; i > 0; i -= BUFSIZ)
273: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
274: perror("kforms write");
275: exit(8);
276: }
277: tossize = (s_textsize * ARCDENSITY / 100) * sizeof(struct tostruct);
278: ktos = kfetch(N_TOS);
279: (void)klseek(kmem, ktos, L_SET);
280: for (i = tossize; i > 0; i -= BUFSIZ)
281: if (write(kmem, buf, i < BUFSIZ ? i : BUFSIZ) < 0) {
282: perror("ktos write");
283: exit(9);
284: }
285: }
286:
287: turnonoff(onoff)
288: int onoff;
289: {
290: (void)klseek(kmem, (long)nl[N_PROFILING].n_value, L_SET);
291: (void)write(kmem, (char *)&onoff, sizeof (onoff));
292: }
293:
294: kfetch(index)
295: int index;
296: {
297: off_t off;
298: int value;
299:
300: if ((off = nl[index].n_value) == 0) {
301: printf("%s: not defined in kernel\n", nl[index].n_name);
302: exit(11);
303: }
304: if (klseek(kmem, off, L_SET) == -1) {
305: perror("lseek");
306: exit(12);
307: }
308: if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {
309: perror("read");
310: exit(13);
311: }
312: return (value);
313: }
314:
315: off_t
316: klseek(fd, base, off)
317: int fd, off;
318: off_t base;
319: {
320: if (kflag) { /* get kernel pte */
321: base &= ~KERNBASE;
322: base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
323: }
324: return (lseek(fd, base, off));
325: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.