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