Print this page
6375 Add native name demangling support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>


   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);


 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 


 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)) {


 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);


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 }


   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  * Copyright 2018, Joyent, Inc.
  28  */
  29 


  30 #include <ctype.h>
  31 #include <string.h>
  32 #include <sys/param.h>
  33 #include <stdlib.h>
  34 #include "conv.h"
  35 #include "gprof.h"
  36 
  37 void print_demangled_name(int, nltype *);
  38 static void stripped_name(char **, size_t *, nltype **);
  39 
  40 extern long hz;
  41 
  42 /*
  43  * Symbols that must never be printed, no matter what.
  44  */
  45 char *splsym[] = {
  46         PRF_ETEXT,
  47         PRF_EXTSYM,
  48         PRF_MEMTERM,
  49         NULL
  50 };
  51 
  52 static bool is_special_sym(nltype *nlp);
  53 
  54 const char *
  55 demangled_name(nltype *selfp)
  56 {
  57         if (!Cflag)
  58                 return (selfp->name);


 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         const char  *c;
 501         c = demangled_name(selfp);
 502 
 503         if (selfp->name != 0) {



 504                 (void) printf("%s", c);
 505 
 506 #ifdef DEBUG
 507                 if (debug & DFNDEBUG)
 508                         (void) printf("{%d} ", selfp->toporder);
 509 
 510                 if (debug & PROPDEBUG)
 511                         (void) printf("%5.2f%% ", selfp->propfraction);
 512 #endif /* DEBUG */
 513         }
 514 
 515         if (selfp->cycleno != 0)
 516                 (void) printf("\t<cycle %d>", selfp->cycleno);
 517 
 518         if (selfp->index != 0) {
 519                 if (selfp->printflag)
 520                         (void) printf(" [%d]", selfp->index);
 521                 else
 522                         (void) printf(" (%d)", selfp->index);
 523         }
 524 
 525         if (c != selfp->name)
 526                 free((void *)c);
 527 }
 528 
 529 void
 530 print_demangled_name(int n, nltype *selfp)
 531 {
 532         char *c = (char *)demangled_name(selfp);
 533         int i;
 534 
 535         if (c == selfp->name)


 536                 return;
 537 
 538         (void) printf("\n");
 539         for (i = 1; i < n; i++)
 540                 (void) printf(" ");
 541         (void) printf("[%s]", selfp->name);
 542 
 543         free(c);
 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 


 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 static int
 866 namecmp(const void *arg1, const void *arg2)
 867 {
 868         nltype **npp1 = (nltype **)arg1;
 869         nltype **npp2 = (nltype **)arg2;
 870 
 871         if (!Cflag)
 872                 return (strcmp((*npp1)->name, (*npp2)->name));
 873         else {
 874                 static char *s1 = NULL, *s2 = NULL;
 875                 static size_t s1len = 0, s2len = 0;
 876 
 877                 stripped_name(&s1, &s1len, npp1);
 878                 stripped_name(&s2, &s2len, npp2);
 879                 return (strcmp(s1, s2));
 880         }
 881 }
 882 
 883 #define NAME_CHUNK 512
 884 #define ROUNDLEN(x) (((x) + NAME_CHUNK - 1) / NAME_CHUNK * NAME_CHUNK)
 885 static void
 886 adjust_size(char **pp, size_t *lenp, const char *name)
 887 {
 888         void *newp;
 889         size_t nlen = strlen(name);
 890         size_t buflen;
 891 
 892         if (*lenp > nlen) {
 893                 (void) memset(*pp, '\0', *lenp);
 894                 return;
 895         }
 896 
 897         buflen = ROUNDLEN(nlen + 1);
 898         if ((newp = realloc(*pp, buflen)) == NULL) {
 899                 (void) fprintf(stderr,
 900                     "gprof: out of memory comparing names\n");
 901                 exit(EXIT_FAILURE);
 902         }
 903         (void) memset(newp, '\0', buflen);
 904 
 905         *lenp = buflen;
 906         *pp = newp;
 907 }
 908 
 909 static void
 910 stripped_name(char **sp, size_t *slenp, nltype **npp)
 911 {
 912         const char *name, *d;
 913         char *c;
 914 
 915         name = d = demangled_name(*npp);
 916         adjust_size(sp, slenp, name);
 917         c = *sp;
 918 
 919         while ((*d != '(') && (*d != '\0')) {
 920                 if (*d != ':')
 921                         *c++ = *d++;
 922                 else
 923                         d++;
 924         }
 925         *c = '\0';
 926 
 927         if ((*npp)->name != name)
 928                 free((void *)name);
 929 }
 930 
 931 /*
 932  * Checks if the current symbol name is the same as its neighbour and
 933  * returns TRUE if it is.
 934  */
 935 static bool
 936 does_clash(nltype **nlp, int ndx, int nnames)
 937 {
 938         /*
 939          * same as previous (if there's one) ?
 940          */
 941         if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
 942                 return (TRUE);
 943 
 944         /*
 945          * same as next (if there's one) ?
 946          */
 947         if ((ndx < (nnames - 1)) &&
 948             (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {


 986 
 987         nnames = 0;
 988         for (mi = &modules; mi; mi = mi->next) {
 989                 for (index = 0; index < mi->nname; index++) {
 990                         if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
 991                             (mi->nl[index]).time == 0) {
 992                                 continue;
 993                         }
 994 
 995                         /*
 996                          * Do not print certain special symbols, like
 997                          * PRF_EXTSYM, etc. even if zflag was on.
 998                          */
 999                         if (is_special_sym(&(mi->nl[index])))
1000                                 continue;
1001 
1002                         namesortnlp[nnames++] = &(mi->nl[index]);
1003                 }
1004         }
1005 





1006         qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
1007 
1008         for (index = 1, todo = nnames; index <= ncycle; index++)
1009                 namesortnlp[todo++] = &cyclenl[index];
1010 
1011         (void) printf("\f\nIndex by function name\n\n");
1012 
1013         if (!Cflag)
1014                 index = (todo + 2) / 3;
1015         else
1016                 index = todo;
1017 
1018         for (i = 0; i < index; i++) {
1019                 if (!Cflag) {
1020                         for (j = i; j < todo; j += index) {
1021                                 nlp = namesortnlp[j];
1022 
1023                                 if (nlp->printflag) {
1024                                         (void) sprintf(peterbuffer,
1025                                             "[%d]", nlp->index);


1047                                         (void) printf("%6.6s ", peterbuffer);
1048                                         (void) sprintf(peterbuffer,
1049                                             "<cycle %d>", nlp->cycleno);
1050                                         (void) printf("%-19.19s", peterbuffer);
1051                                 }
1052                         }
1053                 } else {
1054                         nlp = namesortnlp[i];
1055 
1056                         if (nlp->printflag)
1057                                 (void) sprintf(peterbuffer, "[%d]", nlp->index);
1058                         else
1059                                 (void) sprintf(peterbuffer, "(%d)", nlp->index);
1060 
1061                         if (i < nnames) {
1062                                 const char *d = demangled_name(nlp);
1063 
1064                                 if (does_clash(namesortnlp, i, nnames)) {
1065                                         (void) printf("%6.6s %d:%s\n",
1066                                             peterbuffer, nlp->module->id, d);
1067                                 } else {
1068                                         (void) printf("%6.6s %s\n", peterbuffer,
1069                                             d);
1070                                 }
1071 
1072                                 if (d != nlp->name) {
1073                                         (void) printf("%6.6s   [%s]", "",
1074                                             nlp->name);
1075                                         free((void *)d);
1076                                 }
1077                         } else {
1078                                 (void) printf("%6.6s ", peterbuffer);
1079                                 (void) sprintf(peterbuffer, "<cycle %d>",
1080                                     nlp->cycleno);
1081                                 (void) printf("%-33.33s", peterbuffer);
1082                         }
1083                 }
1084                 (void) printf("\n");
1085         }
1086         free(namesortnlp);
1087 }