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


   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 (c) 1988 AT&T
  24  * Copyright (c) 1989 AT&T
  25  * All Rights Reserved
  26  *
  27  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.

  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <unistd.h>
  33 #include <ctype.h>
  34 #include <locale.h>
  35 #include <libelf.h>
  36 #include <sys/elf_SPARC.h>
  37 
  38 
  39 /* exit return codes */
  40 #define NOARGS  1
  41 #define BADELF  2
  42 #define NOALLOC 3
  43 
  44 #include <fcntl.h>
  45 #include <sys/stat.h>
  46 #include <errno.h>
  47 #include <string.h>


 788         Elf32_Word      *symshndx = 0;
 789         unsigned int    nosymshndx = 0;
 790         int             i;
 791 
 792         if ((buf = calloc(num, sizeof (SYM))) == NULL) {
 793                 (void) fprintf(stderr, gettext("%s: cannot allocate memory\n"),
 794                     prog_name);
 795                 return (NULL);
 796         }
 797 
 798         s = buf;        /* save pointer to head of array */
 799 
 800         for (i = 1; i < num; i++, buf++) {
 801                 (void) gelf_getsym(data, i, &sym);
 802 
 803                 buf->indx = i;
 804                 /* allow to work on machines where NULL-derefs dump core */
 805                 if (sym.st_name == 0)
 806                         buf->name = "";
 807                 else if (C_flag) {
 808                         const char *dn;
 809                         char *name = (char *)elf_strptr(elf, link, sym.st_name);

 810                         dn = conv_demangle_name(name);
 811                         if (strcmp(dn, name) == 0) {    /* Not demangled */
 812                                 if (exotic(name)) {


 813                                         name = FormatName(name, d_buf);
 814                                 }
 815                         } else {  /* name demangled */
 816                                 name = FormatName(name, dn);
 817                         }
 818                         buf->name = name;
 819                 }
 820                 else
 821                         buf->name = (char *)elf_strptr(elf, link, sym.st_name);
 822 
 823                 buf->value   = sym.st_value;
 824                 buf->size    = sym.st_size;
 825                 buf->type    = GELF_ST_TYPE(sym.st_info);
 826                 buf->bind    = GELF_ST_BIND(sym.st_info);
 827                 buf->other   = sym.st_other;
 828                 if ((sym.st_shndx == SHN_XINDEX) &&
 829                     (symshndx == 0) && (nosymshndx == 0)) {
 830                         Elf_Scn         *_scn;
 831                         GElf_Shdr       _shdr;
 832                         _scn = 0;
 833                         while ((_scn = elf_nextscn(elf, _scn)) != 0) {
 834                                 if (gelf_getshdr(_scn, &_shdr) == 0)
 835                                         break;
 836                                 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
 837                                     (_shdr.sh_link == symscnndx)) {


 997                         default:
 998                                 return (0);
 999                         }
1000                 default:
1001                         return (0);
1002                 }
1003         }
1004 
1005         /*
1006          * If it comes here, any symbol can be printed.
1007          *      (So basically, -f is no-op.)
1008          */
1009         return (1);
1010 }
1011 
1012 #ifndef XPG4
1013 /*
1014  * -u flag specified
1015  */
1016 static void
1017 print_with_uflag(
1018         SYM *sym_data,
1019         char *filename
1020 )
1021 {
1022         if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) {
1023                 if (!r_flag) {
1024                         if (R_flag) {
1025                                 if (archive_name != (char *)0)
1026                                         (void) printf("   %s:%s:%s\n",
1027                                             archive_name, filename,
1028                                             sym_data->name);
1029                                 else
1030                                         (void) printf("    %s:%s\n",
1031                                             filename, sym_data->name);
1032                         }
1033                         else
1034                                 (void) printf("    %s\n", sym_data->name);
1035                 }
1036                 else
1037                         (void) printf("    %s:%s\n", filename, sym_data->name);
1038         }
1039 }
1040 #endif


