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/param.h> 28 #include <ctype.h> 29 #include <err.h> 30 #include <getopt.h> 31 #include <libelftc.h> 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <string.h> 35 36 #include "_elftc.h" 37 38 ELFTC_VCSID("$Id: cxxfilt.c 3499 2016-11-25 16:06:29Z emaste $"); 39 40 #define STRBUFSZ 8192 41 42 static int stripus = 0; 43 static int noparam = 0; 44 static int format = 0; 45 46 enum options 47 { 48 OPTION_HELP, 49 OPTION_VERSION 50 }; 51 52 static struct option longopts[] = 53 { 54 {"format", required_argument, NULL, 's'}, 55 {"help", no_argument, NULL, OPTION_HELP}, 56 {"no-params", no_argument, NULL, 'p'}, 57 {"no-strip-underscores", no_argument, NULL, 'n'}, 58 {"strip-underscores", no_argument, NULL, '_'}, 59 {"version", no_argument, NULL, 'V'}, 60 {NULL, 0, NULL, 0} 61 }; 62 63 static struct { 64 const char *fname; 65 int fvalue; 66 } flist[] = { 67 {"auto", 0}, 68 {"arm", ELFTC_DEM_ARM}, 69 {"gnu", ELFTC_DEM_GNU2}, 70 {"gnu-v3", ELFTC_DEM_GNU3} 71 }; 72 73 #define USAGE_MESSAGE "\ 74 Usage: %s [options] [encoded-names...]\n\ 75 Translate C++ symbol names to human-readable form.\n\n\ 76 Options:\n\ 77 -_ | --strip-underscores Remove leading underscores prior to decoding.\n\ 78 -n | --no-strip-underscores Do not remove leading underscores.\n\ 79 -p | --no-params (Accepted but ignored).\n\ 80 -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\ 81 Valid schemes are: 'arm', 'auto', 'gnu' and\n\ 82 'gnu-v3'.\n\ 83 --help Print a help message.\n\ 84 --version Print a version identifier and exit.\n" 85 86 static void 87 usage(void) 88 { 89 90 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 91 exit(1); 92 } 93 94 static void 95 version(void) 96 { 97 fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 98 exit(0); 99 } 100 101 static int 102 find_format(const char *fstr) 103 { 104 int i; 105 106 for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) { 107 if (!strcmp(fstr, flist[i].fname)) 108 return (flist[i].fvalue); 109 } 110 111 return (-1); 112 } 113 114 static char * 115 demangle(char *name) 116 { 117 static char dem[STRBUFSZ]; 118 119 if (stripus && *name == '_') 120 name++; 121 122 if (strlen(name) == 0) 123 return (NULL); 124 125 if (elftc_demangle(name, dem, sizeof(dem), (unsigned) format) < 0) 126 return (NULL); 127 128 return (dem); 129 } 130 131 int 132 main(int argc, char **argv) 133 { 134 char *dem, buf[STRBUFSZ]; 135 size_t p; 136 int c, n, opt; 137 138 while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != 139 -1) { 140 switch (opt) { 141 case '_': 142 stripus = 1; 143 break; 144 case 'n': 145 stripus = 0; 146 break; 147 case 'p': 148 noparam = 1; 149 break; 150 case 's': 151 if ((format = find_format(optarg)) < 0) 152 errx(EXIT_FAILURE, "unsupported format: %s", 153 optarg); 154 break; 155 case 'V': 156 version(); 157 /* NOT REACHED */ 158 case OPTION_HELP: 159 default: 160 usage(); 161 /* NOT REACHED */ 162 } 163 } 164 165 argv += optind; 166 argc -= optind; 167 168 if (*argv != NULL) { 169 for (n = 0; n < argc; n++) { 170 if ((dem = demangle(argv[n])) == NULL) 171 printf("%s\n", argv[n]); 172 else 173 printf("%s\n", dem); 174 } 175 } else { 176 p = 0; 177 for (;;) { 178 setvbuf(stdout, NULL, _IOLBF, 0); 179 c = fgetc(stdin); 180 if (c == EOF || !(isalnum(c) || strchr(".$_", c))) { 181 if (p > 0) { 182 buf[p] = '\0'; 183 if ((dem = demangle(buf)) == NULL) 184 printf("%s", buf); 185 else 186 printf("%s", dem); 187 p = 0; 188 } 189 if (c == EOF) 190 break; 191 putchar(c); 192 } else { 193 if ((size_t) p >= sizeof(buf) - 1) 194 warnx("buffer overflowed"); 195 else 196 buf[p++] = (char) c; 197 } 198 199 } 200 } 201 202 exit(0); 203 } 204