date and time created 82/06/21 00:52:43 by mckusick
[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
4static 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 */
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;
54int kflg;
55
56main(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
179turnonoff(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
192kfetch(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
213klseek(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}