1077                 sym_key = lookup(sym_data->type, sym_data->bind);
1078         }
1079 
1080         if (sym_key != NULL) {
1081                 if (!l_flag)
1082                         (void) printf("%c ", sym_key[0]);
1083                 else
1084                         (void) printf("%-3s", sym_key);
1085         } else {
1086                 if (!l_flag)
1087                         (void) printf("%-2d", sym_data->type);
1088                 else
1089                         (void) printf("%-3d", sym_data->type);
1090         }
1091 }
1092 
1093 /*
1094  * -p flag specified
1095  */
1096 static void
1097 print_with_pflag(
1098         int ndigits,
1099         Elf *elf_file,
1100         unsigned int shstrndx,
1101         SYM *sym_data,
1102         char *filename
1103 )
1104 {
1105         const char * const fmt[] = {
1106                 "%.*llu ",      /* FMT_T_DEC */
1107                 "0x%.*llx ",    /* FMT_T_HEX */
1108                 "0%.*llo "      /* FMT_T_OCT */
1109         };
1110 
1111         if (is_sym_print(sym_data) != 1)
1112                 return;
1113         /*
1114          * -A header
1115          */
1116         if (A_flag != 0)
1117                 (void) printf("%s", A_header);
1118 
1119         /*
1120          * Symbol Value.
1121          *      (hex/octal/decimal)
1122          */
1123         (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value));


