1 /* Demangler for GNU C++
2 Copyright (C) 1989-2024 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
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.
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
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.
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. */
32 /* This file lives in both GCC and libiberty. When making changes, please
33 try not to break either. */
39 #include "safe-ctype.h"
51 #undef CURRENT_DEMANGLING_STYLE
52 #define CURRENT_DEMANGLING_STYLE options
54 #include "libiberty.h"
56 enum demangling_styles current_demangling_style
= auto_demangling
;
58 const struct demangler_engine libiberty_demanglers
[] =
61 NO_DEMANGLING_STYLE_STRING
,
67 AUTO_DEMANGLING_STYLE_STRING
,
69 "Automatic selection based on executable"
73 GNU_V3_DEMANGLING_STYLE_STRING
,
75 "GNU (g++) V3 (Itanium C++ ABI) style demangling"
79 JAVA_DEMANGLING_STYLE_STRING
,
81 "Java style demangling"
85 GNAT_DEMANGLING_STYLE_STRING
,
87 "GNAT style demangling"
91 DLANG_DEMANGLING_STYLE_STRING
,
93 "DLANG style demangling"
97 RUST_DEMANGLING_STYLE_STRING
,
99 "Rust style demangling"
103 NULL
, unknown_demangling
, NULL
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. */
110 enum demangling_styles
111 cplus_demangle_set_style (enum demangling_styles style
)
113 const struct demangler_engine
*demangler
= libiberty_demanglers
;
115 for (; demangler
->demangling_style
!= unknown_demangling
; ++demangler
)
116 if (style
== demangler
->demangling_style
)
118 current_demangling_style
= style
;
119 return current_demangling_style
;
122 return unknown_demangling
;
125 /* Do string name to style translation */
127 enum demangling_styles
128 cplus_demangle_name_to_style (const char *name
)
130 const struct demangler_engine
*demangler
= libiberty_demanglers
;
132 for (; demangler
->demangling_style
!= unknown_demangling
; ++demangler
)
133 if (strcmp (name
, demangler
->demangling_style_name
) == 0)
134 return demangler
->demangling_style
;
136 return unknown_demangling
;
139 /* char *cplus_demangle (const char *mangled, int options)
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
147 Note that any leading underscores, or other such characters prepended by
148 the compilation system, are presumed to have already been stripped from
152 cplus_demangle (const char *mangled
, int options
)
156 if (current_demangling_style
== no_demangling
)
157 return xstrdup (mangled
);
159 if ((options
& DMGL_STYLE_MASK
) == 0)
160 options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
162 /* The Rust demangling is implemented elsewhere.
163 Legacy Rust symbols overlap with GNU_V3, so try Rust first. */
164 if (RUST_DEMANGLING
|| AUTO_DEMANGLING
)
166 ret
= rust_demangle (mangled
, options
);
167 if (ret
|| RUST_DEMANGLING
)
171 /* The V3 ABI demangling is implemented elsewhere. */
172 if (GNU_V3_DEMANGLING
|| AUTO_DEMANGLING
)
174 ret
= cplus_demangle_v3 (mangled
, options
);
175 if (ret
|| GNU_V3_DEMANGLING
)
181 ret
= java_demangle_v3 (mangled
);
187 return ada_demangle (mangled
, options
);
189 if (DLANG_DEMANGLING
|| AUTO_DEMANGLING
)
191 ret
= dlang_demangle (mangled
, options
);
199 /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
202 ada_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
207 char *demangled
= NULL
;
209 /* Discard leading _ada_, which is used for library level subprograms. */
210 if (strncmp (mangled
, "_ada_", 5) == 0)
213 /* All ada unit names are lower-case. */
214 if (!ISLOWER (mangled
[0]))
217 /* Most of the demangling will trivially remove chars. Operator names
218 may add one char but because they are always preceeded by '__' which is
219 replaced by '.', they eventually never expand the size.
220 A few special names such as '___elabs' add a few chars (at most 7), but
221 they occur only once. */
222 len0
= strlen (mangled
) + 7 + 1;
223 demangled
= XNEWVEC (char, len0
);
229 /* An entity names is expected. */
232 /* An identifier, which is always lower case. */
235 while (ISLOWER(*p
) || ISDIGIT (*p
)
236 || (p
[0] == '_' && (ISLOWER (p
[1]) || ISDIGIT (p
[1]))));
238 else if (p
[0] == 'O')
240 /* An operator name. */
241 static const char * const operators
[][2] =
242 {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
243 {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
244 {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
245 {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
246 {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
247 {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
248 {"Oexpon", "**"}, {NULL
, NULL
}};
251 for (k
= 0; operators
[k
][0] != NULL
; k
++)
253 size_t slen
= strlen (operators
[k
][0]);
254 if (strncmp (p
, operators
[k
][0], slen
) == 0)
257 slen
= strlen (operators
[k
][1]);
259 memcpy (d
, operators
[k
][1], slen
);
265 /* Operator not found. */
266 if (operators
[k
][0] == NULL
)
271 /* Not a GNAT encoding. */
275 /* The name can be directly followed by some uppercase letters. */
276 if (p
[0] == 'T' && p
[1] == 'K')
279 if (p
[2] == 'B' && p
[3] == 0)
281 /* Subprogram for task body. */
284 else if (p
[2] == '_' && p
[3] == '_')
286 /* Inner declarations in a task. */
294 if (p
[0] == 'E' && p
[1] == 0)
296 /* Exception name. */
299 if ((p
[0] == 'P' || p
[0] == 'N') && p
[1] == 0)
301 /* Protected type subprogram. */
304 if ((*p
== 'N' || *p
== 'S') && p
[1] == 0)
306 /* Enumerated type name table. */
313 while (p
[0] == 'n' || p
[0] == 'b')
316 if (p
[0] == 'S' && p
[1] != 0 && (p
[2] == '_' || p
[2] == 0))
318 /* Stream operations. */
341 else if (p
[0] == 'D')
343 /* Controlled type operation. */
366 /* Standard separator. Handled first. */
371 /* Overloading number. */
374 while (ISDIGIT (*p
) || (p
[0] == '_' && ISDIGIT (p
[1])));
378 while (p
[0] == 'n' || p
[0] == 'b')
382 else if (p
[0] == '_' && p
[1] != '_')
385 static const char * const special
[][2] = {
386 { "_elabb", "'Elab_Body" },
387 { "_elabs", "'Elab_Spec" },
388 { "_size", "'Size" },
389 { "_alignment", "'Alignment" },
390 { "_assign", ".\":=\"" },
395 for (k
= 0; special
[k
][0] != NULL
; k
++)
397 size_t slen
= strlen (special
[k
][0]);
398 if (strncmp (p
, special
[k
][0], slen
) == 0)
401 slen
= strlen (special
[k
][1]);
402 memcpy (d
, special
[k
][1], slen
);
407 if (special
[k
][0] != NULL
)
418 else if (p
[1] == 'B' || p
[1] == 'E')
420 /* Entry Body or barrier Evaluation. */
424 if (p
[0] == 's' && p
[1] == 0)
433 if (p
[0] == '.' && ISDIGIT (p
[1]))
435 /* Nested subprogram. */
442 /* End of mangled name. */
452 XDELETEVEC (demangled
);
453 len0
= strlen (mangled
);
454 demangled
= XNEWVEC (char, len0
+ 3);
456 if (mangled
[0] == '<')
457 strcpy (demangled
, mangled
);
459 sprintf (demangled
, "<%s>", mangled
);