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 * Copyright 2018 Jason King 27 */ 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 (void) printf("%s", c); 504 505 #ifdef DEBUG 506 if (debug & DFNDEBUG) 507 (void) printf("{%d} ", selfp->toporder); 508 509 if (debug & PROPDEBUG) 510 (void) printf("%5.2f%% ", selfp->propfraction); 511 #endif /* DEBUG */ 512 } 513 514 if (selfp->cycleno != 0) 515 (void) printf("\t<cycle %d>", selfp->cycleno); 516 517 if (selfp->index != 0) { 518 if (selfp->printflag) 519 (void) printf(" [%d]", selfp->index); 520 else 521 (void) printf(" (%d)", selfp->index); 522 } 523 524 if (c != selfp->name) 525 free((void *)c); 526 } 527 528 void 529 print_demangled_name(int n, nltype *selfp) 530 { 531 char *c = demangled_name(selfp); 532 int i; 533 534 if (c == selfp->name) 535 return; 536 537 (void) printf("\n"); 538 for (i = 1; i < n; i++) 539 (void) printf(" "); 540 (void) printf("[%s]", selfp->name); 541 542 free((void *)c); 543 } 544 545 void 546 sortchildren(nltype *parentp) 547 { 548 arctype *arcp; 549 arctype *detachedp; 550 arctype sorted; 551 arctype *prevp; 552 553 /* 554 * unlink children from parent, 555 * then insertion sort back on to sorted's children. 556 * *arcp the arc you have detached and are inserting. 557 * *detachedp the rest of the arcs to be sorted. 558 * sorted arc list onto which you insertion sort. 559 * *prevp arc before the arc you are comparing. 560 */ 561 sorted.arc_childlist = 0; 562 563 /* LINTED: warning: assignment operator */ 564 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 565 arcp; 566 /* LINTED: warning: assignment operator */ 567 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 568 /* 569 * consider *arcp as disconnected 570 * insert it into sorted 571 */ 572 for (prevp = &sorted; prevp->arc_childlist; 573 prevp = prevp->arc_childlist) { 574 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 575 break; 576 } 577 578 arcp->arc_childlist = prevp->arc_childlist; 579 prevp->arc_childlist = arcp; 580 } 581 582 /* 583 * reattach sorted children to parent 584 */ 585 parentp->children = sorted.arc_childlist; 586 } 587 588 void 589 sortparents(nltype *childp) 590 { 591 arctype *arcp; 592 arctype *detachedp; 593 arctype sorted; 594 arctype *prevp; 595 596 /* 597 * unlink parents from child, 598 * then insertion sort back on to sorted's parents. 599 * *arcp the arc you have detached and are inserting. 600 * *detachedp the rest of the arcs to be sorted. 601 * sorted arc list onto which you insertion sort. 602 * *prevp arc before the arc you are comparing. 603 */ 604 sorted.arc_parentlist = 0; 605 606 /* LINTED: warning: assignment operator */ 607 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 608 arcp; 609 /* LINTED: warning: assignment operator */ 610 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 611 /* 612 * consider *arcp as disconnected 613 * insert it into sorted 614 */ 615 for (prevp = &sorted; prevp->arc_parentlist; 616 prevp = prevp->arc_parentlist) { 617 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 618 break; 619 } 620 arcp->arc_parentlist = prevp->arc_parentlist; 621 prevp->arc_parentlist = arcp; 622 } 623 624 /* 625 * reattach sorted arcs to child 626 */ 627 childp->parents = sorted.arc_parentlist; 628 } 629 630 void 631 printcycle(nltype *cyclep) 632 { 633 char kirkbuffer[BUFSIZ]; 634 635 (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 636 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 637 100 * (cyclep->propself + cyclep->propchild) / printtime, 638 cyclep -> propself / hz, cyclep -> propchild / hz, 639 cyclep -> ncall); 640 641 if (cyclep->selfcalls != 0) 642 (void) printf("+%-7lld", cyclep->selfcalls); 643 else 644 (void) printf(" %7.7s", ""); 645 646 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 647 cyclep->index); 648 } 649 650 /* 651 * print the members of a cycle 652 */ 653 void 654 printmembers(nltype *cyclep) 655 { 656 nltype *memberp; 657 658 sortmembers(cyclep); 659 660 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 661 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 662 memberp->propself / hz, memberp->propchild / hz, 663 memberp->ncall); 664 665 if (memberp->selfcalls != 0) 666 (void) printf("+%-7lld", memberp->selfcalls); 667 else 668 (void) printf(" %7.7s", ""); 669 670 (void) printf(" "); 671 printname(memberp); 672 if (Cflag) 673 print_demangled_name(54, memberp); 674 (void) printf("\n"); 675 } 676 } 677 678 /* 679 * sort members of a cycle 680 */ 681 void 682 sortmembers(nltype *cyclep) 683 { 684 nltype *todo; 685 nltype *doing; 686 nltype *prev; 687 688 /* 689 * detach cycle members from cyclehead, 690 * and insertion sort them back on. 691 */ 692 todo = cyclep->cnext; 693 cyclep->cnext = 0; 694 695 /* LINTED: warning: assignment operator */ 696 for ((doing = todo) && (todo = doing->cnext); 697 doing; 698 /* LINTED: warning: assignment operator */ 699 (doing = todo) && (todo = doing->cnext)) { 700 for (prev = cyclep; prev->cnext; prev = prev->cnext) { 701 if (membercmp(doing, prev->cnext) == GREATERTHAN) 702 break; 703 } 704 doing->cnext = prev->cnext; 705 prev->cnext = doing; 706 } 707 } 708 709 /* 710 * major sort is on propself + propchild, 711 * next is sort on ncalls + selfcalls. 712 */ 713 int 714 membercmp(nltype *this, nltype *that) 715 { 716 double thistime = this->propself + this->propchild; 717 double thattime = that->propself + that->propchild; 718 actype thiscalls = this->ncall + this->selfcalls; 719 actype thatcalls = that->ncall + that->selfcalls; 720 721 if (thistime > thattime) 722 return (GREATERTHAN); 723 724 if (thistime < thattime) 725 return (LESSTHAN); 726 727 if (thiscalls > thatcalls) 728 return (GREATERTHAN); 729 730 if (thiscalls < thatcalls) 731 return (LESSTHAN); 732 733 return (EQUALTO); 734 } 735 736 /* 737 * compare two arcs to/from the same child/parent. 738 * - if one arc is a self arc, it's least. 739 * - if one arc is within a cycle, it's less than. 740 * - if both arcs are within a cycle, compare arc counts. 741 * - if neither arc is within a cycle, compare with 742 * arc_time + arc_childtime as major key 743 * arc count as minor key 744 */ 745 int 746 arccmp(arctype *thisp, arctype *thatp) 747 { 748 nltype *thisparentp = thisp->arc_parentp; 749 nltype *thischildp = thisp->arc_childp; 750 nltype *thatparentp = thatp->arc_parentp; 751 nltype *thatchildp = thatp->arc_childp; 752 double thistime; 753 double thattime; 754 755 #ifdef DEBUG 756 if (debug & TIMEDEBUG) { 757 (void) printf("[arccmp] "); 758 printname(thisparentp); 759 (void) printf(" calls "); 760 printname(thischildp); 761 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 762 thisp->arc_childtime, thisp->arc_count, 763 thischildp->ncall); 764 (void) printf("[arccmp] "); 765 printname(thatparentp); 766 (void) printf(" calls "); 767 printname(thatchildp); 768 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 769 thatp->arc_childtime, thatp->arc_count, 770 thatchildp->ncall); 771 (void) printf("\n"); 772 } 773 #endif /* DEBUG */ 774 775 if (thisparentp == thischildp) { 776 /* 777 * this is a self call 778 */ 779 return (LESSTHAN); 780 } 781 782 if (thatparentp == thatchildp) { 783 /* 784 * that is a self call 785 */ 786 return (GREATERTHAN); 787 } 788 789 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 790 thisparentp->cycleno == thischildp->cycleno) { 791 /* 792 * this is a call within a cycle 793 */ 794 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 795 thatparentp->cycleno == thatchildp->cycleno) { 796 /* 797 * that is a call within the cycle, too 798 */ 799 if (thisp->arc_count < thatp->arc_count) 800 return (LESSTHAN); 801 802 if (thisp->arc_count > thatp->arc_count) 803 return (GREATERTHAN); 804 805 return (EQUALTO); 806 } else { 807 /* 808 * that isn't a call within the cycle 809 */ 810 return (LESSTHAN); 811 } 812 } else { 813 /* 814 * this isn't a call within a cycle 815 */ 816 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 817 thatparentp->cycleno == thatchildp->cycleno) { 818 /* 819 * that is a call within a cycle 820 */ 821 return (GREATERTHAN); 822 } else { 823 /* 824 * neither is a call within a cycle 825 */ 826 thistime = thisp->arc_time + thisp->arc_childtime; 827 thattime = thatp->arc_time + thatp->arc_childtime; 828 829 if (thistime < thattime) 830 return (LESSTHAN); 831 832 if (thistime > thattime) 833 return (GREATERTHAN); 834 835 if (thisp->arc_count < thatp->arc_count) 836 return (LESSTHAN); 837 838 if (thisp->arc_count > thatp->arc_count) 839 return (GREATERTHAN); 840 841 return (EQUALTO); 842 } 843 } 844 } 845 846 void 847 printblurb(char *blurbname) 848 { 849 FILE *blurbfile; 850 int input; 851 852 blurbfile = fopen(blurbname, "r"); 853 if (blurbfile == NULL) { 854 perror(blurbname); 855 return; 856 } 857 858 while ((input = getc(blurbfile)) != EOF) 859 (void) putchar(input); 860 861 (void) fclose(blurbfile); 862 } 863 864 char *s1, *s2; 865 866 static int 867 namecmp(const void *arg1, const void *arg2) 868 { 869 nltype **npp1 = (nltype **)arg1; 870 nltype **npp2 = (nltype **)arg2; 871 872 if (!Cflag) 873 return (strcmp((*npp1)->name, (*npp2)->name)); 874 else { 875 striped_name(s1, npp1); 876 striped_name(s2, npp2); 877 return (strcmp(s1, s2)); 878 } 879 } 880 881 void 882 striped_name(char *s, nltype **npp) 883 { 884 const char *name, *d; 885 char *c; 886 887 c = (char *)s; 888 name = d = demangled_name(*npp); 889 890 while ((*d != '(') && (*d != '\0')) { 891 if (*d != ':') 892 *c++ = *d++; 893 else 894 d++; 895 } 896 *c = '\0'; 897 898 if ((*npp)->name != name) 899 free((void *)name); 900 } 901 902 /* 903 * Checks if the current symbol name is the same as its neighbour and 904 * returns TRUE if it is. 905 */ 906 static bool 907 does_clash(nltype **nlp, int ndx, int nnames) 908 { 909 /* 910 * same as previous (if there's one) ? 911 */ 912 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 913 return (TRUE); 914 915 /* 916 * same as next (if there's one) ? 917 */ 918 if ((ndx < (nnames - 1)) && 919 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 920 return (TRUE); 921 } 922 923 return (FALSE); 924 } 925 926 void 927 printmodules() 928 { 929 mod_info_t *mi; 930 931 (void) printf("\f\nObject modules\n\n"); 932 for (mi = &modules; mi; mi = mi->next) 933 (void) printf(" %d: %s\n", mi->id, mi->name); 934 } 935 936 #define IDFMT(id) ((id) < 10 ? 1 : 2) 937 #define NMFMT(id) ((id) < 10 ? 17 : 16) 938 939 void 940 printindex() 941 { 942 nltype **namesortnlp; 943 nltype *nlp; 944 int index, nnames, todo, i, j; 945 char peterbuffer[BUFSIZ]; 946 mod_info_t *mi; 947 948 /* 949 * Now, sort regular function name alphabetically 950 * to create an index. 951 */ 952 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 953 954 if (namesortnlp == NULL) 955 (void) fprintf(stderr, "%s: ran out of memory for sorting\n", 956 whoami); 957 958 nnames = 0; 959 for (mi = &modules; mi; mi = mi->next) { 960 for (index = 0; index < mi->nname; index++) { 961 if (zflag == 0 && (mi->nl[index]).ncall == 0 && 962 (mi->nl[index]).time == 0) { 963 continue; 964 } 965 966 /* 967 * Do not print certain special symbols, like 968 * PRF_EXTSYM, etc. even if zflag was on. 969 */ 970 if (is_special_sym(&(mi->nl[index]))) 971 continue; 972 973 namesortnlp[nnames++] = &(mi->nl[index]); 974 } 975 } 976 977 if (Cflag) { 978 s1 = malloc(500 * sizeof (char)); 979 s2 = malloc(500 * sizeof (char)); 980 } 981 982 qsort(namesortnlp, nnames, sizeof (nltype *), namecmp); 983 984 for (index = 1, todo = nnames; index <= ncycle; index++) 985 namesortnlp[todo++] = &cyclenl[index]; 986 987 (void) printf("\f\nIndex by function name\n\n"); 988 989 if (!Cflag) 990 index = (todo + 2) / 3; 991 else 992 index = todo; 993 994 for (i = 0; i < index; i++) { 995 if (!Cflag) { 996 for (j = i; j < todo; j += index) { 997 nlp = namesortnlp[j]; 998 999 if (nlp->printflag) { 1000 (void) sprintf(peterbuffer, 1001 "[%d]", nlp->index); 1002 } else { 1003 (void) sprintf(peterbuffer, 1004 "(%d)", nlp->index); 1005 } 1006 1007 if (j < nnames) { 1008 if (does_clash(namesortnlp, 1009 j, nnames)) { 1010 (void) printf( 1011 "%6.6s %*d:%-*.*s", 1012 peterbuffer, 1013 IDFMT(nlp->module->id), 1014 nlp->module->id, 1015 NMFMT(nlp->module->id), 1016 NMFMT(nlp->module->id), 1017 nlp->name); 1018 } else { 1019 (void) printf("%6.6s %-19.19s", 1020 peterbuffer, nlp->name); 1021 } 1022 } else { 1023 (void) printf("%6.6s ", peterbuffer); 1024 (void) sprintf(peterbuffer, 1025 "<cycle %d>", nlp->cycleno); 1026 (void) printf("%-19.19s", peterbuffer); 1027 } 1028 } 1029 } else { 1030 nlp = namesortnlp[i]; 1031 1032 if (nlp->printflag) 1033 (void) sprintf(peterbuffer, "[%d]", nlp->index); 1034 else 1035 (void) sprintf(peterbuffer, "(%d)", nlp->index); 1036 1037 if (i < nnames) { 1038 const char *d = demangled_name(nlp); 1039 1040 if (does_clash(namesortnlp, i, nnames)) { 1041 (void) printf("%6.6s %d:%s\n", 1042 peterbuffer, nlp->module->id, d); 1043 } else 1044 (void) printf("%6.6s %s\n", peterbuffer, 1045 d); 1046 1047 if (d != nlp->name) 1048 (void) printf("%6.6s [%s]", "", 1049 nlp->name); 1050 } else { 1051 (void) printf("%6.6s ", peterbuffer); 1052 (void) sprintf(peterbuffer, "<cycle %d>", 1053 nlp->cycleno); 1054 (void) printf("%-33.33s", peterbuffer); 1055 } 1056 } 1057 (void) printf("\n"); 1058 } 1059 free(namesortnlp); 1060 }