1131         if (!r_flag) {
1132                 if (R_flag) {
1133                         if (archive_name != (char *)0)
1134                                 (void) printf("%s:%s:%s\n", archive_name,
1135                                     filename, sym_data->name);
1136                         else
1137                                 (void) printf("%s:%s\n", filename,
1138                                     sym_data->name);
1139                 }
1140                 else
1141                         (void) printf("%s\n", sym_data->name);
1142         }
1143         else
1144                 (void) printf("%s:%s\n", filename, sym_data->name);
1145 }
1146 
1147 /*
1148  * -P flag specified
1149  */
1150 static void
1151 print_with_Pflag(
1152         int ndigits,
1153         Elf *elf_file,
1154         unsigned int shstrndx,
1155         SYM *sym_data
1156 )
1157 {
1158 #define SYM_LEN 10
1159         char sym_name[SYM_LEN+1];
1160         size_t len;
1161         const char * const fmt[] = {
1162                 "%*llu %*llu \n",       /* FMT_T_DEC */
1163                 "%*llx %*llx \n",       /* FMT_T_HEX */
1164                 "%*llo %*llo \n"        /* FMT_T_OCT */
1165         };
1166 
1167         if (is_sym_print(sym_data) != 1)
1168                 return;
1169         /*
1170          * -A header
1171          */
1172         if (A_flag != 0)
1173                 (void) printf("%s", A_header);
1174 
1175         /*
1176          * Symbol name


1183                 (void) printf("%s ", sym_name);
1184         }
1185 
1186         /*
1187          * Symbol Type.
1188          */
1189         print_brief_sym_type(elf_file, shstrndx, sym_data);
1190 
1191         /*
1192          * Symbol Value & size
1193          *      (hex/octal/decimal)
1194          */
1195         (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value),
1196             ndigits, EC_XWORD(sym_data->size));
1197 }
1198 
1199 /*
1200  * other flags specified
1201  */
1202 static void
1203 print_with_otherflags(
1204         int ndigits,
1205         Elf *elf_file,
1206         unsigned int shstrndx,
1207         SYM *sym_data,
1208         char *filename
1209 )
1210 {
1211         const char * const fmt_value_size[] = {
1212                 "%*llu|%*lld|",         /* FMT_T_DEC */
1213                 "0x%.*llx|0x%.*llx|",   /* FMT_T_HEX */
1214                 "0%.*llo|0%.*llo|"      /* FMT_T_OCT */
1215         };
1216         const char * const fmt_int[] = {
1217                 "%-5d",                 /* FMT_T_DEC */
1218                 "%#-5x",                /* FMT_T_HEX */
1219                 "%#-5o"                 /* FMT_T_OCT */
1220         };
1221 
1222         if (is_sym_print(sym_data) != 1)
1223                 return;
1224         (void) printf("%s", A_header);
1225         (void) printf("[%d]\t|", sym_data->indx);
1226         (void) printf(fmt_value_size[fmt_flag], ndigits,
1227             EC_ADDR(sym_data->value), ndigits, EC_XWORD(sym_data->size));
1228 
1229         switch (sym_data->type) {




   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 (c) 1988 AT&T
  24  * Copyright (c) 1989 AT&T
  25  * All Rights Reserved
  26  *
  27  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  28  * Copyright 2018 Jason King
  29  */
  30 
  31 #include <stdio.h>
  32 #include <stdlib.h>
  33 #include <unistd.h>
  34 #include <ctype.h>
  35 #include <locale.h>
  36 #include <libelf.h>
  37 #include <sys/elf_SPARC.h>
  38 
  39 
  40 /* exit return codes */
  41 #define NOARGS  1
  42 #define BADELF  2
  43 #define NOALLOC 3
  44 
  45 #include <fcntl.h>
  46 #include <sys/stat.h>
  47 #include <errno.h>
  48 #include <string.h>


 789         Elf32_Word      *symshndx = 0;
 790         unsigned int    nosymshndx = 0;
 791         int             i;
 792 
 793         if ((buf = calloc(num, sizeof (SYM))) == NULL) {
 794                 (void) fprintf(stderr, gettext("%s: cannot allocate memory\n"),
 795                     prog_name);
 796                 return (NULL);
 797         }
 798 
 799         s = buf;        /* save pointer to head of array */
 800 
 801         for (i = 1; i < num; i++, buf++) {
 802                 (void) gelf_getsym(data, i, &sym);
 803 
 804                 buf->indx = i;
 805                 /* allow to work on machines where NULL-derefs dump core */
 806                 if (sym.st_name == 0)
 807                         buf->name = "";
 808                 else if (C_flag) {
 809                         const char *dn = NULL;
 810                         char *name = (char *)elf_strptr(elf, link, sym.st_name);
 811 
 812                         dn = conv_demangle_name(name);
 813                         if (dn != name) {
 814                                 name = FormatName(name, dn);
 815                                 free((void *)dn);
 816                         } else if (exotic(name)) {
 817                                 name = FormatName(name, d_buf);
 818                         }



 819                         buf->name = name;
 820                 }
 821                 else
 822                         buf->name = (char *)elf_strptr(elf, link, sym.st_name);
 823 
 824                 buf->value   = sym.st_value;
 825                 buf->size    = sym.st_size;
 826                 buf->type    = GELF_ST_TYPE(sym.st_info);
 827                 buf->bind    = GELF_ST_BIND(sym.st_info);
 828                 buf->other   = sym.st_other;
 829                 if ((sym.st_shndx == SHN_XINDEX) &&
 830                     (symshndx == 0) && (nosymshndx == 0)) {
 831                         Elf_Scn         *_scn;
 832                         GElf_Shdr       _shdr;
 833                         _scn = 0;
 834                         while ((_scn = elf_nextscn(elf, _scn)) != 0) {
 835                                 if (gelf_getshdr(_scn, &_shdr) == 0)
 836                                         break;
 837                                 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
 838                                     (_shdr.sh_link == symscnndx)) {


 998                         default:
 999                                 return (0);
1000                         }
1001                 default:
1002                         return (0);
1003                 }
1004         }
1005 
1006         /*
1007          * If it comes here, any symbol can be printed.
1008          *      (So basically, -f is no-op.)
1009          */
1010         return (1);
1011 }
1012 
1013 #ifndef XPG4
1014 /*
1015  * -u flag specified
1016  */
1017 static void
1018 print_with_uflag(SYM *sym_data, char *filename)



1019 {
1020         if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) {
1021                 if (!r_flag) {
1022                         if (R_flag) {
1023                                 if (archive_name != (char *)0)
1024                                         (void) printf("   %s:%s:%s\n",
1025                                             archive_name, filename,
1026                                             sym_data->name);
1027                                 else
1028                                         (void) printf("    %s:%s\n",
1029                                             filename, sym_data->name);
1030                         }
1031                         else
1032                                 (void) printf("    %s\n", sym_data->name);
1033                 }
1034                 else
1035                         (void) printf("    %s:%s\n", filename, sym_data->name);
1036         }
1037 }
1038 #endif


