xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/gdb-demangle.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Basic C++ demangling support for GDB.
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 1991-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    Written by Fred Fish at Cygnus Support.
67d62b00eSchristos 
77d62b00eSchristos    This file is part of GDB.
87d62b00eSchristos 
97d62b00eSchristos    This program is free software; you can redistribute it and/or modify
107d62b00eSchristos    it under the terms of the GNU General Public License as published by
117d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
127d62b00eSchristos    (at your option) any later version.
137d62b00eSchristos 
147d62b00eSchristos    This program is distributed in the hope that it will be useful,
157d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
167d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
177d62b00eSchristos    GNU General Public License for more details.
187d62b00eSchristos 
197d62b00eSchristos    You should have received a copy of the GNU General Public License
207d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
217d62b00eSchristos 
227d62b00eSchristos 
237d62b00eSchristos /*  This file contains support code for C++ demangling that is common
247d62b00eSchristos    to a styles of demangling, and GDB specific.  */
257d62b00eSchristos 
267d62b00eSchristos #include "defs.h"
277d62b00eSchristos #include "cli/cli-utils.h" /* for skip_to_space */
287d62b00eSchristos #include "command.h"
297d62b00eSchristos #include "gdbcmd.h"
307d62b00eSchristos #include "demangle.h"
317d62b00eSchristos #include "gdb-demangle.h"
327d62b00eSchristos #include "language.h"
337d62b00eSchristos 
347d62b00eSchristos /* Select the default C++ demangling style to use.  The default is "auto",
357d62b00eSchristos    which allows gdb to attempt to pick an appropriate demangling style for
367d62b00eSchristos    the executable it has loaded.  It can be set to a specific style ("gnu",
377d62b00eSchristos    "lucid", "arm", "hp", etc.) in which case gdb will never attempt to do auto
387d62b00eSchristos    selection of the style unless you do an explicit "set demangle auto".
397d62b00eSchristos    To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in
407d62b00eSchristos    the appropriate target configuration file.  */
417d62b00eSchristos 
427d62b00eSchristos #ifndef DEFAULT_DEMANGLING_STYLE
437d62b00eSchristos #define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING
447d62b00eSchristos #endif
457d62b00eSchristos 
467d62b00eSchristos /* See documentation in gdb-demangle.h.  */
477d62b00eSchristos bool demangle = true;
487d62b00eSchristos 
497d62b00eSchristos static void
507d62b00eSchristos show_demangle (struct ui_file *file, int from_tty,
517d62b00eSchristos 	       struct cmd_list_element *c, const char *value)
527d62b00eSchristos {
53*6881a400Schristos   gdb_printf (file,
547d62b00eSchristos 	      _("Demangling of encoded C++/ObjC names "
557d62b00eSchristos 		"when displaying symbols is %s.\n"),
567d62b00eSchristos 	      value);
577d62b00eSchristos }
587d62b00eSchristos 
597d62b00eSchristos /* See documentation in gdb-demangle.h.  */
607d62b00eSchristos bool asm_demangle = false;
617d62b00eSchristos 
627d62b00eSchristos static void
637d62b00eSchristos show_asm_demangle (struct ui_file *file, int from_tty,
647d62b00eSchristos 		   struct cmd_list_element *c, const char *value)
657d62b00eSchristos {
66*6881a400Schristos   gdb_printf (file,
677d62b00eSchristos 	      _("Demangling of C++/ObjC names in "
687d62b00eSchristos 		"disassembly listings is %s.\n"),
697d62b00eSchristos 	      value);
707d62b00eSchristos }
717d62b00eSchristos 
727d62b00eSchristos /* String name for the current demangling style.  Set by the
737d62b00eSchristos    "set demangle-style" command, printed as part of the output by the
747d62b00eSchristos    "show demangle-style" command.  */
757d62b00eSchristos 
767d62b00eSchristos static const char *current_demangling_style_string;
777d62b00eSchristos 
787d62b00eSchristos /* The array of names of the known demangling styles.  Generated by
797d62b00eSchristos    _initialize_demangler from libiberty_demanglers[] array.  */
807d62b00eSchristos 
817d62b00eSchristos static const char **demangling_style_names;
827d62b00eSchristos static void
837d62b00eSchristos show_demangling_style_names(struct ui_file *file, int from_tty,
847d62b00eSchristos 			    struct cmd_list_element *c, const char *value)
857d62b00eSchristos {
86*6881a400Schristos   gdb_printf (file, _("The current C++ demangling style is \"%s\".\n"),
877d62b00eSchristos 	      value);
887d62b00eSchristos }
897d62b00eSchristos 
907d62b00eSchristos /* Set current demangling style.  Called by the "set demangle-style"
917d62b00eSchristos    command after it has updated the current_demangling_style_string to
927d62b00eSchristos    match what the user has entered.
937d62b00eSchristos 
947d62b00eSchristos    If the user has entered a string that matches a known demangling style
957d62b00eSchristos    name in the demanglers[] array then just leave the string alone and update
967d62b00eSchristos    the current_demangling_style enum value to match.
977d62b00eSchristos 
987d62b00eSchristos    If the user has entered a string that doesn't match, including an empty
997d62b00eSchristos    string, then print a list of the currently known styles and restore
1007d62b00eSchristos    the current_demangling_style_string to match the current_demangling_style
1017d62b00eSchristos    enum value.
1027d62b00eSchristos 
1037d62b00eSchristos    Note:  Assumes that current_demangling_style_string always points to
1047d62b00eSchristos    a malloc'd string, even if it is a null-string.  */
1057d62b00eSchristos 
1067d62b00eSchristos static void
1077d62b00eSchristos set_demangling_command (const char *ignore,
1087d62b00eSchristos 			int from_tty, struct cmd_list_element *c)
1097d62b00eSchristos {
1107d62b00eSchristos   const struct demangler_engine *dem;
1117d62b00eSchristos   int i;
1127d62b00eSchristos 
1137d62b00eSchristos   /*  First just try to match whatever style name the user supplied with
1147d62b00eSchristos      one of the known ones.  Don't bother special casing for an empty
1157d62b00eSchristos      name, we just treat it as any other style name that doesn't match.
1167d62b00eSchristos      If we match, update the current demangling style enum.  */
1177d62b00eSchristos 
1187d62b00eSchristos   for (dem = libiberty_demanglers, i = 0;
1197d62b00eSchristos        dem->demangling_style != unknown_demangling;
1207d62b00eSchristos        dem++)
1217d62b00eSchristos     {
1227d62b00eSchristos       if (strcmp (current_demangling_style_string,
1237d62b00eSchristos 		  dem->demangling_style_name) == 0)
1247d62b00eSchristos 	{
1257d62b00eSchristos 	  current_demangling_style = dem->demangling_style;
1267d62b00eSchristos 	  current_demangling_style_string = demangling_style_names[i];
1277d62b00eSchristos 	  break;
1287d62b00eSchristos 	}
1297d62b00eSchristos       i++;
1307d62b00eSchristos     }
1317d62b00eSchristos 
1327d62b00eSchristos   /* We should have found a match, given we only add known styles to
1337d62b00eSchristos      the enumeration list.  */
1347d62b00eSchristos   gdb_assert (dem->demangling_style != unknown_demangling);
1357d62b00eSchristos }
1367d62b00eSchristos 
1377d62b00eSchristos /* G++ uses a special character to indicate certain internal names.  Which
1387d62b00eSchristos    character it is depends on the platform:
1397d62b00eSchristos    - Usually '$' on systems where the assembler will accept that
1407d62b00eSchristos    - Usually '.' otherwise (this includes most sysv4-like systems and most
1417d62b00eSchristos      ELF targets)
1427d62b00eSchristos    - Occasionally '_' if neither of the above is usable
1437d62b00eSchristos 
1447d62b00eSchristos    We check '$' first because it is the safest, and '.' often has another
1457d62b00eSchristos    meaning.  We don't currently try to handle '_' because the precise forms
1467d62b00eSchristos    of the names are different on those targets.  */
1477d62b00eSchristos 
1487d62b00eSchristos static char cplus_markers[] = {'$', '.', '\0'};
1497d62b00eSchristos 
1507d62b00eSchristos /* See documentation in gdb-demangle.h.  */
1517d62b00eSchristos 
1527d62b00eSchristos bool
1537d62b00eSchristos is_cplus_marker (int c)
1547d62b00eSchristos {
1557d62b00eSchristos   return c && strchr (cplus_markers, c) != NULL;
1567d62b00eSchristos }
1577d62b00eSchristos 
1587d62b00eSchristos /* Demangle the given string in the current language.  */
1597d62b00eSchristos 
1607d62b00eSchristos static void
1617d62b00eSchristos demangle_command (const char *args, int from_tty)
1627d62b00eSchristos {
1637d62b00eSchristos   const char *name;
1647d62b00eSchristos   const char *arg_start;
1657d62b00eSchristos   int processing_args = 1;
1667d62b00eSchristos   const struct language_defn *lang;
1677d62b00eSchristos 
1687d62b00eSchristos   std::string arg_buf = args != NULL ? args : "";
1697d62b00eSchristos   arg_start = arg_buf.c_str ();
1707d62b00eSchristos 
1717d62b00eSchristos   std::string lang_name;
1727d62b00eSchristos   while (processing_args
1737d62b00eSchristos 	 && *arg_start == '-')
1747d62b00eSchristos     {
1757d62b00eSchristos       const char *p = skip_to_space (arg_start);
1767d62b00eSchristos 
1777d62b00eSchristos       if (strncmp (arg_start, "-l", p - arg_start) == 0)
1787d62b00eSchristos 	lang_name = extract_arg (&p);
1797d62b00eSchristos       else if (strncmp (arg_start, "--", p - arg_start) == 0)
1807d62b00eSchristos 	processing_args = 0;
1817d62b00eSchristos       else
1827d62b00eSchristos 	report_unrecognized_option_error ("demangle", arg_start);
1837d62b00eSchristos 
1847d62b00eSchristos       arg_start = skip_spaces (p);
1857d62b00eSchristos     }
1867d62b00eSchristos 
1877d62b00eSchristos   name = arg_start;
1887d62b00eSchristos 
1897d62b00eSchristos   if (*name == '\0')
1907d62b00eSchristos     error (_("Usage: demangle [-l LANGUAGE] [--] NAME"));
1917d62b00eSchristos 
1927d62b00eSchristos   if (!lang_name.empty ())
1937d62b00eSchristos     {
1947d62b00eSchristos       enum language lang_enum;
1957d62b00eSchristos 
1967d62b00eSchristos       lang_enum = language_enum (lang_name.c_str ());
1977d62b00eSchristos       if (lang_enum == language_unknown)
1987d62b00eSchristos 	error (_("Unknown language \"%s\""), lang_name.c_str ());
1997d62b00eSchristos       lang = language_def (lang_enum);
2007d62b00eSchristos     }
2017d62b00eSchristos   else
2027d62b00eSchristos     lang = current_language;
2037d62b00eSchristos 
204*6881a400Schristos   gdb::unique_xmalloc_ptr<char> demangled
205*6881a400Schristos     = language_demangle (lang, name, DMGL_ANSI | DMGL_PARAMS);
2067d62b00eSchristos   if (demangled != NULL)
207*6881a400Schristos     gdb_printf ("%s\n", demangled.get ());
2087d62b00eSchristos   else
2097d62b00eSchristos     error (_("Can't demangle \"%s\""), name);
2107d62b00eSchristos }
2117d62b00eSchristos 
2127d62b00eSchristos void _initialize_gdb_demangle ();
2137d62b00eSchristos void
2147d62b00eSchristos _initialize_gdb_demangle ()
2157d62b00eSchristos {
2167d62b00eSchristos   int i, ndems;
2177d62b00eSchristos 
2187d62b00eSchristos   /* Fill the demangling_style_names[] array, and set the default
2197d62b00eSchristos      demangling style chosen at compilation time.  */
2207d62b00eSchristos   for (ndems = 0;
2217d62b00eSchristos        libiberty_demanglers[ndems].demangling_style != unknown_demangling;
2227d62b00eSchristos        ndems++)
2237d62b00eSchristos     ;
2247d62b00eSchristos   demangling_style_names = XCNEWVEC (const char *, ndems + 1);
2257d62b00eSchristos   for (i = 0;
2267d62b00eSchristos        libiberty_demanglers[i].demangling_style != unknown_demangling;
2277d62b00eSchristos        i++)
2287d62b00eSchristos     {
2297d62b00eSchristos       demangling_style_names[i]
2307d62b00eSchristos 	= xstrdup (libiberty_demanglers[i].demangling_style_name);
2317d62b00eSchristos 
2327d62b00eSchristos       if (current_demangling_style_string == NULL
2337d62b00eSchristos 	  && strcmp (DEFAULT_DEMANGLING_STYLE, demangling_style_names[i]) == 0)
2347d62b00eSchristos 	current_demangling_style_string = demangling_style_names[i];
2357d62b00eSchristos     }
2367d62b00eSchristos 
2377d62b00eSchristos   add_setshow_boolean_cmd ("demangle", class_support, &demangle, _("\
2387d62b00eSchristos Set demangling of encoded C++/ObjC names when displaying symbols."), _("\
2397d62b00eSchristos Show demangling of encoded C++/ObjC names when displaying symbols."), NULL,
2407d62b00eSchristos 			   NULL,
2417d62b00eSchristos 			   show_demangle,
2427d62b00eSchristos 			   &setprintlist, &showprintlist);
2437d62b00eSchristos 
2447d62b00eSchristos   add_setshow_boolean_cmd ("asm-demangle", class_support, &asm_demangle, _("\
2457d62b00eSchristos Set demangling of C++/ObjC names in disassembly listings."), _("\
2467d62b00eSchristos Show demangling of C++/ObjC names in disassembly listings."), NULL,
2477d62b00eSchristos 			   NULL,
2487d62b00eSchristos 			   show_asm_demangle,
2497d62b00eSchristos 			   &setprintlist, &showprintlist);
2507d62b00eSchristos 
2517d62b00eSchristos   add_setshow_enum_cmd ("demangle-style", class_support,
2527d62b00eSchristos 			demangling_style_names,
2537d62b00eSchristos 			&current_demangling_style_string, _("\
2547d62b00eSchristos Set the current C++ demangling style."), _("\
2557d62b00eSchristos Show the current C++ demangling style."), _("\
2567d62b00eSchristos Use `set demangle-style' without arguments for a list of demangling styles."),
2577d62b00eSchristos 			set_demangling_command,
2587d62b00eSchristos 			show_demangling_style_names,
2597d62b00eSchristos 			&setlist, &showlist);
2607d62b00eSchristos 
2617d62b00eSchristos   add_cmd ("demangle", class_support, demangle_command, _("\
2627d62b00eSchristos Demangle a mangled name.\n\
2637d62b00eSchristos Usage: demangle [-l LANGUAGE] [--] NAME\n\
2647d62b00eSchristos If LANGUAGE is not specified, NAME is demangled in the current language."),
2657d62b00eSchristos 	   &cmdlist);
2667d62b00eSchristos }
267