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