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