|
|
1.1 root 1: #include "sys/types.h"
2: #include "sys/stat.h"
3: #include "a.out.h"
4: /* it wouldn't be better to get this out of sys/param.h */
5: #define HZ 60
6:
7: typedef unsigned short Prof; /* what the counts are stored in! */
8: /* a mon.out consists of a phdr, cnt structs pcnt, and the rest are
9: Profs of pc clicks */
10: struct phdr {
11: char *lopc, *hipc; /* void *? */
12: int cnt;
13: };
14: struct phdr hsv;
15: struct pcnt {
16: char * value;
17: long calls;
18: };
19: char flags[128];
20: char *xfile, *file;
21: struct nlist *names;
22: char *strings, *pbuf;
23: Prof *accum;
24: int accumsz;
25: typedef struct {
26: char *loc;
27: char *name;
28: long calls;
29: long clicks;
30: unsigned char type;
31: } sym;
32: int nsym;
33: sym *syms, nilsym;
34: long lopct, hipct; /* plot stuff */
35: double rscale, roffset;
36:
37: main(argc, argv)
38: char **argv;
39: { int c;
40: extern int optind;
41: extern char **optarg;
42: char *p;
43:
44: while((c = getopt(argc, argv, "alnsvz")) != -1)
45: switch(c) {
46: case 'l': case 'n': case 's': case 'z':
47: flags[c] = 1;
48: continue;
49: case 'v':
50: flags['v'] = 1;
51: p = argv[optind];
52: if(*p != '-' || p[1] > '9' || p[1] < '0')
53: continue;
54: lopct = atoi(p+1);
55: p = argv[++optind];
56: if(*p != '-' || p[1] > '9' || p[1] < '0')
57: continue;
58: hipct = atoi(p+1);
59: optind++;
60: continue;
61: case '?':
62: fatal("usage: %s -[alnsz] files\n", argv[0]);
63: }
64: if(optind < argc)
65: xfile = argv[optind++];
66: else
67: xfile = "a.out";
68: readsyms();
69: if(optind >= argc)
70: doit("mon.out");
71: else
72: for(; optind < argc; optind++)
73: doit(argv[optind]);
74: output();
75: exit(0);
76: }
77:
78: doit(s)
79: char *s;
80: { struct stat stb;
81: int fd;
82:
83: file = s;
84: fd = open(s, 0);
85: if(fd < 0)
86: fatal("couldn't open %s\n", s);
87: fstat(fd, &stb);
88: pbuf = (char *) malloc(stb.st_size);
89: if(pbuf == 0)
90: fatal("couldn't alloc %d bytes for %s\n", stb.st_size, s);
91: if(read(fd, pbuf, stb.st_size) != stb.st_size)
92: fatal("read of %s failed\n", s);
93: if(stb.st_size <= sizeof(struct phdr))
94: fatal("%s not a mon.out\n");
95: close(fd);
96: addcalls();
97: addclicks(stb.st_size);
98: free(pbuf);
99: }
100:
101: addclicks(top)
102: { int i, n, cnt, j;
103: char *x;
104: Prof *p;
105: struct phdr *h;
106: double scale; /* the kernel uses 16 bit fractions */
107:
108: h = (struct phdr *)pbuf;
109: n = ((struct phdr *)pbuf)->cnt;
110: p = (Prof *) (pbuf + sizeof(struct phdr) + n * sizeof(struct pcnt));
111: top -= sizeof(struct phdr) + n * sizeof(struct pcnt);
112: cnt = top/sizeof(Prof); /* number of counters */
113: if(flags['s'] && !accumsz) {
114: accum = (Prof *) malloc(cnt*sizeof(Prof));
115: (void) memset(accum, 0, cnt*sizeof(Prof));
116: accumsz = cnt;
117: hsv = *h;
118: } /* we assume h is fixed across the files */
119: scale = (h->hipc-h->lopc)/(double)cnt;
120: /* in mcrt0.s it's 8 */
121: for(j = i = 0; i < cnt; i++) {
122: x = (char *)(h->lopc + (int)(scale*i));
123: while(j < nsym && syms[j+1].loc < x)
124: j++;
125: if(j > nsym)
126: fatal("cnts out of range %s\n", file);
127: syms[j].clicks += p[i];
128: }
129: if(flags['s'])
130: for(i = 0; i < accumsz; i++) {
131: n = accum[i] + p[i];
132: accum[i] = n;
133: if(n != accum[i]) {
134: mesg("overflow in accumulating counts, -s ignored\n");
135: flags['s'] = 0;
136: return;
137: }
138: }
139: }
140:
141: addcalls()
142: { int n, i;
143: struct pcnt *p;
144:
145: p = (struct pcnt *)(pbuf + sizeof(struct phdr));
146: n = ((struct phdr *)pbuf)->cnt;
147: for(i = 0; i < n; i++, p++)
148: addcall(p->value, p->calls);
149: }
150:
151: addcall(x, n)
152: char *x;
153: { int i;
154: for(i = 0; i < nsym && syms[i+1].loc < x; i++)
155: ;
156: if(i >= nsym) {
157: mesg("cntr out of range (%s), ignored\n", file);
158: return;
159: }
160: if(syms[i+1].loc == x)
161: syms[i+1].calls += n;
162: else
163: syms[i].calls += n;
164: }
165:
166: symnum(a, b)
167: register sym *a, *b;
168: {
169: return(a->loc - b->loc);
170: }
171:
172: readsyms()
173: { int fd, n, i, j;
174: struct exec x;
175: struct stat stb;
176: struct nlist *np;
177:
178: fd = open(xfile, 0);
179: if(fd < 0)
180: fatal("couldn't read %s\n", xfile);
181: if(read(fd, (char *)&x, sizeof(x)) != sizeof(x))
182: fatal("can't read header of %s\n", xfile);
183: if(!x.a_syms)
184: fatal("%s has no symbol table\n", xfile);
185:
186: /* read the symbol table in */
187: lseek(fd, N_SYMOFF(x), 0);
188: names = (struct nlist *) malloc(x.a_syms);
189: read(fd, (char *)names, x.a_syms);
190: nsym = N_STROFF(x) - N_SYMOFF(x);
191: nsym /= sizeof(struct nlist); /* over estimated */
192:
193: /* read the wretched strings in */
194: lseek(fd, N_STROFF(x), 0);
195: fstat(fd, &stb);
196: n = stb.st_size - N_STROFF(x);
197: strings = (char *) malloc(n);
198: if(read(fd, strings, n) != n)
199: fatal("couldn't read string table from %s (%d)\n", xfile, n);
200:
201: /* copy the text symbols into the symbol table */
202: syms = (sym *) malloc(nsym * sizeof(sym));
203: for(i = 0, np = names; np < names + nsym; np++) {
204: if((np->n_type & N_TYPE) != N_TEXT)
205: continue;
206: if(np->n_type & N_STAB)
207: continue;
208: syms[i] = nilsym;
209: syms[i].type = np->n_type;
210: syms[i].loc = (char *)np->n_value;
211: syms[i].name = strings + np->n_un.n_strx;
212: i++;
213: }
214: nsym = i;
215: qsort((char *)syms, nsym, sizeof(sym), symnum);
216:
217: /* now decide which of the ones with the same loc we like */
218: for(i = 0; i < nsym; i = j) {
219: for(j = i+1; j < nsym; j++)
220: if(syms[i].loc != syms[j].loc)
221: break;
222: choose(i, j);
223: }
224: /* and squash it down */
225: for(i = j = 0; i < nsym; i++)
226: if(syms[i].type)
227: syms[j++] = syms[i];
228: nsym = j;
229: syms[nsym].loc = (char *)0x8fffffff; /* a very big end */
230: close(fd);
231: }
232:
233: /* the expert system */
234: choose(i, j)
235: { int n;
236: if(j-i <= 1)
237: return;
238: /* if there is an external text one, take it */
239: for(n = i; n < j; n++)
240: if(syms[n].type & N_EXT)
241: goto found;
242: /* if there is one that starts with _, take it */
243: for(n = i; n < j; n++)
244: if(syms[n].name[0] == '_')
245: goto found;
246: /* if there is one without a . in it, take it */
247: for(n = i; n < j; n++)
248: if(!strchr(syms[n].name, '.'))
249: goto found;
250: /* first must be right, or at least ok */
251: n = i;
252: found:
253: for(; i < j; i++)
254: if(i != n)
255: syms[i].type = 0;
256: }
257:
258: char ebuf[256];
259: mesg(s, a, b, c, d, e, f)
260: char *s;
261: {
262: sprintf(ebuf, s, a, b, c, d, e, f);
263: write(2, ebuf, strlen(ebuf));
264: }
265:
266: fatal(s, a, b, c, d, e, f)
267: char *s;
268: {
269: mesg(s, a, b, c, d, e, f);
270: exit(1);
271: }
272:
273: symcalls(a, b)
274: register sym *a, *b;
275: {
276: return(b->calls - a->calls);
277: }
278:
279: symcnt(a, b)
280: register sym *a, *b;
281: {
282: return(b->clicks - a->clicks); /* largest first */
283: }
284:
285: output()
286: { int i, tot, fd;
287: double x, y;
288:
289: if(flags['v']) {
290: plotout();
291: return;
292: }
293: for(tot = i = 0; i < nsym; i++)
294: tot += syms[i].clicks;
295: if(tot == 0)
296: tot = 1;
297: if(flags['n'])
298: qsort((char *)syms, nsym, sizeof(sym), symcalls);
299: else if(!flags['l'])
300: qsort((char *)syms, nsym, sizeof(sym), symcnt);
301: printf(" %% Time\tCalls\tName\n");
302: for(i = 0; i < nsym; i++) {
303: if(!syms[i].calls && !syms[i].clicks && !flags['z'])
304: continue;
305: x = syms[i].clicks;
306: x /= HZ;
307: y = syms[i].clicks/(double)tot;
308: printf("%4.1f%8.3f %8d\t%s\n", (y*100), x, syms[i].calls,
309: syms[i].name);
310: }
311: if(!flags['s'])
312: return;
313: fd = creat("mon.sum", 0666);
314: if(fd < 0)
315: fatal("can't create mon.sum\n");
316: hsv.cnt = nsym;
317: if(write(fd, (char *)&hsv, sizeof(hsv)) != sizeof(hsv))
318: fatal("write failed\n");
319: for(i = 0; i < nsym; i++) { /* this is very inefficient */
320: write(fd, (char *)&syms[i].loc, 4); /* 4! */
321: write(fd, (char *)&syms[i].calls, 4);
322: }
323: if(write(fd, (char *)accum, accumsz*sizeof(Prof)) != accumsz*sizeof(Prof))
324: fatal("write failed\n");
325: close(fd);
326: }
327:
328: /* most of this is witchcraft */
329: plotout()
330: { int i;
331: /* double lastx, lasty;
332: if(lopct >= 100 || lopct < 0)
333: lopct = 0;
334: if(hipct > 100 || hipct <= 0)
335: hipct = 100;
336: rscale = 100./(hipct-lopct);
337: roffset = 2040.+40.8*lopct*rscale;
338: openpl();
339: erase();
340: range(-2048, -2048, 2048, 2048);
341: line(-2040, -2040, -2040, 2040);
342: for(i = 0; i < 11; i++)
343: line(-2040, 2040-i*408, 0, 2040-i*408);
344: */
345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.