xref: /original-bsd/usr.sbin/kgmon/kgmon.c (revision f0fd5f8a)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)kgmon.c	4.1 82/06/21";
5 #endif
6 
7 #include <sys/param.h>
8 #include <sys/pte.h>
9 #include <stdio.h>
10 #include <nlist.h>
11 #include <ctype.h>
12 #include <sys/crt0.h>
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  */
20 u_short	*froms;
21 struct	tostruct *tos;
22 char	*s_lowpc;
23 u_long	s_textsize;
24 int	ssiz;
25 off_t	sbuf;
26 
27 struct 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 
49 struct	pte *Sysmap;
50 
51 char	*system = "/vmunix";
52 char	*kmemf = "/dev/kmem";
53 int	kmem;
54 int	kflg;
55 
56 main(argc, argv)
57 	int argc;
58 	char *argv[];
59 {
60 	int i, j, k;
61 	char *cp;
62 	long conptr;
63 	int fd;
64 	int fromindex;
65 	u_long frompc;
66 	int toindex;
67 	struct rawarc rawarc;
68 	off_t kfroms, ktos;
69 	char buf[BUFSIZ];
70 	int debug = 0;
71 
72 	argc--, argv++;
73 	if (argc > 0) {
74 		system = *argv;
75 		argv++, argc--;
76 	}
77 	nlist(system, nl);
78 	if (nl[0].n_type == 0) {
79 		fprintf(stderr, "%s: no namelist\n", system);
80 		exit(1);
81 	}
82 	if (argc > 0) {
83 		kmemf = *argv;
84 		kflg++;
85 	}
86 	kmem = open(kmemf, 2);
87 	if (kmem < 0) {
88 		kmem = open(kmemf, 0);
89 		if (kmem < 0) {
90 			fprintf(stderr, "cannot open ");
91 			perror(kmemf);
92 			exit(1);
93 		}
94 		fprintf(stderr,
95 		    "%s opened read-only, data may be inconsistent\n",
96 		    kmemf);
97 	}
98 	if (kflg) {
99 		off_t off;
100 
101 		off = nl[N_SYSMAP].n_value & 0x7fffffff;
102 		lseek(kmem, off, 0);
103 		nl[N_SYSSIZE].n_value *= 4;
104 		Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value);
105 		if (Sysmap == 0) {
106 			perror("Sysmap");
107 			exit(1);
108 		}
109 		read(kmem, Sysmap, nl[N_SYSSIZE].n_value);
110 	}
111 	turnonoff(PROFILING_OFF);
112 	fd = creat("gmon.out", 0666);
113 	if (fd < 0) {
114 		perror("gmon.out");
115 		return;
116 	}
117 	ssiz = kfetch(N_SSIZ);
118 	sbuf = kfetch(N_SBUF);
119 	klseek(kmem, (off_t)sbuf, 0);
120 	for (i = ssiz; i > 0; i -= BUFSIZ) {
121 		read(kmem, buf, i < BUFSIZ ? i : BUFSIZ);
122 		write(fd, buf, i < BUFSIZ ? i : BUFSIZ);
123 	}
124 	s_textsize = kfetch(N_S_TEXTSIZE);
125 	froms = (u_short *)malloc(s_textsize);
126 	kfroms = kfetch(N_FROMS);
127 	klseek(kmem, kfroms, 0);
128 	for (i = 0; i < s_textsize; i += BUFSIZ) {
129 		j = s_textsize - i;
130 		if (j > BUFSIZ)
131 			j = BUFSIZ;
132 		k = read(kmem, ((char *)(froms)) + i, j);
133 		if (j != k) {
134 			fprintf(stderr, "read tos: loc %d, request %d, got %d",
135 			    i, j, k);
136 			perror("");
137 			exit(5);
138 		}
139 	}
140 	tos = (struct tostruct *)malloc(s_textsize);
141 	ktos = kfetch(N_TOS);
142 	klseek(kmem, ktos, 0);
143 	for (i = 0; i < s_textsize; i += BUFSIZ) {
144 		j = s_textsize - i;
145 		if (j > BUFSIZ)
146 			j = BUFSIZ;
147 		k = read(kmem, ((char *)(tos)) + i, j);
148 		if (j != k) {
149 			fprintf(stderr, "read tos: loc %d, request %d, got %d",
150 			    i, j, k);
151 			perror("");
152 			exit(6);
153 		}
154 	}
155 	s_lowpc = (char *)kfetch(N_S_LOWPC);
156 	if (debug)
157 		fprintf(stderr, "s_lowpc 0x%x, s_textsize 0x%x\n",
158 		    s_lowpc, s_textsize);
159 	for (fromindex = 0; fromindex < s_textsize>>1; fromindex++) {
160 		if (froms[fromindex] == 0)
161 			continue;
162 		frompc = (u_long)s_lowpc + (fromindex<<1);
163 		for (toindex = froms[fromindex]; toindex != 0;
164 		   toindex = tos[toindex].link) {
165 			if (debug)
166 			    fprintf(stderr,
167 			    "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
168 			    frompc, tos[toindex].selfpc, tos[toindex].count);
169 			rawarc.raw_frompc = frompc;
170 			rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
171 			rawarc.raw_count = tos[toindex].count;
172 			write(fd, &rawarc, sizeof (rawarc));
173 		}
174 	}
175 	close(fd);
176 	turnonoff(PROFILING_ON);
177 }
178 
179 turnonoff(onoff)
180 	int onoff;
181 {
182 	off_t off;
183 
184 	if ((off = nl[N_PROFILING].n_value) == 0) {
185 		printf("profiling: not defined in kernel\n");
186 		exit(1);
187 	}
188 	klseek(kmem, off, 0);
189 	write(kmem, (char *)&onoff, sizeof (onoff));
190 }
191 
192 kfetch(index)
193 	int index;
194 {
195 	off_t off;
196 	int value;
197 
198 	if ((off = nl[index].n_value) == 0) {
199 		printf("%s: not defined in kernel\n", nl[index].n_name);
200 		exit(1);
201 	}
202 	if (klseek(kmem, off, 0) == -1) {
203 		perror("lseek");
204 		exit(2);
205 	}
206 	if (read(kmem, (char *)&value, sizeof (value)) != sizeof (value)) {
207 		perror("read");
208 		exit(3);
209 	}
210 	return (value);
211 }
212 
213 klseek(fd, base, off)
214 	int fd, base, off;
215 {
216 
217 	if (kflg) {
218 		/* get kernel pte */
219 		base &= 0x7fffffff;
220 		base = Sysmap[base >> 9].pg_pfnum * 512 + (base & 0x1ff);
221 	}
222 	return (lseek(fd, base, off));
223 }
224