1 /* Demangler for GNU C++ 2 Copyright (C) 1989-2020 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 } 463