cxxfilt.c revision 260684
1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2009 Kai Wang 3260684Skaiw * All rights reserved. 4260684Skaiw * 5260684Skaiw * Redistribution and use in source and binary forms, with or without 6260684Skaiw * modification, are permitted provided that the following conditions 7260684Skaiw * are met: 8260684Skaiw * 1. Redistributions of source code must retain the above copyright 9260684Skaiw * notice, this list of conditions and the following disclaimer 10260684Skaiw * in this position and unchanged. 11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 12260684Skaiw * notice, this list of conditions and the following disclaimer in the 13260684Skaiw * documentation and/or other materials provided with the distribution. 14260684Skaiw * 15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18260684Skaiw * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25260684Skaiw */ 26260684Skaiw 27260684Skaiw#include <sys/cdefs.h> 28260684Skaiw#include <sys/param.h> 29260684Skaiw#include <ctype.h> 30260684Skaiw#include <err.h> 31260684Skaiw#include <getopt.h> 32260684Skaiw#include <libelftc.h> 33260684Skaiw#include <stdlib.h> 34260684Skaiw#include <stdio.h> 35260684Skaiw#include <string.h> 36260684Skaiw 37260684Skaiw#include "_elftc.h" 38260684Skaiw 39260684SkaiwELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $"); 40260684Skaiw 41260684Skaiw#define STRBUFSZ 8192 42260684Skaiw 43260684Skaiwstatic int stripus = 0; 44260684Skaiwstatic int noparam = 0; 45260684Skaiwstatic int format = 0; 46260684Skaiw 47260684Skaiwenum options 48260684Skaiw{ 49260684Skaiw OPTION_HELP, 50260684Skaiw OPTION_VERSION 51260684Skaiw}; 52260684Skaiw 53260684Skaiwstatic struct option longopts[] = 54260684Skaiw{ 55260684Skaiw {"format", required_argument, NULL, 's'}, 56260684Skaiw {"help", no_argument, NULL, OPTION_HELP}, 57260684Skaiw {"no-params", no_argument, NULL, 'p'}, 58260684Skaiw {"no-strip-underscores", no_argument, NULL, 'n'}, 59260684Skaiw {"strip-underscores", no_argument, NULL, '_'}, 60260684Skaiw {"version", no_argument, NULL, 'V'}, 61260684Skaiw {NULL, 0, NULL, 0} 62260684Skaiw}; 63260684Skaiw 64260684Skaiwstatic struct { 65260684Skaiw const char *fname; 66260684Skaiw int fvalue; 67260684Skaiw} flist[] = { 68260684Skaiw {"auto", 0}, 69260684Skaiw {"arm", ELFTC_DEM_ARM}, 70260684Skaiw {"gnu", ELFTC_DEM_GNU2}, 71260684Skaiw {"gnu-v3", ELFTC_DEM_GNU3} 72260684Skaiw}; 73260684Skaiw 74260684Skaiw#define USAGE_MESSAGE "\ 75260684SkaiwUsage: %s [options] [encoded-names...]\n\ 76260684Skaiw Translate C++ symbol names to human-readable form.\n\n\ 77260684Skaiw Options:\n\ 78260684Skaiw -_ | --strip-underscores Remove leading underscores prior to decoding.\n\ 79260684Skaiw -n | --no-strip-underscores Do not remove leading underscores.\n\ 80260684Skaiw -p | --no-params (Accepted but ignored).\n\ 81260684Skaiw -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\ 82260684Skaiw Valid schemes are: 'arm', 'auto', 'gnu' and\n\ 83260684Skaiw 'gnu-v3'.\n\ 84260684Skaiw --help Print a help message.\n\ 85260684Skaiw --version Print a version identifier and exit.\n" 86260684Skaiw 87260684Skaiwstatic void 88260684Skaiwusage(void) 89260684Skaiw{ 90260684Skaiw 91260684Skaiw (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 92260684Skaiw exit(1); 93260684Skaiw} 94260684Skaiw 95260684Skaiwstatic void 96260684Skaiwversion(void) 97260684Skaiw{ 98260684Skaiw fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 99260684Skaiw exit(0); 100260684Skaiw} 101260684Skaiw 102260684Skaiwstatic int 103260684Skaiwfind_format(const char *fstr) 104260684Skaiw{ 105260684Skaiw int i; 106260684Skaiw 107260684Skaiw for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) { 108260684Skaiw if (!strcmp(fstr, flist[i].fname)) 109260684Skaiw return (flist[i].fvalue); 110260684Skaiw } 111260684Skaiw 112260684Skaiw return (-1); 113260684Skaiw} 114260684Skaiw 115260684Skaiwstatic char * 116260684Skaiwdemangle(char *name, int strict, int *pos) 117260684Skaiw{ 118260684Skaiw static char dem[STRBUFSZ]; 119260684Skaiw char nb[STRBUFSZ]; 120260684Skaiw int p, t; 121260684Skaiw 122260684Skaiw if (stripus && *name == '_') { 123260684Skaiw strncpy(nb, name + 1, sizeof(nb) - 1); 124260684Skaiw t = 1; 125260684Skaiw } else { 126260684Skaiw strncpy(nb, name, sizeof(nb) - 1); 127260684Skaiw t = 0; 128260684Skaiw } 129260684Skaiw nb[sizeof(nb) - 1] = '\0'; 130260684Skaiw 131260684Skaiw p = strlen(nb); 132260684Skaiw if (p <= 0) 133260684Skaiw return NULL; 134260684Skaiw 135260684Skaiw while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) { 136260684Skaiw if (!strict && p > 1) { 137260684Skaiw nb[--p] = '\0'; 138260684Skaiw continue; 139260684Skaiw } else 140260684Skaiw return (NULL); 141260684Skaiw } 142260684Skaiw 143260684Skaiw if (pos != NULL) 144260684Skaiw *pos = t ? p + 1 : p; 145260684Skaiw 146260684Skaiw return (dem); 147260684Skaiw} 148260684Skaiw 149260684Skaiwint 150260684Skaiwmain(int argc, char **argv) 151260684Skaiw{ 152260684Skaiw char *dem, buf[STRBUFSZ]; 153260684Skaiw int c, i, p, s, opt; 154260684Skaiw 155260684Skaiw while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != 156260684Skaiw -1) { 157260684Skaiw switch (opt) { 158260684Skaiw case '_': 159260684Skaiw stripus = 1; 160260684Skaiw break; 161260684Skaiw case 'n': 162260684Skaiw stripus = 0; 163260684Skaiw break; 164260684Skaiw case 'p': 165260684Skaiw noparam = 1; 166260684Skaiw break; 167260684Skaiw case 's': 168260684Skaiw if ((format = find_format(optarg)) < 0) 169260684Skaiw errx(EXIT_FAILURE, "unsupported format: %s", 170260684Skaiw optarg); 171260684Skaiw break; 172260684Skaiw case 'V': 173260684Skaiw version(); 174260684Skaiw /* NOT REACHED */ 175260684Skaiw case OPTION_HELP: 176260684Skaiw default: 177260684Skaiw usage(); 178260684Skaiw /* NOT REACHED */ 179260684Skaiw } 180260684Skaiw } 181260684Skaiw 182260684Skaiw argv += optind; 183260684Skaiw argc -= optind; 184260684Skaiw 185260684Skaiw if (*argv != NULL) { 186260684Skaiw for (i = 0; i < argc; i++) { 187260684Skaiw if ((dem = demangle(argv[i], 1, NULL)) == NULL) 188260684Skaiw fprintf(stderr, "Failed: %s\n", argv[i]); 189260684Skaiw else 190260684Skaiw printf("%s\n", dem); 191260684Skaiw } 192260684Skaiw } else { 193260684Skaiw p = 0; 194260684Skaiw for (;;) { 195260684Skaiw c = fgetc(stdin); 196260684Skaiw if (c == EOF || !isprint(c) || strchr(" \t\n", c)) { 197260684Skaiw if (p > 0) { 198260684Skaiw buf[p] = '\0'; 199260684Skaiw if ((dem = demangle(buf, 0, &s)) == 200260684Skaiw NULL) 201260684Skaiw printf("%s", buf); 202260684Skaiw else { 203260684Skaiw printf("%s", dem); 204260684Skaiw for (i = s; i < p; i++) 205260684Skaiw putchar(buf[i]); 206260684Skaiw } 207260684Skaiw p = 0; 208260684Skaiw } 209260684Skaiw if (c == EOF) 210260684Skaiw break; 211260684Skaiw if (isprint(c) || strchr(" \t\n", c)) 212260684Skaiw putchar(c); 213260684Skaiw } else { 214260684Skaiw if ((size_t) p >= sizeof(buf) - 1) 215260684Skaiw warnx("buffer overflowed"); 216260684Skaiw else 217260684Skaiw buf[p++] = c; 218260684Skaiw } 219260684Skaiw 220260684Skaiw } 221260684Skaiw } 222260684Skaiw 223260684Skaiw exit(0); 224260684Skaiw} 225