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