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