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