Add debug redirect option
[external/binutils.git] / libiberty / cplus-dem.c
1 /* Demangler for GNU C++
2    Copyright (C) 1989-2019 Free Software Foundation, Inc.
3    Written by James Clark (jjc@jclark.uucp)
4    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
6
7 This file is part of the libiberty library.
8 Libiberty is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 In addition to the permissions in the GNU Library General Public
14 License, the Free Software Foundation gives you unlimited permission
15 to link the compiled version of this file into combinations with other
16 programs, and to distribute those combinations without any restriction
17 coming from the use of this file.  (The Library Public License
18 restrictions do apply in other respects; for example, they cover
19 modification of the file, and distribution when not linked into a
20 combined executable.)
21
22 Libiberty is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 Library General Public License for more details.
26
27 You should have received a copy of the GNU Library General Public
28 License along with libiberty; see the file COPYING.LIB.  If
29 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
30 Boston, MA 02110-1301, USA.  */
31
32 /* This file lives in both GCC and libiberty.  When making changes, please
33    try not to break either.  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "safe-ctype.h"
40
41 #include <string.h>
42
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #else
46 void * malloc ();
47 void * realloc ();
48 #endif
49
50 #include <demangle.h>
51 #undef CURRENT_DEMANGLING_STYLE
52 #define CURRENT_DEMANGLING_STYLE options
53
54 #include "libiberty.h"
55
56 enum demangling_styles current_demangling_style = auto_demangling;
57
58 const struct demangler_engine libiberty_demanglers[] =
59 {
60   {
61     NO_DEMANGLING_STYLE_STRING,
62     no_demangling,
63     "Demangling disabled"
64   }
65   ,
66   {
67     AUTO_DEMANGLING_STYLE_STRING,
68       auto_demangling,
69       "Automatic selection based on executable"
70   }
71   ,
72   {
73     GNU_V3_DEMANGLING_STYLE_STRING,
74     gnu_v3_demangling,
75     "GNU (g++) V3 (Itanium C++ ABI) style demangling"
76   }
77   ,
78   {
79     JAVA_DEMANGLING_STYLE_STRING,
80     java_demangling,
81     "Java style demangling"
82   }
83   ,
84   {
85     GNAT_DEMANGLING_STYLE_STRING,
86     gnat_demangling,
87     "GNAT style demangling"
88   }
89   ,
90   {
91     DLANG_DEMANGLING_STYLE_STRING,
92     dlang_demangling,
93     "DLANG style demangling"
94   }
95   ,
96   {
97     RUST_DEMANGLING_STYLE_STRING,
98     rust_demangling,
99     "Rust style demangling"
100   }
101   ,
102   {
103     NULL, unknown_demangling, NULL
104   }
105 };
106
107 /* Add a routine to set the demangling style to be sure it is valid and
108    allow for any demangler initialization that maybe necessary. */
109
110 enum demangling_styles
111 cplus_demangle_set_style (enum demangling_styles style)
112 {
113   const struct demangler_engine *demangler = libiberty_demanglers; 
114
115   for (; demangler->demangling_style != unknown_demangling; ++demangler)
116     if (style == demangler->demangling_style)
117       {
118         current_demangling_style = style;
119         return current_demangling_style;
120       }
121
122   return unknown_demangling;
123 }
124
125 /* Do string name to style translation */
126
127 enum demangling_styles
128 cplus_demangle_name_to_style (const char *name)
129 {
130   const struct demangler_engine *demangler = libiberty_demanglers; 
131
132   for (; demangler->demangling_style != unknown_demangling; ++demangler)
133     if (strcmp (name, demangler->demangling_style_name) == 0)
134       return demangler->demangling_style;
135
136   return unknown_demangling;
137 }
138
139 /* char *cplus_demangle (const char *mangled, int options)
140
141    If MANGLED is a mangled function name produced by GNU C++, then
142    a pointer to a @code{malloc}ed string giving a C++ representation
143    of the name will be returned; otherwise NULL will be returned.
144    It is the caller's responsibility to free the string which
145    is returned.
146
147    Note that any leading underscores, or other such characters prepended by
148    the compilation system, are presumed to have already been stripped from
149    MANGLED.  */
150
151 char *
152 cplus_demangle (const char *mangled, int options)
153 {
154   char *ret;
155
156   if (current_demangling_style == no_demangling)
157     return xstrdup (mangled);
158
159   if ((options & DMGL_STYLE_MASK) == 0)
160     options |= (int) current_demangling_style & DMGL_STYLE_MASK;
161
162   /* The V3 ABI demangling is implemented elsewhere.  */
163   if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
164     {
165       ret = cplus_demangle_v3 (mangled, options);
166       if (GNU_V3_DEMANGLING)
167         return ret;
168
169       if (ret)
170         {
171           /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
172              The subtitutions are always smaller, so do in place changes.  */
173           if (rust_is_mangled (ret))
174             rust_demangle_sym (ret);
175           else if (RUST_DEMANGLING)
176             {
177               free (ret);
178               ret = NULL;
179             }
180         }
181
182       if (ret || RUST_DEMANGLING)
183         return ret;
184     }
185
186   if (JAVA_DEMANGLING)
187     {
188       ret = java_demangle_v3 (mangled);
189       if (ret)
190         return ret;
191     }
192
193   if (GNAT_DEMANGLING)
194     return ada_demangle (mangled, options);
195
196   if (DLANG_DEMANGLING)
197     {
198       ret = dlang_demangle (mangled, options);
199       if (ret)
200         return ret;
201     }
202
203   return (ret);
204 }
205
206 char *
207 rust_demangle (const char *mangled, int options)
208 {
209   /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.  */
210   char *ret = cplus_demangle_v3 (mangled, options);
211
212   /* The Rust subtitutions are always smaller, so do in place changes.  */
213   if (ret != NULL)
214     {
215       if (rust_is_mangled (ret))
216         rust_demangle_sym (ret);
217       else
218         {
219           free (ret);
220           ret = NULL;
221         }
222     }
223
224   return ret;
225 }
226
227 /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
228
229 char *
230 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
231 {
232   int len0;
233   const char* p;
234   char *d;
235   char *demangled = NULL;
236   
237   /* Discard leading _ada_, which is used for library level subprograms.  */
238   if (strncmp (mangled, "_ada_", 5) == 0)
239     mangled += 5;
240
241   /* All ada unit names are lower-case.  */
242   if (!ISLOWER (mangled[0]))
243     goto unknown;
244
245   /* Most of the demangling will trivially remove chars.  Operator names
246      may add one char but because they are always preceeded by '__' which is
247      replaced by '.', they eventually never expand the size.
248      A few special names such as '___elabs' add a few chars (at most 7), but
249      they occur only once.  */
250   len0 = strlen (mangled) + 7 + 1;
251   demangled = XNEWVEC (char, len0);
252   
253   d = demangled;
254   p = mangled;
255   while (1)
256     {
257       /* An entity names is expected.  */
258       if (ISLOWER (*p))
259         {
260           /* An identifier, which is always lower case.  */
261           do
262             *d++ = *p++;
263           while (ISLOWER(*p) || ISDIGIT (*p)
264                  || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
265         }
266       else if (p[0] == 'O')
267         {
268           /* An operator name.  */
269           static const char * const operators[][2] =
270             {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
271              {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
272              {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
273              {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
274              {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
275              {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
276              {"Oexpon", "**"}, {NULL, NULL}};
277           int k;
278
279           for (k = 0; operators[k][0] != NULL; k++)
280             {
281               size_t slen = strlen (operators[k][0]);
282               if (strncmp (p, operators[k][0], slen) == 0)
283                 {
284                   p += slen;
285                   slen = strlen (operators[k][1]);
286                   *d++ = '"';
287                   memcpy (d, operators[k][1], slen);
288                   d += slen;
289                   *d++ = '"';
290                   break;
291                 }
292             }
293           /* Operator not found.  */
294           if (operators[k][0] == NULL)
295             goto unknown;
296         }
297       else
298         {
299           /* Not a GNAT encoding.  */
300           goto unknown;
301         }
302
303       /* The name can be directly followed by some uppercase letters.  */
304       if (p[0] == 'T' && p[1] == 'K')
305         {
306           /* Task stuff.  */
307           if (p[2] == 'B' && p[3] == 0)
308             {
309               /* Subprogram for task body.  */
310               break;
311             }
312           else if (p[2] == '_' && p[3] == '_')
313             {
314               /* Inner declarations in a task.  */
315               p += 4;
316               *d++ = '.';
317               continue;
318             }
319           else
320             goto unknown;
321         }
322       if (p[0] == 'E' && p[1] == 0)
323         {
324           /* Exception name.  */
325           goto unknown;
326         }
327       if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
328         {
329           /* Protected type subprogram.  */
330           break;
331         }
332       if ((*p == 'N' || *p == 'S') && p[1] == 0)
333         {
334           /* Enumerated type name table.  */
335           goto unknown;
336         }
337       if (p[0] == 'X')
338         {
339           /* Body nested.  */
340           p++;
341           while (p[0] == 'n' || p[0] == 'b')
342             p++;
343         }
344       if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
345         {
346           /* Stream operations.  */
347           const char *name;
348           switch (p[1])
349             {
350             case 'R':
351               name = "'Read";
352               break;
353             case 'W':
354               name = "'Write";
355               break;
356             case 'I':
357               name = "'Input";
358               break;
359             case 'O':
360               name = "'Output";
361               break;
362             default:
363               goto unknown;
364             }
365           p += 2;
366           strcpy (d, name);
367           d += strlen (name);
368         }
369       else if (p[0] == 'D')
370         {
371           /* Controlled type operation.  */
372           const char *name;
373           switch (p[1])
374             {
375             case 'F':
376               name = ".Finalize";
377               break;
378             case 'A':
379               name = ".Adjust";
380               break;
381             default:
382               goto unknown;
383             }
384           strcpy (d, name);
385           d += strlen (name);
386           break;
387         }
388
389       if (p[0] == '_')
390         {
391           /* Separator.  */
392           if (p[1] == '_')
393             {
394               /* Standard separator.  Handled first.  */
395               p += 2;
396
397               if (ISDIGIT (*p))
398                 {
399                   /* Overloading number.  */
400                   do
401                     p++;
402                   while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
403                   if (*p == 'X')
404                     {
405                       p++;
406                       while (p[0] == 'n' || p[0] == 'b')
407                         p++;
408                     }
409                 }
410               else if (p[0] == '_' && p[1] != '_')
411                 {
412                   /* Special names.  */
413                   static const char * const special[][2] = {
414                     { "_elabb", "'Elab_Body" },
415                     { "_elabs", "'Elab_Spec" },
416                     { "_size", "'Size" },
417                     { "_alignment", "'Alignment" },
418                     { "_assign", ".\":=\"" },
419                     { NULL, NULL }
420                   };
421                   int k;
422
423                   for (k = 0; special[k][0] != NULL; k++)
424                     {
425                       size_t slen = strlen (special[k][0]);
426                       if (strncmp (p, special[k][0], slen) == 0)
427                         {
428                           p += slen;
429                           slen = strlen (special[k][1]);
430                           memcpy (d, special[k][1], slen);
431                           d += slen;
432                           break;
433                         }
434                     }
435                   if (special[k][0] != NULL)
436                     break;
437                   else
438                     goto unknown;
439                 }
440               else
441                 {
442                   *d++ = '.';
443                   continue;
444                 }
445             }
446           else if (p[1] == 'B' || p[1] == 'E')
447             {
448               /* Entry Body or barrier Evaluation.  */
449               p += 2;
450               while (ISDIGIT (*p))
451                 p++;
452               if (p[0] == 's' && p[1] == 0)
453                 break;
454               else
455                 goto unknown;
456             }
457           else
458             goto unknown;
459         }
460
461       if (p[0] == '.' && ISDIGIT (p[1]))
462         {
463           /* Nested subprogram.  */
464           p += 2;
465           while (ISDIGIT (*p))
466             p++;
467         }
468       if (*p == 0)
469         {
470           /* End of mangled name.  */
471           break;
472         }
473       else
474         goto unknown;
475     }
476   *d = 0;
477   return demangled;
478
479  unknown:
480   XDELETEVEC (demangled);
481   len0 = strlen (mangled);
482   demangled = XNEWVEC (char, len0 + 3);
483
484   if (mangled[0] == '<')
485      strcpy (demangled, mangled);
486   else
487     sprintf (demangled, "<%s>", mangled);
488
489   return demangled;
490 }