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 2007 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 "gprof.h" 34 35 void print_demangled_name(int, nltype *); 36 void striped_name(char *, nltype **); 37 38 extern long hz; 39 40 /* 41 * Symbols that must never be printed, no matter what. 42 */ 43 char *splsym[] = { 44 PRF_ETEXT, 45 PRF_EXTSYM, 46 PRF_MEMTERM, 47 NULL 48 }; 49 50 static bool is_special_sym(nltype *nlp); 51 52 char * 53 demangled_name(nltype *selfp) 54 { 55 char *name; 56 if (!Cflag) 57 return (selfp->name); 58 59 name = (char *)sgs_demangle(selfp->name); 60 return (name); 61 } 62 63 void 64 printprof(void) 65 { 66 nltype *np; 67 nltype **sortednlp; 68 int i, index; 69 int print_count = number_funcs_toprint; 70 bool print_flag = TRUE; 71 mod_info_t *mi; 72 73 actime = 0.0; 74 (void) printf("\f\n"); 75 flatprofheader(); 76 77 /* 78 * Sort the symbol table in by time 79 */ 80 sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 81 if (sortednlp == (nltype **) 0) { 82 (void) fprintf(stderr, 83 "[printprof] ran out of memory for time sorting\n"); 84 } 85 86 index = 0; 87 for (mi = &modules; mi; mi = mi->next) { 88 for (i = 0; i < mi->nname; i++) 89 sortednlp[index++] = &(mi->nl[i]); 90 } 91 92 qsort(sortednlp, total_names, sizeof (nltype *), timecmp); 93 94 for (index = 0; (index < total_names) && print_flag; index += 1) { 95 np = sortednlp[index]; 96 flatprofline(np); 97 if (nflag) { 98 if (--print_count == 0) 99 print_flag = FALSE; 100 } 101 } 102 actime = 0.0; 103 free(sortednlp); 104 } 105 106 int 107 timecmp(const void *arg1, const void *arg2) 108 { 109 nltype **npp1 = (nltype **)arg1; 110 nltype **npp2 = (nltype **)arg2; 111 double timediff; 112 long calldiff; 113 114 timediff = (*npp2)->time - (*npp1)->time; 115 116 if (timediff > 0.0) 117 return (1); 118 119 if (timediff < 0.0) 120 return (-1); 121 122 calldiff = (*npp2)->ncall - (*npp1)->ncall; 123 124 if (calldiff > 0) 125 return (1); 126 127 if (calldiff < 0) 128 return (-1); 129 130 return (strcmp((*npp1)->name, (*npp2)->name)); 131 } 132 133 /* 134 * header for flatprofline 135 */ 136 void 137 flatprofheader() 138 { 139 140 if (bflag) 141 printblurb(FLAT_BLURB); 142 143 if (old_style) { 144 (void) printf( 145 "\ngranularity: each sample hit covers %d byte(s)", 146 (long)scale * sizeof (UNIT)); 147 if (totime > 0.0) { 148 (void) printf(" for %.2f%% of %.2f seconds\n\n", 149 100.0/totime, totime / hz); 150 } else { 151 (void) printf(" no time accumulated\n\n"); 152 /* 153 * this doesn't hurt since all the numerators will 154 * be zero. 155 */ 156 totime = 1.0; 157 } 158 } 159 160 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 161 "% ", "cumulative", "self ", "", "self ", "total ", ""); 162 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 163 "time", "seconds ", "seconds", "calls", 164 "ms/call", "ms/call", "name"); 165 } 166 167 void 168 flatprofline(nltype *np) 169 { 170 if (zflag == 0 && np->ncall == 0 && np->time == 0) 171 return; 172 173 /* 174 * Do not print certain special symbols, like PRF_EXTSYM, etc. 175 * even if zflag was on. 176 */ 177 if (is_special_sym(np)) 178 return; 179 180 actime += np->time; 181 182 (void) printf("%5.1f %10.2f %8.2f", 183 100 * np->time / totime, actime / hz, np->time / hz); 184 185 if (np->ncall != 0) { 186 (void) printf(" %8lld %8.2f %8.2f ", np->ncall, 187 1000 * np->time / hz / np->ncall, 188 1000 * (np->time + np->childtime) / hz / np->ncall); 189 } else { 190 if (!Cflag) 191 (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 192 else 193 (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 194 } 195 196 printname(np); 197 198 if (Cflag) 199 print_demangled_name(55, np); 200 201 (void) printf("\n"); 202 } 203 204 void 205 gprofheader() 206 { 207 208 if (bflag) 209 printblurb(CALLG_BLURB); 210 211 if (old_style) { 212 213 (void) printf( 214 "\ngranularity: each sample hit covers %d byte(s)", 215 (long)scale * sizeof (UNIT)); 216 217 if (printtime > 0.0) { 218 (void) printf(" for %.2f%% of %.2f seconds\n\n", 219 100.0/printtime, printtime / hz); 220 } else { 221 (void) printf(" no time propagated\n\n"); 222 /* 223 * this doesn't hurt, since all the numerators 224 * will be 0.0 225 */ 226 printtime = 1.0; 227 } 228 } else { 229 (void) printf( 230 "\ngranularity: each pc-hit is considered 1 tick"); 231 if (hz != 1) { 232 (void) printf(" (@ %4.3f seconds per tick)", 233 (double)1.0 / hz); 234 } 235 (void) puts("\n\n"); 236 } 237 238 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 239 "", "", "", "", "called", "total", "parents"); 240 (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", 241 "index", "%time", "self", "descendents", 242 "called", "self", "name", "index"); 243 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 244 "", "", "", "", "called", "total", "children"); 245 (void) printf("\n"); 246 } 247 248 void 249 gprofline(nltype *np) 250 { 251 char kirkbuffer[BUFSIZ]; 252 253 (void) sprintf(kirkbuffer, "[%d]", np->index); 254 (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer, 255 100 * (np->propself + np->propchild) / printtime, 256 np->propself / hz, np->propchild / hz); 257 258 if ((np->ncall + np->selfcalls) != 0) { 259 (void) printf(" %7lld", np->ncall); 260 261 if (np->selfcalls != 0) 262 (void) printf("+%-7lld ", np->selfcalls); 263 else 264 (void) printf(" %7.7s ", ""); 265 } else { 266 (void) printf(" %7.7s %7.7s ", "", ""); 267 } 268 269 printname(np); 270 271 if (Cflag) 272 print_demangled_name(50, np); 273 274 (void) printf("\n"); 275 } 276 277 static bool 278 is_special_sym(nltype *nlp) 279 { 280 int i; 281 282 if (nlp->name == NULL) 283 return (FALSE); 284 285 for (i = 0; splsym[i]; i++) 286 if (strcmp(splsym[i], nlp->name) == 0) 287 return (TRUE); 288 289 return (FALSE); 290 } 291 292 void 293 printgprof(nltype **timesortnlp) 294 { 295 int index; 296 nltype *parentp; 297 int print_count = number_funcs_toprint; 298 bool count_flag = TRUE; 299 300 /* 301 * Print out the structured profiling list 302 */ 303 gprofheader(); 304 305 for (index = 0; index < total_names + ncycle && count_flag; index++) { 306 parentp = timesortnlp[index]; 307 if (zflag == 0 && parentp->ncall == 0 && 308 parentp->selfcalls == 0 && parentp->propself == 0 && 309 parentp -> propchild == 0) 310 continue; 311 312 if (!parentp->printflag) 313 continue; 314 315 /* 316 * Do not print certain special symbols, like PRF_EXTSYM, etc. 317 * even if zflag was on. 318 */ 319 if (is_special_sym(parentp)) 320 continue; 321 322 if (parentp->name == 0 && parentp->cycleno != 0) { 323 /* 324 * cycle header 325 */ 326 printcycle(parentp); 327 printmembers(parentp); 328 } else { 329 printparents(parentp); 330 gprofline(parentp); 331 printchildren(parentp); 332 } 333 334 (void) printf("\n"); 335 (void) printf( 336 "-----------------------------------------------\n"); 337 (void) printf("\n"); 338 339 if (nflag) { 340 --print_count; 341 if (print_count == 0) 342 count_flag = FALSE; 343 } 344 } 345 free(timesortnlp); 346 } 347 348 /* 349 * sort by decreasing propagated time 350 * if times are equal, but one is a cycle header, 351 * say that's first (e.g. less, i.e. -1). 352 * if one's name doesn't have an underscore and the other does, 353 * say the one is first. 354 * all else being equal, sort by names. 355 */ 356 int 357 totalcmp(const void *arg1, const void *arg2) 358 { 359 nltype **npp1 = (nltype **)arg1; 360 nltype **npp2 = (nltype **)arg2; 361 nltype *np1 = *npp1; 362 nltype *np2 = *npp2; 363 double diff; 364 365 diff = (np1->propself + np1->propchild) - 366 (np2->propself + np2->propchild); 367 368 if (diff < 0.0) 369 return (1); 370 if (diff > 0.0) 371 return (-1); 372 if (np1->name == 0 && np1->cycleno != 0) 373 return (-1); 374 if (np2->name == 0 && np2->cycleno != 0) 375 return (1); 376 if (np1->name == 0) 377 return (-1); 378 if (np2->name == 0) 379 return (1); 380 381 if (*(np1->name) != '_' && *(np2->name) == '_') 382 return (-1); 383 if (*(np1->name) == '_' && *(np2->name) != '_') 384 return (1); 385 if (np1->ncall > np2->ncall) 386 return (-1); 387 if (np1->ncall < np2->ncall) 388 return (1); 389 return (strcmp(np1->name, np2->name)); 390 } 391 392 void 393 printparents(nltype *childp) 394 { 395 nltype *parentp; 396 arctype *arcp; 397 nltype *cycleheadp; 398 399 if (childp->cyclehead != 0) 400 cycleheadp = childp -> cyclehead; 401 else 402 cycleheadp = childp; 403 404 if (childp->parents == 0) { 405 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 406 " <spontaneous>\n", "", "", "", "", "", ""); 407 return; 408 } 409 410 sortparents(childp); 411 412 for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 413 parentp = arcp -> arc_parentp; 414 if (childp == parentp || (childp->cycleno != 0 && 415 parentp->cycleno == childp->cycleno)) { 416 /* 417 * selfcall or call among siblings 418 */ 419 (void) printf( 420 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 421 "", "", "", "", arcp->arc_count, ""); 422 printname(parentp); 423 424 if (Cflag) 425 print_demangled_name(54, parentp); 426 427 (void) printf("\n"); 428 } else { 429 /* 430 * regular parent of child 431 */ 432 (void) printf( 433 "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 434 "", arcp->arc_time / hz, arcp->arc_childtime / hz, 435 arcp->arc_count, cycleheadp->ncall); 436 printname(parentp); 437 438 if (Cflag) 439 print_demangled_name(54, parentp); 440 441 (void) printf("\n"); 442 } 443 } 444 } 445 446 void 447 printchildren(nltype *parentp) 448 { 449 nltype *childp; 450 arctype *arcp; 451 452 sortchildren(parentp); 453 454 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 455 childp = arcp->arc_childp; 456 if (childp == parentp || (childp->cycleno != 0 && 457 childp->cycleno == parentp->cycleno)) { 458 /* 459 * self call or call to sibling 460 */ 461 (void) printf( 462 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 463 "", "", "", "", arcp->arc_count, ""); 464 printname(childp); 465 466 if (Cflag) 467 print_demangled_name(54, childp); 468 469 (void) printf("\n"); 470 } else { 471 /* 472 * regular child of parent 473 */ 474 if (childp->cyclehead) 475 (void) printf("%6.6s %5.5s %7.2f %11.2f " 476 "%7lld/%-7lld ", "", "", 477 arcp->arc_time / hz, 478 arcp->arc_childtime / hz, arcp->arc_count, 479 childp->cyclehead->ncall); 480 else 481 (void) printf("%6.6s %5.5s %7.2f %11.2f " 482 "%7lld %7.7s ", 483 "", "", arcp->arc_time / hz, 484 arcp->arc_childtime / hz, arcp->arc_count, 485 ""); 486 487 printname(childp); 488 489 if (Cflag) 490 print_demangled_name(54, childp); 491 492 (void) printf("\n"); 493 } 494 } 495 } 496 497 void 498 printname(nltype *selfp) 499 { 500 char *c; 501 c = demangled_name(selfp); 502 503 if (selfp->name != 0) { 504 if (!Cflag) 505 (void) printf("%s", selfp->name); 506 else 507 (void) printf("%s", c); 508 509 #ifdef DEBUG 510 if (debug & DFNDEBUG) 511 (void) printf("{%d} ", selfp->toporder); 512 513 if (debug & PROPDEBUG) 514 (void) printf("%5.2f%% ", selfp->propfraction); 515 #endif /* DEBUG */ 516 } 517 518 if (selfp->cycleno != 0) 519 (void) printf("\t<cycle %d>", selfp->cycleno); 520 521 if (selfp->index != 0) { 522 if (selfp->printflag) 523 (void) printf(" [%d]", selfp->index); 524 else 525 (void) printf(" (%d)", selfp->index); 526 } 527 } 528 529 void 530 print_demangled_name(int n, nltype *selfp) 531 { 532 char *c; 533 int i; 534 535 c = selfp->name; 536 537 if (strcmp(c, demangled_name(selfp)) == 0) 538 return; 539 else { 540 (void) printf("\n"); 541 for (i = 1; i < n; i++) 542 (void) printf(" "); 543 (void) printf("[%s]", selfp->name); 544 } 545 } 546 547 void 548 sortchildren(nltype *parentp) 549 { 550 arctype *arcp; 551 arctype *detachedp; 552 arctype sorted; 553 arctype *prevp; 554 555 /* 556 * unlink children from parent, 557 * then insertion sort back on to sorted's children. 558 * *arcp the arc you have detached and are inserting. 559 * *detachedp the rest of the arcs to be sorted. 560 * sorted arc list onto which you insertion sort. 561 * *prevp arc before the arc you are comparing. 562 */ 563 sorted.arc_childlist = 0; 564 565 /* LINTED: warning: assignment operator */ 566 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 567 arcp; 568 /* LINTED: warning: assignment operator */ 569 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 570 /* 571 * consider *arcp as disconnected 572 * insert it into sorted 573 */ 574 for (prevp = &sorted; prevp->arc_childlist; 575 prevp = prevp->arc_childlist) { 576 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 577 break; 578 } 579 580 arcp->arc_childlist = prevp->arc_childlist; 581 prevp->arc_childlist = arcp; 582 } 583 584 /* 585 * reattach sorted children to parent 586 */ 587 parentp->children = sorted.arc_childlist; 588 } 589 590 void 591 sortparents(nltype *childp) 592 { 593 arctype *arcp; 594 arctype *detachedp; 595 arctype sorted; 596 arctype *prevp; 597 598 /* 599 * unlink parents from child, 600 * then insertion sort back on to sorted's parents. 601 * *arcp the arc you have detached and are inserting. 602 * *detachedp the rest of the arcs to be sorted. 603 * sorted arc list onto which you insertion sort. 604 * *prevp arc before the arc you are comparing. 605 */ 606 sorted.arc_parentlist = 0; 607 608 /* LINTED: warning: assignment operator */ 609 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 610 arcp; 611 /* LINTED: warning: assignment operator */ 612 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 613 /* 614 * consider *arcp as disconnected 615 * insert it into sorted 616 */ 617 for (prevp = &sorted; prevp->arc_parentlist; 618 prevp = prevp->arc_parentlist) { 619 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 620 break; 621 } 622 arcp->arc_parentlist = prevp->arc_parentlist; 623 prevp->arc_parentlist = arcp; 624 } 625 626 /* 627 * reattach sorted arcs to child 628 */ 629 childp->parents = sorted.arc_parentlist; 630 } 631 632 void 633 printcycle(nltype *cyclep) 634 { 635 char kirkbuffer[BUFSIZ]; 636 637 (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 638 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 639 100 * (cyclep->propself + cyclep->propchild) / printtime, 640 cyclep -> propself / hz, cyclep -> propchild / hz, 641 cyclep -> ncall); 642 643 if (cyclep->selfcalls != 0) 644 (void) printf("+%-7lld", cyclep->selfcalls); 645 else 646 (void) printf(" %7.7s", ""); 647 648 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 649 cyclep->index); 650 } 651 652 /* 653 * print the members of a cycle 654 */ 655 void 656 printmembers(nltype *cyclep) 657 { 658 nltype *memberp; 659 660 sortmembers(cyclep); 661 662 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 663 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 664 memberp->propself / hz, memberp->propchild / hz, 665 memberp->ncall); 666 667 if (memberp->selfcalls != 0) 668 (void) printf("+%-7lld", memberp->selfcalls); 669 else 670 (void) printf(" %7.7s", ""); 671 672 (void) printf(" "); 673 printname(memberp); 674 if (Cflag) 675 print_demangled_name(54, memberp); 676 (void) printf("\n"); 677 } 678 } 679 680 /* 681 * sort members of a cycle 682 */ 683 void 684 sortmembers(nltype *cyclep) 685 { 686 nltype *todo; 687 nltype *doing; 688 nltype *prev; 689 690 /* 691 * detach cycle members from cyclehead, 692 * and insertion sort them back on. 693 */ 694 todo = cyclep->cnext; 695 cyclep->cnext = 0; 696 697 /* LINTED: warning: assignment operator */ 698 for ((doing = todo) && (todo = doing->cnext); 699 doing; 700 /* LINTED: warning: assignment operator */ 701 (doing = todo) && (todo = doing->cnext)) { 702 for (prev = cyclep; prev->cnext; prev = prev->cnext) { 703 if (membercmp(doing, prev->cnext) == GREATERTHAN) 704 break; 705 } 706 doing->cnext = prev->cnext; 707 prev->cnext = doing; 708 } 709 } 710 711 /* 712 * major sort is on propself + propchild, 713 * next is sort on ncalls + selfcalls. 714 */ 715 int 716 membercmp(nltype *this, nltype *that) 717 { 718 double thistime = this->propself + this->propchild; 719 double thattime = that->propself + that->propchild; 720 actype thiscalls = this->ncall + this->selfcalls; 721 actype thatcalls = that->ncall + that->selfcalls; 722 723 if (thistime > thattime) 724 return (GREATERTHAN); 725 726 if (thistime < thattime) 727 return (LESSTHAN); 728 729 if (thiscalls > thatcalls) 730 return (GREATERTHAN); 731 732 if (thiscalls < thatcalls) 733 return (LESSTHAN); 734 735 return (EQUALTO); 736 } 737 738 /* 739 * compare two arcs to/from the same child/parent. 740 * - if one arc is a self arc, it's least. 741 * - if one arc is within a cycle, it's less than. 742 * - if both arcs are within a cycle, compare arc counts. 743 * - if neither arc is within a cycle, compare with 744 * arc_time + arc_childtime as major key 745 * arc count as minor key 746 */ 747 int 748 arccmp(arctype *thisp, arctype *thatp) 749 { 750 nltype *thisparentp = thisp->arc_parentp; 751 nltype *thischildp = thisp->arc_childp; 752 nltype *thatparentp = thatp->arc_parentp; 753 nltype *thatchildp = thatp->arc_childp; 754 double thistime; 755 double thattime; 756 757 #ifdef DEBUG 758 if (debug & TIMEDEBUG) { 759 (void) printf("[arccmp] "); 760 printname(thisparentp); 761 (void) printf(" calls "); 762 printname(thischildp); 763 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 764 thisp->arc_childtime, thisp->arc_count, 765 thischildp->ncall); 766 (void) printf("[arccmp] "); 767 printname(thatparentp); 768 (void) printf(" calls "); 769 printname(thatchildp); 770 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 771 thatp->arc_childtime, thatp->arc_count, 772 thatchildp->ncall); 773 (void) printf("\n"); 774 } 775 #endif /* DEBUG */ 776 777 if (thisparentp == thischildp) { 778 /* 779 * this is a self call 780 */ 781 return (LESSTHAN); 782 } 783 784 if (thatparentp == thatchildp) { 785 /* 786 * that is a self call 787 */ 788 return (GREATERTHAN); 789 } 790 791 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 792 thisparentp->cycleno == thischildp->cycleno) { 793 /* 794 * this is a call within a cycle 795 */ 796 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 797 thatparentp->cycleno == thatchildp->cycleno) { 798 /* 799 * that is a call within the cycle, too 800 */ 801 if (thisp->arc_count < thatp->arc_count) 802 return (LESSTHAN); 803 804 if (thisp->arc_count > thatp->arc_count) 805 return (GREATERTHAN); 806 807 return (EQUALTO); 808 } else { 809 /* 810 * that isn't a call within the cycle 811 */ 812 return (LESSTHAN); 813 } 814 } else { 815 /* 816 * this isn't a call within a cycle 817 */ 818 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 819 thatparentp->cycleno == thatchildp->cycleno) { 820 /* 821 * that is a call within a cycle 822 */ 823 return (GREATERTHAN); 824 } else { 825 /* 826 * neither is a call within a cycle 827 */ 828 thistime = thisp->arc_time + thisp->arc_childtime; 829 thattime = thatp->arc_time + thatp->arc_childtime; 830 831 if (thistime < thattime) 832 return (LESSTHAN); 833 834 if (thistime > thattime) 835 return (GREATERTHAN); 836 837 if (thisp->arc_count < thatp->arc_count) 838 return (LESSTHAN); 839 840 if (thisp->arc_count > thatp->arc_count) 841 return (GREATERTHAN); 842 843 return (EQUALTO); 844 } 845 } 846 } 847 848 void 849 printblurb(char *blurbname) 850 { 851 FILE *blurbfile; 852 int input; 853 854 blurbfile = fopen(blurbname, "r"); 855 if (blurbfile == NULL) { 856 perror(blurbname); 857 return; 858 } 859 860 while ((input = getc(blurbfile)) != EOF) 861 (void) putchar(input); 862 863 (void) fclose(blurbfile); 864 } 865 866 char *s1, *s2; 867 868 static int 869 namecmp(const void *arg1, const void *arg2) 870 { 871 nltype **npp1 = (nltype **)arg1; 872 nltype **npp2 = (nltype **)arg2; 873 874 if (!Cflag) 875 return (strcmp((*npp1)->name, (*npp2)->name)); 876 else { 877 striped_name(s1, npp1); 878 striped_name(s2, npp2); 879 return (strcmp(s1, s2)); 880 } 881 } 882 883 void 884 striped_name(char *s, nltype **npp) 885 { 886 char *d, *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 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