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