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 }
|