1*1424dfb3Schristos /* Demangler for GNU C++ - main program
2*1424dfb3Schristos Copyright (C) 1989-2020 Free Software Foundation, Inc.
3*1424dfb3Schristos Written by James Clark (jjc@jclark.uucp)
4*1424dfb3Schristos Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5*1424dfb3Schristos Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
6*1424dfb3Schristos
7*1424dfb3Schristos This file is part of GNU Binutils.
8*1424dfb3Schristos
9*1424dfb3Schristos This program is free software; you can redistribute it and/or modify
10*1424dfb3Schristos it under the terms of the GNU General Public License as published by
11*1424dfb3Schristos the Free Software Foundation; either version 3 of the License, or (at
12*1424dfb3Schristos your option) any later version.
13*1424dfb3Schristos
14*1424dfb3Schristos This program is distributed in the hope that it will be useful,
15*1424dfb3Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
16*1424dfb3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*1424dfb3Schristos GNU General Public License for more details.
18*1424dfb3Schristos
19*1424dfb3Schristos You should have received a copy of the GNU General Public License
20*1424dfb3Schristos along with GCC; see the file COPYING. If not, write to the Free
21*1424dfb3Schristos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
22*1424dfb3Schristos 02110-1301, USA. */
23*1424dfb3Schristos
24*1424dfb3Schristos #include "sysdep.h"
25*1424dfb3Schristos #include "bfd.h"
26*1424dfb3Schristos #include "libiberty.h"
27*1424dfb3Schristos #include "demangle.h"
28*1424dfb3Schristos #include "getopt.h"
29*1424dfb3Schristos #include "safe-ctype.h"
30*1424dfb3Schristos #include "bucomm.h"
31*1424dfb3Schristos
32*1424dfb3Schristos static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
33*1424dfb3Schristos static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
34*1424dfb3Schristos
35*1424dfb3Schristos static const struct option long_options[] =
36*1424dfb3Schristos {
37*1424dfb3Schristos {"strip-underscore", no_argument, NULL, '_'},
38*1424dfb3Schristos {"format", required_argument, NULL, 's'},
39*1424dfb3Schristos {"help", no_argument, NULL, 'h'},
40*1424dfb3Schristos {"no-params", no_argument, NULL, 'p'},
41*1424dfb3Schristos {"no-strip-underscores", no_argument, NULL, 'n'},
42*1424dfb3Schristos {"no-verbose", no_argument, NULL, 'i'},
43*1424dfb3Schristos {"types", no_argument, NULL, 't'},
44*1424dfb3Schristos {"version", no_argument, NULL, 'v'},
45*1424dfb3Schristos {"recurse-limit", no_argument, NULL, 'R'},
46*1424dfb3Schristos {"recursion-limit", no_argument, NULL, 'R'},
47*1424dfb3Schristos {"no-recurse-limit", no_argument, NULL, 'r'},
48*1424dfb3Schristos {"no-recursion-limit", no_argument, NULL, 'r'},
49*1424dfb3Schristos {NULL, no_argument, NULL, 0}
50*1424dfb3Schristos };
51*1424dfb3Schristos
52*1424dfb3Schristos static void
demangle_it(char * mangled_name)53*1424dfb3Schristos demangle_it (char *mangled_name)
54*1424dfb3Schristos {
55*1424dfb3Schristos char *result;
56*1424dfb3Schristos unsigned int skip_first = 0;
57*1424dfb3Schristos
58*1424dfb3Schristos /* _ and $ are sometimes found at the start of function names
59*1424dfb3Schristos in assembler sources in order to distinguish them from other
60*1424dfb3Schristos names (eg register names). So skip them here. */
61*1424dfb3Schristos if (mangled_name[0] == '.' || mangled_name[0] == '$')
62*1424dfb3Schristos ++skip_first;
63*1424dfb3Schristos if (strip_underscore && mangled_name[skip_first] == '_')
64*1424dfb3Schristos ++skip_first;
65*1424dfb3Schristos
66*1424dfb3Schristos result = cplus_demangle (mangled_name + skip_first, flags);
67*1424dfb3Schristos
68*1424dfb3Schristos if (result == NULL)
69*1424dfb3Schristos printf ("%s", mangled_name);
70*1424dfb3Schristos else
71*1424dfb3Schristos {
72*1424dfb3Schristos if (mangled_name[0] == '.')
73*1424dfb3Schristos putchar ('.');
74*1424dfb3Schristos printf ("%s", result);
75*1424dfb3Schristos free (result);
76*1424dfb3Schristos }
77*1424dfb3Schristos }
78*1424dfb3Schristos
79*1424dfb3Schristos static void
print_demangler_list(FILE * stream)80*1424dfb3Schristos print_demangler_list (FILE *stream)
81*1424dfb3Schristos {
82*1424dfb3Schristos const struct demangler_engine *demangler;
83*1424dfb3Schristos
84*1424dfb3Schristos fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
85*1424dfb3Schristos
86*1424dfb3Schristos for (demangler = libiberty_demanglers + 1;
87*1424dfb3Schristos demangler->demangling_style != unknown_demangling;
88*1424dfb3Schristos ++demangler)
89*1424dfb3Schristos fprintf (stream, ",%s", demangler->demangling_style_name);
90*1424dfb3Schristos
91*1424dfb3Schristos fprintf (stream, "}");
92*1424dfb3Schristos }
93*1424dfb3Schristos
94*1424dfb3Schristos ATTRIBUTE_NORETURN static void
usage(FILE * stream,int status)95*1424dfb3Schristos usage (FILE *stream, int status)
96*1424dfb3Schristos {
97*1424dfb3Schristos fprintf (stream, "\
98*1424dfb3Schristos Usage: %s [options] [mangled names]\n", program_name);
99*1424dfb3Schristos fprintf (stream, "\
100*1424dfb3Schristos Options are:\n\
101*1424dfb3Schristos [-_|--strip-underscore] Ignore first leading underscore%s\n",
102*1424dfb3Schristos TARGET_PREPENDS_UNDERSCORE ? " (default)" : "");
103*1424dfb3Schristos fprintf (stream, "\
104*1424dfb3Schristos [-n|--no-strip-underscore] Do not ignore a leading underscore%s\n",
105*1424dfb3Schristos TARGET_PREPENDS_UNDERSCORE ? "" : " (default)");
106*1424dfb3Schristos fprintf (stream, "\
107*1424dfb3Schristos [-p|--no-params] Do not display function arguments\n\
108*1424dfb3Schristos [-i|--no-verbose] Do not show implementation details (if any)\n\
109*1424dfb3Schristos [-R|--recurse-limit] Enable a limit on recursion whilst demangling. [Default]\n\
110*1424dfb3Schristos ]-r|--no-recurse-limit] Disable a limit on recursion whilst demangling\n\
111*1424dfb3Schristos [-t|--types] Also attempt to demangle type encodings\n\
112*1424dfb3Schristos [-s|--format ");
113*1424dfb3Schristos print_demangler_list (stream);
114*1424dfb3Schristos fprintf (stream, "]\n");
115*1424dfb3Schristos
116*1424dfb3Schristos fprintf (stream, "\
117*1424dfb3Schristos [@<file>] Read extra options from <file>\n\
118*1424dfb3Schristos [-h|--help] Display this information\n\
119*1424dfb3Schristos [-v|--version] Show the version information\n\
120*1424dfb3Schristos Demangled names are displayed to stdout.\n\
121*1424dfb3Schristos If a name cannot be demangled it is just echoed to stdout.\n\
122*1424dfb3Schristos If no names are provided on the command line, stdin is read.\n");
123*1424dfb3Schristos if (REPORT_BUGS_TO[0] && status == 0)
124*1424dfb3Schristos fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
125*1424dfb3Schristos exit (status);
126*1424dfb3Schristos }
127*1424dfb3Schristos
128*1424dfb3Schristos /* Return the string of non-alnum characters that may occur
129*1424dfb3Schristos as a valid symbol component, in the standard assembler symbol
130*1424dfb3Schristos syntax. */
131*1424dfb3Schristos
132*1424dfb3Schristos static const char *
standard_symbol_characters(void)133*1424dfb3Schristos standard_symbol_characters (void)
134*1424dfb3Schristos {
135*1424dfb3Schristos return "_$.";
136*1424dfb3Schristos }
137*1424dfb3Schristos
138*1424dfb3Schristos extern int main (int, char **);
139*1424dfb3Schristos
140*1424dfb3Schristos int
main(int argc,char ** argv)141*1424dfb3Schristos main (int argc, char **argv)
142*1424dfb3Schristos {
143*1424dfb3Schristos int c;
144*1424dfb3Schristos const char *valid_symbols;
145*1424dfb3Schristos enum demangling_styles style = auto_demangling;
146*1424dfb3Schristos
147*1424dfb3Schristos program_name = argv[0];
148*1424dfb3Schristos xmalloc_set_program_name (program_name);
149*1424dfb3Schristos bfd_set_error_program_name (program_name);
150*1424dfb3Schristos
151*1424dfb3Schristos expandargv (&argc, &argv);
152*1424dfb3Schristos
153*1424dfb3Schristos while ((c = getopt_long (argc, argv, "_hinprRs:tv", long_options, (int *) 0)) != EOF)
154*1424dfb3Schristos {
155*1424dfb3Schristos switch (c)
156*1424dfb3Schristos {
157*1424dfb3Schristos case '?':
158*1424dfb3Schristos usage (stderr, 1);
159*1424dfb3Schristos break;
160*1424dfb3Schristos case 'h':
161*1424dfb3Schristos usage (stdout, 0);
162*1424dfb3Schristos case 'n':
163*1424dfb3Schristos strip_underscore = 0;
164*1424dfb3Schristos break;
165*1424dfb3Schristos case 'p':
166*1424dfb3Schristos flags &= ~ DMGL_PARAMS;
167*1424dfb3Schristos break;
168*1424dfb3Schristos case 'r':
169*1424dfb3Schristos flags |= DMGL_NO_RECURSE_LIMIT;
170*1424dfb3Schristos break;
171*1424dfb3Schristos case 'R':
172*1424dfb3Schristos flags &= ~ DMGL_NO_RECURSE_LIMIT;
173*1424dfb3Schristos break;
174*1424dfb3Schristos case 't':
175*1424dfb3Schristos flags |= DMGL_TYPES;
176*1424dfb3Schristos break;
177*1424dfb3Schristos case 'i':
178*1424dfb3Schristos flags &= ~ DMGL_VERBOSE;
179*1424dfb3Schristos break;
180*1424dfb3Schristos case 'v':
181*1424dfb3Schristos print_version ("c++filt");
182*1424dfb3Schristos return 0;
183*1424dfb3Schristos case '_':
184*1424dfb3Schristos strip_underscore = 1;
185*1424dfb3Schristos break;
186*1424dfb3Schristos case 's':
187*1424dfb3Schristos style = cplus_demangle_name_to_style (optarg);
188*1424dfb3Schristos if (style == unknown_demangling)
189*1424dfb3Schristos {
190*1424dfb3Schristos fprintf (stderr, "%s: unknown demangling style `%s'\n",
191*1424dfb3Schristos program_name, optarg);
192*1424dfb3Schristos return 1;
193*1424dfb3Schristos }
194*1424dfb3Schristos cplus_demangle_set_style (style);
195*1424dfb3Schristos break;
196*1424dfb3Schristos }
197*1424dfb3Schristos }
198*1424dfb3Schristos
199*1424dfb3Schristos if (optind < argc)
200*1424dfb3Schristos {
201*1424dfb3Schristos for ( ; optind < argc; optind++)
202*1424dfb3Schristos {
203*1424dfb3Schristos demangle_it (argv[optind]);
204*1424dfb3Schristos putchar ('\n');
205*1424dfb3Schristos }
206*1424dfb3Schristos
207*1424dfb3Schristos return 0;
208*1424dfb3Schristos }
209*1424dfb3Schristos
210*1424dfb3Schristos switch (current_demangling_style)
211*1424dfb3Schristos {
212*1424dfb3Schristos case auto_demangling:
213*1424dfb3Schristos case gnu_v3_demangling:
214*1424dfb3Schristos case java_demangling:
215*1424dfb3Schristos case gnat_demangling:
216*1424dfb3Schristos case dlang_demangling:
217*1424dfb3Schristos case rust_demangling:
218*1424dfb3Schristos valid_symbols = standard_symbol_characters ();
219*1424dfb3Schristos break;
220*1424dfb3Schristos default:
221*1424dfb3Schristos /* Folks should explicitly indicate the appropriate alphabet for
222*1424dfb3Schristos each demangling. Providing a default would allow the
223*1424dfb3Schristos question to go unconsidered. */
224*1424dfb3Schristos fatal ("Internal error: no symbol alphabet for current style");
225*1424dfb3Schristos }
226*1424dfb3Schristos
227*1424dfb3Schristos for (;;)
228*1424dfb3Schristos {
229*1424dfb3Schristos static char mbuffer[32767];
230*1424dfb3Schristos unsigned i = 0;
231*1424dfb3Schristos
232*1424dfb3Schristos c = getchar ();
233*1424dfb3Schristos /* Try to read a mangled name. */
234*1424dfb3Schristos while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
235*1424dfb3Schristos {
236*1424dfb3Schristos if (i >= sizeof (mbuffer) - 1)
237*1424dfb3Schristos break;
238*1424dfb3Schristos mbuffer[i++] = c;
239*1424dfb3Schristos c = getchar ();
240*1424dfb3Schristos }
241*1424dfb3Schristos
242*1424dfb3Schristos if (i > 0)
243*1424dfb3Schristos {
244*1424dfb3Schristos mbuffer[i] = 0;
245*1424dfb3Schristos demangle_it (mbuffer);
246*1424dfb3Schristos }
247*1424dfb3Schristos
248*1424dfb3Schristos if (c == EOF)
249*1424dfb3Schristos break;
250*1424dfb3Schristos
251*1424dfb3Schristos /* Echo the whitespace characters so that the output looks
252*1424dfb3Schristos like the input, only with the mangled names demangled. */
253*1424dfb3Schristos putchar (c);
254*1424dfb3Schristos if (c == '\n')
255*1424dfb3Schristos fflush (stdout);
256*1424dfb3Schristos }
257*1424dfb3Schristos
258*1424dfb3Schristos fflush (stdout);
259*1424dfb3Schristos return 0;
260*1424dfb3Schristos }
261