1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <ctype.h> 30 #include <string.h> 31 #include <sys/param.h> 32 #include <stdlib.h> 33 #include "conv.h" 34 #include "gprof.h" 35 36 void print_demangled_name(int, nltype *); 37 void striped_name(char *, nltype **); 38 39 extern long hz; 40 41 /* 42 * Symbols that must never be printed, no matter what. 43 */ 44 char *splsym[] = { 45 PRF_ETEXT, 46 PRF_EXTSYM, 47 PRF_MEMTERM, 48 NULL 49 }; 50 51 static bool is_special_sym(nltype *nlp); 52 53 const char * 54 demangled_name(nltype *selfp) 55 { 56 if (!Cflag) 57 return (selfp->name); 58 59 return (conv_demangle_name(selfp->name)); 60 } 61 62 void 63 printprof(void) 64 { 65 nltype *np; 66 nltype **sortednlp; 67 int i, index; 68 int print_count = number_funcs_toprint; 69 bool print_flag = TRUE; 70 mod_info_t *mi; 71 72 actime = 0.0; 73 (void) printf("\f\n"); 74 flatprofheader(); 75 76 /* 77 * Sort the symbol table in by time 78 */ 79 sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 80 if (sortednlp == (nltype **) 0) { 81 (void) fprintf(stderr, 82 "[printprof] ran out of memory for time sorting\n"); 83 } 84 85 index = 0; 86 for (mi = &modules; mi; mi = mi->next) { 87 for (i = 0; i < mi->nname; i++) 88 sortednlp[index++] = &(mi->nl[i]); 89 } 90 91 qsort(sortednlp, total_names, sizeof (nltype *), timecmp); 92 93 for (index = 0; (index < total_names) && print_flag; index += 1) { 94 np = sortednlp[index]; 95 flatprofline(np); 96 if (nflag) { 97 if (--print_count == 0) 98 print_flag = FALSE; 99 } 100 } 101 actime = 0.0; 102 free(sortednlp); 103 } 104 105 int 106 timecmp(const void *arg1, const void *arg2) 107 { 108 nltype **npp1 = (nltype **)arg1; 109 nltype **npp2 = (nltype **)arg2; 110 double timediff; 111 long calldiff; 112 113 timediff = (*npp2)->time - (*npp1)->time; 114 115 if (timediff > 0.0) 116 return (1); 117 118 if (timediff < 0.0) 119 return (-1); 120 121 calldiff = (*npp2)->ncall - (*npp1)->ncall; 122 123 if (calldiff > 0) 124 return (1); 125 126 if (calldiff < 0) 127 return (-1); 128 129 return (strcmp((*npp1)->name, (*npp2)->name)); 130 } 131 132 /* 133 * header for flatprofline 134 */ 135 void 136 flatprofheader() 137 { 138 139 if (bflag) 140 printblurb(FLAT_BLURB); 141 142 if (old_style) { 143 (void) printf( 144 "\ngranularity: each sample hit covers %d byte(s)", 145 (long)scale * sizeof (UNIT)); 146 if (totime > 0.0) { 147 (void) printf(" for %.2f%% of %.2f seconds\n\n", 148 100.0/totime, totime / hz); 149 } else { 150 (void) printf(" no time accumulated\n\n"); 151 /* 152 * this doesn't hurt since all the numerators will 153 * be zero. 154 */ 155 totime = 1.0; 156 } 157 } 158 159 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 160 "% ", "cumulative", "self ", "", "self ", "total ", ""); 161 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 162 "time", "seconds ", "seconds", "calls", 163 "ms/call", "ms/call", "name"); 164 } 165 166 void 167 flatprofline(nltype *np) 168 { 169 if (zflag == 0 && np->ncall == 0 && np->time == 0) 170 return; 171 172 /* 173 * Do not print certain special symbols, like PRF_EXTSYM, etc. 174 * even if zflag was on. 175 */ 176 if (is_special_sym(np)) 177 return; 178 179 actime += np->time; 180 181 (void) printf("%5.1f %10.2f %8.2f", 182 100 * np->time / totime, actime / hz, np->time / hz); 183 184 if (np->ncall != 0) { 185 (void) printf(" %8lld %8.2f %8.2f ", np->ncall, 186 1000 * np->time / hz / np->ncall, 187 1000 * (np->time + np->childtime) / hz / np->ncall); 188 } else { 189 if (!Cflag) 190 (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 191 else 192 (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 193 } 194 195 printname(np); 196 197 if (Cflag) 198 print_demangled_name(55, np); 199 200 (void) printf("\n"); 201 } 202 203 void 204 gprofheader() 205 { 206 207 if (bflag) 208 printblurb(CALLG_BLURB); 209 210 if (old_style) { 211 212 (void) printf( 213 "\ngranularity: each sample hit covers %d byte(s)", 214 (long)scale * sizeof (UNIT)); 215 216 if (printtime > 0.0) { 217 (void) printf(" for %.2f%% of %.2f seconds\n\n", 218 100.0/printtime, printtime / hz); 219 } else { 220 (void) printf(" no time propagated\n\n"); 221 /* 222 * this doesn't hurt, since all the numerators 223 * will be 0.0 224 */ 225 printtime = 1.0; 226 } 227 } else { 228 (void) printf( 229 "\ngranularity: each pc-hit is considered 1 tick"); 230 if (hz != 1) { 231 (void) printf(" (@ %4.3f seconds per tick)", 232 (double)1.0 / hz); 233 } 234 (void) puts("\n\n"); 235 } 236 237 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 238 "", "", "", "", "called", "total", "parents"); 239 (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", 240 "index", "%time", "self", "descendents", 241 "called", "self", "name", "index"); 242 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 243 "", "", "", "", "called", "total", "children"); 244 (void) printf("\n"); 245 } 246 247 void 248 gprofline(nltype *np) 249 { 250 char kirkbuffer[BUFSIZ]; 251 252 (void) sprintf(kirkbuffer, "[%d]", np->index); 253 (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer, 254 100 * (np->propself + np->propchild) / printtime, 255 np->propself / hz, np->propchild / hz); 256 257 if ((np->ncall + np->selfcalls) != 0) { 258 (void) printf(" %7lld", np->ncall); 259 260 if (np->selfcalls != 0) 261 (void) printf("+%-7lld ", np->selfcalls); 262 else 263 (void) printf(" %7.7s ", ""); 264 } else { 265 (void) printf(" %7.7s %7.7s ", "", ""); 266 } 267 268 printname(np); 269 270 if (Cflag) 271 print_demangled_name(50, np); 272 273 (void) printf("\n"); 274 } 275 276 static bool 277 is_special_sym(nltype *nlp) 278 { 279 int i; 280 281 if (nlp->name == NULL) 282 return (FALSE); 283 284 for (i = 0; splsym[i]; i++) 285 if (strcmp(splsym[i], nlp->name) == 0) 286 return (TRUE); 287 288 return (FALSE); 289 } 290 291 void 292 printgprof(nltype **timesortnlp) 293 { 294 int index; 295 nltype *parentp; 296 int print_count = number_funcs_toprint; 297 bool count_flag = TRUE; 298 299 /* 300 * Print out the structured profiling list 301 */ 302 gprofheader(); 303 304 for (index = 0; index < total_names + ncycle && count_flag; index++) { 305 parentp = timesortnlp[index]; 306 if (zflag == 0 && parentp->ncall == 0 && 307 parentp->selfcalls == 0 && parentp->propself == 0 && 308 parentp -> propchild == 0) 309 continue; 310 311 if (!parentp->printflag) 312 continue; 313 314 /* 315 * Do not print certain special symbols, like PRF_EXTSYM, etc. 316 * even if zflag was on. 317 */ 318 if (is_special_sym(parentp)) 319 continue; 320 321 if (parentp->name == 0 && parentp->cycleno != 0) { 322 /* 323 * cycle header 324 */ 325 printcycle(parentp); 326 printmembers(parentp); 327 } else { 328 printparents(parentp); 329 gprofline(parentp); 330 printchildren(parentp); 331 } 332 333 (void) printf("\n"); 334 (void) printf( 335 "-----------------------------------------------\n"); 336 (void) printf("\n"); 337 338 if (nflag) { 339 --print_count; 340 if (print_count == 0) 341 count_flag = FALSE; 342 } 343 } 344 free(timesortnlp); 345 } 346 347 /* 348 * sort by decreasing propagated time 349 * if times are equal, but one is a cycle header, 350 * say that's first (e.g. less, i.e. -1). 351 * if one's name doesn't have an underscore and the other does, 352 * say the one is first. 353 * all else being equal, sort by names. 354 */ 355 int 356 totalcmp(const void *arg1, const void *arg2) 357 { 358 nltype **npp1 = (nltype **)arg1; 359 nltype **npp2 = (nltype **)arg2; 360 nltype *np1 = *npp1; 361 nltype *np2 = *npp2; 362 double diff; 363 364 diff = (np1->propself + np1->propchild) - 365 (np2->propself + np2->propchild); 366 367 if (diff < 0.0) 368 return (1); 369 if (diff > 0.0) 370 return (-1); 371 if (np1->name == 0 && np1->cycleno != 0) 372 return (-1); 373 if (np2->name == 0 && np2->cycleno != 0) 374 return (1); 375 if (np1->name == 0) 376 return (-1); 377 if (np2->name == 0) 378 return (1); 379 380 if (*(np1->name) != '_' && *(np2->name) == '_') 381 return (-1); 382 if (*(np1->name) == '_' && *(np2->name) != '_') 383 return (1); 384 if (np1->ncall > np2->ncall) 385 return (-1); 386 if (np1->ncall < np2->ncall) 387 return (1); 388 return (strcmp(np1->name, np2->name)); 389 } 390 391 void 392 printparents(nltype *childp) 393 { 394 nltype *parentp; 395 arctype *arcp; 396 nltype *cycleheadp; 397 398 if (childp->cyclehead != 0) 399 cycleheadp = childp -> cyclehead; 400 else 401 cycleheadp = childp; 402 403 if (childp->parents == 0) { 404 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 405 " <spontaneous>\n", "", "", "", "", "", ""); 406 return; 407 } 408 409 sortparents(childp); 410 411 for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 412 parentp = arcp -> arc_parentp; 413 if (childp == parentp || (childp->cycleno != 0 && 414 parentp->cycleno == childp->cycleno)) { 415 /* 416 * selfcall or call among siblings 417 */ 418 (void) printf( 419 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 420 "", "", "", "", arcp->arc_count, ""); 421 printname(parentp); 422 423 if (Cflag) 424 print_demangled_name(54, parentp); 425 426 (void) printf("\n"); 427 } else { 428 /* 429 * regular parent of child 430 */ 431 (void) printf( 432 "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 433 "", arcp->arc_time / hz, arcp->arc_childtime / hz, 434 arcp->arc_count, cycleheadp->ncall); 435 printname(parentp); 436 437 if (Cflag) 438 print_demangled_name(54, parentp); 439 440 (void) printf("\n"); 441 } 442 } 443 } 444 445 void 446 printchildren(nltype *parentp) 447 { 448 nltype *childp; 449 arctype *arcp; 450 451 sortchildren(parentp); 452 453 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 454 childp = arcp->arc_childp; 455 if (childp == parentp || (childp->cycleno != 0 && 456 childp->cycleno == parentp->cycleno)) { 457 /* 458 * self call or call to sibling 459 */ 460 (void) printf( 461 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 462 "", "", "", "", arcp->arc_count, ""); 463 printname(childp); 464 465 if (Cflag) 466 print_demangled_name(54, childp); 467 468 (void) printf("\n"); 469 } else { 470 /* 471 * regular child of parent 472 */ 473 if (childp->cyclehead) 474 (void) printf("%6.6s %5.5s %7.2f %11.2f " 475 "%7lld/%-7lld ", "", "", 476 arcp->arc_time / hz, 477 arcp->arc_childtime / hz, arcp->arc_count, 478 childp->cyclehead->ncall); 479 else 480 (void) printf("%6.6s %5.5s %7.2f %11.2f " 481 "%7lld %7.7s ", 482 "", "", arcp->arc_time / hz, 483 arcp->arc_childtime / hz, arcp->arc_count, 484 ""); 485 486 printname(childp); 487 488 if (Cflag) 489 print_demangled_name(54, childp); 490 491 (void) printf("\n"); 492 } 493 } 494 } 495 496 void 497 printname(nltype *selfp) 498 { 499 const char *c; 500 c = demangled_name(selfp); 501 502 if (selfp->name != 0) { 503 if (!Cflag) 504 (void) printf("%s", selfp->name); 505 else 506 (void) printf("%s", c); 507 508 #ifdef DEBUG 509 if (debug & DFNDEBUG) 510 (void) printf("{%d} ", selfp->toporder); 511 512 if (debug & PROPDEBUG) 513 (void) printf("%5.2f%% ", selfp->propfraction); 514 #endif /* DEBUG */ 515 } 516 517 if (selfp->cycleno != 0) 518 (void) printf("\t<cycle %d>", selfp->cycleno); 519 520 if (selfp->index != 0) { 521 if (selfp->printflag) 522 (void) printf(" [%d]", selfp->index); 523 else 524 (void) printf(" (%d)", selfp->index); 525 } 526 } 527 528 void 529 print_demangled_name(int n, nltype *selfp) 530 { 531 char *c; 532 int i; 533 534 c = selfp->name; 535 536 if (strcmp(c, demangled_name(selfp)) == 0) 537 return; 538 else { 539 (void) printf("\n"); 540 for (i = 1; i < n; i++) 541 (void) printf(" "); 542 (void) printf("[%s]", selfp->name); 543 } 544 } 545 546 void 547 sortchildren(nltype *parentp) 548 { 549 arctype *arcp; 550 arctype *detachedp; 551 arctype sorted; 552 arctype *prevp; 553 554 /* 555 * unlink children from parent, 556 * then insertion sort back on to sorted's children. 557 * *arcp the arc you have detached and are inserting. 558 * *detachedp the rest of the arcs to be sorted. 559 * sorted arc list onto which you insertion sort. 560 * *prevp arc before the arc you are comparing. 561 */ 562 sorted.arc_childlist = 0; 563 564 /* LINTED: warning: assignment operator */ 565 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 566 arcp; 567 /* LINTED: warning: assignment operator */ 568 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 569 /* 570 * consider *arcp as disconnected 571 * insert it into sorted 572 */ 573 for (prevp = &sorted; prevp->arc_childlist; 574 prevp = prevp->arc_childlist) { 575 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 576 break; 577 } 578 579 arcp->arc_childlist = prevp->arc_childlist; 580 prevp->arc_childlist = arcp; 581 } 582 583 /* 584 * reattach sorted children to parent 585 */ 586 parentp->children = sorted.arc_childlist; 587 } 588 589 void 590 sortparents(nltype *childp) 591 { 592 arctype *arcp; 593 arctype *detachedp; 594 arctype sorted; 595 arctype *prevp; 596 597 /* 598 * unlink parents from child, 599 * then insertion sort back on to sorted's parents. 600 * *arcp the arc you have detached and are inserting. 601 * *detachedp the rest of the arcs to be sorted. 602 * sorted arc list onto which you insertion sort. 603 * *prevp arc before the arc you are comparing. 604 */ 605 sorted.arc_parentlist = 0; 606 607 /* LINTED: warning: assignment operator */ 608 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 609 arcp; 610 /* LINTED: warning: assignment operator */ 611 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 612 /* 613 * consider *arcp as disconnected 614 * insert it into sorted 615 */ 616 for (prevp = &sorted; prevp->arc_parentlist; 617 prevp = prevp->arc_parentlist) { 618 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 619 break; 620 } 621 arcp->arc_parentlist = prevp->arc_parentlist; 622 prevp->arc_parentlist = arcp; 623 } 624 625 /* 626 * reattach sorted arcs to child 627 */ 628 childp->parents = sorted.arc_parentlist; 629 } 630 631 void 632 printcycle(nltype *cyclep) 633 { 634 char kirkbuffer[BUFSIZ]; 635 636 (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 637 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 638 100 * (cyclep->propself + cyclep->propchild) / printtime, 639 cyclep -> propself / hz, cyclep -> propchild / hz, 640 cyclep -> ncall); 641 642 if (cyclep->selfcalls != 0) 643 (void) printf("+%-7lld", cyclep->selfcalls); 644 else 645 (void) printf(" %7.7s", ""); 646 647 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 648 cyclep->index); 649 } 650 651 /* 652 * print the members of a cycle 653 */ 654 void 655 printmembers(nltype *cyclep) 656 { 657 nltype *memberp; 658 659 sortmembers(cyclep); 660 661 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 662 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 663 memberp->propself / hz, memberp->propchild / hz, 664 memberp->ncall); 665 666 if (memberp->selfcalls != 0) 667 (void) printf("+%-7lld", memberp->selfcalls); 668 else 669 (void) printf(" %7.7s", ""); 670 671 (void) printf(" "); 672 printname(memberp); 673 if (Cflag) 674 print_demangled_name(54, memberp); 675 (void) printf("\n"); 676 } 677 } 678 679 /* 680 * sort members of a cycle 681 */ 682 void 683 sortmembers(nltype *cyclep) 684 { 685 nltype *todo; 686 nltype *doing; 687 nltype *prev; 688 689 /* 690 * detach cycle members from cyclehead, 691 * and insertion sort them back on. 692 */ 693 todo = cyclep->cnext; 694 cyclep->cnext = 0; 695 696 /* LINTED: warning: assignment operator */ 697 for ((doing = todo) && (todo = doing->cnext); 698 doing; 699 /* LINTED: warning: assignment operator */ 700 (doing = todo) && (todo = doing->cnext)) { 701 for (prev = cyclep; prev->cnext; prev = prev->cnext) { 702 if (membercmp(doing, prev->cnext) == GREATERTHAN) 703 break; 704 } 705 doing->cnext = prev->cnext; 706 prev->cnext = doing; 707 } 708 } 709 710 /* 711 * major sort is on propself + propchild, 712 * next is sort on ncalls + selfcalls. 713 */ 714 int 715 membercmp(nltype *this, nltype *that) 716 { 717 double thistime = this->propself + this->propchild; 718 double thattime = that->propself + that->propchild; 719 actype thiscalls = this->ncall + this->selfcalls; 720 actype thatcalls = that->ncall + that->selfcalls; 721 722 if (thistime > thattime) 723 return (GREATERTHAN); 724 725 if (thistime < thattime) 726 return (LESSTHAN); 727 728 if (thiscalls > thatcalls) 729 return (GREATERTHAN); 730 731 if (thiscalls < thatcalls) 732 return (LESSTHAN); 733 734 return (EQUALTO); 735 } 736 737 /* 738 * compare two arcs to/from the same child/parent. 739 * - if one arc is a self arc, it's least. 740 * - if one arc is within a cycle, it's less than. 741 * - if both arcs are within a cycle, compare arc counts. 742 * - if neither arc is within a cycle, compare with 743 * arc_time + arc_childtime as major key 744 * arc count as minor key 745 */ 746 int 747 arccmp(arctype *thisp, arctype *thatp) 748 { 749 nltype *thisparentp = thisp->arc_parentp; 750 nltype *thischildp = thisp->arc_childp; 751 nltype *thatparentp = thatp->arc_parentp; 752 nltype *thatchildp = thatp->arc_childp; 753 double thistime; 754 double thattime; 755 756 #ifdef DEBUG 757 if (debug & TIMEDEBUG) { 758 (void) printf("[arccmp] "); 759 printname(thisparentp); 760 (void) printf(" calls "); 761 printname(thischildp); 762 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 763 thisp->arc_childtime, thisp->arc_count, 764 thischildp->ncall); 765 (void) printf("[arccmp] "); 766 printname(thatparentp); 767 (void) printf(" calls "); 768 printname(thatchildp); 769 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 770 thatp->arc_childtime, thatp->arc_count, 771 thatchildp->ncall); 772 (void) printf("\n"); 773 } 774 #endif /* DEBUG */ 775 776 if (thisparentp == thischildp) { 777 /* 778 * this is a self call 779 */ 780 return (LESSTHAN); 781 } 782 783 if (thatparentp == thatchildp) { 784 /* 785 * that is a self call 786 */ 787 return (GREATERTHAN); 788 } 789 790 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 791 thisparentp->cycleno == thischildp->cycleno) { 792 /* 793 * this is a call within a cycle 794 */ 795 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 796 thatparentp->cycleno == thatchildp->cycleno) { 797 /* 798 * that is a call within the cycle, too 799 */ 800 if (thisp->arc_count < thatp->arc_count) 801 return (LESSTHAN); 802 803 if (thisp->arc_count > thatp->arc_count) 804 return (GREATERTHAN); 805 806 return (EQUALTO); 807 } else { 808 /* 809 * that isn't a call within the cycle 810 */ 811 return (LESSTHAN); 812 } 813 } else { 814 /* 815 * this isn't a call within a cycle 816 */ 817 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 818 thatparentp->cycleno == thatchildp->cycleno) { 819 /* 820 * that is a call within a cycle 821 */ 822 return (GREATERTHAN); 823 } else { 824 /* 825 * neither is a call within a cycle 826 */ 827 thistime = thisp->arc_time + thisp->arc_childtime; 828 thattime = thatp->arc_time + thatp->arc_childtime; 829 830 if (thistime < thattime) 831 return (LESSTHAN); 832 833 if (thistime > thattime) 834 return (GREATERTHAN); 835 836 if (thisp->arc_count < thatp->arc_count) 837 return (LESSTHAN); 838 839 if (thisp->arc_count > thatp->arc_count) 840 return (GREATERTHAN); 841 842 return (EQUALTO); 843 } 844 } 845 } 846 847 void 848 printblurb(char *blurbname) 849 { 850 FILE *blurbfile; 851 int input; 852 853 blurbfile = fopen(blurbname, "r"); 854 if (blurbfile == NULL) { 855 perror(blurbname); 856 return; 857 } 858 859 while ((input = getc(blurbfile)) != EOF) 860 (void) putchar(input); 861 862 (void) fclose(blurbfile); 863 } 864 865 char *s1, *s2; 866 867 static int 868 namecmp(const void *arg1, const void *arg2) 869 { 870 nltype **npp1 = (nltype **)arg1; 871 nltype **npp2 = (nltype **)arg2; 872 873 if (!Cflag) 874 return (strcmp((*npp1)->name, (*npp2)->name)); 875 else { 876 striped_name(s1, npp1); 877 striped_name(s2, npp2); 878 return (strcmp(s1, s2)); 879 } 880 } 881 882 void 883 striped_name(char *s, nltype **npp) 884 { 885 const char *d; 886 char *c; 887 888 c = (char *)s; 889 d = demangled_name(*npp); 890 891 while ((*d != '(') && (*d != '\0')) { 892 if (*d != ':') 893 *c++ = *d++; 894 else 895 d++; 896 } 897 *c = '\0'; 898 } 899 900 /* 901 * Checks if the current symbol name is the same as its neighbour and 902 * returns TRUE if it is. 903 */ 904 static bool 905 does_clash(nltype **nlp, int ndx, int nnames) 906 { 907 /* 908 * same as previous (if there's one) ? 909 */ 910 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 911 return (TRUE); 912 913 /* 914 * same as next (if there's one) ? 915 */ 916 if ((ndx < (nnames - 1)) && 917 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 918 return (TRUE); 919 } 920 921 return (FALSE); 922 } 923 924 void 925 printmodules() 926 { 927 mod_info_t *mi; 928 929 (void) printf("\f\nObject modules\n\n"); 930 for (mi = &modules; mi; mi = mi->next) 931 (void) printf(" %d: %s\n", mi->id, mi->name); 932 } 933 934 #define IDFMT(id) ((id) < 10 ? 1 : 2) 935 #define NMFMT(id) ((id) < 10 ? 17 : 16) 936 937 void 938 printindex() 939 { 940 nltype **namesortnlp; 941 nltype *nlp; 942 int index, nnames, todo, i, j; 943 char peterbuffer[BUFSIZ]; 944 mod_info_t *mi; 945 946 /* 947 * Now, sort regular function name alphabetically 948 * to create an index. 949 */ 950 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 951 952 if (namesortnlp == NULL) 953 (void) fprintf(stderr, "%s: ran out of memory for sorting\n", 954 whoami); 955 956 nnames = 0; 957 for (mi = &modules; mi; mi = mi->next) { 958 for (index = 0; index < mi->nname; index++) { 959 if (zflag == 0 && (mi->nl[index]).ncall == 0 && 960 (mi->nl[index]).time == 0) { 961 continue; 962 } 963 964 /* 965 * Do not print certain special symbols, like 966 * PRF_EXTSYM, etc. even if zflag was on. 967 */ 968 if (is_special_sym(&(mi->nl[index]))) 969 continue; 970 971 namesortnlp[nnames++] = &(mi->nl[index]); 972 } 973 } 974 975 if (Cflag) { 976 s1 = malloc(500 * sizeof (char)); 977 s2 = malloc(500 * sizeof (char)); 978 } 979 980 qsort(namesortnlp, nnames, sizeof (nltype *), namecmp); 981 982 for (index = 1, todo = nnames; index <= ncycle; index++) 983 namesortnlp[todo++] = &cyclenl[index]; 984 985 (void) printf("\f\nIndex by function name\n\n"); 986 987 if (!Cflag) 988 index = (todo + 2) / 3; 989 else 990 index = todo; 991 992 for (i = 0; i < index; i++) { 993 if (!Cflag) { 994 for (j = i; j < todo; j += index) { 995 nlp = namesortnlp[j]; 996 997 if (nlp->printflag) { 998 (void) sprintf(peterbuffer, 999 "[%d]", nlp->index); 1000 } else { 1001 (void) sprintf(peterbuffer, 1002 "(%d)", nlp->index); 1003 } 1004 1005 if (j < nnames) { 1006 if (does_clash(namesortnlp, 1007 j, nnames)) { 1008 (void) printf( 1009 "%6.6s %*d:%-*.*s", 1010 peterbuffer, 1011 IDFMT(nlp->module->id), 1012 nlp->module->id, 1013 NMFMT(nlp->module->id), 1014 NMFMT(nlp->module->id), 1015 nlp->name); 1016 } else { 1017 (void) printf("%6.6s %-19.19s", 1018 peterbuffer, nlp->name); 1019 } 1020 } else { 1021 (void) printf("%6.6s ", peterbuffer); 1022 (void) sprintf(peterbuffer, 1023 "<cycle %d>", nlp->cycleno); 1024 (void) printf("%-19.19s", peterbuffer); 1025 } 1026 } 1027 } else { 1028 nlp = namesortnlp[i]; 1029 1030 if (nlp->printflag) 1031 (void) sprintf(peterbuffer, "[%d]", nlp->index); 1032 else 1033 (void) sprintf(peterbuffer, "(%d)", nlp->index); 1034 1035 if (i < nnames) { 1036 const char *d = demangled_name(nlp); 1037 1038 if (does_clash(namesortnlp, i, nnames)) { 1039 (void) printf("%6.6s %d:%s\n", 1040 peterbuffer, nlp->module->id, d); 1041 } else 1042 (void) printf("%6.6s %s\n", peterbuffer, 1043 d); 1044 1045 if (d != nlp->name) 1046 (void) printf("%6.6s [%s]", "", 1047 nlp->name); 1048 } else { 1049 (void) printf("%6.6s ", peterbuffer); 1050 (void) sprintf(peterbuffer, "<cycle %d>", 1051 nlp->cycleno); 1052 (void) printf("%-33.33s", peterbuffer); 1053 } 1054 } 1055 (void) printf("\n"); 1056 } 1057 free(namesortnlp); 1058 } 1059