1075                 sym_key = lookup(sym_data->type, sym_data->bind);
1076         }
1077 
1078         if (sym_key != NULL) {
1079                 if (!l_flag)
1080                         (void) printf("%c ", sym_key[0]);
1081                 else
1082                         (void) printf("%-3s", sym_key);
1083         } else {
1084                 if (!l_flag)
1085                         (void) printf("%-2d", sym_data->type);
1086                 else
1087                         (void) printf("%-3d", sym_data->type);
1088         }
1089 }
1090 
1091 /*
1092  * -p flag specified
1093  */
1094 static void
1095 print_with_pflag(int ndigits, Elf *elf_file, unsigned int shstrndx,
1096     SYM *sym_data, char *filename)





1097 {
1098         const char * const fmt[] = {
1099             "%.*llu ",  /* FMT_T_DEC */
1100             "0x%.*llx ",        /* FMT_T_HEX */
1101             "0%.*llo "  /* FMT_T_OCT */
1102         };
1103 
1104         if (is_sym_print(sym_data) != 1)
1105                 return;
1106         /*
1107          * -A header
1108          */
1109         if (A_flag != 0)
1110                 (void) printf("%s", A_header);
1111 
1112         /*
1113          * Symbol Value.
1114          *      (hex/octal/decimal)
1115          */
1116         (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value));


1124         if (!r_flag) {
1125                 if (R_flag) {
1126                         if (archive_name != (char *)0)
1127                                 (void) printf("%s:%s:%s\n", archive_name,
1128                                     filename, sym_data->name);
1129                         else
1130                                 (void) printf("%s:%s\n", filename,
1131                                     sym_data->name);
1132                 }
1133                 else
1134                         (void) printf("%s\n", sym_data->name);
1135         }
1136         else
1137                 (void) printf("%s:%s\n", filename, sym_data->name);
1138 }
1139 
1140 /*
1141  * -P flag specified
1142  */
1143 static void
1144 print_with_Pflag(int ndigits, Elf *elf_file, unsigned int shstrndx,
1145     SYM *sym_data)




1146 {
1147 #define SYM_LEN 10
1148         char sym_name[SYM_LEN+1];
1149         size_t len;
1150         const char * const fmt[] = {
1151                 "%*llu %*llu \n",       /* FMT_T_DEC */
1152                 "%*llx %*llx \n",       /* FMT_T_HEX */
1153                 "%*llo %*llo \n"        /* FMT_T_OCT */
1154         };
1155 
1156         if (is_sym_print(sym_data) != 1)
1157                 return;
1158         /*
1159          * -A header
1160          */
1161         if (A_flag != 0)
1162                 (void) printf("%s", A_header);
1163 
1164         /*
1165          * Symbol name


1172                 (void) printf("%s ", sym_name);
1173         }
1174 
1175         /*
1176          * Symbol Type.
1177          */
1178         print_brief_sym_type(elf_file, shstrndx, sym_data);
1179 
1180         /*
1181          * Symbol Value & size
1182          *      (hex/octal/decimal)
1183          */
1184         (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value),
1185             ndigits, EC_XWORD(sym_data->size));
1186 }
1187 
1188 /*
1189  * other flags specified
1190  */
1191 static void
1192 print_with_otherflags(int ndigits, Elf *elf_file, unsigned int shstrndx,
1193     SYM *sym_data, char *filename)





1194 {
1195         const char * const fmt_value_size[] = {
1196                 "%*llu|%*lld|",         /* FMT_T_DEC */
1197                 "0x%.*llx|0x%.*llx|",   /* FMT_T_HEX */
1198                 "0%.*llo|0%.*llo|"      /* FMT_T_OCT */
1199         };
1200         const char * const fmt_int[] = {
1201                 "%-5d",                 /* FMT_T_DEC */
1202                 "%#-5x",                /* FMT_T_HEX */
1203                 "%#-5o"                 /* FMT_T_OCT */
1204         };
1205 
1206         if (is_sym_print(sym_data) != 1)
1207                 return;
1208         (void) printf("%s", A_header);
1209         (void) printf("[%d]\t|", sym_data->indx);
1210         (void) printf(fmt_value_size[fmt_flag], ndigits,
1211             EC_ADDR(sym_data->value), ndigits, EC_XWORD(sym_data->size));
1212 
1213         switch (sym_data->type) {