1 1.1 mrg /* Demangler for GNU C++ 2 1.1.1.12 mrg Copyright (C) 1989-2024 Free Software Foundation, Inc. 3 1.1 mrg Written by James Clark (jjc (at) jclark.uucp) 4 1.1 mrg Rewritten by Fred Fish (fnf (at) cygnus.com) for ARM and Lucid demangling 5 1.1 mrg Modified by Satish Pai (pai (at) apollo.hp.com) for HP demangling 6 1.1 mrg 7 1.1 mrg This file is part of the libiberty library. 8 1.1 mrg Libiberty is free software; you can redistribute it and/or 9 1.1 mrg modify it under the terms of the GNU Library General Public 10 1.1 mrg License as published by the Free Software Foundation; either 11 1.1 mrg version 2 of the License, or (at your option) any later version. 12 1.1 mrg 13 1.1 mrg In addition to the permissions in the GNU Library General Public 14 1.1 mrg License, the Free Software Foundation gives you unlimited permission 15 1.1 mrg to link the compiled version of this file into combinations with other 16 1.1 mrg programs, and to distribute those combinations without any restriction 17 1.1 mrg coming from the use of this file. (The Library Public License 18 1.1 mrg restrictions do apply in other respects; for example, they cover 19 1.1 mrg modification of the file, and distribution when not linked into a 20 1.1 mrg combined executable.) 21 1.1 mrg 22 1.1 mrg Libiberty is distributed in the hope that it will be useful, 23 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 24 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 1.1 mrg Library General Public License for more details. 26 1.1 mrg 27 1.1 mrg You should have received a copy of the GNU Library General Public 28 1.1 mrg License along with libiberty; see the file COPYING.LIB. If 29 1.1 mrg not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 30 1.1 mrg Boston, MA 02110-1301, USA. */ 31 1.1 mrg 32 1.1 mrg /* This file lives in both GCC and libiberty. When making changes, please 33 1.1 mrg try not to break either. */ 34 1.1 mrg 35 1.1 mrg #ifdef HAVE_CONFIG_H 36 1.1 mrg #include "config.h" 37 1.1 mrg #endif 38 1.1 mrg 39 1.1 mrg #include "safe-ctype.h" 40 1.1 mrg 41 1.1 mrg #include <string.h> 42 1.1 mrg 43 1.1 mrg #ifdef HAVE_STDLIB_H 44 1.1 mrg #include <stdlib.h> 45 1.1 mrg #else 46 1.1 mrg void * malloc (); 47 1.1 mrg void * realloc (); 48 1.1 mrg #endif 49 1.1 mrg 50 1.1 mrg #include <demangle.h> 51 1.1 mrg #undef CURRENT_DEMANGLING_STYLE 52 1.1.1.9 mrg #define CURRENT_DEMANGLING_STYLE options 53 1.1 mrg 54 1.1 mrg #include "libiberty.h" 55 1.1 mrg 56 1.1 mrg enum demangling_styles current_demangling_style = auto_demangling; 57 1.1 mrg 58 1.1 mrg const struct demangler_engine libiberty_demanglers[] = 59 1.1 mrg { 60 1.1 mrg { 61 1.1 mrg NO_DEMANGLING_STYLE_STRING, 62 1.1 mrg no_demangling, 63 1.1 mrg "Demangling disabled" 64 1.1 mrg } 65 1.1 mrg , 66 1.1 mrg { 67 1.1 mrg AUTO_DEMANGLING_STYLE_STRING, 68 1.1 mrg auto_demangling, 69 1.1 mrg "Automatic selection based on executable" 70 1.1 mrg } 71 1.1 mrg , 72 1.1 mrg { 73 1.1 mrg GNU_V3_DEMANGLING_STYLE_STRING, 74 1.1 mrg gnu_v3_demangling, 75 1.1.1.9 mrg "GNU (g++) V3 (Itanium C++ ABI) style demangling" 76 1.1 mrg } 77 1.1 mrg , 78 1.1 mrg { 79 1.1 mrg JAVA_DEMANGLING_STYLE_STRING, 80 1.1 mrg java_demangling, 81 1.1 mrg "Java style demangling" 82 1.1 mrg } 83 1.1 mrg , 84 1.1 mrg { 85 1.1 mrg GNAT_DEMANGLING_STYLE_STRING, 86 1.1 mrg gnat_demangling, 87 1.1 mrg "GNAT style demangling" 88 1.1 mrg } 89 1.1 mrg , 90 1.1 mrg { 91 1.1.1.3 mrg DLANG_DEMANGLING_STYLE_STRING, 92 1.1.1.3 mrg dlang_demangling, 93 1.1.1.3 mrg "DLANG style demangling" 94 1.1.1.3 mrg } 95 1.1.1.3 mrg , 96 1.1.1.3 mrg { 97 1.1.1.5 mrg RUST_DEMANGLING_STYLE_STRING, 98 1.1.1.5 mrg rust_demangling, 99 1.1.1.5 mrg "Rust style demangling" 100 1.1.1.5 mrg } 101 1.1.1.5 mrg , 102 1.1.1.5 mrg { 103 1.1 mrg NULL, unknown_demangling, NULL 104 1.1 mrg } 105 1.1 mrg }; 106 1.1 mrg 107 1.1 mrg /* Add a routine to set the demangling style to be sure it is valid and 108 1.1 mrg allow for any demangler initialization that maybe necessary. */ 109 1.1 mrg 110 1.1 mrg enum demangling_styles 111 1.1 mrg cplus_demangle_set_style (enum demangling_styles style) 112 1.1 mrg { 113 1.1 mrg const struct demangler_engine *demangler = libiberty_demanglers; 114 1.1 mrg 115 1.1 mrg for (; demangler->demangling_style != unknown_demangling; ++demangler) 116 1.1 mrg if (style == demangler->demangling_style) 117 1.1 mrg { 118 1.1 mrg current_demangling_style = style; 119 1.1 mrg return current_demangling_style; 120 1.1 mrg } 121 1.1 mrg 122 1.1 mrg return unknown_demangling; 123 1.1 mrg } 124 1.1 mrg 125 1.1 mrg /* Do string name to style translation */ 126 1.1 mrg 127 1.1 mrg enum demangling_styles 128 1.1 mrg cplus_demangle_name_to_style (const char *name) 129 1.1 mrg { 130 1.1 mrg const struct demangler_engine *demangler = libiberty_demanglers; 131 1.1 mrg 132 1.1 mrg for (; demangler->demangling_style != unknown_demangling; ++demangler) 133 1.1 mrg if (strcmp (name, demangler->demangling_style_name) == 0) 134 1.1 mrg return demangler->demangling_style; 135 1.1 mrg 136 1.1 mrg return unknown_demangling; 137 1.1 mrg } 138 1.1 mrg 139 1.1 mrg /* char *cplus_demangle (const char *mangled, int options) 140 1.1 mrg 141 1.1 mrg If MANGLED is a mangled function name produced by GNU C++, then 142 1.1 mrg a pointer to a @code{malloc}ed string giving a C++ representation 143 1.1 mrg of the name will be returned; otherwise NULL will be returned. 144 1.1 mrg It is the caller's responsibility to free the string which 145 1.1 mrg is returned. 146 1.1 mrg 147 1.1 mrg Note that any leading underscores, or other such characters prepended by 148 1.1 mrg the compilation system, are presumed to have already been stripped from 149 1.1 mrg MANGLED. */ 150 1.1 mrg 151 1.1 mrg char * 152 1.1 mrg cplus_demangle (const char *mangled, int options) 153 1.1 mrg { 154 1.1 mrg char *ret; 155 1.1 mrg 156 1.1 mrg if (current_demangling_style == no_demangling) 157 1.1 mrg return xstrdup (mangled); 158 1.1 mrg 159 1.1.1.9 mrg if ((options & DMGL_STYLE_MASK) == 0) 160 1.1.1.9 mrg options |= (int) current_demangling_style & DMGL_STYLE_MASK; 161 1.1 mrg 162 1.1.1.10 mrg /* The Rust demangling is implemented elsewhere. 163 1.1.1.10 mrg Legacy Rust symbols overlap with GNU_V3, so try Rust first. */ 164 1.1.1.10 mrg if (RUST_DEMANGLING || AUTO_DEMANGLING) 165 1.1.1.10 mrg { 166 1.1.1.10 mrg ret = rust_demangle (mangled, options); 167 1.1.1.10 mrg if (ret || RUST_DEMANGLING) 168 1.1.1.10 mrg return ret; 169 1.1.1.10 mrg } 170 1.1.1.10 mrg 171 1.1 mrg /* The V3 ABI demangling is implemented elsewhere. */ 172 1.1.1.10 mrg if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) 173 1.1 mrg { 174 1.1.1.9 mrg ret = cplus_demangle_v3 (mangled, options); 175 1.1.1.10 mrg if (ret || GNU_V3_DEMANGLING) 176 1.1 mrg return ret; 177 1.1 mrg } 178 1.1 mrg 179 1.1 mrg if (JAVA_DEMANGLING) 180 1.1 mrg { 181 1.1 mrg ret = java_demangle_v3 (mangled); 182 1.1 mrg if (ret) 183 1.1 mrg return ret; 184 1.1 mrg } 185 1.1 mrg 186 1.1 mrg if (GNAT_DEMANGLING) 187 1.1 mrg return ada_demangle (mangled, options); 188 1.1 mrg 189 1.1.1.12 mrg if (DLANG_DEMANGLING || AUTO_DEMANGLING) 190 1.1.1.3 mrg { 191 1.1.1.3 mrg ret = dlang_demangle (mangled, options); 192 1.1.1.3 mrg if (ret) 193 1.1.1.3 mrg return ret; 194 1.1.1.3 mrg } 195 1.1.1.3 mrg 196 1.1 mrg return (ret); 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ 200 1.1 mrg 201 1.1 mrg char * 202 1.1 mrg ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) 203 1.1 mrg { 204 1.1 mrg int len0; 205 1.1 mrg const char* p; 206 1.1 mrg char *d; 207 1.1.1.5 mrg char *demangled = NULL; 208 1.1 mrg 209 1.1 mrg /* Discard leading _ada_, which is used for library level subprograms. */ 210 1.1 mrg if (strncmp (mangled, "_ada_", 5) == 0) 211 1.1 mrg mangled += 5; 212 1.1 mrg 213 1.1 mrg /* All ada unit names are lower-case. */ 214 1.1 mrg if (!ISLOWER (mangled[0])) 215 1.1 mrg goto unknown; 216 1.1 mrg 217 1.1 mrg /* Most of the demangling will trivially remove chars. Operator names 218 1.1 mrg may add one char but because they are always preceeded by '__' which is 219 1.1.1.2 mrg replaced by '.', they eventually never expand the size. 220 1.1.1.2 mrg A few special names such as '___elabs' add a few chars (at most 7), but 221 1.1.1.2 mrg they occur only once. */ 222 1.1.1.2 mrg len0 = strlen (mangled) + 7 + 1; 223 1.1 mrg demangled = XNEWVEC (char, len0); 224 1.1 mrg 225 1.1 mrg d = demangled; 226 1.1 mrg p = mangled; 227 1.1 mrg while (1) 228 1.1 mrg { 229 1.1.1.2 mrg /* An entity names is expected. */ 230 1.1 mrg if (ISLOWER (*p)) 231 1.1 mrg { 232 1.1.1.2 mrg /* An identifier, which is always lower case. */ 233 1.1 mrg do 234 1.1 mrg *d++ = *p++; 235 1.1 mrg while (ISLOWER(*p) || ISDIGIT (*p) 236 1.1 mrg || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); 237 1.1 mrg } 238 1.1 mrg else if (p[0] == 'O') 239 1.1 mrg { 240 1.1.1.2 mrg /* An operator name. */ 241 1.1 mrg static const char * const operators[][2] = 242 1.1 mrg {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, 243 1.1 mrg {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, 244 1.1 mrg {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="}, 245 1.1 mrg {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"}, 246 1.1 mrg {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"}, 247 1.1 mrg {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"}, 248 1.1 mrg {"Oexpon", "**"}, {NULL, NULL}}; 249 1.1 mrg int k; 250 1.1 mrg 251 1.1.1.2 mrg for (k = 0; operators[k][0] != NULL; k++) 252 1.1 mrg { 253 1.1.1.2 mrg size_t slen = strlen (operators[k][0]); 254 1.1.1.2 mrg if (strncmp (p, operators[k][0], slen) == 0) 255 1.1 mrg { 256 1.1.1.2 mrg p += slen; 257 1.1.1.2 mrg slen = strlen (operators[k][1]); 258 1.1 mrg *d++ = '"'; 259 1.1.1.2 mrg memcpy (d, operators[k][1], slen); 260 1.1.1.2 mrg d += slen; 261 1.1 mrg *d++ = '"'; 262 1.1 mrg break; 263 1.1 mrg } 264 1.1 mrg } 265 1.1 mrg /* Operator not found. */ 266 1.1.1.2 mrg if (operators[k][0] == NULL) 267 1.1 mrg goto unknown; 268 1.1 mrg } 269 1.1 mrg else 270 1.1 mrg { 271 1.1 mrg /* Not a GNAT encoding. */ 272 1.1 mrg goto unknown; 273 1.1 mrg } 274 1.1 mrg 275 1.1.1.2 mrg /* The name can be directly followed by some uppercase letters. */ 276 1.1.1.2 mrg if (p[0] == 'T' && p[1] == 'K') 277 1.1.1.2 mrg { 278 1.1.1.2 mrg /* Task stuff. */ 279 1.1.1.2 mrg if (p[2] == 'B' && p[3] == 0) 280 1.1.1.2 mrg { 281 1.1.1.2 mrg /* Subprogram for task body. */ 282 1.1.1.2 mrg break; 283 1.1.1.2 mrg } 284 1.1.1.2 mrg else if (p[2] == '_' && p[3] == '_') 285 1.1.1.2 mrg { 286 1.1.1.2 mrg /* Inner declarations in a task. */ 287 1.1.1.2 mrg p += 4; 288 1.1.1.2 mrg *d++ = '.'; 289 1.1.1.2 mrg continue; 290 1.1.1.2 mrg } 291 1.1.1.2 mrg else 292 1.1.1.2 mrg goto unknown; 293 1.1.1.2 mrg } 294 1.1.1.2 mrg if (p[0] == 'E' && p[1] == 0) 295 1.1.1.2 mrg { 296 1.1.1.2 mrg /* Exception name. */ 297 1.1.1.2 mrg goto unknown; 298 1.1.1.2 mrg } 299 1.1.1.2 mrg if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) 300 1.1.1.2 mrg { 301 1.1.1.2 mrg /* Protected type subprogram. */ 302 1.1.1.2 mrg break; 303 1.1.1.2 mrg } 304 1.1.1.2 mrg if ((*p == 'N' || *p == 'S') && p[1] == 0) 305 1.1.1.2 mrg { 306 1.1.1.2 mrg /* Enumerated type name table. */ 307 1.1.1.2 mrg goto unknown; 308 1.1.1.2 mrg } 309 1.1.1.2 mrg if (p[0] == 'X') 310 1.1.1.2 mrg { 311 1.1.1.2 mrg /* Body nested. */ 312 1.1.1.2 mrg p++; 313 1.1.1.2 mrg while (p[0] == 'n' || p[0] == 'b') 314 1.1.1.2 mrg p++; 315 1.1.1.2 mrg } 316 1.1.1.2 mrg if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) 317 1.1.1.2 mrg { 318 1.1.1.2 mrg /* Stream operations. */ 319 1.1.1.2 mrg const char *name; 320 1.1.1.2 mrg switch (p[1]) 321 1.1.1.2 mrg { 322 1.1.1.2 mrg case 'R': 323 1.1.1.2 mrg name = "'Read"; 324 1.1.1.2 mrg break; 325 1.1.1.2 mrg case 'W': 326 1.1.1.2 mrg name = "'Write"; 327 1.1.1.2 mrg break; 328 1.1.1.2 mrg case 'I': 329 1.1.1.2 mrg name = "'Input"; 330 1.1.1.2 mrg break; 331 1.1.1.2 mrg case 'O': 332 1.1.1.2 mrg name = "'Output"; 333 1.1.1.2 mrg break; 334 1.1.1.2 mrg default: 335 1.1.1.2 mrg goto unknown; 336 1.1.1.2 mrg } 337 1.1.1.2 mrg p += 2; 338 1.1.1.2 mrg strcpy (d, name); 339 1.1.1.2 mrg d += strlen (name); 340 1.1.1.2 mrg } 341 1.1.1.2 mrg else if (p[0] == 'D') 342 1.1.1.2 mrg { 343 1.1.1.2 mrg /* Controlled type operation. */ 344 1.1.1.2 mrg const char *name; 345 1.1.1.2 mrg switch (p[1]) 346 1.1.1.2 mrg { 347 1.1.1.2 mrg case 'F': 348 1.1.1.2 mrg name = ".Finalize"; 349 1.1.1.2 mrg break; 350 1.1.1.2 mrg case 'A': 351 1.1.1.2 mrg name = ".Adjust"; 352 1.1.1.2 mrg break; 353 1.1.1.2 mrg default: 354 1.1.1.2 mrg goto unknown; 355 1.1.1.2 mrg } 356 1.1.1.2 mrg strcpy (d, name); 357 1.1.1.2 mrg d += strlen (name); 358 1.1.1.2 mrg break; 359 1.1.1.2 mrg } 360 1.1.1.2 mrg 361 1.1 mrg if (p[0] == '_') 362 1.1 mrg { 363 1.1 mrg /* Separator. */ 364 1.1 mrg if (p[1] == '_') 365 1.1 mrg { 366 1.1 mrg /* Standard separator. Handled first. */ 367 1.1 mrg p += 2; 368 1.1.1.2 mrg 369 1.1 mrg if (ISDIGIT (*p)) 370 1.1 mrg { 371 1.1.1.2 mrg /* Overloading number. */ 372 1.1 mrg do 373 1.1 mrg p++; 374 1.1 mrg while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); 375 1.1.1.2 mrg if (*p == 'X') 376 1.1.1.2 mrg { 377 1.1.1.2 mrg p++; 378 1.1.1.2 mrg while (p[0] == 'n' || p[0] == 'b') 379 1.1.1.2 mrg p++; 380 1.1.1.2 mrg } 381 1.1 mrg } 382 1.1.1.2 mrg else if (p[0] == '_' && p[1] != '_') 383 1.1 mrg { 384 1.1.1.2 mrg /* Special names. */ 385 1.1.1.2 mrg static const char * const special[][2] = { 386 1.1.1.2 mrg { "_elabb", "'Elab_Body" }, 387 1.1.1.2 mrg { "_elabs", "'Elab_Spec" }, 388 1.1.1.2 mrg { "_size", "'Size" }, 389 1.1.1.2 mrg { "_alignment", "'Alignment" }, 390 1.1.1.2 mrg { "_assign", ".\":=\"" }, 391 1.1.1.2 mrg { NULL, NULL } 392 1.1.1.2 mrg }; 393 1.1.1.2 mrg int k; 394 1.1.1.2 mrg 395 1.1.1.2 mrg for (k = 0; special[k][0] != NULL; k++) 396 1.1.1.2 mrg { 397 1.1.1.2 mrg size_t slen = strlen (special[k][0]); 398 1.1.1.2 mrg if (strncmp (p, special[k][0], slen) == 0) 399 1.1.1.2 mrg { 400 1.1.1.2 mrg p += slen; 401 1.1.1.2 mrg slen = strlen (special[k][1]); 402 1.1.1.2 mrg memcpy (d, special[k][1], slen); 403 1.1.1.2 mrg d += slen; 404 1.1.1.2 mrg break; 405 1.1.1.2 mrg } 406 1.1.1.2 mrg } 407 1.1.1.2 mrg if (special[k][0] != NULL) 408 1.1.1.2 mrg break; 409 1.1.1.2 mrg else 410 1.1.1.2 mrg goto unknown; 411 1.1 mrg } 412 1.1 mrg else 413 1.1 mrg { 414 1.1 mrg *d++ = '.'; 415 1.1 mrg continue; 416 1.1 mrg } 417 1.1 mrg } 418 1.1 mrg else if (p[1] == 'B' || p[1] == 'E') 419 1.1 mrg { 420 1.1 mrg /* Entry Body or barrier Evaluation. */ 421 1.1 mrg p += 2; 422 1.1 mrg while (ISDIGIT (*p)) 423 1.1 mrg p++; 424 1.1 mrg if (p[0] == 's' && p[1] == 0) 425 1.1 mrg break; 426 1.1 mrg else 427 1.1 mrg goto unknown; 428 1.1 mrg } 429 1.1 mrg else 430 1.1 mrg goto unknown; 431 1.1 mrg } 432 1.1 mrg 433 1.1 mrg if (p[0] == '.' && ISDIGIT (p[1])) 434 1.1 mrg { 435 1.1 mrg /* Nested subprogram. */ 436 1.1 mrg p += 2; 437 1.1 mrg while (ISDIGIT (*p)) 438 1.1 mrg p++; 439 1.1 mrg } 440 1.1 mrg if (*p == 0) 441 1.1 mrg { 442 1.1 mrg /* End of mangled name. */ 443 1.1 mrg break; 444 1.1 mrg } 445 1.1 mrg else 446 1.1 mrg goto unknown; 447 1.1 mrg } 448 1.1 mrg *d = 0; 449 1.1 mrg return demangled; 450 1.1 mrg 451 1.1 mrg unknown: 452 1.1.1.5 mrg XDELETEVEC (demangled); 453 1.1 mrg len0 = strlen (mangled); 454 1.1 mrg demangled = XNEWVEC (char, len0 + 3); 455 1.1 mrg 456 1.1 mrg if (mangled[0] == '<') 457 1.1 mrg strcpy (demangled, mangled); 458 1.1 mrg else 459 1.1 mrg sprintf (demangled, "<%s>", mangled); 460 1.1 mrg 461 1.1 mrg return demangled; 462 1.1 mrg } 463