175fd0b74Schristos /* Demangler for GNU C++ - main program
2*e992f068Schristos Copyright (C) 1989-2022 Free Software Foundation, Inc.
375fd0b74Schristos Written by James Clark (jjc@jclark.uucp)
475fd0b74Schristos Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
575fd0b74Schristos Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
675fd0b74Schristos
775fd0b74Schristos This file is part of GNU Binutils.
875fd0b74Schristos
975fd0b74Schristos This program is free software; you can redistribute it and/or modify
1075fd0b74Schristos it under the terms of the GNU General Public License as published by
1175fd0b74Schristos the Free Software Foundation; either version 3 of the License, or (at
1275fd0b74Schristos your option) any later version.
1375fd0b74Schristos
1475fd0b74Schristos This program is distributed in the hope that it will be useful,
1575fd0b74Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1675fd0b74Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1775fd0b74Schristos GNU General Public License for more details.
1875fd0b74Schristos
1975fd0b74Schristos You should have received a copy of the GNU General Public License
2075fd0b74Schristos along with GCC; see the file COPYING. If not, write to the Free
2175fd0b74Schristos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
2275fd0b74Schristos 02110-1301, USA. */
2375fd0b74Schristos
2475fd0b74Schristos #include "sysdep.h"
2575fd0b74Schristos #include "bfd.h"
2675fd0b74Schristos #include "libiberty.h"
2775fd0b74Schristos #include "demangle.h"
2875fd0b74Schristos #include "getopt.h"
2975fd0b74Schristos #include "safe-ctype.h"
3075fd0b74Schristos #include "bucomm.h"
3175fd0b74Schristos
3275fd0b74Schristos static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
3375fd0b74Schristos static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
3475fd0b74Schristos
3575fd0b74Schristos static const struct option long_options[] =
3675fd0b74Schristos {
3775fd0b74Schristos {"strip-underscore", no_argument, NULL, '_'},
3875fd0b74Schristos {"format", required_argument, NULL, 's'},
3975fd0b74Schristos {"help", no_argument, NULL, 'h'},
4075fd0b74Schristos {"no-params", no_argument, NULL, 'p'},
4175fd0b74Schristos {"no-strip-underscores", no_argument, NULL, 'n'},
4275fd0b74Schristos {"no-verbose", no_argument, NULL, 'i'},
4375fd0b74Schristos {"types", no_argument, NULL, 't'},
4475fd0b74Schristos {"version", no_argument, NULL, 'v'},
45012573ebSchristos {"recurse-limit", no_argument, NULL, 'R'},
46012573ebSchristos {"recursion-limit", no_argument, NULL, 'R'},
47012573ebSchristos {"no-recurse-limit", no_argument, NULL, 'r'},
48012573ebSchristos {"no-recursion-limit", no_argument, NULL, 'r'},
4975fd0b74Schristos {NULL, no_argument, NULL, 0}
5075fd0b74Schristos };
5175fd0b74Schristos
5275fd0b74Schristos static void
demangle_it(char * mangled_name)5375fd0b74Schristos demangle_it (char *mangled_name)
5475fd0b74Schristos {
5575fd0b74Schristos char *result;
5675fd0b74Schristos unsigned int skip_first = 0;
5775fd0b74Schristos
5875fd0b74Schristos /* _ and $ are sometimes found at the start of function names
5975fd0b74Schristos in assembler sources in order to distinguish them from other
6075fd0b74Schristos names (eg register names). So skip them here. */
6175fd0b74Schristos if (mangled_name[0] == '.' || mangled_name[0] == '$')
6275fd0b74Schristos ++skip_first;
6375fd0b74Schristos if (strip_underscore && mangled_name[skip_first] == '_')
6475fd0b74Schristos ++skip_first;
6575fd0b74Schristos
6675fd0b74Schristos result = cplus_demangle (mangled_name + skip_first, flags);
6775fd0b74Schristos
6875fd0b74Schristos if (result == NULL)
6975fd0b74Schristos printf ("%s", mangled_name);
7075fd0b74Schristos else
7175fd0b74Schristos {
7275fd0b74Schristos if (mangled_name[0] == '.')
7375fd0b74Schristos putchar ('.');
7475fd0b74Schristos printf ("%s", result);
7575fd0b74Schristos free (result);
7675fd0b74Schristos }
7775fd0b74Schristos }
7875fd0b74Schristos
7975fd0b74Schristos static void
print_demangler_list(FILE * stream)8075fd0b74Schristos print_demangler_list (FILE *stream)
8175fd0b74Schristos {
8275fd0b74Schristos const struct demangler_engine *demangler;
8375fd0b74Schristos
8475fd0b74Schristos fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
8575fd0b74Schristos
8675fd0b74Schristos for (demangler = libiberty_demanglers + 1;
8775fd0b74Schristos demangler->demangling_style != unknown_demangling;
8875fd0b74Schristos ++demangler)
8975fd0b74Schristos fprintf (stream, ",%s", demangler->demangling_style_name);
9075fd0b74Schristos
9175fd0b74Schristos fprintf (stream, "}");
9275fd0b74Schristos }
9375fd0b74Schristos
94ede78133Schristos ATTRIBUTE_NORETURN static void
usage(FILE * stream,int status)9575fd0b74Schristos usage (FILE *stream, int status)
9675fd0b74Schristos {
9775fd0b74Schristos fprintf (stream, "\
9875fd0b74Schristos Usage: %s [options] [mangled names]\n", program_name);
9975fd0b74Schristos fprintf (stream, "\
10075fd0b74Schristos Options are:\n\
10175fd0b74Schristos [-_|--strip-underscore] Ignore first leading underscore%s\n",
10275fd0b74Schristos TARGET_PREPENDS_UNDERSCORE ? " (default)" : "");
10375fd0b74Schristos fprintf (stream, "\
10475fd0b74Schristos [-n|--no-strip-underscore] Do not ignore a leading underscore%s\n",
10575fd0b74Schristos TARGET_PREPENDS_UNDERSCORE ? "" : " (default)");
10675fd0b74Schristos fprintf (stream, "\
10775fd0b74Schristos [-p|--no-params] Do not display function arguments\n\
10875fd0b74Schristos [-i|--no-verbose] Do not show implementation details (if any)\n\
109012573ebSchristos [-R|--recurse-limit] Enable a limit on recursion whilst demangling. [Default]\n\
110012573ebSchristos ]-r|--no-recurse-limit] Disable a limit on recursion whilst demangling\n\
11175fd0b74Schristos [-t|--types] Also attempt to demangle type encodings\n\
11275fd0b74Schristos [-s|--format ");
11375fd0b74Schristos print_demangler_list (stream);
11475fd0b74Schristos fprintf (stream, "]\n");
11575fd0b74Schristos
11675fd0b74Schristos fprintf (stream, "\
11775fd0b74Schristos [@<file>] Read extra options from <file>\n\
11875fd0b74Schristos [-h|--help] Display this information\n\
11975fd0b74Schristos [-v|--version] Show the version information\n\
12075fd0b74Schristos Demangled names are displayed to stdout.\n\
12175fd0b74Schristos If a name cannot be demangled it is just echoed to stdout.\n\
12275fd0b74Schristos If no names are provided on the command line, stdin is read.\n");
12375fd0b74Schristos if (REPORT_BUGS_TO[0] && status == 0)
12475fd0b74Schristos fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
12575fd0b74Schristos exit (status);
12675fd0b74Schristos }
12775fd0b74Schristos
12875fd0b74Schristos /* Return the string of non-alnum characters that may occur
12975fd0b74Schristos as a valid symbol component, in the standard assembler symbol
13075fd0b74Schristos syntax. */
13175fd0b74Schristos
13275fd0b74Schristos static const char *
standard_symbol_characters(void)13375fd0b74Schristos standard_symbol_characters (void)
13475fd0b74Schristos {
13575fd0b74Schristos return "_$.";
13675fd0b74Schristos }
13775fd0b74Schristos
13875fd0b74Schristos extern int main (int, char **);
13975fd0b74Schristos
14075fd0b74Schristos int
main(int argc,char ** argv)14175fd0b74Schristos main (int argc, char **argv)
14275fd0b74Schristos {
14375fd0b74Schristos int c;
14475fd0b74Schristos const char *valid_symbols;
14575fd0b74Schristos enum demangling_styles style = auto_demangling;
14675fd0b74Schristos
14775fd0b74Schristos program_name = argv[0];
14875fd0b74Schristos xmalloc_set_program_name (program_name);
14975fd0b74Schristos bfd_set_error_program_name (program_name);
15075fd0b74Schristos
15175fd0b74Schristos expandargv (&argc, &argv);
15275fd0b74Schristos
153012573ebSchristos while ((c = getopt_long (argc, argv, "_hinprRs:tv", long_options, (int *) 0)) != EOF)
15475fd0b74Schristos {
15575fd0b74Schristos switch (c)
15675fd0b74Schristos {
15775fd0b74Schristos case '?':
15875fd0b74Schristos usage (stderr, 1);
15975fd0b74Schristos break;
16075fd0b74Schristos case 'h':
16175fd0b74Schristos usage (stdout, 0);
16275fd0b74Schristos case 'n':
16375fd0b74Schristos strip_underscore = 0;
16475fd0b74Schristos break;
16575fd0b74Schristos case 'p':
16675fd0b74Schristos flags &= ~ DMGL_PARAMS;
16775fd0b74Schristos break;
168012573ebSchristos case 'r':
169012573ebSchristos flags |= DMGL_NO_RECURSE_LIMIT;
170012573ebSchristos break;
171012573ebSchristos case 'R':
172012573ebSchristos flags &= ~ DMGL_NO_RECURSE_LIMIT;
173012573ebSchristos break;
17475fd0b74Schristos case 't':
17575fd0b74Schristos flags |= DMGL_TYPES;
17675fd0b74Schristos break;
17775fd0b74Schristos case 'i':
17875fd0b74Schristos flags &= ~ DMGL_VERBOSE;
17975fd0b74Schristos break;
18075fd0b74Schristos case 'v':
18175fd0b74Schristos print_version ("c++filt");
18275fd0b74Schristos return 0;
18375fd0b74Schristos case '_':
18475fd0b74Schristos strip_underscore = 1;
18575fd0b74Schristos break;
18675fd0b74Schristos case 's':
18775fd0b74Schristos style = cplus_demangle_name_to_style (optarg);
18875fd0b74Schristos if (style == unknown_demangling)
18975fd0b74Schristos {
19075fd0b74Schristos fprintf (stderr, "%s: unknown demangling style `%s'\n",
19175fd0b74Schristos program_name, optarg);
19275fd0b74Schristos return 1;
19375fd0b74Schristos }
19475fd0b74Schristos cplus_demangle_set_style (style);
19575fd0b74Schristos break;
19675fd0b74Schristos }
19775fd0b74Schristos }
19875fd0b74Schristos
19975fd0b74Schristos if (optind < argc)
20075fd0b74Schristos {
20175fd0b74Schristos for ( ; optind < argc; optind++)
20275fd0b74Schristos {
20375fd0b74Schristos demangle_it (argv[optind]);
20475fd0b74Schristos putchar ('\n');
20575fd0b74Schristos }
20675fd0b74Schristos
20775fd0b74Schristos return 0;
20875fd0b74Schristos }
20975fd0b74Schristos
21075fd0b74Schristos switch (current_demangling_style)
21175fd0b74Schristos {
212012573ebSchristos case auto_demangling:
21375fd0b74Schristos case gnu_v3_demangling:
214012573ebSchristos case java_demangling:
215012573ebSchristos case gnat_demangling:
21675fd0b74Schristos case dlang_demangling:
217ede78133Schristos case rust_demangling:
21875fd0b74Schristos valid_symbols = standard_symbol_characters ();
21975fd0b74Schristos break;
22075fd0b74Schristos default:
22175fd0b74Schristos /* Folks should explicitly indicate the appropriate alphabet for
22275fd0b74Schristos each demangling. Providing a default would allow the
22375fd0b74Schristos question to go unconsidered. */
22475fd0b74Schristos fatal ("Internal error: no symbol alphabet for current style");
22575fd0b74Schristos }
22675fd0b74Schristos
22775fd0b74Schristos for (;;)
22875fd0b74Schristos {
22975fd0b74Schristos static char mbuffer[32767];
23075fd0b74Schristos unsigned i = 0;
23175fd0b74Schristos
23275fd0b74Schristos c = getchar ();
23375fd0b74Schristos /* Try to read a mangled name. */
23475fd0b74Schristos while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
23575fd0b74Schristos {
23675fd0b74Schristos if (i >= sizeof (mbuffer) - 1)
23775fd0b74Schristos break;
23875fd0b74Schristos mbuffer[i++] = c;
23975fd0b74Schristos c = getchar ();
24075fd0b74Schristos }
24175fd0b74Schristos
24275fd0b74Schristos if (i > 0)
24375fd0b74Schristos {
24475fd0b74Schristos mbuffer[i] = 0;
24575fd0b74Schristos demangle_it (mbuffer);
24675fd0b74Schristos }
24775fd0b74Schristos
24875fd0b74Schristos if (c == EOF)
24975fd0b74Schristos break;
25075fd0b74Schristos
25175fd0b74Schristos /* Echo the whitespace characters so that the output looks
25275fd0b74Schristos like the input, only with the mangled names demangled. */
25375fd0b74Schristos putchar (c);
25475fd0b74Schristos if (c == '\n')
25575fd0b74Schristos fflush (stdout);
25675fd0b74Schristos }
25775fd0b74Schristos
25875fd0b74Schristos fflush (stdout);
25975fd0b74Schristos return 0;
26075fd0b74Schristos }
261