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