1 /*- 2 * Copyright (c) 2009 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 #include <sys/param.h> 29 #include <ctype.h> 30 #include <err.h> 31 #include <getopt.h> 32 #include <libelftc.h> 33 #include <stdlib.h> 34 #include <stdio.h> 35 #include <string.h> 36 37 #include "_elftc.h" 38 39 ELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $"); 40 41 #define STRBUFSZ 8192 42 43 static int stripus = 0; 44 static int noparam = 0; 45 static int format = 0; 46 47 enum options 48 { 49 OPTION_HELP, 50 OPTION_VERSION 51 }; 52 53 static struct option longopts[] = 54 { 55 {"format", required_argument, NULL, 's'}, 56 {"help", no_argument, NULL, OPTION_HELP}, 57 {"no-params", no_argument, NULL, 'p'}, 58 {"no-strip-underscores", no_argument, NULL, 'n'}, 59 {"strip-underscores", no_argument, NULL, '_'}, 60 {"version", no_argument, NULL, 'V'}, 61 {NULL, 0, NULL, 0} 62 }; 63 64 static struct { 65 const char *fname; 66 int fvalue; 67 } flist[] = { 68 {"auto", 0}, 69 {"arm", ELFTC_DEM_ARM}, 70 {"gnu", ELFTC_DEM_GNU2}, 71 {"gnu-v3", ELFTC_DEM_GNU3} 72 }; 73 74 #define USAGE_MESSAGE "\ 75 Usage: %s [options] [encoded-names...]\n\ 76 Translate C++ symbol names to human-readable form.\n\n\ 77 Options:\n\ 78 -_ | --strip-underscores Remove leading underscores prior to decoding.\n\ 79 -n | --no-strip-underscores Do not remove leading underscores.\n\ 80 -p | --no-params (Accepted but ignored).\n\ 81 -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\ 82 Valid schemes are: 'arm', 'auto', 'gnu' and\n\ 83 'gnu-v3'.\n\ 84 --help Print a help message.\n\ 85 --version Print a version identifier and exit.\n" 86 87 static void 88 usage(void) 89 { 90 91 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 92 exit(1); 93 } 94 95 static void 96 version(void) 97 { 98 fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 99 exit(0); 100 } 101 102 static int 103 find_format(const char *fstr) 104 { 105 int i; 106 107 for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) { 108 if (!strcmp(fstr, flist[i].fname)) 109 return (flist[i].fvalue); 110 } 111 112 return (-1); 113 } 114 115 static char * 116 demangle(char *name, int strict, int *pos) 117 { 118 static char dem[STRBUFSZ]; 119 char nb[STRBUFSZ]; 120 int p, t; 121 122 if (stripus && *name == '_') { 123 strncpy(nb, name + 1, sizeof(nb) - 1); 124 t = 1; 125 } else { 126 strncpy(nb, name, sizeof(nb) - 1); 127 t = 0; 128 } 129 nb[sizeof(nb) - 1] = '\0'; 130 131 p = strlen(nb); 132 if (p <= 0) 133 return NULL; 134 135 while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) { 136 if (!strict && p > 1) { 137 nb[--p] = '\0'; 138 continue; 139 } else 140 return (NULL); 141 } 142 143 if (pos != NULL) 144 *pos = t ? p + 1 : p; 145 146 return (dem); 147 } 148 149 int 150 main(int argc, char **argv) 151 { 152 char *dem, buf[STRBUFSZ]; 153 int c, i, p, s, opt; 154 155 while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != 156 -1) { 157 switch (opt) { 158 case '_': 159 stripus = 1; 160 break; 161 case 'n': 162 stripus = 0; 163 break; 164 case 'p': 165 noparam = 1; 166 break; 167 case 's': 168 if ((format = find_format(optarg)) < 0) 169 errx(EXIT_FAILURE, "unsupported format: %s", 170 optarg); 171 break; 172 case 'V': 173 version(); 174 /* NOT REACHED */ 175 case OPTION_HELP: 176 default: 177 usage(); 178 /* NOT REACHED */ 179 } 180 } 181 182 argv += optind; 183 argc -= optind; 184 185 if (*argv != NULL) { 186 for (i = 0; i < argc; i++) { 187 if ((dem = demangle(argv[i], 1, NULL)) == NULL) 188 fprintf(stderr, "Failed: %s\n", argv[i]); 189 else 190 printf("%s\n", dem); 191 } 192 } else { 193 p = 0; 194 for (;;) { 195 c = fgetc(stdin); 196 if (c == EOF || !isprint(c) || strchr(" \t\n", c)) { 197 if (p > 0) { 198 buf[p] = '\0'; 199 if ((dem = demangle(buf, 0, &s)) == 200 NULL) 201 printf("%s", buf); 202 else { 203 printf("%s", dem); 204 for (i = s; i < p; i++) 205 putchar(buf[i]); 206 } 207 p = 0; 208 } 209 if (c == EOF) 210 break; 211 if (isprint(c) || strchr(" \t\n", c)) 212 putchar(c); 213 } else { 214 if ((size_t) p >= sizeof(buf) - 1) 215 warnx("buffer overflowed"); 216 else 217 buf[p++] = c; 218 } 219 220 } 221 } 222 223 exit(0); 224 } 225