demangle.cc
Go to the documentation of this file.
1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Satoru Takabayashi
31 //
32 // For reference check out:
33 // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
34 //
35 // Note that we only have partial C++0x support yet.
36 
37 #include <cstdio> // for NULL
38 
39 #include "demangle.h"
40 #include "utilities.h"
41 
42 #if defined(GLOG_OS_WINDOWS)
43 #include <dbghelp.h>
44 #endif
45 
47 
48 #if !defined(GLOG_OS_WINDOWS)
49 typedef struct {
50  const char *abbrev;
51  const char *real_name;
52 } AbbrevPair;
53 
54 // List of operators from Itanium C++ ABI.
55 static const AbbrevPair kOperatorList[] = {
56  { "nw", "new" },
57  { "na", "new[]" },
58  { "dl", "delete" },
59  { "da", "delete[]" },
60  { "ps", "+" },
61  { "ng", "-" },
62  { "ad", "&" },
63  { "de", "*" },
64  { "co", "~" },
65  { "pl", "+" },
66  { "mi", "-" },
67  { "ml", "*" },
68  { "dv", "/" },
69  { "rm", "%" },
70  { "an", "&" },
71  { "or", "|" },
72  { "eo", "^" },
73  { "aS", "=" },
74  { "pL", "+=" },
75  { "mI", "-=" },
76  { "mL", "*=" },
77  { "dV", "/=" },
78  { "rM", "%=" },
79  { "aN", "&=" },
80  { "oR", "|=" },
81  { "eO", "^=" },
82  { "ls", "<<" },
83  { "rs", ">>" },
84  { "lS", "<<=" },
85  { "rS", ">>=" },
86  { "eq", "==" },
87  { "ne", "!=" },
88  { "lt", "<" },
89  { "gt", ">" },
90  { "le", "<=" },
91  { "ge", ">=" },
92  { "nt", "!" },
93  { "aa", "&&" },
94  { "oo", "||" },
95  { "pp", "++" },
96  { "mm", "--" },
97  { "cm", "," },
98  { "pm", "->*" },
99  { "pt", "->" },
100  { "cl", "()" },
101  { "ix", "[]" },
102  { "qu", "?" },
103  { "st", "sizeof" },
104  { "sz", "sizeof" },
105  { NULL, NULL },
106 };
107 
108 // List of builtin types from Itanium C++ ABI.
109 static const AbbrevPair kBuiltinTypeList[] = {
110  { "v", "void" },
111  { "w", "wchar_t" },
112  { "b", "bool" },
113  { "c", "char" },
114  { "a", "signed char" },
115  { "h", "unsigned char" },
116  { "s", "short" },
117  { "t", "unsigned short" },
118  { "i", "int" },
119  { "j", "unsigned int" },
120  { "l", "long" },
121  { "m", "unsigned long" },
122  { "x", "long long" },
123  { "y", "unsigned long long" },
124  { "n", "__int128" },
125  { "o", "unsigned __int128" },
126  { "f", "float" },
127  { "d", "double" },
128  { "e", "long double" },
129  { "g", "__float128" },
130  { "z", "ellipsis" },
131  { NULL, NULL }
132 };
133 
134 // List of substitutions Itanium C++ ABI.
135 static const AbbrevPair kSubstitutionList[] = {
136  { "St", "" },
137  { "Sa", "allocator" },
138  { "Sb", "basic_string" },
139  // std::basic_string<char, std::char_traits<char>,std::allocator<char> >
140  { "Ss", "string"},
141  // std::basic_istream<char, std::char_traits<char> >
142  { "Si", "istream" },
143  // std::basic_ostream<char, std::char_traits<char> >
144  { "So", "ostream" },
145  // std::basic_iostream<char, std::char_traits<char> >
146  { "Sd", "iostream" },
147  { NULL, NULL }
148 };
149 
150 // State needed for demangling.
151 typedef struct {
152  const char *mangled_cur; // Cursor of mangled name.
153  char *out_cur; // Cursor of output string.
154  const char *out_begin; // Beginning of output string.
155  const char *out_end; // End of output string.
156  const char *prev_name; // For constructors/destructors.
157  int prev_name_length; // For constructors/destructors.
158  short nest_level; // For nested names.
159  bool append; // Append flag.
160  bool overflowed; // True if output gets overflowed.
161 } State;
162 
163 // We don't use strlen() in libc since it's not guaranteed to be async
164 // signal safe.
165 static size_t StrLen(const char *str) {
166  size_t len = 0;
167  while (*str != '\0') {
168  ++str;
169  ++len;
170  }
171  return len;
172 }
173 
174 // Returns true if "str" has at least "n" characters remaining.
175 static bool AtLeastNumCharsRemaining(const char *str, int n) {
176  for (int i = 0; i < n; ++i) {
177  if (str[i] == '\0') {
178  return false;
179  }
180  }
181  return true;
182 }
183 
184 // Returns true if "str" has "prefix" as a prefix.
185 static bool StrPrefix(const char *str, const char *prefix) {
186  size_t i = 0;
187  while (str[i] != '\0' && prefix[i] != '\0' &&
188  str[i] == prefix[i]) {
189  ++i;
190  }
191  return prefix[i] == '\0'; // Consumed everything in "prefix".
192 }
193 
194 static void InitState(State *state, const char *mangled,
195  char *out, size_t out_size) {
196  state->mangled_cur = mangled;
197  state->out_cur = out;
198  state->out_begin = out;
199  state->out_end = out + out_size;
200  state->prev_name = NULL;
201  state->prev_name_length = -1;
202  state->nest_level = -1;
203  state->append = true;
204  state->overflowed = false;
205 }
206 
207 // Returns true and advances "mangled_cur" if we find "one_char_token"
208 // at "mangled_cur" position. It is assumed that "one_char_token" does
209 // not contain '\0'.
210 static bool ParseOneCharToken(State *state, const char one_char_token) {
211  if (state->mangled_cur[0] == one_char_token) {
212  ++state->mangled_cur;
213  return true;
214  }
215  return false;
216 }
217 
218 // Returns true and advances "mangled_cur" if we find "two_char_token"
219 // at "mangled_cur" position. It is assumed that "two_char_token" does
220 // not contain '\0'.
221 static bool ParseTwoCharToken(State *state, const char *two_char_token) {
222  if (state->mangled_cur[0] == two_char_token[0] &&
223  state->mangled_cur[1] == two_char_token[1]) {
224  state->mangled_cur += 2;
225  return true;
226  }
227  return false;
228 }
229 
230 // Returns true and advances "mangled_cur" if we find any character in
231 // "char_class" at "mangled_cur" position.
232 static bool ParseCharClass(State *state, const char *char_class) {
233  const char *p = char_class;
234  for (; *p != '\0'; ++p) {
235  if (state->mangled_cur[0] == *p) {
236  ++state->mangled_cur;
237  return true;
238  }
239  }
240  return false;
241 }
242 
243 // This function is used for handling an optional non-terminal.
244 static bool Optional(bool) {
245  return true;
246 }
247 
248 // This function is used for handling <non-terminal>+ syntax.
249 typedef bool (*ParseFunc)(State *);
250 static bool OneOrMore(ParseFunc parse_func, State *state) {
251  if (parse_func(state)) {
252  while (parse_func(state)) {
253  }
254  return true;
255  }
256  return false;
257 }
258 
259 // This function is used for handling <non-terminal>* syntax. The function
260 // always returns true and must be followed by a termination token or a
261 // terminating sequence not handled by parse_func (e.g.
262 // ParseOneCharToken(state, 'E')).
263 static bool ZeroOrMore(ParseFunc parse_func, State *state) {
264  while (parse_func(state)) {
265  }
266  return true;
267 }
268 
269 // Append "str" at "out_cur". If there is an overflow, "overflowed"
270 // is set to true for later use. The output string is ensured to
271 // always terminate with '\0' as long as there is no overflow.
272 static void Append(State *state, const char * const str, const int length) {
273  int i;
274  for (i = 0; i < length; ++i) {
275  if (state->out_cur + 1 < state->out_end) { // +1 for '\0'
276  *state->out_cur = str[i];
277  ++state->out_cur;
278  } else {
279  state->overflowed = true;
280  break;
281  }
282  }
283  if (!state->overflowed) {
284  *state->out_cur = '\0'; // Terminate it with '\0'
285  }
286 }
287 
288 // We don't use equivalents in libc to avoid locale issues.
289 static bool IsLower(char c) {
290  return c >= 'a' && c <= 'z';
291 }
292 
293 static bool IsAlpha(char c) {
294  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
295 }
296 
297 static bool IsDigit(char c) {
298  return c >= '0' && c <= '9';
299 }
300 
301 // Returns true if "str" is a function clone suffix. These suffixes are used
302 // by GCC 4.5.x and later versions to indicate functions which have been
303 // cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as
304 // a function clone suffix.
305 static bool IsFunctionCloneSuffix(const char *str) {
306  size_t i = 0;
307  while (str[i] != '\0') {
308  // Consume a single .<alpha>+.<digit>+ sequence.
309  if (str[i] != '.' || !IsAlpha(str[i + 1])) {
310  return false;
311  }
312  i += 2;
313  while (IsAlpha(str[i])) {
314  ++i;
315  }
316  if (str[i] != '.' || !IsDigit(str[i + 1])) {
317  return false;
318  }
319  i += 2;
320  while (IsDigit(str[i])) {
321  ++i;
322  }
323  }
324  return true; // Consumed everything in "str".
325 }
326 
327 // Append "str" with some tweaks, iff "append" state is true.
328 // Returns true so that it can be placed in "if" conditions.
329 static void MaybeAppendWithLength(State *state, const char * const str,
330  const int length) {
331  if (state->append && length > 0) {
332  // Append a space if the output buffer ends with '<' and "str"
333  // starts with '<' to avoid <<<.
334  if (str[0] == '<' && state->out_begin < state->out_cur &&
335  state->out_cur[-1] == '<') {
336  Append(state, " ", 1);
337  }
338  // Remember the last identifier name for ctors/dtors.
339  if (IsAlpha(str[0]) || str[0] == '_') {
340  state->prev_name = state->out_cur;
341  state->prev_name_length = length;
342  }
343  Append(state, str, length);
344  }
345 }
346 
347 // A convenient wrapper arount MaybeAppendWithLength().
348 static bool MaybeAppend(State *state, const char * const str) {
349  if (state->append) {
350  int length = StrLen(str);
352  }
353  return true;
354 }
355 
356 // This function is used for handling nested names.
357 static bool EnterNestedName(State *state) {
358  state->nest_level = 0;
359  return true;
360 }
361 
362 // This function is used for handling nested names.
363 static bool LeaveNestedName(State *state, short prev_value) {
364  state->nest_level = prev_value;
365  return true;
366 }
367 
368 // Disable the append mode not to print function parameters, etc.
369 static bool DisableAppend(State *state) {
370  state->append = false;
371  return true;
372 }
373 
374 // Restore the append mode to the previous state.
375 static bool RestoreAppend(State *state, bool prev_value) {
376  state->append = prev_value;
377  return true;
378 }
379 
380 // Increase the nest level for nested names.
381 static void MaybeIncreaseNestLevel(State *state) {
382  if (state->nest_level > -1) {
383  ++state->nest_level;
384  }
385 }
386 
387 // Appends :: for nested names if necessary.
388 static void MaybeAppendSeparator(State *state) {
389  if (state->nest_level >= 1) {
390  MaybeAppend(state, "::");
391  }
392 }
393 
394 // Cancel the last separator if necessary.
395 static void MaybeCancelLastSeparator(State *state) {
396  if (state->nest_level >= 1 && state->append &&
397  state->out_begin <= state->out_cur - 2) {
398  state->out_cur -= 2;
399  *state->out_cur = '\0';
400  }
401 }
402 
403 // Returns true if the identifier of the given length pointed to by
404 // "mangled_cur" is anonymous namespace.
405 static bool IdentifierIsAnonymousNamespace(State *state, int length) {
406  static const char anon_prefix[] = "_GLOBAL__N_";
407  return (length >
408  static_cast<int>(sizeof(anon_prefix)) - 1 && // Should be longer.
409  StrPrefix(state->mangled_cur, anon_prefix));
410 }
411 
412 // Forward declarations of our parsing functions.
413 static bool ParseMangledName(State *state);
414 static bool ParseEncoding(State *state);
415 static bool ParseName(State *state);
416 static bool ParseUnscopedName(State *state);
417 static bool ParseUnscopedTemplateName(State *state);
418 static bool ParseNestedName(State *state);
419 static bool ParsePrefix(State *state);
420 static bool ParseUnqualifiedName(State *state);
421 static bool ParseSourceName(State *state);
422 static bool ParseLocalSourceName(State *state);
423 static bool ParseNumber(State *state, int *number_out);
424 static bool ParseFloatNumber(State *state);
425 static bool ParseSeqId(State *state);
426 static bool ParseIdentifier(State *state, int length);
427 static bool ParseAbiTags(State *state);
428 static bool ParseAbiTag(State *state);
429 static bool ParseOperatorName(State *state);
430 static bool ParseSpecialName(State *state);
431 static bool ParseCallOffset(State *state);
432 static bool ParseNVOffset(State *state);
433 static bool ParseVOffset(State *state);
434 static bool ParseCtorDtorName(State *state);
435 static bool ParseType(State *state);
436 static bool ParseCVQualifiers(State *state);
437 static bool ParseBuiltinType(State *state);
438 static bool ParseFunctionType(State *state);
439 static bool ParseBareFunctionType(State *state);
440 static bool ParseClassEnumType(State *state);
441 static bool ParseArrayType(State *state);
442 static bool ParsePointerToMemberType(State *state);
443 static bool ParseTemplateParam(State *state);
444 static bool ParseTemplateTemplateParam(State *state);
445 static bool ParseTemplateArgs(State *state);
446 static bool ParseTemplateArg(State *state);
447 static bool ParseExpression(State *state);
448 static bool ParseExprPrimary(State *state);
449 static bool ParseLocalName(State *state);
450 static bool ParseDiscriminator(State *state);
451 static bool ParseSubstitution(State *state);
452 
453 // Implementation note: the following code is a straightforward
454 // translation of the Itanium C++ ABI defined in BNF with a couple of
455 // exceptions.
456 //
457 // - Support GNU extensions not defined in the Itanium C++ ABI
458 // - <prefix> and <template-prefix> are combined to avoid infinite loop
459 // - Reorder patterns to shorten the code
460 // - Reorder patterns to give greedier functions precedence
461 // We'll mark "Less greedy than" for these cases in the code
462 //
463 // Each parsing function changes the state and returns true on
464 // success. Otherwise, don't change the state and returns false. To
465 // ensure that the state isn't changed in the latter case, we save the
466 // original state before we call more than one parsing functions
467 // consecutively with &&, and restore the state if unsuccessful. See
468 // ParseEncoding() as an example of this convention. We follow the
469 // convention throughout the code.
470 //
471 // Originally we tried to do demangling without following the full ABI
472 // syntax but it turned out we needed to follow the full syntax to
473 // parse complicated cases like nested template arguments. Note that
474 // implementing a full-fledged demangler isn't trivial (libiberty's
475 // cp-demangle.c has +4300 lines).
476 //
477 // Note that (foo) in <(foo) ...> is a modifier to be ignored.
478 //
479 // Reference:
480 // - Itanium C++ ABI
481 // <http://www.codesourcery.com/cxx-abi/abi.html#mangling>
482 
483 // <mangled-name> ::= _Z <encoding>
484 static bool ParseMangledName(State *state) {
485  return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
486 }
487 
488 // <encoding> ::= <(function) name> <bare-function-type>
489 // ::= <(data) name>
490 // ::= <special-name>
491 static bool ParseEncoding(State *state) {
492  State copy = *state;
493  if (ParseName(state) && ParseBareFunctionType(state)) {
494  return true;
495  }
496  *state = copy;
497 
498  if (ParseName(state) || ParseSpecialName(state)) {
499  return true;
500  }
501  return false;
502 }
503 
504 // <name> ::= <nested-name>
505 // ::= <unscoped-template-name> <template-args>
506 // ::= <unscoped-name>
507 // ::= <local-name>
508 static bool ParseName(State *state) {
509  if (ParseNestedName(state) || ParseLocalName(state)) {
510  return true;
511  }
512 
513  State copy = *state;
514  if (ParseUnscopedTemplateName(state) &&
515  ParseTemplateArgs(state)) {
516  return true;
517  }
518  *state = copy;
519 
520  // Less greedy than <unscoped-template-name> <template-args>.
521  if (ParseUnscopedName(state)) {
522  return true;
523  }
524  return false;
525 }
526 
527 // <unscoped-name> ::= <unqualified-name>
528 // ::= St <unqualified-name>
529 static bool ParseUnscopedName(State *state) {
530  if (ParseUnqualifiedName(state)) {
531  return true;
532  }
533 
534  State copy = *state;
535  if (ParseTwoCharToken(state, "St") &&
536  MaybeAppend(state, "std::") &&
537  ParseUnqualifiedName(state)) {
538  return true;
539  }
540  *state = copy;
541  return false;
542 }
543 
544 // <unscoped-template-name> ::= <unscoped-name>
545 // ::= <substitution>
546 static bool ParseUnscopedTemplateName(State *state) {
547  return ParseUnscopedName(state) || ParseSubstitution(state);
548 }
549 
550 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
551 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
552 static bool ParseNestedName(State *state) {
553  State copy = *state;
554  if (ParseOneCharToken(state, 'N') &&
555  EnterNestedName(state) &&
556  Optional(ParseCVQualifiers(state)) &&
557  ParsePrefix(state) &&
558  LeaveNestedName(state, copy.nest_level) &&
559  ParseOneCharToken(state, 'E')) {
560  return true;
561  }
562  *state = copy;
563  return false;
564 }
565 
566 // This part is tricky. If we literally translate them to code, we'll
567 // end up infinite loop. Hence we merge them to avoid the case.
568 //
569 // <prefix> ::= <prefix> <unqualified-name>
570 // ::= <template-prefix> <template-args>
571 // ::= <template-param>
572 // ::= <substitution>
573 // ::= # empty
574 // <template-prefix> ::= <prefix> <(template) unqualified-name>
575 // ::= <template-param>
576 // ::= <substitution>
577 static bool ParsePrefix(State *state) {
578  bool has_something = false;
579  while (true) {
580  MaybeAppendSeparator(state);
581  if (ParseTemplateParam(state) ||
582  ParseSubstitution(state) ||
583  ParseUnscopedName(state)) {
584  has_something = true;
585  MaybeIncreaseNestLevel(state);
586  continue;
587  }
589  if (has_something && ParseTemplateArgs(state)) {
590  return ParsePrefix(state);
591  } else {
592  break;
593  }
594  }
595  return true;
596 }
597 
598 // <unqualified-name> ::= <operator-name>
599 // ::= <ctor-dtor-name>
600 // ::= <source-name> [<abi-tags>]
601 // ::= <local-source-name> [<abi-tags>]
602 static bool ParseUnqualifiedName(State *state) {
603  return (ParseOperatorName(state) ||
604  ParseCtorDtorName(state) ||
605  (ParseSourceName(state) && Optional(ParseAbiTags(state))) ||
606  (ParseLocalSourceName(state) && Optional(ParseAbiTags(state))));
607 }
608 
609 // <source-name> ::= <positive length number> <identifier>
610 static bool ParseSourceName(State *state) {
611  State copy = *state;
612  int length = -1;
613  if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
614  return true;
615  }
616  *state = copy;
617  return false;
618 }
619 
620 // <local-source-name> ::= L <source-name> [<discriminator>]
621 //
622 // References:
623 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
624 // http://gcc.gnu.org/viewcvs?view=rev&revision=124467
625 static bool ParseLocalSourceName(State *state) {
626  State copy = *state;
627  if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&
628  Optional(ParseDiscriminator(state))) {
629  return true;
630  }
631  *state = copy;
632  return false;
633 }
634 
635 // <number> ::= [n] <non-negative decimal integer>
636 // If "number_out" is non-null, then *number_out is set to the value of the
637 // parsed number on success.
638 static bool ParseNumber(State *state, int *number_out) {
639  int sign = 1;
640  if (ParseOneCharToken(state, 'n')) {
641  sign = -1;
642  }
643  const char *p = state->mangled_cur;
644  int number = 0;
645  for (;*p != '\0'; ++p) {
646  if (IsDigit(*p)) {
647  number = number * 10 + (*p - '0');
648  } else {
649  break;
650  }
651  }
652  if (p != state->mangled_cur) { // Conversion succeeded.
653  state->mangled_cur = p;
654  if (number_out != NULL) {
655  *number_out = number * sign;
656  }
657  return true;
658  }
659  return false;
660 }
661 
662 // Floating-point literals are encoded using a fixed-length lowercase
663 // hexadecimal string.
664 static bool ParseFloatNumber(State *state) {
665  const char *p = state->mangled_cur;
666  for (;*p != '\0'; ++p) {
667  if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {
668  break;
669  }
670  }
671  if (p != state->mangled_cur) { // Conversion succeeded.
672  state->mangled_cur = p;
673  return true;
674  }
675  return false;
676 }
677 
678 // The <seq-id> is a sequence number in base 36,
679 // using digits and upper case letters
680 static bool ParseSeqId(State *state) {
681  const char *p = state->mangled_cur;
682  for (;*p != '\0'; ++p) {
683  if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {
684  break;
685  }
686  }
687  if (p != state->mangled_cur) { // Conversion succeeded.
688  state->mangled_cur = p;
689  return true;
690  }
691  return false;
692 }
693 
694 // <identifier> ::= <unqualified source code identifier> (of given length)
695 static bool ParseIdentifier(State *state, int length) {
696  if (length == -1 ||
698  return false;
699  }
701  MaybeAppend(state, "(anonymous namespace)");
702  } else {
703  MaybeAppendWithLength(state, state->mangled_cur, length);
704  }
705  state->mangled_cur += length;
706  return true;
707 }
708 
709 // <abi-tags> ::= <abi-tag> [<abi-tags>]
710 static bool ParseAbiTags(State *state) {
711  State copy = *state;
712  DisableAppend(state);
713  if (OneOrMore(ParseAbiTag, state)) {
714  RestoreAppend(state, copy.append);
715  return true;
716  }
717  *state = copy;
718  return false;
719 }
720 
721 // <abi-tag> ::= B <source-name>
722 static bool ParseAbiTag(State *state) {
723  return ParseOneCharToken(state, 'B') && ParseSourceName(state);
724 }
725 
726 // <operator-name> ::= nw, and other two letters cases
727 // ::= cv <type> # (cast)
728 // ::= v <digit> <source-name> # vendor extended operator
729 static bool ParseOperatorName(State *state) {
730  if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) {
731  return false;
732  }
733  // First check with "cv" (cast) case.
734  State copy = *state;
735  if (ParseTwoCharToken(state, "cv") &&
736  MaybeAppend(state, "operator ") &&
737  EnterNestedName(state) &&
738  ParseType(state) &&
739  LeaveNestedName(state, copy.nest_level)) {
740  return true;
741  }
742  *state = copy;
743 
744  // Then vendor extended operators.
745  if (ParseOneCharToken(state, 'v') && ParseCharClass(state, "0123456789") &&
746  ParseSourceName(state)) {
747  return true;
748  }
749  *state = copy;
750 
751  // Other operator names should start with a lower alphabet followed
752  // by a lower/upper alphabet.
753  if (!(IsLower(state->mangled_cur[0]) &&
754  IsAlpha(state->mangled_cur[1]))) {
755  return false;
756  }
757  // We may want to perform a binary search if we really need speed.
758  const AbbrevPair *p;
759  for (p = kOperatorList; p->abbrev != NULL; ++p) {
760  if (state->mangled_cur[0] == p->abbrev[0] &&
761  state->mangled_cur[1] == p->abbrev[1]) {
762  MaybeAppend(state, "operator");
763  if (IsLower(*p->real_name)) { // new, delete, etc.
764  MaybeAppend(state, " ");
765  }
766  MaybeAppend(state, p->real_name);
767  state->mangled_cur += 2;
768  return true;
769  }
770  }
771  return false;
772 }
773 
774 // <special-name> ::= TV <type>
775 // ::= TT <type>
776 // ::= TI <type>
777 // ::= TS <type>
778 // ::= Tc <call-offset> <call-offset> <(base) encoding>
779 // ::= GV <(object) name>
780 // ::= T <call-offset> <(base) encoding>
781 // G++ extensions:
782 // ::= TC <type> <(offset) number> _ <(base) type>
783 // ::= TF <type>
784 // ::= TJ <type>
785 // ::= GR <name>
786 // ::= GA <encoding>
787 // ::= Th <call-offset> <(base) encoding>
788 // ::= Tv <call-offset> <(base) encoding>
789 //
790 // Note: we don't care much about them since they don't appear in
791 // stack traces. The are special data.
792 static bool ParseSpecialName(State *state) {
793  State copy = *state;
794  if (ParseOneCharToken(state, 'T') &&
795  ParseCharClass(state, "VTIS") &&
796  ParseType(state)) {
797  return true;
798  }
799  *state = copy;
800 
801  if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) &&
802  ParseCallOffset(state) && ParseEncoding(state)) {
803  return true;
804  }
805  *state = copy;
806 
807  if (ParseTwoCharToken(state, "GV") &&
808  ParseName(state)) {
809  return true;
810  }
811  *state = copy;
812 
813  if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) &&
814  ParseEncoding(state)) {
815  return true;
816  }
817  *state = copy;
818 
819  // G++ extensions
820  if (ParseTwoCharToken(state, "TC") && ParseType(state) &&
821  ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
822  DisableAppend(state) &&
823  ParseType(state)) {
824  RestoreAppend(state, copy.append);
825  return true;
826  }
827  *state = copy;
828 
829  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") &&
830  ParseType(state)) {
831  return true;
832  }
833  *state = copy;
834 
835  if (ParseTwoCharToken(state, "GR") && ParseName(state)) {
836  return true;
837  }
838  *state = copy;
839 
840  if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) {
841  return true;
842  }
843  *state = copy;
844 
845  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") &&
846  ParseCallOffset(state) && ParseEncoding(state)) {
847  return true;
848  }
849  *state = copy;
850  return false;
851 }
852 
853 // <call-offset> ::= h <nv-offset> _
854 // ::= v <v-offset> _
855 static bool ParseCallOffset(State *state) {
856  State copy = *state;
857  if (ParseOneCharToken(state, 'h') &&
858  ParseNVOffset(state) && ParseOneCharToken(state, '_')) {
859  return true;
860  }
861  *state = copy;
862 
863  if (ParseOneCharToken(state, 'v') &&
864  ParseVOffset(state) && ParseOneCharToken(state, '_')) {
865  return true;
866  }
867  *state = copy;
868 
869  return false;
870 }
871 
872 // <nv-offset> ::= <(offset) number>
873 static bool ParseNVOffset(State *state) {
874  return ParseNumber(state, NULL);
875 }
876 
877 // <v-offset> ::= <(offset) number> _ <(virtual offset) number>
878 static bool ParseVOffset(State *state) {
879  State copy = *state;
880  if (ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
881  ParseNumber(state, NULL)) {
882  return true;
883  }
884  *state = copy;
885  return false;
886 }
887 
888 // <ctor-dtor-name> ::= C1 | C2 | C3
889 // ::= D0 | D1 | D2
890 static bool ParseCtorDtorName(State *state) {
891  State copy = *state;
892  if (ParseOneCharToken(state, 'C') &&
893  ParseCharClass(state, "123")) {
894  const char * const prev_name = state->prev_name;
895  const int prev_name_length = state->prev_name_length;
896  MaybeAppendWithLength(state, prev_name, prev_name_length);
897  return true;
898  }
899  *state = copy;
900 
901  if (ParseOneCharToken(state, 'D') &&
902  ParseCharClass(state, "012")) {
903  const char * const prev_name = state->prev_name;
904  const int prev_name_length = state->prev_name_length;
905  MaybeAppend(state, "~");
906  MaybeAppendWithLength(state, prev_name, prev_name_length);
907  return true;
908  }
909  *state = copy;
910  return false;
911 }
912 
913 // <type> ::= <CV-qualifiers> <type>
914 // ::= P <type> # pointer-to
915 // ::= R <type> # reference-to
916 // ::= O <type> # rvalue reference-to (C++0x)
917 // ::= C <type> # complex pair (C 2000)
918 // ::= G <type> # imaginary (C 2000)
919 // ::= U <source-name> <type> # vendor extended type qualifier
920 // ::= <builtin-type>
921 // ::= <function-type>
922 // ::= <class-enum-type>
923 // ::= <array-type>
924 // ::= <pointer-to-member-type>
925 // ::= <template-template-param> <template-args>
926 // ::= <template-param>
927 // ::= <substitution>
928 // ::= Dp <type> # pack expansion of (C++0x)
929 // ::= Dt <expression> E # decltype of an id-expression or class
930 // # member access (C++0x)
931 // ::= DT <expression> E # decltype of an expression (C++0x)
932 //
933 static bool ParseType(State *state) {
934  // We should check CV-qualifers, and PRGC things first.
935  State copy = *state;
936  if (ParseCVQualifiers(state) && ParseType(state)) {
937  return true;
938  }
939  *state = copy;
940 
941  if (ParseCharClass(state, "OPRCG") && ParseType(state)) {
942  return true;
943  }
944  *state = copy;
945 
946  if (ParseTwoCharToken(state, "Dp") && ParseType(state)) {
947  return true;
948  }
949  *state = copy;
950 
951  if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") &&
952  ParseExpression(state) && ParseOneCharToken(state, 'E')) {
953  return true;
954  }
955  *state = copy;
956 
957  if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
958  ParseType(state)) {
959  return true;
960  }
961  *state = copy;
962 
963  if (ParseBuiltinType(state) ||
964  ParseFunctionType(state) ||
965  ParseClassEnumType(state) ||
966  ParseArrayType(state) ||
967  ParsePointerToMemberType(state) ||
968  ParseSubstitution(state)) {
969  return true;
970  }
971 
972  if (ParseTemplateTemplateParam(state) &&
973  ParseTemplateArgs(state)) {
974  return true;
975  }
976  *state = copy;
977 
978  // Less greedy than <template-template-param> <template-args>.
979  if (ParseTemplateParam(state)) {
980  return true;
981  }
982 
983  return false;
984 }
985 
986 // <CV-qualifiers> ::= [r] [V] [K]
987 // We don't allow empty <CV-qualifiers> to avoid infinite loop in
988 // ParseType().
989 static bool ParseCVQualifiers(State *state) {
990  int num_cv_qualifiers = 0;
991  num_cv_qualifiers += ParseOneCharToken(state, 'r');
992  num_cv_qualifiers += ParseOneCharToken(state, 'V');
993  num_cv_qualifiers += ParseOneCharToken(state, 'K');
994  return num_cv_qualifiers > 0;
995 }
996 
997 // <builtin-type> ::= v, etc.
998 // ::= u <source-name>
999 static bool ParseBuiltinType(State *state) {
1000  const AbbrevPair *p;
1001  for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) {
1002  if (state->mangled_cur[0] == p->abbrev[0]) {
1003  MaybeAppend(state, p->real_name);
1004  ++state->mangled_cur;
1005  return true;
1006  }
1007  }
1008 
1009  State copy = *state;
1010  if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
1011  return true;
1012  }
1013  *state = copy;
1014  return false;
1015 }
1016 
1017 // <function-type> ::= F [Y] <bare-function-type> E
1018 static bool ParseFunctionType(State *state) {
1019  State copy = *state;
1020  if (ParseOneCharToken(state, 'F') &&
1021  Optional(ParseOneCharToken(state, 'Y')) &&
1022  ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) {
1023  return true;
1024  }
1025  *state = copy;
1026  return false;
1027 }
1028 
1029 // <bare-function-type> ::= <(signature) type>+
1030 static bool ParseBareFunctionType(State *state) {
1031  State copy = *state;
1032  DisableAppend(state);
1033  if (OneOrMore(ParseType, state)) {
1034  RestoreAppend(state, copy.append);
1035  MaybeAppend(state, "()");
1036  return true;
1037  }
1038  *state = copy;
1039  return false;
1040 }
1041 
1042 // <class-enum-type> ::= <name>
1043 static bool ParseClassEnumType(State *state) {
1044  return ParseName(state);
1045 }
1046 
1047 // <array-type> ::= A <(positive dimension) number> _ <(element) type>
1048 // ::= A [<(dimension) expression>] _ <(element) type>
1049 static bool ParseArrayType(State *state) {
1050  State copy = *state;
1051  if (ParseOneCharToken(state, 'A') && ParseNumber(state, NULL) &&
1052  ParseOneCharToken(state, '_') && ParseType(state)) {
1053  return true;
1054  }
1055  *state = copy;
1056 
1057  if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) &&
1058  ParseOneCharToken(state, '_') && ParseType(state)) {
1059  return true;
1060  }
1061  *state = copy;
1062  return false;
1063 }
1064 
1065 // <pointer-to-member-type> ::= M <(class) type> <(member) type>
1066 static bool ParsePointerToMemberType(State *state) {
1067  State copy = *state;
1068  if (ParseOneCharToken(state, 'M') && ParseType(state) &&
1069  ParseType(state)) {
1070  return true;
1071  }
1072  *state = copy;
1073  return false;
1074 }
1075 
1076 // <template-param> ::= T_
1077 // ::= T <parameter-2 non-negative number> _
1078 static bool ParseTemplateParam(State *state) {
1079  if (ParseTwoCharToken(state, "T_")) {
1080  MaybeAppend(state, "?"); // We don't support template substitutions.
1081  return true;
1082  }
1083 
1084  State copy = *state;
1085  if (ParseOneCharToken(state, 'T') && ParseNumber(state, NULL) &&
1086  ParseOneCharToken(state, '_')) {
1087  MaybeAppend(state, "?"); // We don't support template substitutions.
1088  return true;
1089  }
1090  *state = copy;
1091  return false;
1092 }
1093 
1094 
1095 // <template-template-param> ::= <template-param>
1096 // ::= <substitution>
1097 static bool ParseTemplateTemplateParam(State *state) {
1098  return (ParseTemplateParam(state) ||
1099  ParseSubstitution(state));
1100 }
1101 
1102 // <template-args> ::= I <template-arg>+ E
1103 static bool ParseTemplateArgs(State *state) {
1104  State copy = *state;
1105  DisableAppend(state);
1106  if (ParseOneCharToken(state, 'I') &&
1107  OneOrMore(ParseTemplateArg, state) &&
1108  ParseOneCharToken(state, 'E')) {
1109  RestoreAppend(state, copy.append);
1110  MaybeAppend(state, "<>");
1111  return true;
1112  }
1113  *state = copy;
1114  return false;
1115 }
1116 
1117 // <template-arg> ::= <type>
1118 // ::= <expr-primary>
1119 // ::= I <template-arg>* E # argument pack
1120 // ::= J <template-arg>* E # argument pack
1121 // ::= X <expression> E
1122 static bool ParseTemplateArg(State *state) {
1123  State copy = *state;
1124  if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) &&
1125  ZeroOrMore(ParseTemplateArg, state) &&
1126  ParseOneCharToken(state, 'E')) {
1127  return true;
1128  }
1129  *state = copy;
1130 
1131  if (ParseType(state) ||
1132  ParseExprPrimary(state)) {
1133  return true;
1134  }
1135  *state = copy;
1136 
1137  if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&
1138  ParseOneCharToken(state, 'E')) {
1139  return true;
1140  }
1141  *state = copy;
1142  return false;
1143 }
1144 
1145 // <expression> ::= <template-param>
1146 // ::= <expr-primary>
1147 // ::= <unary operator-name> <expression>
1148 // ::= <binary operator-name> <expression> <expression>
1149 // ::= <trinary operator-name> <expression> <expression>
1150 // <expression>
1151 // ::= st <type>
1152 // ::= sr <type> <unqualified-name> <template-args>
1153 // ::= sr <type> <unqualified-name>
1154 static bool ParseExpression(State *state) {
1155  if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
1156  return true;
1157  }
1158 
1159  State copy = *state;
1160  if (ParseOperatorName(state) &&
1161  ParseExpression(state) &&
1162  ParseExpression(state) &&
1163  ParseExpression(state)) {
1164  return true;
1165  }
1166  *state = copy;
1167 
1168  if (ParseOperatorName(state) &&
1169  ParseExpression(state) &&
1170  ParseExpression(state)) {
1171  return true;
1172  }
1173  *state = copy;
1174 
1175  if (ParseOperatorName(state) &&
1176  ParseExpression(state)) {
1177  return true;
1178  }
1179  *state = copy;
1180 
1181  if (ParseTwoCharToken(state, "st") && ParseType(state)) {
1182  return true;
1183  }
1184  *state = copy;
1185 
1186  if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
1187  ParseUnqualifiedName(state) &&
1188  ParseTemplateArgs(state)) {
1189  return true;
1190  }
1191  *state = copy;
1192 
1193  if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
1194  ParseUnqualifiedName(state)) {
1195  return true;
1196  }
1197  *state = copy;
1198  return false;
1199 }
1200 
1201 // <expr-primary> ::= L <type> <(value) number> E
1202 // ::= L <type> <(value) float> E
1203 // ::= L <mangled-name> E
1204 // // A bug in g++'s C++ ABI version 2 (-fabi-version=2).
1205 // ::= LZ <encoding> E
1206 static bool ParseExprPrimary(State *state) {
1207  State copy = *state;
1208  if (ParseOneCharToken(state, 'L') && ParseType(state) &&
1209  ParseNumber(state, NULL) &&
1210  ParseOneCharToken(state, 'E')) {
1211  return true;
1212  }
1213  *state = copy;
1214 
1215  if (ParseOneCharToken(state, 'L') && ParseType(state) &&
1216  ParseFloatNumber(state) &&
1217  ParseOneCharToken(state, 'E')) {
1218  return true;
1219  }
1220  *state = copy;
1221 
1222  if (ParseOneCharToken(state, 'L') && ParseMangledName(state) &&
1223  ParseOneCharToken(state, 'E')) {
1224  return true;
1225  }
1226  *state = copy;
1227 
1228  if (ParseTwoCharToken(state, "LZ") && ParseEncoding(state) &&
1229  ParseOneCharToken(state, 'E')) {
1230  return true;
1231  }
1232  *state = copy;
1233 
1234  return false;
1235 }
1236 
1237 // <local-name> := Z <(function) encoding> E <(entity) name>
1238 // [<discriminator>]
1239 // := Z <(function) encoding> E s [<discriminator>]
1240 static bool ParseLocalName(State *state) {
1241  State copy = *state;
1242  if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
1243  ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") &&
1244  ParseName(state) && Optional(ParseDiscriminator(state))) {
1245  return true;
1246  }
1247  *state = copy;
1248 
1249  if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
1250  ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) {
1251  return true;
1252  }
1253  *state = copy;
1254  return false;
1255 }
1256 
1257 // <discriminator> := _ <(non-negative) number>
1258 static bool ParseDiscriminator(State *state) {
1259  State copy = *state;
1260  if (ParseOneCharToken(state, '_') && ParseNumber(state, NULL)) {
1261  return true;
1262  }
1263  *state = copy;
1264  return false;
1265 }
1266 
1267 // <substitution> ::= S_
1268 // ::= S <seq-id> _
1269 // ::= St, etc.
1270 static bool ParseSubstitution(State *state) {
1271  if (ParseTwoCharToken(state, "S_")) {
1272  MaybeAppend(state, "?"); // We don't support substitutions.
1273  return true;
1274  }
1275 
1276  State copy = *state;
1277  if (ParseOneCharToken(state, 'S') && ParseSeqId(state) &&
1278  ParseOneCharToken(state, '_')) {
1279  MaybeAppend(state, "?"); // We don't support substitutions.
1280  return true;
1281  }
1282  *state = copy;
1283 
1284  // Expand abbreviations like "St" => "std".
1285  if (ParseOneCharToken(state, 'S')) {
1286  const AbbrevPair *p;
1287  for (p = kSubstitutionList; p->abbrev != NULL; ++p) {
1288  if (state->mangled_cur[0] == p->abbrev[1]) {
1289  MaybeAppend(state, "std");
1290  if (p->real_name[0] != '\0') {
1291  MaybeAppend(state, "::");
1292  MaybeAppend(state, p->real_name);
1293  }
1294  ++state->mangled_cur;
1295  return true;
1296  }
1297  }
1298  }
1299  *state = copy;
1300  return false;
1301 }
1302 
1303 // Parse <mangled-name>, optionally followed by either a function-clone suffix
1304 // or version suffix. Returns true only if all of "mangled_cur" was consumed.
1305 static bool ParseTopLevelMangledName(State *state) {
1306  if (ParseMangledName(state)) {
1307  if (state->mangled_cur[0] != '\0') {
1308  // Drop trailing function clone suffix, if any.
1309  if (IsFunctionCloneSuffix(state->mangled_cur)) {
1310  return true;
1311  }
1312  // Append trailing version suffix if any.
1313  // ex. _Z3foo@@GLIBCXX_3.4
1314  if (state->mangled_cur[0] == '@') {
1315  MaybeAppend(state, state->mangled_cur);
1316  return true;
1317  }
1318  return false; // Unconsumed suffix.
1319  }
1320  return true;
1321  }
1322  return false;
1323 }
1324 #endif
1325 
1326 // The demangler entry point.
1327 bool Demangle(const char *mangled, char *out, size_t out_size) {
1328 #if defined(GLOG_OS_WINDOWS)
1329 #if defined(HAVE_DBGHELP)
1330  // When built with incremental linking, the Windows debugger
1331  // library provides a more complicated `Symbol->Name` with the
1332  // Incremental Linking Table offset, which looks like
1333  // `@ILT+1105(?func@Foo@@SAXH@Z)`. However, the demangler expects
1334  // only the mangled symbol, `?func@Foo@@SAXH@Z`. Fortunately, the
1335  // mangled symbol is guaranteed not to have parentheses,
1336  // so we search for `(` and extract up to `)`.
1337  //
1338  // Since we may be in a signal handler here, we cannot use `std::string`.
1339  char buffer[1024]; // Big enough for a sane symbol.
1340  const char *lparen = strchr(mangled, '(');
1341  if (lparen) {
1342  // Extract the string `(?...)`
1343  const char *rparen = strchr(lparen, ')');
1344  size_t length = static_cast<size_t>(rparen - lparen) - 1;
1345  strncpy(buffer, lparen + 1, length);
1346  buffer[length] = '\0';
1347  mangled = buffer;
1348  } // Else the symbol wasn't inside a set of parentheses
1349  // We use the ANSI version to ensure the string type is always `char *`.
1350  return UnDecorateSymbolName(mangled, out, out_size, UNDNAME_COMPLETE);
1351 #else
1352  (void)mangled;
1353  (void)out;
1354  (void)out_size;
1355  return false;
1356 #endif
1357 #else
1358  State state;
1359  InitState(&state, mangled, out, out_size);
1360  return ParseTopLevelMangledName(&state) && !state.overflowed;
1361 #endif
1362 }
1363 
1364 _END_GOOGLE_NAMESPACE_
ParseExpression
static bool ParseExpression(State *state)
Definition: demangle.cc:1154
ParseLocalSourceName
static bool ParseLocalSourceName(State *state)
Definition: demangle.cc:625
ParseTemplateTemplateParam
static bool ParseTemplateTemplateParam(State *state)
Definition: demangle.cc:1097
RestoreAppend
static bool RestoreAppend(State *state, bool prev_value)
Definition: demangle.cc:375
NULL
NULL
Definition: test_security_zap.cpp:405
ParsePrefix
static bool ParsePrefix(State *state)
Definition: demangle.cc:577
ParseSubstitution
static bool ParseSubstitution(State *state)
Definition: demangle.cc:1270
ParseCtorDtorName
static bool ParseCtorDtorName(State *state)
Definition: demangle.cc:890
MaybeIncreaseNestLevel
static void MaybeIncreaseNestLevel(State *state)
Definition: demangle.cc:381
length
GLenum GLuint GLenum GLsizei length
Definition: glcorearb.h:2695
kBuiltinTypeList
static const AbbrevPair kBuiltinTypeList[]
Definition: demangle.cc:109
AtLeastNumCharsRemaining
static bool AtLeastNumCharsRemaining(const char *str, int n)
Definition: demangle.cc:175
ParseCharClass
static bool ParseCharClass(State *state, const char *char_class)
Definition: demangle.cc:232
ParseFunctionType
static bool ParseFunctionType(State *state)
Definition: demangle.cc:1018
ParseIdentifier
static bool ParseIdentifier(State *state, int length)
Definition: demangle.cc:695
ParseOperatorName
static bool ParseOperatorName(State *state)
Definition: demangle.cc:729
State::out_cur
char * out_cur
Definition: demangle.cc:153
State::prev_name_length
int prev_name_length
Definition: demangle.cc:157
ParseCVQualifiers
static bool ParseCVQualifiers(State *state)
Definition: demangle.cc:989
Append
static void Append(State *state, const char *const str, const int length)
Definition: demangle.cc:272
OneOrMore
static bool OneOrMore(ParseFunc parse_func, State *state)
Definition: demangle.cc:250
ParseAbiTags
static bool ParseAbiTags(State *state)
Definition: demangle.cc:710
ParseTemplateParam
static bool ParseTemplateParam(State *state)
Definition: demangle.cc:1078
AbbrevPair::abbrev
const char * abbrev
Definition: demangle.cc:50
ParseCallOffset
static bool ParseCallOffset(State *state)
Definition: demangle.cc:855
IsFunctionCloneSuffix
static bool IsFunctionCloneSuffix(const char *str)
Definition: demangle.cc:305
Demangle
bool Demangle(const char *mangled, char *out, size_t out_size)
Definition: demangle.cc:1327
ParseNumber
static bool ParseNumber(State *state, int *number_out)
Definition: demangle.cc:638
State::prev_name
const char * prev_name
Definition: demangle.cc:156
ParseBareFunctionType
static bool ParseBareFunctionType(State *state)
Definition: demangle.cc:1030
IdentifierIsAnonymousNamespace
static bool IdentifierIsAnonymousNamespace(State *state, int length)
Definition: demangle.cc:405
AbbrevPair
Definition: demangle.cc:49
State::nest_level
short nest_level
Definition: demangle.cc:158
MaybeCancelLastSeparator
static void MaybeCancelLastSeparator(State *state)
Definition: demangle.cc:395
ParseFunc
bool(* ParseFunc)(State *)
Definition: demangle.cc:249
IsAlpha
static bool IsAlpha(char c)
Definition: demangle.cc:293
prefix
static const char prefix[]
Definition: test_pair_ipc.cpp:26
buffer
GLuint buffer
Definition: glcorearb.h:2939
ParseFloatNumber
static bool ParseFloatNumber(State *state)
Definition: demangle.cc:664
update_failure_list.str
str
Definition: update_failure_list.py:41
ParseTwoCharToken
static bool ParseTwoCharToken(State *state, const char *two_char_token)
Definition: demangle.cc:221
ParseDiscriminator
static bool ParseDiscriminator(State *state)
Definition: demangle.cc:1258
p
const char * p
Definition: gmock-matchers_test.cc:3863
InitState
static void InitState(State *state, const char *mangled, char *out, size_t out_size)
Definition: demangle.cc:194
State::mangled_cur
const char * mangled_cur
Definition: demangle.cc:152
ParseVOffset
static bool ParseVOffset(State *state)
Definition: demangle.cc:878
ParseTemplateArg
static bool ParseTemplateArg(State *state)
Definition: demangle.cc:1122
ParseType
static bool ParseType(State *state)
Definition: demangle.cc:933
buffer
Definition: buffer_processor.h:43
utilities.h
ParseUnqualifiedName
static bool ParseUnqualifiedName(State *state)
Definition: demangle.cc:602
void
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
n
GLdouble n
Definition: glcorearb.h:4153
IsLower
static bool IsLower(char c)
Definition: demangle.cc:289
i
int i
Definition: gmock-matchers_test.cc:764
ParseTemplateArgs
static bool ParseTemplateArgs(State *state)
Definition: demangle.cc:1103
ParseSourceName
static bool ParseSourceName(State *state)
Definition: demangle.cc:610
State::append
bool append
Definition: demangle.cc:159
LeaveNestedName
static bool LeaveNestedName(State *state, short prev_value)
Definition: demangle.cc:363
ParseAbiTag
static bool ParseAbiTag(State *state)
Definition: demangle.cc:722
_START_GOOGLE_NAMESPACE_
Definition: signalhandler.cc:51
State
Definition: demangle.cc:151
len
int len
Definition: php/ext/google/protobuf/map.c:206
ParseExprPrimary
static bool ParseExprPrimary(State *state)
Definition: demangle.cc:1206
IsDigit
static bool IsDigit(char c)
Definition: demangle.cc:297
ParseBuiltinType
static bool ParseBuiltinType(State *state)
Definition: demangle.cc:999
State::out_begin
const char * out_begin
Definition: demangle.cc:154
ParseEncoding
static bool ParseEncoding(State *state)
Definition: demangle.cc:491
AbbrevPair::real_name
const char * real_name
Definition: demangle.cc:51
demangle.h
ParseSeqId
static bool ParseSeqId(State *state)
Definition: demangle.cc:680
MaybeAppend
static bool MaybeAppend(State *state, const char *const str)
Definition: demangle.cc:348
MaybeAppendWithLength
static void MaybeAppendWithLength(State *state, const char *const str, const int length)
Definition: demangle.cc:329
State::overflowed
bool overflowed
Definition: demangle.cc:160
ParseNVOffset
static bool ParseNVOffset(State *state)
Definition: demangle.cc:873
DisableAppend
static bool DisableAppend(State *state)
Definition: demangle.cc:369
StrLen
static size_t StrLen(const char *str)
Definition: demangle.cc:165
ParseUnscopedName
static bool ParseUnscopedName(State *state)
Definition: demangle.cc:529
EnterNestedName
static bool EnterNestedName(State *state)
Definition: demangle.cc:357
kSubstitutionList
static const AbbrevPair kSubstitutionList[]
Definition: demangle.cc:135
ParseUnscopedTemplateName
static bool ParseUnscopedTemplateName(State *state)
Definition: demangle.cc:546
kOperatorList
static const AbbrevPair kOperatorList[]
Definition: demangle.cc:55
ParseMangledName
static bool ParseMangledName(State *state)
Definition: demangle.cc:484
ParseLocalName
static bool ParseLocalName(State *state)
Definition: demangle.cc:1240
ZeroOrMore
static bool ZeroOrMore(ParseFunc parse_func, State *state)
Definition: demangle.cc:263
ParseTopLevelMangledName
static bool ParseTopLevelMangledName(State *state)
Definition: demangle.cc:1305
MaybeAppendSeparator
static void MaybeAppendSeparator(State *state)
Definition: demangle.cc:388
StrPrefix
static bool StrPrefix(const char *str, const char *prefix)
Definition: demangle.cc:185
State::out_end
const char * out_end
Definition: demangle.cc:155
ParseName
static bool ParseName(State *state)
Definition: demangle.cc:508
ParsePointerToMemberType
static bool ParsePointerToMemberType(State *state)
Definition: demangle.cc:1066
ParseArrayType
static bool ParseArrayType(State *state)
Definition: demangle.cc:1049
ParseNestedName
static bool ParseNestedName(State *state)
Definition: demangle.cc:552
ParseSpecialName
static bool ParseSpecialName(State *state)
Definition: demangle.cc:792
number
double number
Definition: cJSON.h:326
Optional
static bool Optional(bool)
Definition: demangle.cc:244
ParseClassEnumType
static bool ParseClassEnumType(State *state)
Definition: demangle.cc:1043
ParseOneCharToken
static bool ParseOneCharToken(State *state, const char one_char_token)
Definition: demangle.cc:210


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:49