1*9161Ssam /* subr_prof.c 4.2 82/11/13 */ 27332Ssam 37332Ssam #ifdef GPROF 47332Ssam #include "../h/crt0.h" 57332Ssam #include "../h/param.h" 67332Ssam #include "../h/systm.h" 77332Ssam 87332Ssam /* 97332Ssam * Froms is actually a bunch of unsigned shorts indexing tos 107332Ssam */ 117332Ssam int profiling = 3; 127332Ssam u_short *froms = 0; 137332Ssam struct tostruct *tos = 0; 147332Ssam u_short tolimit = 0; 157332Ssam char *s_lowpc = (char *)0x80000000; 167332Ssam extern char etext; 177332Ssam char *s_highpc = &etext; 187332Ssam u_long s_textsize = 0; 197332Ssam int ssiz; 207332Ssam u_short *sbuf; 217332Ssam u_short *kcount; 227332Ssam 237332Ssam kmstartup() 247332Ssam { 257332Ssam u_long limit; 267332Ssam 277332Ssam s_textsize = s_highpc - s_lowpc; 287332Ssam ssiz = s_textsize + sizeof(struct phdr); 297332Ssam printf("Profiling kernel, s_textsize=%d [%x..%x]\n", 307332Ssam s_textsize, s_lowpc, s_highpc); 31*9161Ssam sbuf = (u_short *)wmemall(memall, ssiz); 327332Ssam if (sbuf == 0) { 337332Ssam printf("No space for monitor buffer(s)\n"); 347332Ssam return; 357332Ssam } 367332Ssam blkclr((caddr_t)sbuf, ssiz); 37*9161Ssam froms = (u_short *)wmemall(memall, s_textsize); 387332Ssam if (froms == 0) { 397332Ssam printf("No space for monitor buffer(s)\n"); 407332Ssam wmemfree(sbuf, ssiz); 417332Ssam sbuf = 0; 427332Ssam return; 437332Ssam } 447332Ssam blkclr((caddr_t)froms, s_textsize); 45*9161Ssam tos = (struct tostruct *)wmemall(memall, s_textsize); 467332Ssam if (tos == 0) { 477332Ssam printf("No space for monitor buffer(s)\n"); 487332Ssam wmemfree(sbuf, ssiz); 497332Ssam sbuf = 0; 507332Ssam wmemfree(froms, s_textsize); 517332Ssam froms = 0; 527332Ssam return; 537332Ssam } 547332Ssam blkclr((caddr_t)tos, s_textsize); 557332Ssam tos[0].link = 0; 567332Ssam limit = s_textsize / sizeof(struct tostruct); 577332Ssam /* 587332Ssam * Tolimit is what mcount checks to see if 597332Ssam * all the data structures are ready!!! 607332Ssam * Make sure it won't overflow. 617332Ssam */ 627332Ssam tolimit = limit > 65534 ? 65534 : limit; 637332Ssam ((struct phdr *)sbuf)->lpc = s_lowpc; 647332Ssam ((struct phdr *)sbuf)->hpc = s_highpc; 657332Ssam ((struct phdr *)sbuf)->ncnt = ssiz; 667332Ssam kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr)); 677332Ssam #ifdef notdef 687332Ssam profiling = 0; /* patch by hand when you're ready */ 697332Ssam #endif 707332Ssam } 717332Ssam 727332Ssam /* 737332Ssam * This routine is massaged so that it may be jsb'ed to 747332Ssam */ 757332Ssam asm("#define _mcount mcount"); 767332Ssam mcount() 777332Ssam { 787332Ssam register char *selfpc; /* r11 */ 797332Ssam register u_short *frompcindex; /* r10 */ 807332Ssam register struct tostruct *top; /* r9 */ 817332Ssam 827332Ssam asm(" forgot to run ex script on gcrt0.s"); 837332Ssam asm("#define r11 r5"); 847332Ssam asm("#define r10 r4"); 857332Ssam asm("#define r9 r3"); 867332Ssam #ifdef lint 877332Ssam selfpc = (char *) 0; 887332Ssam frompcindex = 0; 897332Ssam #else not lint 907332Ssam /* 917332Ssam * Find the return address for mcount, 927332Ssam * and the return address for mcount's caller. 937332Ssam */ 947332Ssam asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ 957332Ssam asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ 967332Ssam #endif not lint 977332Ssam /* 987332Ssam * Check that we are profiling 997332Ssam * and that we aren't recursively invoked. 1007332Ssam */ 1017332Ssam if (tolimit == 0) 1027332Ssam goto out; 1037332Ssam if (profiling) 1047332Ssam goto out; 1057332Ssam profiling++; 1067332Ssam /* 1077332Ssam * Check that frompcindex is a reasonable pc value. 1087332Ssam * For example: signal catchers get called from the stack, 1097332Ssam * not from text space. too bad. 1107332Ssam */ 1117332Ssam frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc); 1127332Ssam if ((u_long)frompcindex > s_textsize) 1137332Ssam goto done; 1147332Ssam frompcindex = &froms[((long)frompcindex) >> 1]; 1157332Ssam if (*frompcindex != 0) 1167332Ssam top = &tos[*frompcindex]; 1177332Ssam else { 1187332Ssam *frompcindex = ++tos[0].link; 1197332Ssam if (*frompcindex >= tolimit) 1207332Ssam goto overflow; 1217332Ssam top = &tos[*frompcindex]; 1227332Ssam top->selfpc = selfpc; 1237332Ssam top->count = 0; 1247332Ssam top->link = 0; 1257332Ssam } 1267332Ssam for (; /* break */; top = &tos[top->link]) { 1277332Ssam if (top->selfpc == selfpc) { 1287332Ssam top->count++; 1297332Ssam break; 1307332Ssam } 1317332Ssam if (top->link != 0) 1327332Ssam continue; 1337332Ssam top->link = ++tos[0].link; 1347332Ssam if (top->link >= tolimit) 1357332Ssam goto overflow; 1367332Ssam top = &tos[top->link]; 1377332Ssam top->selfpc = selfpc; 1387332Ssam top->count = 1; 1397332Ssam top->link = 0; 1407332Ssam break; 1417332Ssam } 1427332Ssam done: 1437332Ssam profiling--; 1447332Ssam /* and fall through */ 1457332Ssam out: 1467332Ssam asm(" rsb"); 1477332Ssam asm("#undef r11"); 1487332Ssam asm("#undef r10"); 1497332Ssam asm("#undef r9"); 1507332Ssam asm("#undef _mcount"); 1517332Ssam 1527332Ssam overflow: 1537332Ssam tolimit = 0; 1547332Ssam printf("mcount: tos overflow\n"); 1557332Ssam goto out; 1567332Ssam } 1577332Ssam #endif GPROF 158