xref: /dflybsd-src/contrib/binutils-2.34/binutils/cxxfilt.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
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