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