xref: /csrg-svn/lib/libc/gmon/gmon.c (revision 4540)
1 static	char *sccsid = "@(#)gmon.c	1.2 (Berkeley) 10/17/81";
2 
3 #include <stdio.h>
4 
5 #include "monitor.h"
6 
7     /*	froms is actually a bunch of unsigned shorts indexing tos */
8 static unsigned short	*froms;
9 static struct tostruct	*tos = 0;
10 static unsigned short	tolimit = 0;
11 static char		*s_lowpc = 0;
12 static char		*s_highpc = 0;
13 
14 static	int	ssiz;
15 static	int	*sbuf;
16 
17 char	*sbrk();
18 #define	MSG "No space for monitor buffer(s)\n"
19 
20 	/*ARGSUSED*/
21 exit(code)
22 	register int	code;
23 {
24 	fflush(stdout);
25 	_mcleanup();
26 	_cleanup();
27 #ifdef lint
28 	code = code;
29 #endif lint
30 	asm("	movl r11, r0");
31 	asm("	chmk $1");
32 }
33 
34 _mstartup(lowpc, highpc)
35 	char	*lowpc;
36 	char	*highpc;
37 {
38 	int	monsize;
39 	char	*buffer;
40 	int	textsize;
41 
42 	s_lowpc = lowpc;
43 	s_highpc = highpc;
44 	textsize = ((char *)highpc - (char *)lowpc);
45 	monsize = textsize + sizeof(struct phdr);
46 	buffer = sbrk(monsize);
47 	if ( buffer == (char *) -1 ) {
48 	    write(2, MSG, sizeof(MSG));
49 	    return;
50 	}
51 	froms = (unsigned short *) sbrk(textsize);
52 	if ( froms == (unsigned short *) -1 ) {
53 	    write(2 , MSG , sizeof(MSG) );
54 	    froms = 0;
55 	    return;
56 	}
57 	tos = (struct tostruct *) sbrk(textsize);
58 	if ( tos == (struct tostruct *) -1 ) {
59 	    write(2 , MSG , sizeof(MSG) );
60 	    froms = 0;
61 	    tos = 0;
62 	    return;
63 	}
64 	tolimit = textsize / sizeof(struct tostruct);
65 	tos[0].link = 0;
66 	monitor(lowpc, highpc, buffer, monsize);
67 }
68 
69 _peek()
70 {
71 }
72 
73 _mcleanup()
74 {
75     FILE	*fd;
76     int		fromindex;
77     char	*frompc;
78     int		toindex;
79     int		textsize;
80 
81     monitor((int (*)())0);
82     fd = fopen( "dmon.out" , "w" );
83     if ( fd == NULL ) {
84 	perror( "mcount: dmon.out" );
85 	return;
86     }
87     fwrite( sbuf , ssiz , 1 , fd );
88     textsize = s_highpc - s_lowpc;
89     for ( fromindex = 0 ; fromindex < textsize>>1 ; fromindex++ ) {
90 	if ( froms[fromindex] == 0 ) {
91 	    continue;
92 	}
93 	frompc = s_lowpc + (fromindex<<1);
94 	for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
95 #	    ifdef DEBUG
96 		printf( "[mcleanup] frompc %d selfpc %d count %d\n" ,
97 			frompc , tos[toindex].selfpc , tos[toindex].count );
98 #	    endif DEBUG
99 	    fwrite( &frompc, 1, sizeof frompc, fd );
100 	    fwrite( &tos[toindex].selfpc, 1, sizeof tos[toindex].selfpc, fd );
101 	    fwrite( &tos[toindex].count, 1, sizeof tos[toindex].count, fd );
102 	}
103     }
104     fclose( fd );
105 }
106 
107 /*
108  *	This routine is massaged so that it may be jsb'ed to
109  */
110 asm("#define _mcount mcount");
111 mcount()
112 {
113     register char		*selfpc;	/* r11 */
114     register unsigned short	*frompcindex;	/* r10 */
115     register struct tostruct	*top;		/* r9 */
116     static int			profiling = 0;
117 
118     asm( "	forgot to run ex script on monitor.s" );
119     asm( "#define r11 r5" );
120     asm( "#define r10 r4" );
121     asm( "#define r9 r3" );
122 #ifdef lint
123     selfpc = (char *) 0;
124     frompcindex = 0;
125 #else not lint
126 	/*
127 	 *	find the return address for mcount,
128 	 *	and the return address for mcount's caller.
129 	 */
130     asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
131     asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
132 #endif not lint
133 	/*
134 	 *	check that we are profiling
135 	 */
136     if ( profiling || tos == 0 ) {
137 	goto out;
138     }
139     profiling = 1;
140 	/*
141 	 *	check that frompcindex is a reasonable pc value.
142 	 *	for example:	signal catchers get called from the stack,
143 	 *			not from text space.  too bad.
144 	 */
145     if ( (char *) frompcindex < s_lowpc || (char *) frompcindex > s_highpc ) {
146 	goto done;
147     }
148     frompcindex = &froms[ ( (long) frompcindex - (long) s_lowpc ) >> 1 ];
149     if ( *frompcindex == 0 ) {
150 	*frompcindex = ++tos[0].link;
151 	if ( *frompcindex >= tolimit ) {
152 	    goto overflow;
153 	}
154 	top = &tos[ *frompcindex ];
155 	top->selfpc = selfpc;
156 	top->count = 0;
157 	top->link = 0;
158     } else {
159 	top = &tos[ *frompcindex ];
160     }
161     for ( ; /* goto done */ ; top = &tos[ top -> link ] ) {
162 	if ( top -> selfpc == selfpc ) {
163 	    top -> count++;
164 	    goto done;
165 	}
166 	if ( top -> link == 0 ) {
167 	    top -> link = ++tos[0].link;
168 	    if ( top -> link >= tolimit )
169 		goto overflow;
170 	    top = &tos[ top -> link ];
171 	    top -> selfpc = selfpc;
172 	    top -> count = 1;
173 	    top -> link = 0;
174 	    goto done;
175 	}
176     }
177 done:
178     profiling = 0;
179     /* and fall through */
180 out:
181     asm( "	rsb" );
182     asm( "#undef r11" );
183     asm( "#undef r10" );
184     asm( "#undef r9" );
185     asm( "#undef _mcount");
186 
187 overflow:
188 #   define	TOLIMIT	"mcount: tos overflow\n"
189     write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
190     tos = 0;
191     froms = 0;
192     goto out;
193 }
194 
195 monitor(lowpc, highpc, buf, bufsiz)
196 	char	*lowpc;
197 	/*VARARGS1*/
198 	char	*highpc;
199 	int *buf, bufsiz;
200 {
201 	register o;
202 
203 	if (lowpc == 0) {
204 		profil((char *)0, 0, 0, 0);
205 		return;
206 	}
207 	sbuf = buf;
208 	ssiz = bufsiz;
209 	((struct phdr *)buf)->lpc = lowpc;
210 	((struct phdr *)buf)->hpc = highpc;
211 	((struct phdr *)buf)->ncnt = ssiz;
212 	o = sizeof(struct phdr);
213 	buf = (int *) (((int)buf) + o);
214 	bufsiz -= o;
215 	if (bufsiz<=0)
216 		return;
217 	o = (((char *)highpc - (char *)lowpc)>>1);
218 	if(bufsiz < o)
219 		o = ((float) bufsiz / o) * 32768;
220 	else
221 		o = 0177777;
222 	profil(buf, bufsiz, lowpc, o);
223 }
224 
225