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