xref: /csrg-svn/lib/libc/gmon/gmon.c (revision 9433)
1*9433Smckusick static	char *sccsid = "@(#)gmon.c	4.5 (Berkeley) 12/04/82";
24514Speter 
34869Smckusic #ifdef DEBUG
44514Speter #include <stdio.h>
54869Smckusic #endif DEBUG
64514Speter 
7*9433Smckusick #include "gmon.h"
84514Speter 
94564Speter     /*
104564Speter      *	froms is actually a bunch of unsigned shorts indexing tos
114564Speter      */
124514Speter static unsigned short	*froms;
134514Speter static struct tostruct	*tos = 0;
144514Speter static unsigned short	tolimit = 0;
154514Speter static char		*s_lowpc = 0;
164514Speter static char		*s_highpc = 0;
174850Speter static unsigned long	s_textsize = 0;
186253Smckusick static char		*minsbrk = 0;
194514Speter 
204564Speter static int	ssiz;
214564Speter static int	*sbuf;
224514Speter 
234514Speter #define	MSG "No space for monitor buffer(s)\n"
244514Speter 
25*9433Smckusick monstartup(lowpc, highpc)
264564Speter     char	*lowpc;
274564Speter     char	*highpc;
284514Speter {
294850Speter     int			monsize;
304850Speter     char		*buffer;
314850Speter     char		*sbrk();
324850Speter     unsigned long	limit;
334514Speter 
344564Speter     s_lowpc = lowpc;
354564Speter     s_highpc = highpc;
364850Speter     s_textsize = highpc - lowpc;
374850Speter     monsize = s_textsize + sizeof(struct phdr);
384564Speter     buffer = sbrk( monsize );
394564Speter     if ( buffer == (char *) -1 ) {
404564Speter 	write( 2 , MSG , sizeof(MSG) );
414564Speter 	return;
424564Speter     }
434850Speter     froms = (unsigned short *) sbrk( s_textsize );
444564Speter     if ( froms == (unsigned short *) -1 ) {
454564Speter 	write( 2 , MSG , sizeof(MSG) );
464564Speter 	froms = 0;
474564Speter 	return;
484564Speter     }
494850Speter     tos = (struct tostruct *) sbrk(s_textsize);
504564Speter     if ( tos == (struct tostruct *) -1 ) {
514564Speter 	write( 2 , MSG , sizeof(MSG) );
524564Speter 	froms = 0;
534564Speter 	tos = 0;
544564Speter 	return;
554564Speter     }
564564Speter     tos[0].link = 0;
574850Speter     limit = s_textsize / sizeof(struct tostruct);
584850Speter 	/*
594850Speter 	 *	tolimit is what mcount checks to see if
604850Speter 	 *	all the data structures are ready!!!
614850Speter 	 *	make sure it won't overflow.
624850Speter 	 */
634850Speter     tolimit = limit > 65534 ? 65534 : limit;
64*9433Smckusick     monitor( lowpc , highpc , buffer , monsize , tolimit );
654514Speter }
664514Speter 
674514Speter _mcleanup()
684514Speter {
694869Smckusic     int			fd;
704869Smckusic     int			fromindex;
714869Smckusic     char		*frompc;
724869Smckusic     int			toindex;
734869Smckusic     struct rawarc	rawarc;
744514Speter 
754869Smckusic     fd = creat( "gmon.out" , 0666 );
764869Smckusic     if ( fd < 0 ) {
774564Speter 	perror( "mcount: gmon.out" );
784514Speter 	return;
794514Speter     }
804564Speter #   ifdef DEBUG
814564Speter 	fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
824564Speter #   endif DEBUG
834869Smckusic     write( fd , sbuf , ssiz );
844850Speter     for ( fromindex = 0 ; fromindex < s_textsize>>1 ; fromindex++ ) {
854514Speter 	if ( froms[fromindex] == 0 ) {
864514Speter 	    continue;
874514Speter 	}
884514Speter 	frompc = s_lowpc + (fromindex<<1);
894514Speter 	for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
904514Speter #	    ifdef DEBUG
914748Speter 		fprintf( stderr ,
924748Speter 			"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
934514Speter 			frompc , tos[toindex].selfpc , tos[toindex].count );
944514Speter #	    endif DEBUG
954869Smckusic 	    rawarc.raw_frompc = (unsigned long) frompc;
964869Smckusic 	    rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
974869Smckusic 	    rawarc.raw_count = tos[toindex].count;
984869Smckusic 	    write( fd , &rawarc , sizeof rawarc );
994514Speter 	}
1004514Speter     }
1014869Smckusic     close( fd );
1024514Speter }
1034514Speter 
1044564Speter     /*
1054564Speter      *	This routine is massaged so that it may be jsb'ed to
1064564Speter      */
1074514Speter asm("#define _mcount mcount");
1084514Speter mcount()
1094514Speter {
1104514Speter     register char		*selfpc;	/* r11 */
1114514Speter     register unsigned short	*frompcindex;	/* r10 */
1124514Speter     register struct tostruct	*top;		/* r9 */
1134540Speter     static int			profiling = 0;
1144514Speter 
1154869Smckusic     asm( "	forgot to run ex script on gcrt0.s" );
1164514Speter     asm( "#define r11 r5" );
1174514Speter     asm( "#define r10 r4" );
1184514Speter     asm( "#define r9 r3" );
1194514Speter #ifdef lint
1204514Speter     selfpc = (char *) 0;
1214514Speter     frompcindex = 0;
1224514Speter #else not lint
1234514Speter 	/*
1244540Speter 	 *	find the return address for mcount,
1254540Speter 	 *	and the return address for mcount's caller.
1264514Speter 	 */
1274514Speter     asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
1284514Speter     asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
1294514Speter #endif not lint
1304540Speter 	/*
1314540Speter 	 *	check that we are profiling
1324564Speter 	 *	and that we aren't recursively invoked.
1334540Speter 	 */
1344850Speter     if ( tolimit == 0 ) {
1354514Speter 	goto out;
1364514Speter     }
1374564Speter     if ( profiling ) {
1384564Speter 	goto out;
1394564Speter     }
1404540Speter     profiling = 1;
1414540Speter 	/*
1424540Speter 	 *	check that frompcindex is a reasonable pc value.
1434540Speter 	 *	for example:	signal catchers get called from the stack,
1444540Speter 	 *			not from text space.  too bad.
1454540Speter 	 */
1464850Speter     frompcindex = (unsigned short *) ( (long) frompcindex - (long) s_lowpc );
1474850Speter     if ( (unsigned long) frompcindex > s_textsize ) {
1484540Speter 	goto done;
1494540Speter     }
1504850Speter     frompcindex = &froms[ ( (long) frompcindex ) >> 1 ];
1514514Speter     if ( *frompcindex == 0 ) {
1524514Speter 	*frompcindex = ++tos[0].link;
1534514Speter 	if ( *frompcindex >= tolimit ) {
1544514Speter 	    goto overflow;
1554514Speter 	}
1564514Speter 	top = &tos[ *frompcindex ];
1574514Speter 	top->selfpc = selfpc;
1584514Speter 	top->count = 0;
1594514Speter 	top->link = 0;
1604514Speter     } else {
1614514Speter 	top = &tos[ *frompcindex ];
1624514Speter     }
1634540Speter     for ( ; /* goto done */ ; top = &tos[ top -> link ] ) {
1644514Speter 	if ( top -> selfpc == selfpc ) {
1654514Speter 	    top -> count++;
1664540Speter 	    goto done;
1674514Speter 	}
1684514Speter 	if ( top -> link == 0 ) {
1694514Speter 	    top -> link = ++tos[0].link;
1704514Speter 	    if ( top -> link >= tolimit )
1714514Speter 		goto overflow;
1724514Speter 	    top = &tos[ top -> link ];
1734514Speter 	    top -> selfpc = selfpc;
1744514Speter 	    top -> count = 1;
1754514Speter 	    top -> link = 0;
1764540Speter 	    goto done;
1774514Speter 	}
1784514Speter     }
1794540Speter done:
1804540Speter     profiling = 0;
1814540Speter     /* and fall through */
1824514Speter out:
1834514Speter     asm( "	rsb" );
1844514Speter     asm( "#undef r11" );
1854514Speter     asm( "#undef r10" );
1864514Speter     asm( "#undef r9" );
1874514Speter     asm( "#undef _mcount");
1884514Speter 
1894514Speter overflow:
1904850Speter     tolimit = 0;
1914514Speter #   define	TOLIMIT	"mcount: tos overflow\n"
1924514Speter     write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
1934514Speter     goto out;
1944514Speter }
1954514Speter 
196*9433Smckusick /*VARARGS1*/
197*9433Smckusick monitor( lowpc , highpc , buf , bufsiz , nfunc )
1984564Speter     char	*lowpc;
1994564Speter     char	*highpc;
2004564Speter     int		*buf, bufsiz;
201*9433Smckusick     int		nfunc;	/* not used, available for compatability only */
2024514Speter {
2034564Speter     register o;
2044514Speter 
2054564Speter     if ( lowpc == 0 ) {
2064564Speter 	profil( (char *) 0 , 0 , 0 , 0 );
207*9433Smckusick 	_mcleanup();
2084564Speter 	return;
2094564Speter     }
2104564Speter     sbuf = buf;
2114564Speter     ssiz = bufsiz;
2124564Speter     ( (struct phdr *) buf ) -> lpc = lowpc;
2134564Speter     ( (struct phdr *) buf ) -> hpc = highpc;
2144564Speter     ( (struct phdr *) buf ) -> ncnt = ssiz;
2154564Speter     o = sizeof(struct phdr);
2164564Speter     buf = (int *) ( ( (int) buf ) + o );
2174564Speter     bufsiz -= o;
2184564Speter     if ( bufsiz <= 0 )
2194564Speter 	return;
2205070Smckusic     o = ( ( (char *) highpc - (char *) lowpc) );
2214564Speter     if( bufsiz < o )
2225070Smckusic 	o = ( (float) bufsiz / o ) * 65536;
2234564Speter     else
2245070Smckusic 	o = 65536;
2254564Speter     profil( buf , bufsiz , lowpc , o );
2264514Speter }
2276177Smckusick 
2286177Smckusick /*
2296177Smckusick  * This is a stub for the "brk" system call, which we want to
2306253Smckusick  * catch so that it will not deallocate our data space.
2316253Smckusick  * (of which the program is not aware)
2326177Smckusick  */
2336253Smckusick asm("#define _curbrk curbrk");
2346253Smckusick extern char *curbrk;
2356253Smckusick 
2366177Smckusick brk(addr)
2376253Smckusick 	char *addr;
2386177Smckusick {
2396253Smckusick 
2406253Smckusick 	if (addr < minsbrk)
2416253Smckusick 		addr = minsbrk;
2426253Smckusick 	asm("	chmk	$17");
243*9433Smckusick 	asm("	jcc	1f");
244*9433Smckusick 	asm("	jmp	cerror");
245*9433Smckusick asm("1:");
2466253Smckusick 	curbrk = addr;
2476253Smckusick 	return (0);
2486177Smckusick }
249