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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 22*211Smike_s 230Sstevel@tonic-gate /* 24*211Smike_s * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*211Smike_s * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <ctype.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <sys/param.h> 330Sstevel@tonic-gate #include <stdlib.h> 340Sstevel@tonic-gate #include "gprof.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate extern int find_run_directory(char *, char *, char *, char **, char *); 370Sstevel@tonic-gate void print_demangled_name(int, nltype *); 380Sstevel@tonic-gate void striped_name(char *, nltype **); 390Sstevel@tonic-gate 400Sstevel@tonic-gate extern long hz; 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * Symbols that must never be printed, no matter what. 440Sstevel@tonic-gate */ 450Sstevel@tonic-gate char *splsym[] = { 460Sstevel@tonic-gate PRF_ETEXT, 470Sstevel@tonic-gate PRF_EXTSYM, 480Sstevel@tonic-gate PRF_MEMTERM, 49*211Smike_s NULL 500Sstevel@tonic-gate }; 510Sstevel@tonic-gate 52*211Smike_s static bool is_special_sym(nltype *nlp); 53*211Smike_s 540Sstevel@tonic-gate char * 550Sstevel@tonic-gate demangled_name(nltype *selfp) 560Sstevel@tonic-gate { 570Sstevel@tonic-gate char *name; 580Sstevel@tonic-gate if (!Cflag) 590Sstevel@tonic-gate return (selfp->name); 600Sstevel@tonic-gate 61*211Smike_s name = (char *)sgs_demangle(selfp->name); 620Sstevel@tonic-gate return (name); 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate void 66*211Smike_s printprof(void) 670Sstevel@tonic-gate { 680Sstevel@tonic-gate nltype *np; 690Sstevel@tonic-gate nltype **sortednlp; 700Sstevel@tonic-gate int i, index; 710Sstevel@tonic-gate int print_count = number_funcs_toprint; 720Sstevel@tonic-gate bool print_flag = TRUE; 730Sstevel@tonic-gate mod_info_t *mi; 740Sstevel@tonic-gate 750Sstevel@tonic-gate actime = 0.0; 76*211Smike_s (void) printf("\f\n"); 770Sstevel@tonic-gate flatprofheader(); 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* 800Sstevel@tonic-gate * Sort the symbol table in by time 810Sstevel@tonic-gate */ 820Sstevel@tonic-gate sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 830Sstevel@tonic-gate if (sortednlp == (nltype **) 0) { 84*211Smike_s (void) fprintf(stderr, 850Sstevel@tonic-gate "[printprof] ran out of memory for time sorting\n"); 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate index = 0; 890Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 900Sstevel@tonic-gate for (i = 0; i < mi->nname; i++) 910Sstevel@tonic-gate sortednlp[index++] = &(mi->nl[i]); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 94*211Smike_s qsort(sortednlp, total_names, sizeof (nltype *), timecmp); 950Sstevel@tonic-gate 960Sstevel@tonic-gate for (index = 0; (index < total_names) && print_flag; index += 1) { 970Sstevel@tonic-gate np = sortednlp[index]; 980Sstevel@tonic-gate flatprofline(np); 990Sstevel@tonic-gate if (nflag) { 1000Sstevel@tonic-gate if (--print_count == 0) 1010Sstevel@tonic-gate print_flag = FALSE; 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate actime = 0.0; 1050Sstevel@tonic-gate free(sortednlp); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate int 109*211Smike_s timecmp(const void *arg1, const void *arg2) 1100Sstevel@tonic-gate { 111*211Smike_s nltype **npp1 = (nltype **)arg1; 112*211Smike_s nltype **npp2 = (nltype **)arg2; 1130Sstevel@tonic-gate double timediff; 1140Sstevel@tonic-gate long calldiff; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate timediff = (*npp2)->time - (*npp1)->time; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate if (timediff > 0.0) 1190Sstevel@tonic-gate return (1); 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate if (timediff < 0.0) 1220Sstevel@tonic-gate return (-1); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate calldiff = (*npp2)->ncall - (*npp1)->ncall; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if (calldiff > 0) 1270Sstevel@tonic-gate return (1); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate if (calldiff < 0) 1300Sstevel@tonic-gate return (-1); 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* 1360Sstevel@tonic-gate * header for flatprofline 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate void 1390Sstevel@tonic-gate flatprofheader() 1400Sstevel@tonic-gate { 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate if (bflag) 1430Sstevel@tonic-gate printblurb(FLAT_BLURB); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if (old_style) { 146*211Smike_s (void) printf( 147*211Smike_s "\ngranularity: each sample hit covers %d byte(s)", 148*211Smike_s (long)scale * sizeof (UNIT)); 1490Sstevel@tonic-gate if (totime > 0.0) { 150*211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 1510Sstevel@tonic-gate 100.0/totime, totime / hz); 1520Sstevel@tonic-gate } else { 153*211Smike_s (void) printf(" no time accumulated\n\n"); 1540Sstevel@tonic-gate /* 1550Sstevel@tonic-gate * this doesn't hurt since all the numerators will 1560Sstevel@tonic-gate * be zero. 1570Sstevel@tonic-gate */ 1580Sstevel@tonic-gate totime = 1.0; 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 162*211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1630Sstevel@tonic-gate "% ", "cumulative", "self ", "", "self ", "total ", ""); 164*211Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1650Sstevel@tonic-gate "time", "seconds ", "seconds", "calls", 1660Sstevel@tonic-gate "ms/call", "ms/call", "name"); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate void 1700Sstevel@tonic-gate flatprofline(nltype *np) 1710Sstevel@tonic-gate { 1720Sstevel@tonic-gate if (zflag == 0 && np->ncall == 0 && np->time == 0) 1730Sstevel@tonic-gate return; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 1770Sstevel@tonic-gate * even if zflag was on. 1780Sstevel@tonic-gate */ 1790Sstevel@tonic-gate if (is_special_sym(np)) 1800Sstevel@tonic-gate return; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate actime += np->time; 1830Sstevel@tonic-gate 184*211Smike_s (void) printf("%5.1f %10.2f %8.2f", 1850Sstevel@tonic-gate 100 * np->time / totime, actime / hz, np->time / hz); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate if (np->ncall != 0) { 188*211Smike_s (void) printf(" %8lld %8.2f %8.2f ", np->ncall, 1890Sstevel@tonic-gate 1000 * np->time / hz / np->ncall, 1900Sstevel@tonic-gate 1000 * (np->time + np->childtime) / hz / np->ncall); 1910Sstevel@tonic-gate } else { 1920Sstevel@tonic-gate if (!Cflag) 193*211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1940Sstevel@tonic-gate else 195*211Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate printname(np); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate if (Cflag) 2010Sstevel@tonic-gate print_demangled_name(55, np); 2020Sstevel@tonic-gate 203*211Smike_s (void) printf("\n"); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate void 2070Sstevel@tonic-gate gprofheader() 2080Sstevel@tonic-gate { 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate if (bflag) 2110Sstevel@tonic-gate printblurb(CALLG_BLURB); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if (old_style) { 2140Sstevel@tonic-gate 215*211Smike_s (void) printf( 216*211Smike_s "\ngranularity: each sample hit covers %d byte(s)", 217*211Smike_s (long)scale * sizeof (UNIT)); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate if (printtime > 0.0) { 220*211Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 2210Sstevel@tonic-gate 100.0/printtime, printtime / hz); 2220Sstevel@tonic-gate } else { 223*211Smike_s (void) printf(" no time propagated\n\n"); 2240Sstevel@tonic-gate /* 2250Sstevel@tonic-gate * this doesn't hurt, since all the numerators 2260Sstevel@tonic-gate * will be 0.0 2270Sstevel@tonic-gate */ 2280Sstevel@tonic-gate printtime = 1.0; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate } else { 231*211Smike_s (void) printf( 232*211Smike_s "\ngranularity: each pc-hit is considered 1 tick"); 2330Sstevel@tonic-gate if (hz != 1) { 234*211Smike_s (void) printf(" (@ %4.3f seconds per tick)", 235*211Smike_s (double)1.0 / hz); 2360Sstevel@tonic-gate } 237*211Smike_s (void) puts("\n\n"); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 240*211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2410Sstevel@tonic-gate "", "", "", "", "called", "total", "parents"); 242*211Smike_s (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", 2430Sstevel@tonic-gate "index", "%time", "self", "descendents", 2440Sstevel@tonic-gate "called", "self", "name", "index"); 245*211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2460Sstevel@tonic-gate "", "", "", "", "called", "total", "children"); 247*211Smike_s (void) printf("\n"); 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate void 2510Sstevel@tonic-gate gprofline(nltype *np) 2520Sstevel@tonic-gate { 2530Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 2540Sstevel@tonic-gate 255*211Smike_s (void) sprintf(kirkbuffer, "[%d]", np->index); 256*211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer, 2570Sstevel@tonic-gate 100 * (np->propself + np->propchild) / printtime, 2580Sstevel@tonic-gate np->propself / hz, np->propchild / hz); 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if ((np->ncall + np->selfcalls) != 0) { 261*211Smike_s (void) printf(" %7lld", np->ncall); 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate if (np->selfcalls != 0) 264*211Smike_s (void) printf("+%-7lld ", np->selfcalls); 2650Sstevel@tonic-gate else 266*211Smike_s (void) printf(" %7.7s ", ""); 2670Sstevel@tonic-gate } else { 268*211Smike_s (void) printf(" %7.7s %7.7s ", "", ""); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate printname(np); 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate if (Cflag) 2740Sstevel@tonic-gate print_demangled_name(50, np); 2750Sstevel@tonic-gate 276*211Smike_s (void) printf("\n"); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate static bool 2800Sstevel@tonic-gate is_special_sym(nltype *nlp) 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate int i; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate if (nlp->name == NULL) 2850Sstevel@tonic-gate return (FALSE); 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate for (i = 0; splsym[i]; i++) 2880Sstevel@tonic-gate if (strcmp(splsym[i], nlp->name) == 0) 2890Sstevel@tonic-gate return (TRUE); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate return (FALSE); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate void 2950Sstevel@tonic-gate printgprof(nltype **timesortnlp) 2960Sstevel@tonic-gate { 2970Sstevel@tonic-gate int index; 2980Sstevel@tonic-gate nltype *parentp; 2990Sstevel@tonic-gate int print_count = number_funcs_toprint; 3000Sstevel@tonic-gate bool count_flag = TRUE; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Print out the structured profiling list 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate gprofheader(); 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate for (index = 0; index < total_names + ncycle && count_flag; index++) { 3080Sstevel@tonic-gate parentp = timesortnlp[index]; 3090Sstevel@tonic-gate if (zflag == 0 && parentp->ncall == 0 && 3100Sstevel@tonic-gate parentp->selfcalls == 0 && parentp->propself == 0 && 3110Sstevel@tonic-gate parentp -> propchild == 0) 3120Sstevel@tonic-gate continue; 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate if (!parentp->printflag) 3150Sstevel@tonic-gate continue; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 3190Sstevel@tonic-gate * even if zflag was on. 3200Sstevel@tonic-gate */ 3210Sstevel@tonic-gate if (is_special_sym(parentp)) 3220Sstevel@tonic-gate continue; 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate if (parentp->name == 0 && parentp->cycleno != 0) { 3250Sstevel@tonic-gate /* 3260Sstevel@tonic-gate * cycle header 3270Sstevel@tonic-gate */ 3280Sstevel@tonic-gate printcycle(parentp); 3290Sstevel@tonic-gate printmembers(parentp); 3300Sstevel@tonic-gate } else { 3310Sstevel@tonic-gate printparents(parentp); 3320Sstevel@tonic-gate gprofline(parentp); 3330Sstevel@tonic-gate printchildren(parentp); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 336*211Smike_s (void) printf("\n"); 337*211Smike_s (void) printf( 338*211Smike_s "-----------------------------------------------\n"); 339*211Smike_s (void) printf("\n"); 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate if (nflag) { 3420Sstevel@tonic-gate --print_count; 3430Sstevel@tonic-gate if (print_count == 0) 3440Sstevel@tonic-gate count_flag = FALSE; 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate free(timesortnlp); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate /* 3510Sstevel@tonic-gate * sort by decreasing propagated time 3520Sstevel@tonic-gate * if times are equal, but one is a cycle header, 3530Sstevel@tonic-gate * say that's first (e.g. less, i.e. -1). 3540Sstevel@tonic-gate * if one's name doesn't have an underscore and the other does, 3550Sstevel@tonic-gate * say the one is first. 3560Sstevel@tonic-gate * all else being equal, sort by names. 3570Sstevel@tonic-gate */ 3580Sstevel@tonic-gate int 359*211Smike_s totalcmp(const void *arg1, const void *arg2) 3600Sstevel@tonic-gate { 361*211Smike_s nltype **npp1 = (nltype **)arg1; 362*211Smike_s nltype **npp2 = (nltype **)arg2; 3630Sstevel@tonic-gate nltype *np1 = *npp1; 3640Sstevel@tonic-gate nltype *np2 = *npp2; 3650Sstevel@tonic-gate double diff; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate diff = (np1->propself + np1->propchild) - 3680Sstevel@tonic-gate (np2->propself + np2->propchild); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate if (diff < 0.0) 3710Sstevel@tonic-gate return (1); 3720Sstevel@tonic-gate if (diff > 0.0) 3730Sstevel@tonic-gate return (-1); 3740Sstevel@tonic-gate if (np1->name == 0 && np1->cycleno != 0) 3750Sstevel@tonic-gate return (-1); 3760Sstevel@tonic-gate if (np2->name == 0 && np2->cycleno != 0) 3770Sstevel@tonic-gate return (1); 3780Sstevel@tonic-gate if (np1->name == 0) 3790Sstevel@tonic-gate return (-1); 3800Sstevel@tonic-gate if (np2->name == 0) 3810Sstevel@tonic-gate return (1); 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate if (*(np1->name) != '_' && *(np2->name) == '_') 3840Sstevel@tonic-gate return (-1); 3850Sstevel@tonic-gate if (*(np1->name) == '_' && *(np2->name) != '_') 3860Sstevel@tonic-gate return (1); 3870Sstevel@tonic-gate if (np1->ncall > np2->ncall) 3880Sstevel@tonic-gate return (-1); 3890Sstevel@tonic-gate if (np1->ncall < np2->ncall) 3900Sstevel@tonic-gate return (1); 3910Sstevel@tonic-gate return (strcmp(np1->name, np2->name)); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate void 3950Sstevel@tonic-gate printparents(nltype *childp) 3960Sstevel@tonic-gate { 3970Sstevel@tonic-gate nltype *parentp; 3980Sstevel@tonic-gate arctype *arcp; 3990Sstevel@tonic-gate nltype *cycleheadp; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate if (childp->cyclehead != 0) 4020Sstevel@tonic-gate cycleheadp = childp -> cyclehead; 4030Sstevel@tonic-gate else 4040Sstevel@tonic-gate cycleheadp = childp; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (childp->parents == 0) { 407*211Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 4080Sstevel@tonic-gate " <spontaneous>\n", "", "", "", "", "", ""); 4090Sstevel@tonic-gate return; 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate sortparents(childp); 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 4150Sstevel@tonic-gate parentp = arcp -> arc_parentp; 4160Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4170Sstevel@tonic-gate parentp->cycleno == childp->cycleno)) { 4180Sstevel@tonic-gate /* 4190Sstevel@tonic-gate * selfcall or call among siblings 4200Sstevel@tonic-gate */ 421*211Smike_s (void) printf( 422*211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4230Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4240Sstevel@tonic-gate printname(parentp); 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if (Cflag) 4270Sstevel@tonic-gate print_demangled_name(54, parentp); 4280Sstevel@tonic-gate 429*211Smike_s (void) printf("\n"); 4300Sstevel@tonic-gate } else { 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * regular parent of child 4330Sstevel@tonic-gate */ 434*211Smike_s (void) printf( 435*211Smike_s "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 4360Sstevel@tonic-gate "", arcp->arc_time / hz, arcp->arc_childtime / hz, 4370Sstevel@tonic-gate arcp->arc_count, cycleheadp->ncall); 4380Sstevel@tonic-gate printname(parentp); 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate if (Cflag) 4410Sstevel@tonic-gate print_demangled_name(54, parentp); 4420Sstevel@tonic-gate 443*211Smike_s (void) printf("\n"); 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate void 4490Sstevel@tonic-gate printchildren(nltype *parentp) 4500Sstevel@tonic-gate { 4510Sstevel@tonic-gate nltype *childp; 4520Sstevel@tonic-gate arctype *arcp; 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate sortchildren(parentp); 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 4570Sstevel@tonic-gate childp = arcp->arc_childp; 4580Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4590Sstevel@tonic-gate childp->cycleno == parentp->cycleno)) { 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * self call or call to sibling 4620Sstevel@tonic-gate */ 463*211Smike_s (void) printf( 464*211Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4650Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4660Sstevel@tonic-gate printname(childp); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate if (Cflag) 4690Sstevel@tonic-gate print_demangled_name(54, childp); 4700Sstevel@tonic-gate 471*211Smike_s (void) printf("\n"); 4720Sstevel@tonic-gate } else { 4730Sstevel@tonic-gate /* 4740Sstevel@tonic-gate * regular child of parent 4750Sstevel@tonic-gate */ 4760Sstevel@tonic-gate if (childp->cyclehead) 477*211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4780Sstevel@tonic-gate "%7lld/%-7lld ", "", "", 4790Sstevel@tonic-gate arcp->arc_time / hz, 4800Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4810Sstevel@tonic-gate childp->cyclehead->ncall); 4820Sstevel@tonic-gate else 483*211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4840Sstevel@tonic-gate "%7lld %7.7s ", 4850Sstevel@tonic-gate "", "", arcp->arc_time / hz, 4860Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4870Sstevel@tonic-gate ""); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate printname(childp); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate if (Cflag) 4920Sstevel@tonic-gate print_demangled_name(54, childp); 4930Sstevel@tonic-gate 494*211Smike_s (void) printf("\n"); 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate void 5000Sstevel@tonic-gate printname(nltype *selfp) 5010Sstevel@tonic-gate { 5020Sstevel@tonic-gate char *c; 5030Sstevel@tonic-gate c = demangled_name(selfp); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (selfp->name != 0) { 5060Sstevel@tonic-gate if (!Cflag) 507*211Smike_s (void) printf("%s", selfp->name); 5080Sstevel@tonic-gate else 509*211Smike_s (void) printf("%s", c); 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate #ifdef DEBUG 5120Sstevel@tonic-gate if (debug & DFNDEBUG) 513*211Smike_s (void) printf("{%d} ", selfp->toporder); 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate if (debug & PROPDEBUG) 516*211Smike_s (void) printf("%5.2f%% ", selfp->propfraction); 517*211Smike_s #endif /* DEBUG */ 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate if (selfp->cycleno != 0) 521*211Smike_s (void) printf("\t<cycle %d>", selfp->cycleno); 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate if (selfp->index != 0) { 5240Sstevel@tonic-gate if (selfp->printflag) 525*211Smike_s (void) printf(" [%d]", selfp->index); 5260Sstevel@tonic-gate else 527*211Smike_s (void) printf(" (%d)", selfp->index); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate void 5320Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp) 5330Sstevel@tonic-gate { 5340Sstevel@tonic-gate char *c; 5350Sstevel@tonic-gate int i; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate c = selfp->name; 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate if (strcmp(c, demangled_name(selfp)) == 0) 5400Sstevel@tonic-gate return; 5410Sstevel@tonic-gate else { 542*211Smike_s (void) printf("\n"); 5430Sstevel@tonic-gate for (i = 1; i < n; i++) 544*211Smike_s (void) printf(" "); 545*211Smike_s (void) printf("[%s]", selfp->name); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate void 5500Sstevel@tonic-gate sortchildren(nltype *parentp) 5510Sstevel@tonic-gate { 5520Sstevel@tonic-gate arctype *arcp; 5530Sstevel@tonic-gate arctype *detachedp; 5540Sstevel@tonic-gate arctype sorted; 5550Sstevel@tonic-gate arctype *prevp; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate /* 5580Sstevel@tonic-gate * unlink children from parent, 5590Sstevel@tonic-gate * then insertion sort back on to sorted's children. 5600Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 5610Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 5620Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 5630Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 5640Sstevel@tonic-gate */ 5650Sstevel@tonic-gate sorted.arc_childlist = 0; 5660Sstevel@tonic-gate 567*211Smike_s /* LINTED: warning: assignment operator */ 5680Sstevel@tonic-gate for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 5690Sstevel@tonic-gate arcp; 570*211Smike_s /* LINTED: warning: assignment operator */ 5710Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 5720Sstevel@tonic-gate /* 5730Sstevel@tonic-gate * consider *arcp as disconnected 5740Sstevel@tonic-gate * insert it into sorted 5750Sstevel@tonic-gate */ 5760Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_childlist; 5770Sstevel@tonic-gate prevp = prevp->arc_childlist) { 5780Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 5790Sstevel@tonic-gate break; 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate arcp->arc_childlist = prevp->arc_childlist; 5830Sstevel@tonic-gate prevp->arc_childlist = arcp; 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate /* 5870Sstevel@tonic-gate * reattach sorted children to parent 5880Sstevel@tonic-gate */ 5890Sstevel@tonic-gate parentp->children = sorted.arc_childlist; 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate void 5930Sstevel@tonic-gate sortparents(nltype *childp) 5940Sstevel@tonic-gate { 5950Sstevel@tonic-gate arctype *arcp; 5960Sstevel@tonic-gate arctype *detachedp; 5970Sstevel@tonic-gate arctype sorted; 5980Sstevel@tonic-gate arctype *prevp; 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate /* 6010Sstevel@tonic-gate * unlink parents from child, 6020Sstevel@tonic-gate * then insertion sort back on to sorted's parents. 6030Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 6040Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 6050Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 6060Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 6070Sstevel@tonic-gate */ 6080Sstevel@tonic-gate sorted.arc_parentlist = 0; 6090Sstevel@tonic-gate 610*211Smike_s /* LINTED: warning: assignment operator */ 6110Sstevel@tonic-gate for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 6120Sstevel@tonic-gate arcp; 613*211Smike_s /* LINTED: warning: assignment operator */ 6140Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 6150Sstevel@tonic-gate /* 6160Sstevel@tonic-gate * consider *arcp as disconnected 6170Sstevel@tonic-gate * insert it into sorted 6180Sstevel@tonic-gate */ 6190Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_parentlist; 6200Sstevel@tonic-gate prevp = prevp->arc_parentlist) { 6210Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 6220Sstevel@tonic-gate break; 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate arcp->arc_parentlist = prevp->arc_parentlist; 6250Sstevel@tonic-gate prevp->arc_parentlist = arcp; 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate /* 6290Sstevel@tonic-gate * reattach sorted arcs to child 6300Sstevel@tonic-gate */ 6310Sstevel@tonic-gate childp->parents = sorted.arc_parentlist; 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate void 6350Sstevel@tonic-gate printcycle(nltype *cyclep) 6360Sstevel@tonic-gate { 6370Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 6380Sstevel@tonic-gate 639*211Smike_s (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 640*211Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 6410Sstevel@tonic-gate 100 * (cyclep->propself + cyclep->propchild) / printtime, 6420Sstevel@tonic-gate cyclep -> propself / hz, cyclep -> propchild / hz, 6430Sstevel@tonic-gate cyclep -> ncall); 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (cyclep->selfcalls != 0) 646*211Smike_s (void) printf("+%-7lld", cyclep->selfcalls); 6470Sstevel@tonic-gate else 648*211Smike_s (void) printf(" %7.7s", ""); 6490Sstevel@tonic-gate 650*211Smike_s (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 6510Sstevel@tonic-gate cyclep->index); 6520Sstevel@tonic-gate } 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate /* 6550Sstevel@tonic-gate * print the members of a cycle 6560Sstevel@tonic-gate */ 6570Sstevel@tonic-gate void 6580Sstevel@tonic-gate printmembers(nltype *cyclep) 6590Sstevel@tonic-gate { 6600Sstevel@tonic-gate nltype *memberp; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate sortmembers(cyclep); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 665*211Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 6660Sstevel@tonic-gate memberp->propself / hz, memberp->propchild / hz, 6670Sstevel@tonic-gate memberp->ncall); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (memberp->selfcalls != 0) 670*211Smike_s (void) printf("+%-7lld", memberp->selfcalls); 6710Sstevel@tonic-gate else 672*211Smike_s (void) printf(" %7.7s", ""); 6730Sstevel@tonic-gate 674*211Smike_s (void) printf(" "); 6750Sstevel@tonic-gate printname(memberp); 6760Sstevel@tonic-gate if (Cflag) 6770Sstevel@tonic-gate print_demangled_name(54, memberp); 678*211Smike_s (void) printf("\n"); 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate /* 6830Sstevel@tonic-gate * sort members of a cycle 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate void 6860Sstevel@tonic-gate sortmembers(nltype *cyclep) 6870Sstevel@tonic-gate { 6880Sstevel@tonic-gate nltype *todo; 6890Sstevel@tonic-gate nltype *doing; 6900Sstevel@tonic-gate nltype *prev; 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate /* 6930Sstevel@tonic-gate * detach cycle members from cyclehead, 6940Sstevel@tonic-gate * and insertion sort them back on. 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate todo = cyclep->cnext; 6970Sstevel@tonic-gate cyclep->cnext = 0; 6980Sstevel@tonic-gate 699*211Smike_s /* LINTED: warning: assignment operator */ 7000Sstevel@tonic-gate for ((doing = todo) && (todo = doing->cnext); 701*211Smike_s doing; 702*211Smike_s /* LINTED: warning: assignment operator */ 703*211Smike_s (doing = todo) && (todo = doing->cnext)) { 7040Sstevel@tonic-gate for (prev = cyclep; prev->cnext; prev = prev->cnext) { 7050Sstevel@tonic-gate if (membercmp(doing, prev->cnext) == GREATERTHAN) 7060Sstevel@tonic-gate break; 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate doing->cnext = prev->cnext; 7090Sstevel@tonic-gate prev->cnext = doing; 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * major sort is on propself + propchild, 7150Sstevel@tonic-gate * next is sort on ncalls + selfcalls. 7160Sstevel@tonic-gate */ 7170Sstevel@tonic-gate int 7180Sstevel@tonic-gate membercmp(nltype *this, nltype *that) 7190Sstevel@tonic-gate { 7200Sstevel@tonic-gate double thistime = this->propself + this->propchild; 7210Sstevel@tonic-gate double thattime = that->propself + that->propchild; 7220Sstevel@tonic-gate actype thiscalls = this->ncall + this->selfcalls; 7230Sstevel@tonic-gate actype thatcalls = that->ncall + that->selfcalls; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (thistime > thattime) 7260Sstevel@tonic-gate return (GREATERTHAN); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate if (thistime < thattime) 7290Sstevel@tonic-gate return (LESSTHAN); 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate if (thiscalls > thatcalls) 7320Sstevel@tonic-gate return (GREATERTHAN); 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate if (thiscalls < thatcalls) 7350Sstevel@tonic-gate return (LESSTHAN); 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate return (EQUALTO); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate /* 7410Sstevel@tonic-gate * compare two arcs to/from the same child/parent. 7420Sstevel@tonic-gate * - if one arc is a self arc, it's least. 7430Sstevel@tonic-gate * - if one arc is within a cycle, it's less than. 7440Sstevel@tonic-gate * - if both arcs are within a cycle, compare arc counts. 7450Sstevel@tonic-gate * - if neither arc is within a cycle, compare with 7460Sstevel@tonic-gate * arc_time + arc_childtime as major key 7470Sstevel@tonic-gate * arc count as minor key 7480Sstevel@tonic-gate */ 7490Sstevel@tonic-gate int 7500Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp) 7510Sstevel@tonic-gate { 7520Sstevel@tonic-gate nltype *thisparentp = thisp->arc_parentp; 7530Sstevel@tonic-gate nltype *thischildp = thisp->arc_childp; 7540Sstevel@tonic-gate nltype *thatparentp = thatp->arc_parentp; 7550Sstevel@tonic-gate nltype *thatchildp = thatp->arc_childp; 7560Sstevel@tonic-gate double thistime; 7570Sstevel@tonic-gate double thattime; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate #ifdef DEBUG 7600Sstevel@tonic-gate if (debug & TIMEDEBUG) { 761*211Smike_s (void) printf("[arccmp] "); 7620Sstevel@tonic-gate printname(thisparentp); 763*211Smike_s (void) printf(" calls "); 7640Sstevel@tonic-gate printname(thischildp); 765*211Smike_s (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 7660Sstevel@tonic-gate thisp->arc_childtime, thisp->arc_count, 7670Sstevel@tonic-gate thischildp->ncall); 768*211Smike_s (void) printf("[arccmp] "); 7690Sstevel@tonic-gate printname(thatparentp); 770*211Smike_s (void) printf(" calls "); 7710Sstevel@tonic-gate printname(thatchildp); 772*211Smike_s (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 7730Sstevel@tonic-gate thatp->arc_childtime, thatp->arc_count, 7740Sstevel@tonic-gate thatchildp->ncall); 775*211Smike_s (void) printf("\n"); 7760Sstevel@tonic-gate } 777*211Smike_s #endif /* DEBUG */ 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate if (thisparentp == thischildp) { 7800Sstevel@tonic-gate /* 7810Sstevel@tonic-gate * this is a self call 7820Sstevel@tonic-gate */ 7830Sstevel@tonic-gate return (LESSTHAN); 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate if (thatparentp == thatchildp) { 7870Sstevel@tonic-gate /* 7880Sstevel@tonic-gate * that is a self call 7890Sstevel@tonic-gate */ 7900Sstevel@tonic-gate return (GREATERTHAN); 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 7940Sstevel@tonic-gate thisparentp->cycleno == thischildp->cycleno) { 7950Sstevel@tonic-gate /* 7960Sstevel@tonic-gate * this is a call within a cycle 7970Sstevel@tonic-gate */ 7980Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 7990Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 8000Sstevel@tonic-gate /* 8010Sstevel@tonic-gate * that is a call within the cycle, too 8020Sstevel@tonic-gate */ 8030Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8040Sstevel@tonic-gate return (LESSTHAN); 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8070Sstevel@tonic-gate return (GREATERTHAN); 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate return (EQUALTO); 8100Sstevel@tonic-gate } else { 8110Sstevel@tonic-gate /* 8120Sstevel@tonic-gate * that isn't a call within the cycle 8130Sstevel@tonic-gate */ 8140Sstevel@tonic-gate return (LESSTHAN); 8150Sstevel@tonic-gate } 8160Sstevel@tonic-gate } else { 8170Sstevel@tonic-gate /* 8180Sstevel@tonic-gate * this isn't a call within a cycle 8190Sstevel@tonic-gate */ 8200Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 8210Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 8220Sstevel@tonic-gate /* 8230Sstevel@tonic-gate * that is a call within a cycle 8240Sstevel@tonic-gate */ 8250Sstevel@tonic-gate return (GREATERTHAN); 8260Sstevel@tonic-gate } else { 8270Sstevel@tonic-gate /* 8280Sstevel@tonic-gate * neither is a call within a cycle 8290Sstevel@tonic-gate */ 8300Sstevel@tonic-gate thistime = thisp->arc_time + thisp->arc_childtime; 8310Sstevel@tonic-gate thattime = thatp->arc_time + thatp->arc_childtime; 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate if (thistime < thattime) 8340Sstevel@tonic-gate return (LESSTHAN); 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate if (thistime > thattime) 8370Sstevel@tonic-gate return (GREATERTHAN); 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8400Sstevel@tonic-gate return (LESSTHAN); 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8430Sstevel@tonic-gate return (GREATERTHAN); 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate return (EQUALTO); 8460Sstevel@tonic-gate } 8470Sstevel@tonic-gate } 8480Sstevel@tonic-gate } 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate void 8510Sstevel@tonic-gate printblurb(char *blurbname) 8520Sstevel@tonic-gate { 8530Sstevel@tonic-gate FILE *blurbfile; 8540Sstevel@tonic-gate int input; 8550Sstevel@tonic-gate char blurb_directory[MAXPATHLEN]; 8560Sstevel@tonic-gate char cwd[MAXPATHLEN]; 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate cwd[0] = '.'; 8590Sstevel@tonic-gate cwd[1] = '\0'; 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate if (find_run_directory(prog_name, cwd, blurb_directory, 8620Sstevel@tonic-gate NULL, getenv("PATH")) != 0) { 8630Sstevel@tonic-gate (void) fprintf(stderr, "Error in finding run directory."); 8640Sstevel@tonic-gate return; 8650Sstevel@tonic-gate } else { 866*211Smike_s (void) strcat(blurb_directory, blurbname); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate blurbfile = fopen(blurb_directory, "r"); 8700Sstevel@tonic-gate if (blurbfile == NULL) { 8710Sstevel@tonic-gate perror(blurb_directory); 8720Sstevel@tonic-gate return; 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate while ((input = getc(blurbfile)) != EOF) 876*211Smike_s (void) putchar(input); 8770Sstevel@tonic-gate 878*211Smike_s (void) fclose(blurbfile); 8790Sstevel@tonic-gate } 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate char *s1, *s2; 8820Sstevel@tonic-gate 883*211Smike_s static int 884*211Smike_s namecmp(const void *arg1, const void *arg2) 8850Sstevel@tonic-gate { 886*211Smike_s nltype **npp1 = (nltype **)arg1; 887*211Smike_s nltype **npp2 = (nltype **)arg2; 888*211Smike_s 8890Sstevel@tonic-gate if (!Cflag) 8900Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 8910Sstevel@tonic-gate else { 8920Sstevel@tonic-gate striped_name(s1, npp1); 8930Sstevel@tonic-gate striped_name(s2, npp2); 8940Sstevel@tonic-gate return (strcmp(s1, s2)); 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate } 8970Sstevel@tonic-gate 8980Sstevel@tonic-gate void 8990Sstevel@tonic-gate striped_name(char *s, nltype **npp) 9000Sstevel@tonic-gate { 9010Sstevel@tonic-gate char *d, *c; 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate c = (char *)s; 9040Sstevel@tonic-gate d = demangled_name(*npp); 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate while ((*d != '(') && (*d != '\0')) { 9070Sstevel@tonic-gate if (*d != ':') 9080Sstevel@tonic-gate *c++ = *d++; 9090Sstevel@tonic-gate else 9100Sstevel@tonic-gate d++; 9110Sstevel@tonic-gate } 9120Sstevel@tonic-gate *c = '\0'; 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate /* 9160Sstevel@tonic-gate * Checks if the current symbol name is the same as its neighbour and 9170Sstevel@tonic-gate * returns TRUE if it is. 9180Sstevel@tonic-gate */ 9190Sstevel@tonic-gate static bool 9200Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames) 9210Sstevel@tonic-gate { 9220Sstevel@tonic-gate /* 9230Sstevel@tonic-gate * same as previous (if there's one) ? 9240Sstevel@tonic-gate */ 9250Sstevel@tonic-gate if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 9260Sstevel@tonic-gate return (TRUE); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate /* 9290Sstevel@tonic-gate * same as next (if there's one) ? 9300Sstevel@tonic-gate */ 9310Sstevel@tonic-gate if ((ndx < (nnames - 1)) && 9320Sstevel@tonic-gate (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 9330Sstevel@tonic-gate return (TRUE); 9340Sstevel@tonic-gate } 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate return (FALSE); 9370Sstevel@tonic-gate } 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate void 9400Sstevel@tonic-gate printmodules() 9410Sstevel@tonic-gate { 9420Sstevel@tonic-gate mod_info_t *mi; 9430Sstevel@tonic-gate 944*211Smike_s (void) printf("\f\nObject modules\n\n"); 9450Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) 946*211Smike_s (void) printf(" %d: %s\n", mi->id, mi->name); 9470Sstevel@tonic-gate } 9480Sstevel@tonic-gate 9490Sstevel@tonic-gate #define IDFMT(id) ((id) < 10 ? 1 : 2) 9500Sstevel@tonic-gate #define NMFMT(id) ((id) < 10 ? 17 : 16) 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate void 9530Sstevel@tonic-gate printindex() 9540Sstevel@tonic-gate { 9550Sstevel@tonic-gate nltype **namesortnlp; 9560Sstevel@tonic-gate nltype *nlp; 9570Sstevel@tonic-gate int index, nnames, todo, i, j; 9580Sstevel@tonic-gate char peterbuffer[BUFSIZ]; 9590Sstevel@tonic-gate mod_info_t *mi; 9600Sstevel@tonic-gate 9610Sstevel@tonic-gate /* 9620Sstevel@tonic-gate * Now, sort regular function name alphabetically 9630Sstevel@tonic-gate * to create an index. 9640Sstevel@tonic-gate */ 9650Sstevel@tonic-gate namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate if (namesortnlp == NULL) 968*211Smike_s (void) fprintf(stderr, "%s: ran out of memory for sorting\n", 969*211Smike_s whoami); 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate nnames = 0; 9720Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 9730Sstevel@tonic-gate for (index = 0; index < mi->nname; index++) { 9740Sstevel@tonic-gate if (zflag == 0 && (mi->nl[index]).ncall == 0 && 9750Sstevel@tonic-gate (mi->nl[index]).time == 0) { 9760Sstevel@tonic-gate continue; 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate /* 9800Sstevel@tonic-gate * Do not print certain special symbols, like 9810Sstevel@tonic-gate * PRF_EXTSYM, etc. even if zflag was on. 9820Sstevel@tonic-gate */ 9830Sstevel@tonic-gate if (is_special_sym(&(mi->nl[index]))) 9840Sstevel@tonic-gate continue; 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate namesortnlp[nnames++] = &(mi->nl[index]); 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate } 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate if (Cflag) { 9910Sstevel@tonic-gate s1 = malloc(500 * sizeof (char)); 9920Sstevel@tonic-gate s2 = malloc(500 * sizeof (char)); 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 995*211Smike_s qsort(namesortnlp, nnames, sizeof (nltype *), namecmp); 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate for (index = 1, todo = nnames; index <= ncycle; index++) 9980Sstevel@tonic-gate namesortnlp[todo++] = &cyclenl[index]; 9990Sstevel@tonic-gate 1000*211Smike_s (void) printf("\f\nIndex by function name\n\n"); 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate if (!Cflag) 10030Sstevel@tonic-gate index = (todo + 2) / 3; 10040Sstevel@tonic-gate else 10050Sstevel@tonic-gate index = todo; 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate for (i = 0; i < index; i++) { 10080Sstevel@tonic-gate if (!Cflag) { 10090Sstevel@tonic-gate for (j = i; j < todo; j += index) { 10100Sstevel@tonic-gate nlp = namesortnlp[j]; 10110Sstevel@tonic-gate 10120Sstevel@tonic-gate if (nlp->printflag) { 1013*211Smike_s (void) sprintf(peterbuffer, 10140Sstevel@tonic-gate "[%d]", nlp->index); 10150Sstevel@tonic-gate } else { 1016*211Smike_s (void) sprintf(peterbuffer, 10170Sstevel@tonic-gate "(%d)", nlp->index); 10180Sstevel@tonic-gate } 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate if (j < nnames) { 10210Sstevel@tonic-gate if (does_clash(namesortnlp, 10220Sstevel@tonic-gate j, nnames)) { 1023*211Smike_s (void) printf( 1024*211Smike_s "%6.6s %*d:%-*.*s", 10250Sstevel@tonic-gate peterbuffer, 10260Sstevel@tonic-gate IDFMT(nlp->module->id), 10270Sstevel@tonic-gate nlp->module->id, 10280Sstevel@tonic-gate NMFMT(nlp->module->id), 10290Sstevel@tonic-gate NMFMT(nlp->module->id), 10300Sstevel@tonic-gate nlp->name); 10310Sstevel@tonic-gate } else { 1032*211Smike_s (void) printf("%6.6s %-19.19s", 10330Sstevel@tonic-gate peterbuffer, nlp->name); 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate } else { 1036*211Smike_s (void) printf("%6.6s ", peterbuffer); 1037*211Smike_s (void) sprintf(peterbuffer, 10380Sstevel@tonic-gate "<cycle %d>", nlp->cycleno); 1039*211Smike_s (void) printf("%-19.19s", peterbuffer); 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate } 10420Sstevel@tonic-gate } else { 10430Sstevel@tonic-gate nlp = namesortnlp[i]; 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate if (nlp->printflag) 1046*211Smike_s (void) sprintf(peterbuffer, "[%d]", nlp->index); 10470Sstevel@tonic-gate else 1048*211Smike_s (void) sprintf(peterbuffer, "(%d)", nlp->index); 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate if (i < nnames) { 10510Sstevel@tonic-gate char *d = demangled_name(nlp); 10520Sstevel@tonic-gate 10530Sstevel@tonic-gate if (does_clash(namesortnlp, i, nnames)) { 1054*211Smike_s (void) printf("%6.6s %d:%s\n", 1055*211Smike_s peterbuffer, nlp->module->id, d); 10560Sstevel@tonic-gate } else 1057*211Smike_s (void) printf("%6.6s %s\n", peterbuffer, 1058*211Smike_s d); 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate if (d != nlp->name) 1061*211Smike_s (void) printf("%6.6s [%s]", "", 1062*211Smike_s nlp->name); 10630Sstevel@tonic-gate } else { 1064*211Smike_s (void) printf("%6.6s ", peterbuffer); 1065*211Smike_s (void) sprintf(peterbuffer, "<cycle %d>", 10660Sstevel@tonic-gate nlp->cycleno); 1067*211Smike_s (void) printf("%-33.33s", peterbuffer); 10680Sstevel@tonic-gate } 10690Sstevel@tonic-gate } 1070*211Smike_s (void) printf("\n"); 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate free(namesortnlp); 10730Sstevel@tonic-gate } 1074