xref: /netbsd/external/gpl3/gdb/dist/binutils/cxxfilt.c (revision 1424dfb3)
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