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