|
|
1.1 root 1: /*
2: * Copyright (c) 1980 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: #if defined(LIBC_SCCS) && !defined(lint)
8: static char sccsid[] = "@(#)gmon.c 5.1 (Berkeley) 8/27/87";
9: #endif LIBC_SCCS and not lint
10:
11: #include "gmon.h"
12:
13: /*
14: * froms is actually a bunch of unsigned shorts indexing tos
15: */
16: static int profiling = 3;
17: static unsigned short *froms;
18: static struct tostruct *tos = 0;
19: static long tolimit = 0;
20: static char *s_lowpc = 0;
21: static char *s_highpc = 0;
22: static unsigned long s_textsize = 0;
23:
24: static int ssiz;
25: static char *sbuf;
26: static int s_scale;
27: /* see profil(2) where this is describe (incorrectly) */
28: #define SCALE_1_TO_1 0x10000L
29:
30: #define MSG "No space for monitor buffer(s)\n"
31:
32: monstartup(lowpc, highpc)
33: char *lowpc;
34: char *highpc;
35: {
36: int monsize;
37: char *buffer;
38: char *sbrk();
39: extern char *minbrk;
40:
41: /*
42: * round lowpc and highpc to multiples of the density we're using
43: * so the rest of the scaling (here and in gprof) stays in ints.
44: */
45: lowpc = (char *)
46: ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
47: s_lowpc = lowpc;
48: highpc = (char *)
49: ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
50: s_highpc = highpc;
51: s_textsize = highpc - lowpc;
52: monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
53: monsize = (monsize + 3) & ~3;
54: buffer = sbrk( monsize );
55: if ( buffer == (char *) -1 ) {
56: write( 2 , MSG , sizeof(MSG) - 1 );
57: return;
58: }
59: froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
60: if ( froms == (unsigned short *) -1 ) {
61: write( 2 , MSG , sizeof(MSG) - 1 );
62: froms = 0;
63: return;
64: }
65: tolimit = s_textsize * ARCDENSITY / 100;
66: if ( tolimit < MINARCS ) {
67: tolimit = MINARCS;
68: } else if ( tolimit > 65534 ) {
69: tolimit = 65534;
70: }
71: tos = (struct tostruct *) sbrk( (tolimit*sizeof(struct tostruct)+3)&~3 );
72: if ( tos == (struct tostruct *) -1 ) {
73: write( 2 , MSG , sizeof(MSG) - 1 );
74: froms = 0;
75: tos = 0;
76: return;
77: }
78: minbrk = sbrk(0);
79: tos[0].link = 0;
80: monitor( lowpc , highpc , buffer , monsize , tolimit );
81: }
82:
83: _mcleanup()
84: {
85: int fd;
86: int fromindex;
87: int endfrom;
88: char *frompc;
89: int toindex;
90: struct rawarc rawarc;
91:
92: fd = creat( "gmon.out" , 0666 );
93: if ( fd < 0 ) {
94: perror( "mcount: gmon.out" );
95: return;
96: }
97: # ifdef DEBUG
98: fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
99: # endif DEBUG
100: write( fd , sbuf , ssiz );
101: endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
102: for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
103: if ( froms[fromindex] == 0 ) {
104: continue;
105: }
106: frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
107: for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
108: # ifdef DEBUG
109: fprintf( stderr ,
110: "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
111: frompc , tos[toindex].selfpc , tos[toindex].count );
112: # endif DEBUG
113: rawarc.raw_frompc = (unsigned long) frompc;
114: rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
115: rawarc.raw_count = tos[toindex].count;
116: write( fd , &rawarc , sizeof rawarc );
117: }
118: }
119: close( fd );
120: }
121:
122: mcount(cntpa)
123: long **cntpa;
124: {
125: register char *selfpc;
126: register unsigned short *frompcindex;
127: register struct tostruct *top;
128: register struct tostruct *prevtop;
129: register long toindex;
130:
131: /*
132: * find the return address for mcount,
133: * and address of counter pointer
134: */
135: selfpc = *((char **)&cntpa-3); /* -8(fp) */
136: frompcindex = (unsigned short *)(*((((long *)*((char **)&cntpa-1)))-2));
137: /*
138: * check that we are profiling
139: * and that we aren't recursively invoked.
140: */
141: if (profiling) {
142: goto out;
143: }
144: profiling++;
145: /*
146: * check that frompcindex is a reasonable pc value.
147: * for example: signal catchers get called from the stack,
148: * not from text space. too bad.
149: */
150: frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
151: if ((unsigned long)frompcindex > s_textsize) {
152: goto done;
153: }
154: frompcindex =
155: &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
156: toindex = *frompcindex;
157: if (toindex == 0) {
158: /*
159: * first time traversing this arc
160: */
161: toindex = ++tos[0].link;
162: if (toindex >= tolimit) {
163: goto overflow;
164: }
165: *frompcindex = toindex;
166: top = &tos[toindex];
167: top->selfpc = selfpc;
168: top->count = 1;
169: top->link = 0;
170: goto done;
171: }
172: top = &tos[toindex];
173: if (top->selfpc == selfpc) {
174: /*
175: * arc at front of chain; usual case.
176: */
177: top->count++;
178: goto done;
179: }
180: /*
181: * have to go looking down chain for it.
182: * top points to what we are looking at,
183: * prevtop points to previous top.
184: * we know it is not at the head of the chain.
185: */
186: for (; /* goto done */; ) {
187: if (top->link == 0) {
188: /*
189: * top is end of the chain and none of the chain
190: * had top->selfpc == selfpc.
191: * so we allocate a new tostruct
192: * and link it to the head of the chain.
193: */
194: toindex = ++tos[0].link;
195: if (toindex >= tolimit) {
196: goto overflow;
197: }
198: top = &tos[toindex];
199: top->selfpc = selfpc;
200: top->count = 1;
201: top->link = *frompcindex;
202: *frompcindex = toindex;
203: goto done;
204: }
205: /*
206: * otherwise, check the next arc on the chain.
207: */
208: prevtop = top;
209: top = &tos[top->link];
210: if (top->selfpc == selfpc) {
211: /*
212: * there it is.
213: * increment its count
214: * move it to the head of the chain.
215: */
216: top->count++;
217: toindex = prevtop->link;
218: prevtop->link = top->link;
219: top->link = *frompcindex;
220: *frompcindex = toindex;
221: goto done;
222: }
223:
224: }
225: done:
226: profiling--;
227: out:
228: return;
229:
230: overflow:
231: # define TOLIMIT "mcount: tos overflow\n"
232: write(2, TOLIMIT, sizeof(TOLIMIT) - 1);
233: goto out;
234: }
235:
236: /*VARARGS1*/
237: monitor( lowpc , highpc , buf , bufsiz , nfunc )
238: char *lowpc;
239: char *highpc;
240: char *buf; /* declared ``short buffer[]'' in monitor(3) */
241: int bufsiz;
242: int nfunc; /* not used, available for compatability only */
243: {
244: register o;
245:
246: if ( lowpc == 0 ) {
247: moncontrol(0);
248: _mcleanup();
249: return;
250: }
251: sbuf = buf;
252: ssiz = bufsiz;
253: ( (struct phdr *) buf ) -> lpc = lowpc;
254: ( (struct phdr *) buf ) -> hpc = highpc;
255: ( (struct phdr *) buf ) -> ncnt = ssiz;
256: bufsiz -= sizeof(struct phdr);
257: if ( bufsiz <= 0 )
258: return;
259: o = highpc - lowpc;
260: if( bufsiz < o )
261: s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1;
262: else
263: s_scale = SCALE_1_TO_1;
264: moncontrol(1);
265: }
266:
267: /*
268: * Control profiling
269: * profiling is what mcount checks to see if
270: * all the data structures are ready.
271: */
272: moncontrol(mode)
273: int mode;
274: {
275: if (mode) {
276: /* start */
277: profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
278: s_lowpc, s_scale);
279: profiling = 0;
280: } else {
281: /* stop */
282: profil((char *)0, 0, 0, 0);
283: profiling = 3;
284: }
285: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.