10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4538Sdamico * Common Development and Distribution License (the "License"). 6*4538Sdamico * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21211Smike_s 220Sstevel@tonic-gate /* 23*4538Sdamico * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24211Smike_s * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <ctype.h> 300Sstevel@tonic-gate #include <string.h> 310Sstevel@tonic-gate #include <sys/param.h> 320Sstevel@tonic-gate #include <stdlib.h> 330Sstevel@tonic-gate #include "gprof.h" 340Sstevel@tonic-gate 350Sstevel@tonic-gate void print_demangled_name(int, nltype *); 360Sstevel@tonic-gate void striped_name(char *, nltype **); 370Sstevel@tonic-gate 380Sstevel@tonic-gate extern long hz; 390Sstevel@tonic-gate 400Sstevel@tonic-gate /* 410Sstevel@tonic-gate * Symbols that must never be printed, no matter what. 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate char *splsym[] = { 440Sstevel@tonic-gate PRF_ETEXT, 450Sstevel@tonic-gate PRF_EXTSYM, 460Sstevel@tonic-gate PRF_MEMTERM, 47211Smike_s NULL 480Sstevel@tonic-gate }; 490Sstevel@tonic-gate 50211Smike_s static bool is_special_sym(nltype *nlp); 51211Smike_s 520Sstevel@tonic-gate char * 530Sstevel@tonic-gate demangled_name(nltype *selfp) 540Sstevel@tonic-gate { 550Sstevel@tonic-gate char *name; 560Sstevel@tonic-gate if (!Cflag) 570Sstevel@tonic-gate return (selfp->name); 580Sstevel@tonic-gate 59211Smike_s name = (char *)sgs_demangle(selfp->name); 600Sstevel@tonic-gate return (name); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 630Sstevel@tonic-gate void 64211Smike_s printprof(void) 650Sstevel@tonic-gate { 660Sstevel@tonic-gate nltype *np; 670Sstevel@tonic-gate nltype **sortednlp; 680Sstevel@tonic-gate int i, index; 690Sstevel@tonic-gate int print_count = number_funcs_toprint; 700Sstevel@tonic-gate bool print_flag = TRUE; 710Sstevel@tonic-gate mod_info_t *mi; 720Sstevel@tonic-gate 730Sstevel@tonic-gate actime = 0.0; 74211Smike_s (void) printf("\f\n"); 750Sstevel@tonic-gate flatprofheader(); 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* 780Sstevel@tonic-gate * Sort the symbol table in by time 790Sstevel@tonic-gate */ 800Sstevel@tonic-gate sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 810Sstevel@tonic-gate if (sortednlp == (nltype **) 0) { 82211Smike_s (void) fprintf(stderr, 830Sstevel@tonic-gate "[printprof] ran out of memory for time sorting\n"); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate 860Sstevel@tonic-gate index = 0; 870Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 880Sstevel@tonic-gate for (i = 0; i < mi->nname; i++) 890Sstevel@tonic-gate sortednlp[index++] = &(mi->nl[i]); 900Sstevel@tonic-gate } 910Sstevel@tonic-gate 92211Smike_s qsort(sortednlp, total_names, sizeof (nltype *), timecmp); 930Sstevel@tonic-gate 940Sstevel@tonic-gate for (index = 0; (index < total_names) && print_flag; index += 1) { 950Sstevel@tonic-gate np = sortednlp[index]; 960Sstevel@tonic-gate flatprofline(np); 970Sstevel@tonic-gate if (nflag) { 980Sstevel@tonic-gate if (--print_count == 0) 990Sstevel@tonic-gate print_flag = FALSE; 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate actime = 0.0; 1030Sstevel@tonic-gate free(sortednlp); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate int 107211Smike_s timecmp(const void *arg1, const void *arg2) 1080Sstevel@tonic-gate { 109211Smike_s nltype **npp1 = (nltype **)arg1; 110211Smike_s nltype **npp2 = (nltype **)arg2; 1110Sstevel@tonic-gate double timediff; 1120Sstevel@tonic-gate long calldiff; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate timediff = (*npp2)->time - (*npp1)->time; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate if (timediff > 0.0) 1170Sstevel@tonic-gate return (1); 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate if (timediff < 0.0) 1200Sstevel@tonic-gate return (-1); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate calldiff = (*npp2)->ncall - (*npp1)->ncall; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate if (calldiff > 0) 1250Sstevel@tonic-gate return (1); 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate if (calldiff < 0) 1280Sstevel@tonic-gate return (-1); 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * header for flatprofline 1350Sstevel@tonic-gate */ 1360Sstevel@tonic-gate void 1370Sstevel@tonic-gate flatprofheader() 1380Sstevel@tonic-gate { 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate if (bflag) 1410Sstevel@tonic-gate printblurb(FLAT_BLURB); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate if (old_style) { 144211Smike_s (void) printf( 145211Smike_s "\ngranularity: each sample hit covers %d byte(s)", 146211Smike_s (long)scale * sizeof (UNIT)); 1470Sstevel@tonic-gate if (totime > 0.0) { 148211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 1490Sstevel@tonic-gate 100.0/totime, totime / hz); 1500Sstevel@tonic-gate } else { 151211Smike_s (void) printf(" no time accumulated\n\n"); 1520Sstevel@tonic-gate /* 1530Sstevel@tonic-gate * this doesn't hurt since all the numerators will 1540Sstevel@tonic-gate * be zero. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate totime = 1.0; 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 160211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1610Sstevel@tonic-gate "% ", "cumulative", "self ", "", "self ", "total ", ""); 162211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1630Sstevel@tonic-gate "time", "seconds ", "seconds", "calls", 1640Sstevel@tonic-gate "ms/call", "ms/call", "name"); 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate void 1680Sstevel@tonic-gate flatprofline(nltype *np) 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate if (zflag == 0 && np->ncall == 0 && np->time == 0) 1710Sstevel@tonic-gate return; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 1750Sstevel@tonic-gate * even if zflag was on. 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate if (is_special_sym(np)) 1780Sstevel@tonic-gate return; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate actime += np->time; 1810Sstevel@tonic-gate 182211Smike_s (void) printf("%5.1f %10.2f %8.2f", 1830Sstevel@tonic-gate 100 * np->time / totime, actime / hz, np->time / hz); 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate if (np->ncall != 0) { 186211Smike_s (void) printf(" %8lld %8.2f %8.2f ", np->ncall, 1870Sstevel@tonic-gate 1000 * np->time / hz / np->ncall, 1880Sstevel@tonic-gate 1000 * (np->time + np->childtime) / hz / np->ncall); 1890Sstevel@tonic-gate } else { 1900Sstevel@tonic-gate if (!Cflag) 191211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1920Sstevel@tonic-gate else 193211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate printname(np); 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate if (Cflag) 1990Sstevel@tonic-gate print_demangled_name(55, np); 2000Sstevel@tonic-gate 201211Smike_s (void) printf("\n"); 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate void 2050Sstevel@tonic-gate gprofheader() 2060Sstevel@tonic-gate { 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate if (bflag) 2090Sstevel@tonic-gate printblurb(CALLG_BLURB); 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate if (old_style) { 2120Sstevel@tonic-gate 213211Smike_s (void) printf( 214211Smike_s "\ngranularity: each sample hit covers %d byte(s)", 215211Smike_s (long)scale * sizeof (UNIT)); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate if (printtime > 0.0) { 218211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 2190Sstevel@tonic-gate 100.0/printtime, printtime / hz); 2200Sstevel@tonic-gate } else { 221211Smike_s (void) printf(" no time propagated\n\n"); 2220Sstevel@tonic-gate /* 2230Sstevel@tonic-gate * this doesn't hurt, since all the numerators 2240Sstevel@tonic-gate * will be 0.0 2250Sstevel@tonic-gate */ 2260Sstevel@tonic-gate printtime = 1.0; 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate } else { 229211Smike_s (void) printf( 230211Smike_s "\ngranularity: each pc-hit is considered 1 tick"); 2310Sstevel@tonic-gate if (hz != 1) { 232211Smike_s (void) printf(" (@ %4.3f seconds per tick)", 233211Smike_s (double)1.0 / hz); 2340Sstevel@tonic-gate } 235211Smike_s (void) puts("\n\n"); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 238211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2390Sstevel@tonic-gate "", "", "", "", "called", "total", "parents"); 240211Smike_s (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", 2410Sstevel@tonic-gate "index", "%time", "self", "descendents", 2420Sstevel@tonic-gate "called", "self", "name", "index"); 243211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2440Sstevel@tonic-gate "", "", "", "", "called", "total", "children"); 245211Smike_s (void) printf("\n"); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate void 2490Sstevel@tonic-gate gprofline(nltype *np) 2500Sstevel@tonic-gate { 2510Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 2520Sstevel@tonic-gate 253211Smike_s (void) sprintf(kirkbuffer, "[%d]", np->index); 254211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer, 2550Sstevel@tonic-gate 100 * (np->propself + np->propchild) / printtime, 2560Sstevel@tonic-gate np->propself / hz, np->propchild / hz); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate if ((np->ncall + np->selfcalls) != 0) { 259211Smike_s (void) printf(" %7lld", np->ncall); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate if (np->selfcalls != 0) 262211Smike_s (void) printf("+%-7lld ", np->selfcalls); 2630Sstevel@tonic-gate else 264211Smike_s (void) printf(" %7.7s ", ""); 2650Sstevel@tonic-gate } else { 266211Smike_s (void) printf(" %7.7s %7.7s ", "", ""); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate printname(np); 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate if (Cflag) 2720Sstevel@tonic-gate print_demangled_name(50, np); 2730Sstevel@tonic-gate 274211Smike_s (void) printf("\n"); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate static bool 2780Sstevel@tonic-gate is_special_sym(nltype *nlp) 2790Sstevel@tonic-gate { 2800Sstevel@tonic-gate int i; 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (nlp->name == NULL) 2830Sstevel@tonic-gate return (FALSE); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate for (i = 0; splsym[i]; i++) 2860Sstevel@tonic-gate if (strcmp(splsym[i], nlp->name) == 0) 2870Sstevel@tonic-gate return (TRUE); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate return (FALSE); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate void 2930Sstevel@tonic-gate printgprof(nltype **timesortnlp) 2940Sstevel@tonic-gate { 2950Sstevel@tonic-gate int index; 2960Sstevel@tonic-gate nltype *parentp; 2970Sstevel@tonic-gate int print_count = number_funcs_toprint; 2980Sstevel@tonic-gate bool count_flag = TRUE; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Print out the structured profiling list 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate gprofheader(); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate for (index = 0; index < total_names + ncycle && count_flag; index++) { 3060Sstevel@tonic-gate parentp = timesortnlp[index]; 3070Sstevel@tonic-gate if (zflag == 0 && parentp->ncall == 0 && 3080Sstevel@tonic-gate parentp->selfcalls == 0 && parentp->propself == 0 && 3090Sstevel@tonic-gate parentp -> propchild == 0) 3100Sstevel@tonic-gate continue; 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate if (!parentp->printflag) 3130Sstevel@tonic-gate continue; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate /* 3160Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 3170Sstevel@tonic-gate * even if zflag was on. 3180Sstevel@tonic-gate */ 3190Sstevel@tonic-gate if (is_special_sym(parentp)) 3200Sstevel@tonic-gate continue; 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate if (parentp->name == 0 && parentp->cycleno != 0) { 3230Sstevel@tonic-gate /* 3240Sstevel@tonic-gate * cycle header 3250Sstevel@tonic-gate */ 3260Sstevel@tonic-gate printcycle(parentp); 3270Sstevel@tonic-gate printmembers(parentp); 3280Sstevel@tonic-gate } else { 3290Sstevel@tonic-gate printparents(parentp); 3300Sstevel@tonic-gate gprofline(parentp); 3310Sstevel@tonic-gate printchildren(parentp); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 334211Smike_s (void) printf("\n"); 335211Smike_s (void) printf( 336211Smike_s "-----------------------------------------------\n"); 337211Smike_s (void) printf("\n"); 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate if (nflag) { 3400Sstevel@tonic-gate --print_count; 3410Sstevel@tonic-gate if (print_count == 0) 3420Sstevel@tonic-gate count_flag = FALSE; 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate free(timesortnlp); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate /* 3490Sstevel@tonic-gate * sort by decreasing propagated time 3500Sstevel@tonic-gate * if times are equal, but one is a cycle header, 3510Sstevel@tonic-gate * say that's first (e.g. less, i.e. -1). 3520Sstevel@tonic-gate * if one's name doesn't have an underscore and the other does, 3530Sstevel@tonic-gate * say the one is first. 3540Sstevel@tonic-gate * all else being equal, sort by names. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate int 357211Smike_s totalcmp(const void *arg1, const void *arg2) 3580Sstevel@tonic-gate { 359211Smike_s nltype **npp1 = (nltype **)arg1; 360211Smike_s nltype **npp2 = (nltype **)arg2; 3610Sstevel@tonic-gate nltype *np1 = *npp1; 3620Sstevel@tonic-gate nltype *np2 = *npp2; 3630Sstevel@tonic-gate double diff; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate diff = (np1->propself + np1->propchild) - 3660Sstevel@tonic-gate (np2->propself + np2->propchild); 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate if (diff < 0.0) 3690Sstevel@tonic-gate return (1); 3700Sstevel@tonic-gate if (diff > 0.0) 3710Sstevel@tonic-gate return (-1); 3720Sstevel@tonic-gate if (np1->name == 0 && np1->cycleno != 0) 3730Sstevel@tonic-gate return (-1); 3740Sstevel@tonic-gate if (np2->name == 0 && np2->cycleno != 0) 3750Sstevel@tonic-gate return (1); 3760Sstevel@tonic-gate if (np1->name == 0) 3770Sstevel@tonic-gate return (-1); 3780Sstevel@tonic-gate if (np2->name == 0) 3790Sstevel@tonic-gate return (1); 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate if (*(np1->name) != '_' && *(np2->name) == '_') 3820Sstevel@tonic-gate return (-1); 3830Sstevel@tonic-gate if (*(np1->name) == '_' && *(np2->name) != '_') 3840Sstevel@tonic-gate return (1); 3850Sstevel@tonic-gate if (np1->ncall > np2->ncall) 3860Sstevel@tonic-gate return (-1); 3870Sstevel@tonic-gate if (np1->ncall < np2->ncall) 3880Sstevel@tonic-gate return (1); 3890Sstevel@tonic-gate return (strcmp(np1->name, np2->name)); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate void 3930Sstevel@tonic-gate printparents(nltype *childp) 3940Sstevel@tonic-gate { 3950Sstevel@tonic-gate nltype *parentp; 3960Sstevel@tonic-gate arctype *arcp; 3970Sstevel@tonic-gate nltype *cycleheadp; 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate if (childp->cyclehead != 0) 4000Sstevel@tonic-gate cycleheadp = childp -> cyclehead; 4010Sstevel@tonic-gate else 4020Sstevel@tonic-gate cycleheadp = childp; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate if (childp->parents == 0) { 405211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 4060Sstevel@tonic-gate " <spontaneous>\n", "", "", "", "", "", ""); 4070Sstevel@tonic-gate return; 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate sortparents(childp); 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 4130Sstevel@tonic-gate parentp = arcp -> arc_parentp; 4140Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4150Sstevel@tonic-gate parentp->cycleno == childp->cycleno)) { 4160Sstevel@tonic-gate /* 4170Sstevel@tonic-gate * selfcall or call among siblings 4180Sstevel@tonic-gate */ 419211Smike_s (void) printf( 420211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4210Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4220Sstevel@tonic-gate printname(parentp); 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate if (Cflag) 4250Sstevel@tonic-gate print_demangled_name(54, parentp); 4260Sstevel@tonic-gate 427211Smike_s (void) printf("\n"); 4280Sstevel@tonic-gate } else { 4290Sstevel@tonic-gate /* 4300Sstevel@tonic-gate * regular parent of child 4310Sstevel@tonic-gate */ 432211Smike_s (void) printf( 433211Smike_s "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 4340Sstevel@tonic-gate "", arcp->arc_time / hz, arcp->arc_childtime / hz, 4350Sstevel@tonic-gate arcp->arc_count, cycleheadp->ncall); 4360Sstevel@tonic-gate printname(parentp); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate if (Cflag) 4390Sstevel@tonic-gate print_demangled_name(54, parentp); 4400Sstevel@tonic-gate 441211Smike_s (void) printf("\n"); 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate void 4470Sstevel@tonic-gate printchildren(nltype *parentp) 4480Sstevel@tonic-gate { 4490Sstevel@tonic-gate nltype *childp; 4500Sstevel@tonic-gate arctype *arcp; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate sortchildren(parentp); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 4550Sstevel@tonic-gate childp = arcp->arc_childp; 4560Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4570Sstevel@tonic-gate childp->cycleno == parentp->cycleno)) { 4580Sstevel@tonic-gate /* 4590Sstevel@tonic-gate * self call or call to sibling 4600Sstevel@tonic-gate */ 461211Smike_s (void) printf( 462211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4630Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4640Sstevel@tonic-gate printname(childp); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate if (Cflag) 4670Sstevel@tonic-gate print_demangled_name(54, childp); 4680Sstevel@tonic-gate 469211Smike_s (void) printf("\n"); 4700Sstevel@tonic-gate } else { 4710Sstevel@tonic-gate /* 4720Sstevel@tonic-gate * regular child of parent 4730Sstevel@tonic-gate */ 4740Sstevel@tonic-gate if (childp->cyclehead) 475211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4760Sstevel@tonic-gate "%7lld/%-7lld ", "", "", 4770Sstevel@tonic-gate arcp->arc_time / hz, 4780Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4790Sstevel@tonic-gate childp->cyclehead->ncall); 4800Sstevel@tonic-gate else 481211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4820Sstevel@tonic-gate "%7lld %7.7s ", 4830Sstevel@tonic-gate "", "", arcp->arc_time / hz, 4840Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4850Sstevel@tonic-gate ""); 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate printname(childp); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate if (Cflag) 4900Sstevel@tonic-gate print_demangled_name(54, childp); 4910Sstevel@tonic-gate 492211Smike_s (void) printf("\n"); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate void 4980Sstevel@tonic-gate printname(nltype *selfp) 4990Sstevel@tonic-gate { 5000Sstevel@tonic-gate char *c; 5010Sstevel@tonic-gate c = demangled_name(selfp); 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate if (selfp->name != 0) { 5040Sstevel@tonic-gate if (!Cflag) 505211Smike_s (void) printf("%s", selfp->name); 5060Sstevel@tonic-gate else 507211Smike_s (void) printf("%s", c); 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate #ifdef DEBUG 5100Sstevel@tonic-gate if (debug & DFNDEBUG) 511211Smike_s (void) printf("{%d} ", selfp->toporder); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate if (debug & PROPDEBUG) 514211Smike_s (void) printf("%5.2f%% ", selfp->propfraction); 515211Smike_s #endif /* DEBUG */ 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate if (selfp->cycleno != 0) 519211Smike_s (void) printf("\t<cycle %d>", selfp->cycleno); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if (selfp->index != 0) { 5220Sstevel@tonic-gate if (selfp->printflag) 523211Smike_s (void) printf(" [%d]", selfp->index); 5240Sstevel@tonic-gate else 525211Smike_s (void) printf(" (%d)", selfp->index); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate void 5300Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp) 5310Sstevel@tonic-gate { 5320Sstevel@tonic-gate char *c; 5330Sstevel@tonic-gate int i; 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate c = selfp->name; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate if (strcmp(c, demangled_name(selfp)) == 0) 5380Sstevel@tonic-gate return; 5390Sstevel@tonic-gate else { 540211Smike_s (void) printf("\n"); 5410Sstevel@tonic-gate for (i = 1; i < n; i++) 542211Smike_s (void) printf(" "); 543211Smike_s (void) printf("[%s]", selfp->name); 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate void 5480Sstevel@tonic-gate sortchildren(nltype *parentp) 5490Sstevel@tonic-gate { 5500Sstevel@tonic-gate arctype *arcp; 5510Sstevel@tonic-gate arctype *detachedp; 5520Sstevel@tonic-gate arctype sorted; 5530Sstevel@tonic-gate arctype *prevp; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate /* 5560Sstevel@tonic-gate * unlink children from parent, 5570Sstevel@tonic-gate * then insertion sort back on to sorted's children. 5580Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 5590Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 5600Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 5610Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 5620Sstevel@tonic-gate */ 5630Sstevel@tonic-gate sorted.arc_childlist = 0; 5640Sstevel@tonic-gate 565211Smike_s /* LINTED: warning: assignment operator */ 5660Sstevel@tonic-gate for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 5670Sstevel@tonic-gate arcp; 568211Smike_s /* LINTED: warning: assignment operator */ 5690Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 5700Sstevel@tonic-gate /* 5710Sstevel@tonic-gate * consider *arcp as disconnected 5720Sstevel@tonic-gate * insert it into sorted 5730Sstevel@tonic-gate */ 5740Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_childlist; 5750Sstevel@tonic-gate prevp = prevp->arc_childlist) { 5760Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 5770Sstevel@tonic-gate break; 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate arcp->arc_childlist = prevp->arc_childlist; 5810Sstevel@tonic-gate prevp->arc_childlist = arcp; 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* 5850Sstevel@tonic-gate * reattach sorted children to parent 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate parentp->children = sorted.arc_childlist; 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate void 5910Sstevel@tonic-gate sortparents(nltype *childp) 5920Sstevel@tonic-gate { 5930Sstevel@tonic-gate arctype *arcp; 5940Sstevel@tonic-gate arctype *detachedp; 5950Sstevel@tonic-gate arctype sorted; 5960Sstevel@tonic-gate arctype *prevp; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate /* 5990Sstevel@tonic-gate * unlink parents from child, 6000Sstevel@tonic-gate * then insertion sort back on to sorted's parents. 6010Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 6020Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 6030Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 6040Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 6050Sstevel@tonic-gate */ 6060Sstevel@tonic-gate sorted.arc_parentlist = 0; 6070Sstevel@tonic-gate 608211Smike_s /* LINTED: warning: assignment operator */ 6090Sstevel@tonic-gate for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 6100Sstevel@tonic-gate arcp; 611211Smike_s /* LINTED: warning: assignment operator */ 6120Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * consider *arcp as disconnected 6150Sstevel@tonic-gate * insert it into sorted 6160Sstevel@tonic-gate */ 6170Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_parentlist; 6180Sstevel@tonic-gate prevp = prevp->arc_parentlist) { 6190Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 6200Sstevel@tonic-gate break; 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate arcp->arc_parentlist = prevp->arc_parentlist; 6230Sstevel@tonic-gate prevp->arc_parentlist = arcp; 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate /* 6270Sstevel@tonic-gate * reattach sorted arcs to child 6280Sstevel@tonic-gate */ 6290Sstevel@tonic-gate childp->parents = sorted.arc_parentlist; 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate void 6330Sstevel@tonic-gate printcycle(nltype *cyclep) 6340Sstevel@tonic-gate { 6350Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 6360Sstevel@tonic-gate 637211Smike_s (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 638211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 6390Sstevel@tonic-gate 100 * (cyclep->propself + cyclep->propchild) / printtime, 6400Sstevel@tonic-gate cyclep -> propself / hz, cyclep -> propchild / hz, 6410Sstevel@tonic-gate cyclep -> ncall); 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate if (cyclep->selfcalls != 0) 644211Smike_s (void) printf("+%-7lld", cyclep->selfcalls); 6450Sstevel@tonic-gate else 646211Smike_s (void) printf(" %7.7s", ""); 6470Sstevel@tonic-gate 648211Smike_s (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 6490Sstevel@tonic-gate cyclep->index); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* 6530Sstevel@tonic-gate * print the members of a cycle 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate void 6560Sstevel@tonic-gate printmembers(nltype *cyclep) 6570Sstevel@tonic-gate { 6580Sstevel@tonic-gate nltype *memberp; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate sortmembers(cyclep); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 663211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 6640Sstevel@tonic-gate memberp->propself / hz, memberp->propchild / hz, 6650Sstevel@tonic-gate memberp->ncall); 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate if (memberp->selfcalls != 0) 668211Smike_s (void) printf("+%-7lld", memberp->selfcalls); 6690Sstevel@tonic-gate else 670211Smike_s (void) printf(" %7.7s", ""); 6710Sstevel@tonic-gate 672211Smike_s (void) printf(" "); 6730Sstevel@tonic-gate printname(memberp); 6740Sstevel@tonic-gate if (Cflag) 6750Sstevel@tonic-gate print_demangled_name(54, memberp); 676211Smike_s (void) printf("\n"); 6770Sstevel@tonic-gate } 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate /* 6810Sstevel@tonic-gate * sort members of a cycle 6820Sstevel@tonic-gate */ 6830Sstevel@tonic-gate void 6840Sstevel@tonic-gate sortmembers(nltype *cyclep) 6850Sstevel@tonic-gate { 6860Sstevel@tonic-gate nltype *todo; 6870Sstevel@tonic-gate nltype *doing; 6880Sstevel@tonic-gate nltype *prev; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate /* 6910Sstevel@tonic-gate * detach cycle members from cyclehead, 6920Sstevel@tonic-gate * and insertion sort them back on. 6930Sstevel@tonic-gate */ 6940Sstevel@tonic-gate todo = cyclep->cnext; 6950Sstevel@tonic-gate cyclep->cnext = 0; 6960Sstevel@tonic-gate 697211Smike_s /* LINTED: warning: assignment operator */ 6980Sstevel@tonic-gate for ((doing = todo) && (todo = doing->cnext); 699211Smike_s doing; 700211Smike_s /* LINTED: warning: assignment operator */ 701211Smike_s (doing = todo) && (todo = doing->cnext)) { 7020Sstevel@tonic-gate for (prev = cyclep; prev->cnext; prev = prev->cnext) { 7030Sstevel@tonic-gate if (membercmp(doing, prev->cnext) == GREATERTHAN) 7040Sstevel@tonic-gate break; 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate doing->cnext = prev->cnext; 7070Sstevel@tonic-gate prev->cnext = doing; 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate /* 7120Sstevel@tonic-gate * major sort is on propself + propchild, 7130Sstevel@tonic-gate * next is sort on ncalls + selfcalls. 7140Sstevel@tonic-gate */ 7150Sstevel@tonic-gate int 7160Sstevel@tonic-gate membercmp(nltype *this, nltype *that) 7170Sstevel@tonic-gate { 7180Sstevel@tonic-gate double thistime = this->propself + this->propchild; 7190Sstevel@tonic-gate double thattime = that->propself + that->propchild; 7200Sstevel@tonic-gate actype thiscalls = this->ncall + this->selfcalls; 7210Sstevel@tonic-gate actype thatcalls = that->ncall + that->selfcalls; 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate if (thistime > thattime) 7240Sstevel@tonic-gate return (GREATERTHAN); 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate if (thistime < thattime) 7270Sstevel@tonic-gate return (LESSTHAN); 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if (thiscalls > thatcalls) 7300Sstevel@tonic-gate return (GREATERTHAN); 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate if (thiscalls < thatcalls) 7330Sstevel@tonic-gate return (LESSTHAN); 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate return (EQUALTO); 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate /* 7390Sstevel@tonic-gate * compare two arcs to/from the same child/parent. 7400Sstevel@tonic-gate * - if one arc is a self arc, it's least. 7410Sstevel@tonic-gate * - if one arc is within a cycle, it's less than. 7420Sstevel@tonic-gate * - if both arcs are within a cycle, compare arc counts. 7430Sstevel@tonic-gate * - if neither arc is within a cycle, compare with 7440Sstevel@tonic-gate * arc_time + arc_childtime as major key 7450Sstevel@tonic-gate * arc count as minor key 7460Sstevel@tonic-gate */ 7470Sstevel@tonic-gate int 7480Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp) 7490Sstevel@tonic-gate { 7500Sstevel@tonic-gate nltype *thisparentp = thisp->arc_parentp; 7510Sstevel@tonic-gate nltype *thischildp = thisp->arc_childp; 7520Sstevel@tonic-gate nltype *thatparentp = thatp->arc_parentp; 7530Sstevel@tonic-gate nltype *thatchildp = thatp->arc_childp; 7540Sstevel@tonic-gate double thistime; 7550Sstevel@tonic-gate double thattime; 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate #ifdef DEBUG 7580Sstevel@tonic-gate if (debug & TIMEDEBUG) { 759211Smike_s (void) printf("[arccmp] "); 7600Sstevel@tonic-gate printname(thisparentp); 761211Smike_s (void) printf(" calls "); 7620Sstevel@tonic-gate printname(thischildp); 763211Smike_s (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 7640Sstevel@tonic-gate thisp->arc_childtime, thisp->arc_count, 7650Sstevel@tonic-gate thischildp->ncall); 766211Smike_s (void) printf("[arccmp] "); 7670Sstevel@tonic-gate printname(thatparentp); 768211Smike_s (void) printf(" calls "); 7690Sstevel@tonic-gate printname(thatchildp); 770211Smike_s (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 7710Sstevel@tonic-gate thatp->arc_childtime, thatp->arc_count, 7720Sstevel@tonic-gate thatchildp->ncall); 773211Smike_s (void) printf("\n"); 7740Sstevel@tonic-gate } 775211Smike_s #endif /* DEBUG */ 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate if (thisparentp == thischildp) { 7780Sstevel@tonic-gate /* 7790Sstevel@tonic-gate * this is a self call 7800Sstevel@tonic-gate */ 7810Sstevel@tonic-gate return (LESSTHAN); 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate if (thatparentp == thatchildp) { 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * that is a self call 7870Sstevel@tonic-gate */ 7880Sstevel@tonic-gate return (GREATERTHAN); 7890Sstevel@tonic-gate } 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 7920Sstevel@tonic-gate thisparentp->cycleno == thischildp->cycleno) { 7930Sstevel@tonic-gate /* 7940Sstevel@tonic-gate * this is a call within a cycle 7950Sstevel@tonic-gate */ 7960Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 7970Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 7980Sstevel@tonic-gate /* 7990Sstevel@tonic-gate * that is a call within the cycle, too 8000Sstevel@tonic-gate */ 8010Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8020Sstevel@tonic-gate return (LESSTHAN); 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8050Sstevel@tonic-gate return (GREATERTHAN); 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate return (EQUALTO); 8080Sstevel@tonic-gate } else { 8090Sstevel@tonic-gate /* 8100Sstevel@tonic-gate * that isn't a call within the cycle 8110Sstevel@tonic-gate */ 8120Sstevel@tonic-gate return (LESSTHAN); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate } else { 8150Sstevel@tonic-gate /* 8160Sstevel@tonic-gate * this isn't a call within a cycle 8170Sstevel@tonic-gate */ 8180Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 8190Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 8200Sstevel@tonic-gate /* 8210Sstevel@tonic-gate * that is a call within a cycle 8220Sstevel@tonic-gate */ 8230Sstevel@tonic-gate return (GREATERTHAN); 8240Sstevel@tonic-gate } else { 8250Sstevel@tonic-gate /* 8260Sstevel@tonic-gate * neither is a call within a cycle 8270Sstevel@tonic-gate */ 8280Sstevel@tonic-gate thistime = thisp->arc_time + thisp->arc_childtime; 8290Sstevel@tonic-gate thattime = thatp->arc_time + thatp->arc_childtime; 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate if (thistime < thattime) 8320Sstevel@tonic-gate return (LESSTHAN); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate if (thistime > thattime) 8350Sstevel@tonic-gate return (GREATERTHAN); 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8380Sstevel@tonic-gate return (LESSTHAN); 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8410Sstevel@tonic-gate return (GREATERTHAN); 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate return (EQUALTO); 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate } 8460Sstevel@tonic-gate } 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate void 8490Sstevel@tonic-gate printblurb(char *blurbname) 8500Sstevel@tonic-gate { 8510Sstevel@tonic-gate FILE *blurbfile; 8520Sstevel@tonic-gate int input; 8530Sstevel@tonic-gate 854*4538Sdamico blurbfile = fopen(blurbname, "r"); 8550Sstevel@tonic-gate if (blurbfile == NULL) { 856*4538Sdamico perror(blurbname); 8570Sstevel@tonic-gate return; 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate 8600Sstevel@tonic-gate while ((input = getc(blurbfile)) != EOF) 861211Smike_s (void) putchar(input); 8620Sstevel@tonic-gate 863211Smike_s (void) fclose(blurbfile); 8640Sstevel@tonic-gate } 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate char *s1, *s2; 8670Sstevel@tonic-gate 868211Smike_s static int 869211Smike_s namecmp(const void *arg1, const void *arg2) 8700Sstevel@tonic-gate { 871211Smike_s nltype **npp1 = (nltype **)arg1; 872211Smike_s nltype **npp2 = (nltype **)arg2; 873211Smike_s 8740Sstevel@tonic-gate if (!Cflag) 8750Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 8760Sstevel@tonic-gate else { 8770Sstevel@tonic-gate striped_name(s1, npp1); 8780Sstevel@tonic-gate striped_name(s2, npp2); 8790Sstevel@tonic-gate return (strcmp(s1, s2)); 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate } 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate void 8840Sstevel@tonic-gate striped_name(char *s, nltype **npp) 8850Sstevel@tonic-gate { 8860Sstevel@tonic-gate char *d, *c; 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate c = (char *)s; 8890Sstevel@tonic-gate d = demangled_name(*npp); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate while ((*d != '(') && (*d != '\0')) { 8920Sstevel@tonic-gate if (*d != ':') 8930Sstevel@tonic-gate *c++ = *d++; 8940Sstevel@tonic-gate else 8950Sstevel@tonic-gate d++; 8960Sstevel@tonic-gate } 8970Sstevel@tonic-gate *c = '\0'; 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate /* 9010Sstevel@tonic-gate * Checks if the current symbol name is the same as its neighbour and 9020Sstevel@tonic-gate * returns TRUE if it is. 9030Sstevel@tonic-gate */ 9040Sstevel@tonic-gate static bool 9050Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames) 9060Sstevel@tonic-gate { 9070Sstevel@tonic-gate /* 9080Sstevel@tonic-gate * same as previous (if there's one) ? 9090Sstevel@tonic-gate */ 9100Sstevel@tonic-gate if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 9110Sstevel@tonic-gate return (TRUE); 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate /* 9140Sstevel@tonic-gate * same as next (if there's one) ? 9150Sstevel@tonic-gate */ 9160Sstevel@tonic-gate if ((ndx < (nnames - 1)) && 917*4538Sdamico (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 9180Sstevel@tonic-gate return (TRUE); 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate return (FALSE); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate void 9250Sstevel@tonic-gate printmodules() 9260Sstevel@tonic-gate { 9270Sstevel@tonic-gate mod_info_t *mi; 9280Sstevel@tonic-gate 929211Smike_s (void) printf("\f\nObject modules\n\n"); 9300Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) 931211Smike_s (void) printf(" %d: %s\n", mi->id, mi->name); 9320Sstevel@tonic-gate } 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate #define IDFMT(id) ((id) < 10 ? 1 : 2) 9350Sstevel@tonic-gate #define NMFMT(id) ((id) < 10 ? 17 : 16) 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate void 9380Sstevel@tonic-gate printindex() 9390Sstevel@tonic-gate { 9400Sstevel@tonic-gate nltype **namesortnlp; 9410Sstevel@tonic-gate nltype *nlp; 9420Sstevel@tonic-gate int index, nnames, todo, i, j; 9430Sstevel@tonic-gate char peterbuffer[BUFSIZ]; 9440Sstevel@tonic-gate mod_info_t *mi; 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate /* 9470Sstevel@tonic-gate * Now, sort regular function name alphabetically 9480Sstevel@tonic-gate * to create an index. 9490Sstevel@tonic-gate */ 9500Sstevel@tonic-gate namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate if (namesortnlp == NULL) 953211Smike_s (void) fprintf(stderr, "%s: ran out of memory for sorting\n", 954211Smike_s whoami); 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate nnames = 0; 9570Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 9580Sstevel@tonic-gate for (index = 0; index < mi->nname; index++) { 9590Sstevel@tonic-gate if (zflag == 0 && (mi->nl[index]).ncall == 0 && 960*4538Sdamico (mi->nl[index]).time == 0) { 9610Sstevel@tonic-gate continue; 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate /* 9650Sstevel@tonic-gate * Do not print certain special symbols, like 9660Sstevel@tonic-gate * PRF_EXTSYM, etc. even if zflag was on. 9670Sstevel@tonic-gate */ 9680Sstevel@tonic-gate if (is_special_sym(&(mi->nl[index]))) 9690Sstevel@tonic-gate continue; 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate namesortnlp[nnames++] = &(mi->nl[index]); 9720Sstevel@tonic-gate } 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate if (Cflag) { 9760Sstevel@tonic-gate s1 = malloc(500 * sizeof (char)); 9770Sstevel@tonic-gate s2 = malloc(500 * sizeof (char)); 9780Sstevel@tonic-gate } 9790Sstevel@tonic-gate 980211Smike_s qsort(namesortnlp, nnames, sizeof (nltype *), namecmp); 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate for (index = 1, todo = nnames; index <= ncycle; index++) 9830Sstevel@tonic-gate namesortnlp[todo++] = &cyclenl[index]; 9840Sstevel@tonic-gate 985211Smike_s (void) printf("\f\nIndex by function name\n\n"); 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate if (!Cflag) 9880Sstevel@tonic-gate index = (todo + 2) / 3; 9890Sstevel@tonic-gate else 9900Sstevel@tonic-gate index = todo; 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate for (i = 0; i < index; i++) { 9930Sstevel@tonic-gate if (!Cflag) { 9940Sstevel@tonic-gate for (j = i; j < todo; j += index) { 9950Sstevel@tonic-gate nlp = namesortnlp[j]; 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate if (nlp->printflag) { 998211Smike_s (void) sprintf(peterbuffer, 9990Sstevel@tonic-gate "[%d]", nlp->index); 10000Sstevel@tonic-gate } else { 1001211Smike_s (void) sprintf(peterbuffer, 10020Sstevel@tonic-gate "(%d)", nlp->index); 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate if (j < nnames) { 10060Sstevel@tonic-gate if (does_clash(namesortnlp, 1007*4538Sdamico j, nnames)) { 1008211Smike_s (void) printf( 1009211Smike_s "%6.6s %*d:%-*.*s", 1010*4538Sdamico peterbuffer, 1011*4538Sdamico IDFMT(nlp->module->id), 1012*4538Sdamico nlp->module->id, 1013*4538Sdamico NMFMT(nlp->module->id), 1014*4538Sdamico NMFMT(nlp->module->id), 1015*4538Sdamico nlp->name); 10160Sstevel@tonic-gate } else { 1017*4538Sdamico (void) printf("%6.6s %-19.19s", 1018*4538Sdamico peterbuffer, nlp->name); 10190Sstevel@tonic-gate } 10200Sstevel@tonic-gate } else { 1021211Smike_s (void) printf("%6.6s ", peterbuffer); 1022211Smike_s (void) sprintf(peterbuffer, 10230Sstevel@tonic-gate "<cycle %d>", nlp->cycleno); 1024211Smike_s (void) printf("%-19.19s", peterbuffer); 10250Sstevel@tonic-gate } 10260Sstevel@tonic-gate } 10270Sstevel@tonic-gate } else { 10280Sstevel@tonic-gate nlp = namesortnlp[i]; 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate if (nlp->printflag) 1031211Smike_s (void) sprintf(peterbuffer, "[%d]", nlp->index); 10320Sstevel@tonic-gate else 1033211Smike_s (void) sprintf(peterbuffer, "(%d)", nlp->index); 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate if (i < nnames) { 10360Sstevel@tonic-gate char *d = demangled_name(nlp); 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate if (does_clash(namesortnlp, i, nnames)) { 1039211Smike_s (void) printf("%6.6s %d:%s\n", 1040211Smike_s peterbuffer, nlp->module->id, d); 10410Sstevel@tonic-gate } else 1042211Smike_s (void) printf("%6.6s %s\n", peterbuffer, 1043211Smike_s d); 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate if (d != nlp->name) 1046211Smike_s (void) printf("%6.6s [%s]", "", 1047211Smike_s nlp->name); 10480Sstevel@tonic-gate } else { 1049211Smike_s (void) printf("%6.6s ", peterbuffer); 1050211Smike_s (void) sprintf(peterbuffer, "<cycle %d>", 10510Sstevel@tonic-gate nlp->cycleno); 1052211Smike_s (void) printf("%-33.33s", peterbuffer); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate } 1055211Smike_s (void) printf("\n"); 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate free(namesortnlp); 10580Sstevel@tonic-gate } 1059