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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1990-1998 by Sun Microsystems, Inc. 24 * All rights reserved. 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 extern int find_run_directory(char *, char *, char *, char **, char *); 36 void print_demangled_name(int, nltype *); 37 void striped_name(char *, nltype **); 38 39 40 extern char *demangle(); 41 char *strstr(); 42 char *parsename(); 43 char name_buffer[512]; 44 extern long hz; 45 46 /* 47 * Symbols that must never be printed, no matter what. 48 */ 49 char *splsym[] = { 50 PRF_ETEXT, 51 PRF_EXTSYM, 52 PRF_MEMTERM, 53 0 54 }; 55 56 char * 57 demangled_name(nltype *selfp) 58 { 59 char *name; 60 if (!Cflag) 61 return (selfp->name); 62 63 name = (char *) sgs_demangle(selfp->name); 64 return (name); 65 } 66 67 void 68 printprof() 69 { 70 nltype *np; 71 nltype **sortednlp; 72 int i, index; 73 int print_count = number_funcs_toprint; 74 bool print_flag = TRUE; 75 mod_info_t *mi; 76 77 actime = 0.0; 78 printf("\f\n"); 79 flatprofheader(); 80 81 /* 82 * Sort the symbol table in by time 83 */ 84 sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 85 if (sortednlp == (nltype **) 0) { 86 fprintf(stderr, 87 "[printprof] ran out of memory for time sorting\n"); 88 } 89 90 index = 0; 91 for (mi = &modules; mi; mi = mi->next) { 92 for (i = 0; i < mi->nname; i++) 93 sortednlp[index++] = &(mi->nl[i]); 94 } 95 96 qsort(sortednlp, total_names, sizeof (nltype *), 97 (int(*)(const void *, const void *))timecmp); 98 99 for (index = 0; (index < total_names) && print_flag; index += 1) { 100 np = sortednlp[index]; 101 flatprofline(np); 102 if (nflag) { 103 if (--print_count == 0) 104 print_flag = FALSE; 105 } 106 } 107 actime = 0.0; 108 free(sortednlp); 109 } 110 111 int 112 timecmp(nltype **npp1, nltype **npp2) 113 { 114 double timediff; 115 long calldiff; 116 117 timediff = (*npp2)->time - (*npp1)->time; 118 119 if (timediff > 0.0) 120 return (1); 121 122 if (timediff < 0.0) 123 return (-1); 124 125 calldiff = (*npp2)->ncall - (*npp1)->ncall; 126 127 if (calldiff > 0) 128 return (1); 129 130 if (calldiff < 0) 131 return (-1); 132 133 return (strcmp((*npp1)->name, (*npp2)->name)); 134 } 135 136 /* 137 * header for flatprofline 138 */ 139 void 140 flatprofheader() 141 { 142 143 if (bflag) 144 printblurb(FLAT_BLURB); 145 146 if (old_style) { 147 printf("\ngranularity: each sample hit covers %d byte(s)", 148 (long)scale * sizeof (UNIT)); 149 if (totime > 0.0) { 150 printf(" for %.2f%% of %.2f seconds\n\n", 151 100.0/totime, totime / hz); 152 } else { 153 printf(" no time accumulated\n\n"); 154 /* 155 * this doesn't hurt since all the numerators will 156 * be zero. 157 */ 158 totime = 1.0; 159 } 160 } 161 162 printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 163 "% ", "cumulative", "self ", "", "self ", "total ", ""); 164 printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 165 "time", "seconds ", "seconds", "calls", 166 "ms/call", "ms/call", "name"); 167 } 168 169 void 170 flatprofline(nltype *np) 171 { 172 if (zflag == 0 && np->ncall == 0 && np->time == 0) 173 return; 174 175 /* 176 * Do not print certain special symbols, like PRF_EXTSYM, etc. 177 * even if zflag was on. 178 */ 179 if (is_special_sym(np)) 180 return; 181 182 actime += np->time; 183 184 printf("%5.1f %10.2f %8.2f", 185 100 * np->time / totime, actime / hz, np->time / hz); 186 187 if (np->ncall != 0) { 188 printf(" %8lld %8.2f %8.2f ", np->ncall, 189 1000 * np->time / hz / np->ncall, 190 1000 * (np->time + np->childtime) / hz / np->ncall); 191 } else { 192 if (!Cflag) 193 printf(" %8.8s %8.8s %8.8s ", "", "", ""); 194 else 195 printf(" %8.8s %8.8s %8.8s ", "", "", ""); 196 } 197 198 printname(np); 199 200 if (Cflag) 201 print_demangled_name(55, np); 202 203 printf("\n"); 204 } 205 206 void 207 gprofheader() 208 { 209 210 if (bflag) 211 printblurb(CALLG_BLURB); 212 213 if (old_style) { 214 215 printf("\ngranularity: each sample hit covers %d byte(s)", 216 (long)scale * sizeof (UNIT)); 217 218 if (printtime > 0.0) { 219 printf(" for %.2f%% of %.2f seconds\n\n", 220 100.0/printtime, printtime / hz); 221 } else { 222 printf(" no time propagated\n\n"); 223 /* 224 * this doesn't hurt, since all the numerators 225 * will be 0.0 226 */ 227 printtime = 1.0; 228 } 229 } else { 230 printf("\ngranularity: each pc-hit is considered 1 tick"); 231 if (hz != 1) { 232 printf(" (@ %4.3f seconds per tick)", 233 (double) 1.0 / hz); 234 } 235 puts("\n\n"); 236 } 237 238 printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 239 "", "", "", "", "called", "total", "parents"); 240 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 printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 244 "", "", "", "", "called", "total", "children"); 245 printf("\n"); 246 } 247 248 void 249 gprofline(nltype *np) 250 { 251 char kirkbuffer[BUFSIZ]; 252 253 sprintf(kirkbuffer, "[%d]", np->index); 254 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 printf(" %7lld", np->ncall); 260 261 if (np->selfcalls != 0) 262 printf("+%-7lld ", np->selfcalls); 263 else 264 printf(" %7.7s ", ""); 265 } else { 266 printf(" %7.7s %7.7s ", "", ""); 267 } 268 269 printname(np); 270 271 if (Cflag) 272 print_demangled_name(50, np); 273 274 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 printf("\n"); 335 printf("-----------------------------------------------\n"); 336 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(nltype **npp1, nltype **npp2) 357 { 358 nltype *np1 = *npp1; 359 nltype *np2 = *npp2; 360 double diff; 361 362 diff = (np1->propself + np1->propchild) - 363 (np2->propself + np2->propchild); 364 365 if (diff < 0.0) 366 return (1); 367 if (diff > 0.0) 368 return (-1); 369 if (np1->name == 0 && np1->cycleno != 0) 370 return (-1); 371 if (np2->name == 0 && np2->cycleno != 0) 372 return (1); 373 if (np1->name == 0) 374 return (-1); 375 if (np2->name == 0) 376 return (1); 377 378 if (*(np1->name) != '_' && *(np2->name) == '_') 379 return (-1); 380 if (*(np1->name) == '_' && *(np2->name) != '_') 381 return (1); 382 if (np1->ncall > np2->ncall) 383 return (-1); 384 if (np1->ncall < np2->ncall) 385 return (1); 386 return (strcmp(np1->name, np2->name)); 387 } 388 389 void 390 printparents(nltype *childp) 391 { 392 nltype *parentp; 393 arctype *arcp; 394 nltype *cycleheadp; 395 396 if (childp->cyclehead != 0) 397 cycleheadp = childp -> cyclehead; 398 else 399 cycleheadp = childp; 400 401 if (childp->parents == 0) { 402 printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 403 " <spontaneous>\n", "", "", "", "", "", ""); 404 return; 405 } 406 407 sortparents(childp); 408 409 for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 410 parentp = arcp -> arc_parentp; 411 if (childp == parentp || (childp->cycleno != 0 && 412 parentp->cycleno == childp->cycleno)) { 413 /* 414 * selfcall or call among siblings 415 */ 416 printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 417 "", "", "", "", arcp->arc_count, ""); 418 printname(parentp); 419 420 if (Cflag) 421 print_demangled_name(54, parentp); 422 423 printf("\n"); 424 } else { 425 /* 426 * regular parent of child 427 */ 428 printf("%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 429 "", arcp->arc_time / hz, arcp->arc_childtime / hz, 430 arcp->arc_count, cycleheadp->ncall); 431 printname(parentp); 432 433 if (Cflag) 434 print_demangled_name(54, parentp); 435 436 printf("\n"); 437 } 438 } 439 } 440 441 void 442 printchildren(nltype *parentp) 443 { 444 nltype *childp; 445 arctype *arcp; 446 447 sortchildren(parentp); 448 449 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 450 childp = arcp->arc_childp; 451 if (childp == parentp || (childp->cycleno != 0 && 452 childp->cycleno == parentp->cycleno)) { 453 /* 454 * self call or call to sibling 455 */ 456 printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 457 "", "", "", "", arcp->arc_count, ""); 458 printname(childp); 459 460 if (Cflag) 461 print_demangled_name(54, childp); 462 463 printf("\n"); 464 } else { 465 /* 466 * regular child of parent 467 */ 468 if (childp->cyclehead) 469 printf("%6.6s %5.5s %7.2f %11.2f " 470 "%7lld/%-7lld ", "", "", 471 arcp->arc_time / hz, 472 arcp->arc_childtime / hz, arcp->arc_count, 473 childp->cyclehead->ncall); 474 else 475 printf("%6.6s %5.5s %7.2f %11.2f " 476 "%7lld %7.7s ", 477 "", "", arcp->arc_time / hz, 478 arcp->arc_childtime / hz, arcp->arc_count, 479 ""); 480 481 printname(childp); 482 483 if (Cflag) 484 print_demangled_name(54, childp); 485 486 printf("\n"); 487 } 488 } 489 } 490 491 void 492 printname(nltype *selfp) 493 { 494 char *c; 495 c = demangled_name(selfp); 496 497 if (selfp->name != 0) { 498 if (!Cflag) 499 printf("%s", selfp->name); 500 else 501 printf("%s", c); 502 503 #ifdef DEBUG 504 if (debug & DFNDEBUG) 505 printf("{%d} ", selfp->toporder); 506 507 if (debug & PROPDEBUG) 508 printf("%5.2f%% ", selfp->propfraction); 509 #endif DEBUG 510 } 511 512 if (selfp->cycleno != 0) 513 printf("\t<cycle %d>", selfp->cycleno); 514 515 if (selfp->index != 0) { 516 if (selfp->printflag) 517 printf(" [%d]", selfp->index); 518 else 519 printf(" (%d)", selfp->index); 520 } 521 } 522 523 void 524 print_demangled_name(int n, nltype *selfp) 525 { 526 char *c; 527 int i; 528 529 c = selfp->name; 530 531 if (strcmp(c, demangled_name(selfp)) == 0) 532 return; 533 else { 534 printf("\n"); 535 for (i = 1; i < n; i++) 536 printf(" "); 537 printf("[%s]", selfp->name); 538 } 539 } 540 541 char *exotic(); 542 543 void 544 sortchildren(nltype *parentp) 545 { 546 arctype *arcp; 547 arctype *detachedp; 548 arctype sorted; 549 arctype *prevp; 550 551 /* 552 * unlink children from parent, 553 * then insertion sort back on to sorted's children. 554 * *arcp the arc you have detached and are inserting. 555 * *detachedp the rest of the arcs to be sorted. 556 * sorted arc list onto which you insertion sort. 557 * *prevp arc before the arc you are comparing. 558 */ 559 sorted.arc_childlist = 0; 560 561 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 562 arcp; 563 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 564 /* 565 * consider *arcp as disconnected 566 * insert it into sorted 567 */ 568 for (prevp = &sorted; prevp->arc_childlist; 569 prevp = prevp->arc_childlist) { 570 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 571 break; 572 } 573 574 arcp->arc_childlist = prevp->arc_childlist; 575 prevp->arc_childlist = arcp; 576 } 577 578 /* 579 * reattach sorted children to parent 580 */ 581 parentp->children = sorted.arc_childlist; 582 } 583 584 void 585 sortparents(nltype *childp) 586 { 587 arctype *arcp; 588 arctype *detachedp; 589 arctype sorted; 590 arctype *prevp; 591 592 /* 593 * unlink parents from child, 594 * then insertion sort back on to sorted's parents. 595 * *arcp the arc you have detached and are inserting. 596 * *detachedp the rest of the arcs to be sorted. 597 * sorted arc list onto which you insertion sort. 598 * *prevp arc before the arc you are comparing. 599 */ 600 sorted.arc_parentlist = 0; 601 602 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 603 arcp; 604 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 605 /* 606 * consider *arcp as disconnected 607 * insert it into sorted 608 */ 609 for (prevp = &sorted; prevp->arc_parentlist; 610 prevp = prevp->arc_parentlist) { 611 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 612 break; 613 } 614 arcp->arc_parentlist = prevp->arc_parentlist; 615 prevp->arc_parentlist = arcp; 616 } 617 618 /* 619 * reattach sorted arcs to child 620 */ 621 childp->parents = sorted.arc_parentlist; 622 } 623 624 void 625 printcycle(nltype *cyclep) 626 { 627 char kirkbuffer[BUFSIZ]; 628 629 sprintf(kirkbuffer, "[%d]", cyclep->index); 630 printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 631 100 * (cyclep->propself + cyclep->propchild) / printtime, 632 cyclep -> propself / hz, cyclep -> propchild / hz, 633 cyclep -> ncall); 634 635 if (cyclep->selfcalls != 0) 636 printf("+%-7lld", cyclep->selfcalls); 637 else 638 printf(" %7.7s", ""); 639 640 printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 641 cyclep->index); 642 } 643 644 /* 645 * print the members of a cycle 646 */ 647 void 648 printmembers(nltype *cyclep) 649 { 650 nltype *memberp; 651 652 sortmembers(cyclep); 653 654 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 655 printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 656 memberp->propself / hz, memberp->propchild / hz, 657 memberp->ncall); 658 659 if (memberp->selfcalls != 0) 660 printf("+%-7lld", memberp->selfcalls); 661 else 662 printf(" %7.7s", ""); 663 664 printf(" "); 665 printname(memberp); 666 if (Cflag) 667 print_demangled_name(54, memberp); 668 printf("\n"); 669 } 670 } 671 672 /* 673 * sort members of a cycle 674 */ 675 void 676 sortmembers(nltype *cyclep) 677 { 678 nltype *todo; 679 nltype *doing; 680 nltype *prev; 681 682 /* 683 * detach cycle members from cyclehead, 684 * and insertion sort them back on. 685 */ 686 todo = cyclep->cnext; 687 cyclep->cnext = 0; 688 689 for ((doing = todo) && (todo = doing->cnext); 690 doing; (doing = todo) && (todo = doing->cnext)) { 691 for (prev = cyclep; prev->cnext; prev = prev->cnext) { 692 if (membercmp(doing, prev->cnext) == GREATERTHAN) 693 break; 694 } 695 doing->cnext = prev->cnext; 696 prev->cnext = doing; 697 } 698 } 699 700 /* 701 * major sort is on propself + propchild, 702 * next is sort on ncalls + selfcalls. 703 */ 704 int 705 membercmp(nltype *this, nltype *that) 706 { 707 double thistime = this->propself + this->propchild; 708 double thattime = that->propself + that->propchild; 709 actype thiscalls = this->ncall + this->selfcalls; 710 actype thatcalls = that->ncall + that->selfcalls; 711 712 if (thistime > thattime) 713 return (GREATERTHAN); 714 715 if (thistime < thattime) 716 return (LESSTHAN); 717 718 if (thiscalls > thatcalls) 719 return (GREATERTHAN); 720 721 if (thiscalls < thatcalls) 722 return (LESSTHAN); 723 724 return (EQUALTO); 725 } 726 727 /* 728 * compare two arcs to/from the same child/parent. 729 * - if one arc is a self arc, it's least. 730 * - if one arc is within a cycle, it's less than. 731 * - if both arcs are within a cycle, compare arc counts. 732 * - if neither arc is within a cycle, compare with 733 * arc_time + arc_childtime as major key 734 * arc count as minor key 735 */ 736 int 737 arccmp(arctype *thisp, arctype *thatp) 738 { 739 nltype *thisparentp = thisp->arc_parentp; 740 nltype *thischildp = thisp->arc_childp; 741 nltype *thatparentp = thatp->arc_parentp; 742 nltype *thatchildp = thatp->arc_childp; 743 double thistime; 744 double thattime; 745 746 #ifdef DEBUG 747 if (debug & TIMEDEBUG) { 748 printf("[arccmp] "); 749 printname(thisparentp); 750 printf(" calls "); 751 printname(thischildp); 752 printf(" %f + %f %lld/%lld\n", thisp->arc_time, 753 thisp->arc_childtime, thisp->arc_count, 754 thischildp->ncall); 755 printf("[arccmp] "); 756 printname(thatparentp); 757 printf(" calls "); 758 printname(thatchildp); 759 printf(" %f + %f %lld/%lld\n", thatp->arc_time, 760 thatp->arc_childtime, thatp->arc_count, 761 thatchildp->ncall); 762 printf("\n"); 763 } 764 #endif DEBUG 765 766 if (thisparentp == thischildp) { 767 /* 768 * this is a self call 769 */ 770 return (LESSTHAN); 771 } 772 773 if (thatparentp == thatchildp) { 774 /* 775 * that is a self call 776 */ 777 return (GREATERTHAN); 778 } 779 780 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 781 thisparentp->cycleno == thischildp->cycleno) { 782 /* 783 * this is a call within a cycle 784 */ 785 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 786 thatparentp->cycleno == thatchildp->cycleno) { 787 /* 788 * that is a call within the cycle, too 789 */ 790 if (thisp->arc_count < thatp->arc_count) 791 return (LESSTHAN); 792 793 if (thisp->arc_count > thatp->arc_count) 794 return (GREATERTHAN); 795 796 return (EQUALTO); 797 } else { 798 /* 799 * that isn't a call within the cycle 800 */ 801 return (LESSTHAN); 802 } 803 } else { 804 /* 805 * this isn't a call within a cycle 806 */ 807 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 808 thatparentp->cycleno == thatchildp->cycleno) { 809 /* 810 * that is a call within a cycle 811 */ 812 return (GREATERTHAN); 813 } else { 814 /* 815 * neither is a call within a cycle 816 */ 817 thistime = thisp->arc_time + thisp->arc_childtime; 818 thattime = thatp->arc_time + thatp->arc_childtime; 819 820 if (thistime < thattime) 821 return (LESSTHAN); 822 823 if (thistime > thattime) 824 return (GREATERTHAN); 825 826 if (thisp->arc_count < thatp->arc_count) 827 return (LESSTHAN); 828 829 if (thisp->arc_count > thatp->arc_count) 830 return (GREATERTHAN); 831 832 return (EQUALTO); 833 } 834 } 835 } 836 837 void 838 printblurb(char *blurbname) 839 { 840 FILE *blurbfile; 841 int input; 842 char blurb_directory[MAXPATHLEN]; 843 char cwd[MAXPATHLEN]; 844 845 cwd[0] = '.'; 846 cwd[1] = '\0'; 847 848 if (find_run_directory(prog_name, cwd, blurb_directory, 849 NULL, getenv("PATH")) != 0) { 850 (void) fprintf(stderr, "Error in finding run directory."); 851 return; 852 } else { 853 strcat(blurb_directory, blurbname); 854 } 855 856 blurbfile = fopen(blurb_directory, "r"); 857 if (blurbfile == NULL) { 858 perror(blurb_directory); 859 return; 860 } 861 862 while ((input = getc(blurbfile)) != EOF) 863 putchar(input); 864 865 fclose(blurbfile); 866 } 867 868 char *s1, *s2; 869 870 int 871 namecmp(nltype **npp1, nltype **npp2) 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 char *d, *c; 886 887 c = (char *)s; 888 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 899 /* 900 * Checks if the current symbol name is the same as its neighbour and 901 * returns TRUE if it is. 902 */ 903 static bool 904 does_clash(nltype **nlp, int ndx, int nnames) 905 { 906 /* 907 * same as previous (if there's one) ? 908 */ 909 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 910 return (TRUE); 911 912 /* 913 * same as next (if there's one) ? 914 */ 915 if ((ndx < (nnames - 1)) && 916 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 917 return (TRUE); 918 } 919 920 return (FALSE); 921 } 922 923 void 924 printmodules() 925 { 926 mod_info_t *mi; 927 928 printf("\f\nObject modules\n\n"); 929 for (mi = &modules; mi; mi = mi->next) 930 printf(" %d: %s\n", mi->id, mi->name); 931 } 932 933 #define IDFMT(id) ((id) < 10 ? 1 : 2) 934 #define NMFMT(id) ((id) < 10 ? 17 : 16) 935 936 void 937 printindex() 938 { 939 nltype **namesortnlp; 940 nltype *nlp; 941 int index, nnames, todo, i, j; 942 char peterbuffer[BUFSIZ]; 943 mod_info_t *mi; 944 945 /* 946 * Now, sort regular function name alphabetically 947 * to create an index. 948 */ 949 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 950 951 if (namesortnlp == NULL) 952 fprintf(stderr, "%s: ran out of memory for sorting\n", whoami); 953 954 nnames = 0; 955 for (mi = &modules; mi; mi = mi->next) { 956 for (index = 0; index < mi->nname; index++) { 957 if (zflag == 0 && (mi->nl[index]).ncall == 0 && 958 (mi->nl[index]).time == 0) { 959 continue; 960 } 961 962 /* 963 * Do not print certain special symbols, like 964 * PRF_EXTSYM, etc. even if zflag was on. 965 */ 966 if (is_special_sym(&(mi->nl[index]))) 967 continue; 968 969 namesortnlp[nnames++] = &(mi->nl[index]); 970 } 971 } 972 973 if (Cflag) { 974 s1 = malloc(500 * sizeof (char)); 975 s2 = malloc(500 * sizeof (char)); 976 } 977 978 qsort(namesortnlp, nnames, sizeof (nltype *), 979 (int(*)(const void *, const void *))namecmp); 980 981 for (index = 1, todo = nnames; index <= ncycle; index++) 982 namesortnlp[todo++] = &cyclenl[index]; 983 984 printf("\f\nIndex by function name\n\n"); 985 986 if (!Cflag) 987 index = (todo + 2) / 3; 988 else 989 index = todo; 990 991 for (i = 0; i < index; i++) { 992 if (!Cflag) { 993 for (j = i; j < todo; j += index) { 994 nlp = namesortnlp[j]; 995 996 if (nlp->printflag) { 997 sprintf(peterbuffer, 998 "[%d]", nlp->index); 999 } else { 1000 sprintf(peterbuffer, 1001 "(%d)", nlp->index); 1002 } 1003 1004 if (j < nnames) { 1005 if (does_clash(namesortnlp, 1006 j, nnames)) { 1007 printf("%6.6s %*d:%-*.*s", 1008 peterbuffer, 1009 IDFMT(nlp->module->id), 1010 nlp->module->id, 1011 NMFMT(nlp->module->id), 1012 NMFMT(nlp->module->id), 1013 nlp->name); 1014 } else { 1015 printf("%6.6s %-19.19s", 1016 peterbuffer, nlp->name); 1017 } 1018 } else { 1019 printf("%6.6s ", peterbuffer); 1020 sprintf(peterbuffer, 1021 "<cycle %d>", nlp->cycleno); 1022 printf("%-19.19s", peterbuffer); 1023 } 1024 } 1025 } else { 1026 nlp = namesortnlp[i]; 1027 1028 if (nlp->printflag) 1029 sprintf(peterbuffer, "[%d]", nlp->index); 1030 else 1031 sprintf(peterbuffer, "(%d)", nlp->index); 1032 1033 if (i < nnames) { 1034 char *d = demangled_name(nlp); 1035 1036 if (does_clash(namesortnlp, i, nnames)) { 1037 printf("%6.6s %d:%s\n", peterbuffer, 1038 nlp->module->id, d); 1039 } else 1040 printf("%6.6s %s\n", peterbuffer, d); 1041 1042 if (d != nlp->name) 1043 printf("%6.6s [%s]", "", nlp->name); 1044 } else { 1045 printf("%6.6s ", peterbuffer); 1046 sprintf(peterbuffer, "<cycle %d>", 1047 nlp->cycleno); 1048 printf("%-33.33s", peterbuffer); 1049 } 1050 } 1051 printf("\n"); 1052 } 1053 free(namesortnlp); 1054 } 1055 1056 1057 char dname[500]; 1058 1059 char * 1060 exotic(char *s) 1061 { 1062 char *name; 1063 int i = 0, j; 1064 char *p, *s1 = "static constructor function for "; 1065 1066 name = malloc(500 * sizeof (char)); 1067 1068 if (strncmp(s, "__sti__", 7) == 0) { 1069 i = 0; 1070 s += 7; 1071 1072 if ((p = strstr(s, "_c_")) == NULL) { 1073 if ((p = strstr(s, "_C_")) == NULL) { 1074 if ((p = strstr(s, "_cc_")) == NULL) { 1075 if ((p = strstr(s, "_cxx_")) == NULL) { 1076 if ((p = 1077 strstr(s, "_h_")) == NULL) 1078 return (NULL); 1079 } 1080 } 1081 } 1082 } else { 1083 p += 3; 1084 *p = '\0'; 1085 } 1086 1087 for (i = 0; s1[i] != '\0'; i++) 1088 dname[i] = s1[i]; 1089 j = i; 1090 1091 for (i = 0; s[i] != '\0'; i++) 1092 dname[j + i] = s[i]; 1093 dname[j + i] = '\0'; 1094 1095 free(name); 1096 return (dname); 1097 } 1098 1099 if (strncmp(s, "__std__", 7) == 0) { 1100 char *s1 = "static destructor function for "; 1101 i = 0; 1102 s += 7; 1103 1104 if ((p = strstr(s, "_c_")) == NULL) { 1105 if ((p = strstr(s, "_C_")) == NULL) { 1106 if ((p = strstr(s, "_cc_")) == NULL) { 1107 if ((p = strstr(s, "_cxx_")) == NULL) { 1108 if ((p = 1109 strstr(s, "_h_")) == NULL) 1110 return (NULL); 1111 } 1112 } 1113 } 1114 } else { 1115 p += 3; 1116 *p = '\0'; 1117 } 1118 1119 for (i = 0; s1[i] != '\0'; i++) 1120 dname[i] = s1[i]; 1121 j = i; 1122 1123 for (i = 0; s[i] != '\0'; i++) 1124 dname[j + i] = s[i]; 1125 dname[j + i] = '\0'; 1126 1127 free(name); 1128 return (dname); 1129 } 1130 1131 if (strncmp(s, "__vtbl__", 8) == 0) { 1132 char *s1 = "virtual table for "; 1133 char *printname, *return_p = dname; 1134 1135 s += 8; 1136 printname = parsename(s); 1137 return_p = '\0'; 1138 strcat(return_p, s1); 1139 strcat(return_p, printname); 1140 1141 free(name); 1142 return (dname); 1143 } 1144 1145 if (strncmp(s, "__ptbl__", 8) == 0) { 1146 char *s1 = "pointer to the virtual table for "; 1147 char *printname, *return_p = dname; 1148 1149 s += 8; 1150 printname = parsename(s); 1151 return_p = '\0'; 1152 strcat(return_p, s1); 1153 strcat(return_p, printname); 1154 1155 free(name); 1156 return (return_p); 1157 } 1158 1159 free(name); 1160 return (s); 1161 } 1162 1163 char * 1164 parsename(char *s) 1165 { 1166 char *d = name_buffer; 1167 int len; 1168 char c_init; 1169 char *len_pointer = s; 1170 1171 *d = '\0'; 1172 1173 strcat(d, "class "); 1174 1175 while (isdigit(*s)) 1176 s++; 1177 c_init = *s; 1178 *s = '\0'; 1179 1180 len = atoi(len_pointer); 1181 *s = c_init; 1182 1183 /* 1184 * only one class name 1185 */ 1186 if (*(s + len) == '\0') { 1187 strcat(d, s); 1188 return (d); 1189 } else { 1190 /* 1191 * two classname %drootname__%dchildname 1192 */ 1193 char *child; 1194 char *root; 1195 int child_len; 1196 char *child_len_p; 1197 root = s; 1198 child = s + len + 2; 1199 child_len_p = child; 1200 1201 if (!isdigit(*child)) { /* ptbl file name */ 1202 c_init = *(root + len); 1203 *(root + len) = '\0'; 1204 strcat(d, root); 1205 *(root + len) = c_init; 1206 strcat(d, " in "); 1207 strcat(d, child); 1208 return (d); 1209 } 1210 1211 while (isdigit(*child)) 1212 child++; 1213 c_init = *child; 1214 *child = '\0'; 1215 child_len = atoi(child_len_p); 1216 *child = c_init; 1217 if (*(child + child_len) == '\0') { 1218 strcat(d, child); 1219 strcat(d, " derived from "); 1220 c_init = *(root + len); 1221 *(root + len) = '\0'; 1222 strcat(d, root); 1223 *(root + len) = c_init; 1224 return (d); 1225 } else { /* %drootname__%dchildname__filename */ 1226 c_init = *(child + child_len); 1227 *(child + child_len) = '\0'; 1228 strcat(d, child); 1229 *(child+ child_len) = c_init; 1230 strcat(d, " derived from "); 1231 c_init = *(root + len); 1232 *(root + len) = '\0'; 1233 strcat(d, root); 1234 *(root + len) = c_init; 1235 strcat(d, " in "); 1236 strcat(d, child + child_len + 2); 1237 return (d); 1238 } 1239 } 1240 } 1241