(root)/
binutils-2.41/
libiberty/
cplus-dem.c
       1  /* Demangler for GNU C++
       2     Copyright (C) 1989-2023 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 Rust demangling is implemented elsewhere.
     163       Legacy Rust symbols overlap with GNU_V3, so try Rust first.  */
     164    if (RUST_DEMANGLING || AUTO_DEMANGLING)
     165      {
     166        ret = rust_demangle (mangled, options);
     167        if (ret || RUST_DEMANGLING)
     168          return ret;
     169      }
     170  
     171    /* The V3 ABI demangling is implemented elsewhere.  */
     172    if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
     173      {
     174        ret = cplus_demangle_v3 (mangled, options);
     175        if (ret || GNU_V3_DEMANGLING)
     176  	return ret;
     177      }
     178  
     179    if (JAVA_DEMANGLING)
     180      {
     181        ret = java_demangle_v3 (mangled);
     182        if (ret)
     183          return ret;
     184      }
     185  
     186    if (GNAT_DEMANGLING)
     187      return ada_demangle (mangled, options);
     188  
     189    if (DLANG_DEMANGLING)
     190      {
     191        ret = dlang_demangle (mangled, options);
     192        if (ret)
     193  	return ret;
     194      }
     195  
     196    return (ret);
     197  }
     198  
     199  /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
     200  
     201  char *
     202  ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
     203  {
     204    int len0;
     205    const char* p;
     206    char *d;
     207    char *demangled = NULL;
     208    
     209    /* Discard leading _ada_, which is used for library level subprograms.  */
     210    if (strncmp (mangled, "_ada_", 5) == 0)
     211      mangled += 5;
     212  
     213    /* All ada unit names are lower-case.  */
     214    if (!ISLOWER (mangled[0]))
     215      goto unknown;
     216  
     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);
     224    
     225    d = demangled;
     226    p = mangled;
     227    while (1)
     228      {
     229        /* An entity names is expected.  */
     230        if (ISLOWER (*p))
     231          {
     232            /* An identifier, which is always lower case.  */
     233            do
     234              *d++ = *p++;
     235            while (ISLOWER(*p) || ISDIGIT (*p)
     236                   || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
     237          }
     238        else if (p[0] == 'O')
     239          {
     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}};
     249            int k;
     250  
     251            for (k = 0; operators[k][0] != NULL; k++)
     252              {
     253                size_t slen = strlen (operators[k][0]);
     254                if (strncmp (p, operators[k][0], slen) == 0)
     255                  {
     256                    p += slen;
     257                    slen = strlen (operators[k][1]);
     258                    *d++ = '"';
     259                    memcpy (d, operators[k][1], slen);
     260                    d += slen;
     261                    *d++ = '"';
     262                    break;
     263                  }
     264              }
     265            /* Operator not found.  */
     266            if (operators[k][0] == NULL)
     267              goto unknown;
     268          }
     269        else
     270          {
     271            /* Not a GNAT encoding.  */
     272            goto unknown;
     273          }
     274  
     275        /* The name can be directly followed by some uppercase letters.  */
     276        if (p[0] == 'T' && p[1] == 'K')
     277          {
     278            /* Task stuff.  */
     279            if (p[2] == 'B' && p[3] == 0)
     280              {
     281                /* Subprogram for task body.  */
     282                break;
     283              }
     284            else if (p[2] == '_' && p[3] == '_')
     285              {
     286                /* Inner declarations in a task.  */
     287                p += 4;
     288                *d++ = '.';
     289                continue;
     290              }
     291            else
     292              goto unknown;
     293          }
     294        if (p[0] == 'E' && p[1] == 0)
     295          {
     296            /* Exception name.  */
     297            goto unknown;
     298          }
     299        if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
     300          {
     301            /* Protected type subprogram.  */
     302            break;
     303          }
     304        if ((*p == 'N' || *p == 'S') && p[1] == 0)
     305          {
     306            /* Enumerated type name table.  */
     307            goto unknown;
     308          }
     309        if (p[0] == 'X')
     310          {
     311            /* Body nested.  */
     312            p++;
     313            while (p[0] == 'n' || p[0] == 'b')
     314              p++;
     315          }
     316        if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
     317          {
     318            /* Stream operations.  */
     319            const char *name;
     320            switch (p[1])
     321              {
     322              case 'R':
     323                name = "'Read";
     324                break;
     325              case 'W':
     326                name = "'Write";
     327                break;
     328              case 'I':
     329                name = "'Input";
     330                break;
     331              case 'O':
     332                name = "'Output";
     333                break;
     334              default:
     335                goto unknown;
     336              }
     337            p += 2;
     338            strcpy (d, name);
     339            d += strlen (name);
     340          }
     341        else if (p[0] == 'D')
     342          {
     343            /* Controlled type operation.  */
     344            const char *name;
     345            switch (p[1])
     346              {
     347              case 'F':
     348                name = ".Finalize";
     349                break;
     350              case 'A':
     351                name = ".Adjust";
     352                break;
     353              default:
     354                goto unknown;
     355              }
     356            strcpy (d, name);
     357            d += strlen (name);
     358            break;
     359          }
     360  
     361        if (p[0] == '_')
     362          {
     363            /* Separator.  */
     364            if (p[1] == '_')
     365              {
     366                /* Standard separator.  Handled first.  */
     367                p += 2;
     368  
     369                if (ISDIGIT (*p))
     370                  {
     371                    /* Overloading number.  */
     372                    do
     373                      p++;
     374                    while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
     375                    if (*p == 'X')
     376                      {
     377                        p++;
     378                        while (p[0] == 'n' || p[0] == 'b')
     379                          p++;
     380                      }
     381                  }
     382                else if (p[0] == '_' && p[1] != '_')
     383                  {
     384                    /* Special names.  */
     385                    static const char * const special[][2] = {
     386                      { "_elabb", "'Elab_Body" },
     387                      { "_elabs", "'Elab_Spec" },
     388                      { "_size", "'Size" },
     389                      { "_alignment", "'Alignment" },
     390                      { "_assign", ".\":=\"" },
     391                      { NULL, NULL }
     392                    };
     393                    int k;
     394  
     395                    for (k = 0; special[k][0] != NULL; k++)
     396                      {
     397                        size_t slen = strlen (special[k][0]);
     398                        if (strncmp (p, special[k][0], slen) == 0)
     399                          {
     400                            p += slen;
     401                            slen = strlen (special[k][1]);
     402                            memcpy (d, special[k][1], slen);
     403                            d += slen;
     404                            break;
     405                          }
     406                      }
     407                    if (special[k][0] != NULL)
     408                      break;
     409                    else
     410                      goto unknown;
     411                  }
     412                else
     413                  {
     414                    *d++ = '.';
     415                    continue;
     416                  }
     417              }
     418            else if (p[1] == 'B' || p[1] == 'E')
     419              {
     420                /* Entry Body or barrier Evaluation.  */
     421                p += 2;
     422                while (ISDIGIT (*p))
     423                  p++;
     424                if (p[0] == 's' && p[1] == 0)
     425                  break;
     426                else
     427                  goto unknown;
     428              }
     429            else
     430              goto unknown;
     431          }
     432  
     433        if (p[0] == '.' && ISDIGIT (p[1]))
     434          {
     435            /* Nested subprogram.  */
     436            p += 2;
     437            while (ISDIGIT (*p))
     438              p++;
     439          }
     440        if (*p == 0)
     441          {
     442            /* End of mangled name.  */
     443            break;
     444          }
     445        else
     446          goto unknown;
     447      }
     448    *d = 0;
     449    return demangled;
     450  
     451   unknown:
     452    XDELETEVEC (demangled);
     453    len0 = strlen (mangled);
     454    demangled = XNEWVEC (char, len0 + 3);
     455  
     456    if (mangled[0] == '<')
     457       strcpy (demangled, mangled);
     458    else
     459      sprintf (demangled, "<%s>", mangled);
     460  
     461    return demangled;
     462  }