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