xref: /csrg-svn/lib/libc/gmon/gmon.c (revision 4514)
1 static	char *sccsid = "@(#)gmon.c	1.1 (Berkeley) 10/15/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: mon.out2" );
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     /* !!! if you add anything, you have to fix the pushr and popr !!! */
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 	 *	we've pushed the old r11, r10, and r9,
128 	 *	so the return address for a plain old jsb
129 	 *	which should be at 0(sp) is now at 12(sp)
130 	 */
131     asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
132     asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
133 #endif not lint
134     /*
135      *	check that we are profiling
136      */
137     if ( tos == 0 ) {
138 	goto out;
139     }
140     frompcindex = &froms[ ( (long) frompcindex - (long) s_lowpc ) >> 1 ];
141     if ( *frompcindex == 0 ) {
142 	*frompcindex = ++tos[0].link;
143 	if ( *frompcindex >= tolimit ) {
144 	    goto overflow;
145 	}
146 	top = &tos[ *frompcindex ];
147 	top->selfpc = selfpc;
148 	top->count = 0;
149 	top->link = 0;
150     } else {
151 	top = &tos[ *frompcindex ];
152     }
153     for ( ; /*break*/ ; top = &tos[ top -> link ] ) {
154 	if ( top -> selfpc == selfpc ) {
155 	    top -> count++;
156 	    break;
157 	}
158 	if ( top -> link == 0 ) {
159 	    top -> link = ++tos[0].link;
160 	    if ( top -> link >= tolimit )
161 		goto overflow;
162 	    top = &tos[ top -> link ];
163 	    top -> selfpc = selfpc;
164 	    top -> count = 1;
165 	    top -> link = 0;
166 	    break;
167 	}
168     }
169 out:
170     asm( "	rsb" );
171     asm( "#undef r11" );
172     asm( "#undef r10" );
173     asm( "#undef r9" );
174     asm( "#undef _mcount");
175 
176 overflow:
177 #   define	TOLIMIT	"mcount: tos overflow\n"
178     write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
179     tos = 0;
180     froms = 0;
181     goto out;
182 }
183 
184 monitor(lowpc, highpc, buf, bufsiz)
185 	char	*lowpc;
186 	/*VARARGS1*/
187 	char	*highpc;
188 	int *buf, bufsiz;
189 {
190 	register o;
191 
192 	if (lowpc == 0) {
193 		profil((char *)0, 0, 0, 0);
194 		return;
195 	}
196 	sbuf = buf;
197 	ssiz = bufsiz;
198 	((struct phdr *)buf)->lpc = lowpc;
199 	((struct phdr *)buf)->hpc = highpc;
200 	((struct phdr *)buf)->ncnt = ssiz;
201 	o = sizeof(struct phdr);
202 	buf = (int *) (((int)buf) + o);
203 	bufsiz -= o;
204 	if (bufsiz<=0)
205 		return;
206 	o = (((char *)highpc - (char *)lowpc)>>1);
207 	if(bufsiz < o)
208 		o = ((float) bufsiz / o) * 32768;
209 	else
210 		o = 0177777;
211 	profil(buf, bufsiz, lowpc, o);
212 }
213 
214