Wolfgang Thallergcc16 merge934c3885 months agoHistory
1604 lines · 34.7 KB · C
RawDownload
/* Demangler for the Rust programming language   Copyright (C) 2016-2026 Free Software Foundation, Inc.   Written by David Tolnay (dtolnay@gmail.com).   Rewritten by Eduard-Mihai Burtescu (eddyb@lyken.rs) for v0 support. This file is part of the libiberty library.Libiberty is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General PublicLicense as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version. In addition to the permissions in the GNU Library General PublicLicense, the Free Software Foundation gives you unlimited permissionto link the compiled version of this file into combinations with otherprograms, and to distribute those combinations without any restrictioncoming from the use of this file.  (The Library Public Licenserestrictions do apply in other respects; for example, they covermodification of the file, and distribution when not linked into acombined executable.) Libiberty is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULibrary General Public License for more details. You should have received a copy of the GNU Library General PublicLicense along with libiberty; see the file COPYING.LIB.If not, see <http://www.gnu.org/licenses/>.  */  #ifdef HAVE_CONFIG_H#include "config.h"#endif #include "safe-ctype.h" #include <inttypes.h>#include <sys/types.h>#include <string.h>#include <stdio.h>#include <stdlib.h> #ifdef HAVE_STRING_H#include <string.h>#elseextern size_t strlen(const char *s);extern int strncmp(const char *s1, const char *s2, size_t n);extern void *memset(void *s, int c, size_t n);#endif #include <demangle.h>#include "libiberty.h" struct rust_demangler{  const char *sym;  size_t sym_len;   void *callback_opaque;  demangle_callbackref callback;   /* Position of the next character to read from the symbol. */  size_t next;   /* Non-zero if any error occurred. */  int errored;   /* Non-zero if nothing should be printed. */  int skipping_printing;   /* Non-zero if printing should be verbose (e.g. include hashes). */  int verbose;   /* Rust mangling version, with legacy mangling being -1. */  int version;   /* Recursion depth.  */  unsigned int recursion;  /* Maximum number of times demangle_path may be called recursively.  */#define RUST_MAX_RECURSION_COUNT  1024#define RUST_NO_RECURSION_LIMIT   ((unsigned int) -1)   uint64_t bound_lifetime_depth;}; /* Parsing functions. */ static charpeek (const struct rust_demangler *rdm){  if (rdm->next < rdm->sym_len)    return rdm->sym[rdm->next];  return 0;} static inteat (struct rust_demangler *rdm, char c){  if (peek (rdm) == c)    {      rdm->next++;      return 1;    }  else    return 0;} static charnext (struct rust_demangler *rdm){  char c = peek (rdm);  if (!c)    rdm->errored = 1;  else    rdm->next++;  return c;} static uint64_tparse_integer_62 (struct rust_demangler *rdm){  char c;  uint64_t x;   if (eat (rdm, '_'))    return 0;   x = 0;  while (!eat (rdm, '_') && !rdm->errored)    {      c = next (rdm);      x *= 62;      if (ISDIGIT (c))        x += c - '0';      else if (ISLOWER (c))        x += 10 + (c - 'a');      else if (ISUPPER (c))        x += 10 + 26 + (c - 'A');      else        {          rdm->errored = 1;          return 0;        }    }  return x + 1;} static uint64_tparse_opt_integer_62 (struct rust_demangler *rdm, char tag){  if (!eat (rdm, tag))    return 0;  return 1 + parse_integer_62 (rdm);} static uint64_tparse_disambiguator (struct rust_demangler *rdm){  return parse_opt_integer_62 (rdm, 's');} static size_tparse_hex_nibbles (struct rust_demangler *rdm, uint64_t *value){  char c;  size_t hex_len;   hex_len = 0;  *value = 0;   while (!eat (rdm, '_'))    {      *value <<= 4;       c = next (rdm);      if (ISDIGIT (c))        *value |= c - '0';      else if (c >= 'a' && c <= 'f')        *value |= 10 + (c - 'a');      else        {          rdm->errored = 1;          return 0;        }      hex_len++;    }   return hex_len;} struct rust_mangled_ident{  /* ASCII part of the identifier. */  const char *ascii;  size_t ascii_len;   /* Punycode insertion codes for Unicode codepoints, if any. */  const char *punycode;  size_t punycode_len;}; static struct rust_mangled_identparse_ident (struct rust_demangler *rdm){  char c;  size_t start, len;  int is_punycode = 0;  struct rust_mangled_ident ident;   ident.ascii = NULL;  ident.ascii_len = 0;  ident.punycode = NULL;  ident.punycode_len = 0;   if (rdm->version != -1)    is_punycode = eat (rdm, 'u');   c = next (rdm);  if (!ISDIGIT (c))    {      rdm->errored = 1;      return ident;    }  len = c - '0';   if (c != '0')    while (ISDIGIT (peek (rdm)))      len = len * 10 + (next (rdm) - '0');   /* Skip past the optional `_` separator (v0). */  if (rdm->version != -1)    eat (rdm, '_');   start = rdm->next;  rdm->next += len;  /* Check for overflows. */  if ((start > rdm->next) || (rdm->next > rdm->sym_len))    {      rdm->errored = 1;      return ident;    }   ident.ascii = rdm->sym + start;  ident.ascii_len = len;   if (is_punycode)    {      ident.punycode_len = 0;      while (ident.ascii_len > 0)        {          ident.ascii_len--;           /* The last '_' is a separator between ascii & punycode. */          if (ident.ascii[ident.ascii_len] == '_')            break;           ident.punycode_len++;        }      if (!ident.punycode_len)        {          rdm->errored = 1;          return ident;        }      ident.punycode = ident.ascii + (len - ident.punycode_len);    }   if (ident.ascii_len == 0)    ident.ascii = NULL;   return ident;} /* Printing functions. */ static voidprint_str (struct rust_demangler *rdm, const char *data, size_t len){  if (!rdm->errored && !rdm->skipping_printing)    rdm->callback (data, len, rdm->callback_opaque);} #define PRINT(s) print_str (rdm, s, strlen (s)) static voidprint_uint64 (struct rust_demangler *rdm, uint64_t x){  char s[21];  snprintf (s, 21, "%" PRIu64, x);  PRINT (s);} static voidprint_uint64_hex (struct rust_demangler *rdm, uint64_t x){  char s[17];  snprintf (s, 17, "%" PRIx64, x);  PRINT (s);} /* Return a 0x0-0xf value if the char is 0-9a-f, and -1 otherwise. */static intdecode_lower_hex_nibble (char nibble){  if ('0' <= nibble && nibble <= '9')    return nibble - '0';  if ('a' <= nibble && nibble <= 'f')    return 0xa + (nibble - 'a');  return -1;} /* Return the unescaped character for a "$...$" escape, or 0 if invalid. */static chardecode_legacy_escape (const char *e, size_t len, size_t *out_len){  char c = 0;  size_t escape_len = 0;  int lo_nibble = -1, hi_nibble = -1;   if (len < 3 || e[0] != '$')    return 0;   e++;  len--;   if (e[0] == 'C')    {      escape_len = 1;       c = ',';    }  else if (len > 2)    {      escape_len = 2;       if (e[0] == 'S' && e[1] == 'P')        c = '@';      else if (e[0] == 'B' && e[1] == 'P')        c = '*';      else if (e[0] == 'R' && e[1] == 'F')        c = '&';      else if (e[0] == 'L' && e[1] == 'T')        c = '<';      else if (e[0] == 'G' && e[1] == 'T')        c = '>';      else if (e[0] == 'L' && e[1] == 'P')        c = '(';      else if (e[0] == 'R' && e[1] == 'P')        c = ')';      else if (e[0] == 'u' && len > 3)        {          escape_len = 3;           hi_nibble = decode_lower_hex_nibble (e[1]);          if (hi_nibble < 0)            return 0;          lo_nibble = decode_lower_hex_nibble (e[2]);          if (lo_nibble < 0)            return 0;           /* Only allow non-control ASCII characters. */          if (hi_nibble > 7)            return 0;          c = (hi_nibble << 4) | lo_nibble;          if (c < 0x20)            return 0;        }    }   if (!c || len <= escape_len || e[escape_len] != '$')    return 0;   *out_len = 2 + escape_len;  return c;} static voidprint_ident (struct rust_demangler *rdm, struct rust_mangled_ident ident){  char unescaped;  uint8_t *out, *p, d;  size_t len, cap, punycode_pos, j;  /* Punycode parameters and state. */  uint32_t c;  size_t base, t_min, t_max, skew, damp, bias, i;  size_t delta, w, k, t;   if (rdm->errored || rdm->skipping_printing)    return;   if (rdm->version == -1)    {      /* Ignore leading underscores preceding escape sequences.         The mangler inserts an underscore to make sure the         identifier begins with a XID_Start character. */      if (ident.ascii_len >= 2 && ident.ascii[0] == '_'          && ident.ascii[1] == '$')        {          ident.ascii++;          ident.ascii_len--;        }       while (ident.ascii_len > 0)        {          /* Handle legacy escape sequences ("$...$", ".." or "."). */          if (ident.ascii[0] == '$')            {              unescaped                  = decode_legacy_escape (ident.ascii, ident.ascii_len, &len);              if (unescaped)                print_str (rdm, &unescaped, 1);              else                {                  /* Unexpected escape sequence, print the rest verbatim. */                  print_str (rdm, ident.ascii, ident.ascii_len);                  return;                }            }          else if (ident.ascii[0] == '.')            {              if (ident.ascii_len >= 2 && ident.ascii[1] == '.')                {                  /* ".." becomes "::" */                  PRINT ("::");                  len = 2;                }              else                {                  PRINT (".");                  len = 1;                }            }          else            {              /* Print everything before the next escape sequence, at once. */              for (len = 0; len < ident.ascii_len; len++)                if (ident.ascii[len] == '$' || ident.ascii[len] == '.')                  break;               print_str (rdm, ident.ascii, len);            }           ident.ascii += len;          ident.ascii_len -= len;        }       return;    }   if (!ident.punycode)    {      print_str (rdm, ident.ascii, ident.ascii_len);      return;    }   len = 0;  cap = 4;  while (cap < ident.ascii_len)    {      cap *= 2;      /* Check for overflows. */      if ((cap * 4) / 4 != cap)        {          rdm->errored = 1;          return;        }    }   /* Store the output codepoints as groups of 4 UTF-8 bytes. */  out = (uint8_t *)malloc (cap * 4);  if (!out)    {      rdm->errored = 1;      return;    }   /* Populate initial output from ASCII fragment. */  for (len = 0; len < ident.ascii_len; len++)    {      p = out + 4 * len;      p[0] = 0;      p[1] = 0;      p[2] = 0;      p[3] = ident.ascii[len];    }   /* Punycode parameters and initial state. */  base = 36;  t_min = 1;  t_max = 26;  skew = 38;  damp = 700;  bias = 72;  i = 0;  c = 0x80;   punycode_pos = 0;  while (punycode_pos < ident.punycode_len)    {      /* Read one delta value. */      delta = 0;

Lines 1–500 of 1604.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t