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