1 /*- 2 * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <assert.h> 29 #include <ctype.h> 30 #include <errno.h> 31 #include <libelftc.h> 32 #include <limits.h> 33 #include <stdbool.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 #include "_libelftc.h" 39 40 ELFTC_VCSID("$Id: libelftc_dem_gnu2.c 2065 2011-10-26 15:24:47Z jkoshy $"); 41 42 /** 43 * @file cpp_demangle_gnu2.c 44 * @brief Decode function name encoding in GNU 2. 45 * 46 * Function name encoding in GNU 2 based on ARM style. 47 */ 48 49 enum encode_type { 50 ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER, 51 ENCODE_OP_TF, ENCODE_OP_TI, ENCODE_OP_VT 52 }; 53 54 struct cstring { 55 char *buf; 56 size_t size; 57 }; 58 59 struct demangle_data { 60 bool ptr, ref, cnst, array, cnst_fn, class_name; 61 struct cstring array_str; 62 const char *p; 63 enum encode_type type; 64 struct vector_str vec; 65 struct vector_str arg; 66 }; 67 68 #define SIMPLE_HASH(x,y) (64 * x + y) 69 #define CPP_DEMANGLE_GNU2_TRY 128 70 71 static void dest_cstring(struct cstring *); 72 static void dest_demangle_data(struct demangle_data *); 73 static bool init_cstring(struct cstring *, size_t); 74 static bool init_demangle_data(struct demangle_data *); 75 static bool push_CTDT(const char *, size_t, struct vector_str *); 76 static bool read_array(struct demangle_data *); 77 static bool read_class(struct demangle_data *); 78 static bool read_func(struct demangle_data *); 79 static bool read_func_name(struct demangle_data *); 80 static bool read_func_ptr(struct demangle_data *); 81 static bool read_memptr(struct demangle_data *); 82 static bool read_op(struct demangle_data *); 83 static bool read_op_user(struct demangle_data *); 84 static bool read_qual_name(struct demangle_data *); 85 static int read_subst(struct demangle_data *); 86 static int read_subst_iter(struct demangle_data *); 87 static bool read_type(struct demangle_data *); 88 89 /** 90 * @brief Decode the input string by the GNU 2 style. 91 * 92 * @return New allocated demangled string or NULL if failed. 93 */ 94 char * 95 cpp_demangle_gnu2(const char *org) 96 { 97 struct demangle_data d; 98 size_t arg_begin, arg_len; 99 unsigned int try; 100 char *rtn, *arg; 101 102 if (org == NULL) 103 return (NULL); 104 105 if (init_demangle_data(&d) == false) 106 return (NULL); 107 108 try = 0; 109 rtn = NULL; 110 111 d.p = org; 112 if (read_func_name(&d) == false) 113 goto clean; 114 115 switch (d.type) { 116 case ENCODE_FUNC : 117 case ENCODE_OP : 118 break; 119 120 case ENCODE_OP_CT : 121 if (push_CTDT("::", 2, &d.vec) == false) 122 goto clean; 123 124 break; 125 case ENCODE_OP_DT : 126 if (push_CTDT("::~", 3, &d.vec) == false) 127 goto clean; 128 129 if (vector_str_push(&d.vec, "(void)", 6) == false) 130 goto clean; 131 132 goto flat; 133 case ENCODE_OP_USER : 134 case ENCODE_OP_TF : 135 case ENCODE_OP_TI : 136 case ENCODE_OP_VT : 137 goto flat; 138 }; 139 140 if (*d.p == 'F') 141 ++d.p; 142 else if (*d.p == '\0') { 143 if (d.class_name == true) { 144 if (vector_str_push(&d.vec, "(void)", 6) == false) 145 goto clean; 146 147 goto flat; 148 } else 149 goto clean; 150 } 151 152 /* start argument types */ 153 if (vector_str_push(&d.vec, "(", 1) == false) 154 goto clean; 155 156 for (;;) { 157 if (*d.p == 'T') { 158 const int rtn_subst = read_subst(&d); 159 160 if (rtn_subst == -1) 161 goto clean; 162 else if (rtn_subst == 1) 163 break; 164 165 continue; 166 } 167 168 if (*d.p == 'N') { 169 const int rtn_subst_iter = read_subst_iter(&d); 170 171 if (rtn_subst_iter == -1) 172 goto clean; 173 else if(rtn_subst_iter == 1) 174 break; 175 176 continue; 177 } 178 179 arg_begin = d.vec.size; 180 181 if (read_type(&d) == false) 182 goto clean; 183 184 if (d.ptr == true) { 185 if (vector_str_push(&d.vec, "*", 1) == false) 186 goto clean; 187 188 d.ptr = false; 189 } 190 191 if (d.ref == true) { 192 if (vector_str_push(&d.vec, "&", 1) == false) 193 goto clean; 194 195 d.ref = false; 196 } 197 198 if (d.cnst == true) { 199 if (vector_str_push(&d.vec, " const", 6) == false) 200 goto clean; 201 202 d.cnst = false; 203 } 204 205 if (d.array == true) { 206 if (vector_str_push(&d.vec, d.array_str.buf, 207 d.array_str.size) == false) 208 goto clean; 209 210 dest_cstring(&d.array_str); 211 d.array = false; 212 } 213 214 if (*d.p == '\0') 215 break; 216 217 if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1, 218 &arg_len)) == NULL) 219 goto clean; 220 221 if (vector_str_push(&d.arg, arg, arg_len) == false) 222 goto clean; 223 224 free(arg); 225 226 if (vector_str_push(&d.vec, ", ", 2) == false) 227 goto clean; 228 229 if (++try > CPP_DEMANGLE_GNU2_TRY) 230 goto clean; 231 } 232 233 /* end argument types */ 234 if (vector_str_push(&d.vec, ")", 1) == false) 235 goto clean; 236 flat: 237 if (d.cnst_fn == true && vector_str_push(&d.vec, " const", 6) == false) 238 goto clean; 239 240 rtn = vector_str_get_flat(&d.vec, NULL); 241 clean: 242 dest_demangle_data(&d); 243 244 return (rtn); 245 } 246 247 /** 248 * @brief Test input string is encoded by the GNU 2 style. 249 * 250 * @return True if input string is encoded by the GNU 2 style. 251 */ 252 bool 253 is_cpp_mangled_gnu2(const char *org) 254 { 255 char *str; 256 bool rtn = false; 257 258 if (org == NULL) 259 return (false); 260 261 /* search valid text to end */ 262 str = strstr(org, "__"); 263 while (str != NULL) { 264 if (*(str + 2) != '\0') { 265 if (*(str + 2) == 'C' || 266 *(str + 2) == 'F' || 267 *(str + 2) == 'Q' || 268 ELFTC_ISDIGIT(*(str + 2))) { 269 rtn |= true; 270 271 break; 272 } 273 274 if (*(str + 3) != '\0') { 275 switch (SIMPLE_HASH(*(str + 2), *(str + 3))) { 276 case SIMPLE_HASH('m', 'l') : 277 case SIMPLE_HASH('d', 'v') : 278 case SIMPLE_HASH('m', 'd') : 279 case SIMPLE_HASH('p', 'l') : 280 case SIMPLE_HASH('m', 'i') : 281 case SIMPLE_HASH('l', 's') : 282 case SIMPLE_HASH('r', 's') : 283 case SIMPLE_HASH('e', 'q') : 284 case SIMPLE_HASH('n', 'e') : 285 case SIMPLE_HASH('l', 't') : 286 case SIMPLE_HASH('g', 't') : 287 case SIMPLE_HASH('l', 'e') : 288 case SIMPLE_HASH('g', 'e') : 289 case SIMPLE_HASH('a', 'd') : 290 case SIMPLE_HASH('o', 'r') : 291 case SIMPLE_HASH('e', 'r') : 292 case SIMPLE_HASH('a', 'a') : 293 case SIMPLE_HASH('o', 'o') : 294 case SIMPLE_HASH('n', 't') : 295 case SIMPLE_HASH('c', 'o') : 296 case SIMPLE_HASH('p', 'p') : 297 case SIMPLE_HASH('m', 'm') : 298 case SIMPLE_HASH('a', 's') : 299 case SIMPLE_HASH('r', 'f') : 300 case SIMPLE_HASH('a', 'p') : 301 case SIMPLE_HASH('a', 'm') : 302 case SIMPLE_HASH('a', 'l') : 303 case SIMPLE_HASH('a', 'r') : 304 case SIMPLE_HASH('a', 'o') : 305 case SIMPLE_HASH('a', 'e') : 306 case SIMPLE_HASH('c', 'm') : 307 case SIMPLE_HASH('r', 'm') : 308 case SIMPLE_HASH('c', 'l') : 309 case SIMPLE_HASH('v', 'c') : 310 case SIMPLE_HASH('n', 'w') : 311 case SIMPLE_HASH('d', 'l') : 312 case SIMPLE_HASH('o', 'p') : 313 case SIMPLE_HASH('t', 'f') : 314 case SIMPLE_HASH('t', 'i') : 315 rtn |= true; 316 317 break; 318 }; 319 } 320 } 321 322 str = strstr(str + 2, "__"); 323 } 324 325 rtn |= strstr(org, "_$_") != NULL; 326 rtn |= strstr(org, "_vt$") != NULL; 327 328 return (rtn); 329 } 330 331 static void 332 dest_cstring(struct cstring *s) 333 { 334 335 if (s == NULL) 336 return; 337 338 free(s->buf); 339 s->buf = NULL; 340 s->size = 0; 341 } 342 343 static void 344 dest_demangle_data(struct demangle_data *d) 345 { 346 347 if (d != NULL) { 348 vector_str_dest(&d->arg); 349 vector_str_dest(&d->vec); 350 351 dest_cstring(&d->array_str); 352 } 353 } 354 355 static bool 356 init_cstring(struct cstring *s, size_t len) 357 { 358 359 if (s == NULL || len <= 1) 360 return (false); 361 362 if ((s->buf = malloc(sizeof(char) * len)) == NULL) 363 return (false); 364 365 s->size = len - 1; 366 367 return (true); 368 } 369 370 static bool 371 init_demangle_data(struct demangle_data *d) 372 { 373 374 if (d == NULL) 375 return (false); 376 377 d->ptr = false; 378 d->ref = false; 379 d->cnst = false; 380 d->array = false; 381 d->cnst_fn = false; 382 d->class_name = false; 383 384 d->array_str.buf = NULL; 385 d->array_str.size = 0; 386 387 d->type = ENCODE_FUNC; 388 389 if (vector_str_init(&d->vec) == false) 390 return (false); 391 392 if (vector_str_init(&d->arg) == false) { 393 vector_str_dest(&d->vec); 394 395 return (false); 396 } 397 398 return (true); 399 } 400 401 static bool 402 push_CTDT(const char *s, size_t l, struct vector_str *v) 403 { 404 405 if (s == NULL || l == 0 || v == NULL) 406 return (false); 407 408 if (vector_str_push(v, s, l) == false) 409 return (false); 410 411 assert(v->size > 1); 412 413 return (vector_str_push(v, v->container[v->size - 2], 414 strlen(v->container[v->size - 2]))); 415 } 416 417 static bool 418 read_array(struct demangle_data *d) 419 { 420 size_t len; 421 const char *end; 422 423 if (d == NULL || d->p == NULL) 424 return (false); 425 426 end = d->p; 427 assert(end != NULL); 428 429 for (;;) { 430 if (*end == '\0') 431 return (false); 432 433 if (ELFTC_ISDIGIT(*end) == 0) 434 break; 435 436 ++end; 437 } 438 439 if (*end != '_') 440 return (false); 441 442 len = end - d->p; 443 assert(len > 0); 444 445 dest_cstring(&d->array_str); 446 if (init_cstring(&d->array_str, len + 3) == false) 447 return (false); 448 449 strncpy(d->array_str.buf + 1, d->p, len); 450 *d->array_str.buf = '['; 451 *(d->array_str.buf + len + 1) = ']'; 452 453 d->array = true; 454 d->p = end + 1; 455 456 return (true); 457 } 458 459 static bool 460 read_class(struct demangle_data *d) 461 { 462 size_t len; 463 char *str; 464 465 if (d == NULL) 466 return (false); 467 468 len = strtol(d->p, &str, 10); 469 if (len == 0 && (errno == EINVAL || errno == ERANGE)) 470 return (false); 471 472 assert(len > 0); 473 assert(str != NULL); 474 475 if (vector_str_push(&d->vec, str, len) == false) 476 return (false); 477 478 d->p = str + len; 479 480 d->class_name = true; 481 482 return (true); 483 } 484 485 static bool 486 read_func(struct demangle_data *d) 487 { 488 size_t len; 489 const char *name; 490 char *delim; 491 492 if (d == NULL) 493 return (false); 494 495 assert(d->p != NULL && "d->p (org str) is NULL"); 496 if ((delim = strstr(d->p, "__")) == NULL) 497 return (false); 498 499 len = delim - d->p; 500 assert(len != 0); 501 502 name = d->p; 503 504 d->p = delim + 2; 505 506 if (*d->p == 'C') { 507 ++d->p; 508 509 d->cnst_fn = true; 510 } 511 512 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { 513 ++d->p; 514 515 if (read_qual_name(d) == false) 516 return (false); 517 } else if (ELFTC_ISDIGIT(*d->p)) { 518 if (read_class(d) == false) 519 return (false); 520 521 if (vector_str_push(&d->vec, "::", 2) == false) 522 return (false); 523 } 524 525 return (vector_str_push(&d->vec, name, len)); 526 } 527 528 static bool 529 read_func_name(struct demangle_data *d) 530 { 531 size_t len; 532 bool rtn; 533 char *op_name; 534 535 if (d == NULL) 536 return (false); 537 538 rtn = false; 539 op_name = NULL; 540 541 assert(d->p != NULL && "d->p (org str) is NULL"); 542 543 if (*d->p == '_' && *(d->p + 1) == '_') { 544 d->p += 2; 545 546 /* CTOR */ 547 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { 548 ++d->p; 549 d->type = ENCODE_OP_CT; 550 551 if (read_qual_name(d) == false) 552 return (false); 553 554 return (vector_str_pop(&d->vec)); 555 } else if (ELFTC_ISDIGIT(*d->p)) { 556 d->type = ENCODE_OP_CT; 557 558 return (read_class(d)); 559 } 560 561 d->type = ENCODE_OP; 562 if (read_op(d) == false) { 563 /* not good condition, start function name with '__' */ 564 d->type = ENCODE_FUNC; 565 566 if (vector_str_push(&d->vec, "__", 2) == false) 567 return (false); 568 569 return (read_func(d)); 570 } 571 572 if (d->type == ENCODE_OP_USER || 573 d->type == ENCODE_OP_TF || 574 d->type == ENCODE_OP_TI) 575 return (true); 576 577 /* skip "__" */ 578 d->p += 2; 579 580 if (*d->p == 'C') { 581 ++d->p; 582 583 d->cnst_fn = true; 584 } 585 586 /* assume delimiter is removed */ 587 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { 588 ++d->p; 589 590 assert(d->vec.size > 0); 591 592 len = strlen(d->vec.container[d->vec.size - 1]); 593 if ((op_name = malloc(sizeof(char) * (len + 1))) 594 == NULL) 595 return (false); 596 597 snprintf(op_name, len + 1, "%s", 598 d->vec.container[d->vec.size - 1]); 599 vector_str_pop(&d->vec); 600 601 if (read_qual_name(d) == false) 602 goto clean; 603 604 if (vector_str_push(&d->vec, "::", 2) == false) 605 goto clean; 606 607 if (vector_str_push(&d->vec, op_name, len) == false) 608 goto clean; 609 610 rtn = true; 611 } else if (ELFTC_ISDIGIT(*d->p)) { 612 assert(d->vec.size > 0); 613 614 len = strlen(d->vec.container[d->vec.size - 1]); 615 if ((op_name = malloc(sizeof(char) * (len + 1))) 616 == NULL) 617 return (false); 618 619 snprintf(op_name, len + 1, "%s", 620 d->vec.container[d->vec.size - 1]); 621 vector_str_pop(&d->vec); 622 623 if (read_class(d) == false) 624 goto clean; 625 626 if (vector_str_push(&d->vec, "::", 2) == false) 627 goto clean; 628 629 if (vector_str_push(&d->vec, op_name, len) == false) 630 goto clean; 631 632 rtn = true; 633 } 634 } else if (memcmp(d->p, "_$_", 3) == 0) { 635 /* DTOR */ 636 d->p += 3; 637 d->type = ENCODE_OP_DT; 638 639 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { 640 ++d->p; 641 642 if (read_qual_name(d) == false) 643 return (false); 644 645 return (vector_str_pop(&d->vec)); 646 } else if (ELFTC_ISDIGIT(*d->p)) 647 return (read_class(d)); 648 649 return (false); 650 } else if (memcmp(d->p, "_vt$", 4) == 0) { 651 /* vtable */ 652 d->p += 4; 653 d->type = ENCODE_OP_VT; 654 655 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { 656 ++d->p; 657 658 if (read_qual_name(d) == false) 659 return (false); 660 661 if (vector_str_pop(&d->vec) == false) 662 return (false); 663 } else if (ELFTC_ISDIGIT(*d->p)) { 664 if (read_class(d) == false) 665 return (false); 666 } 667 668 return (vector_str_push(&d->vec, " virtual table", 14)); 669 } else 670 return (read_func(d)); 671 clean: 672 free(op_name); 673 674 return (rtn); 675 } 676 677 /* Read function ptr type */ 678 static bool 679 read_func_ptr(struct demangle_data *d) 680 { 681 struct demangle_data fptr; 682 size_t arg_len, rtn_len; 683 char *arg_type, *rtn_type; 684 int lim; 685 686 if (d == NULL) 687 return (false); 688 689 if (init_demangle_data(&fptr) == false) 690 return (false); 691 692 fptr.p = d->p + 1; 693 lim = 0; 694 arg_type = NULL; 695 rtn_type = NULL; 696 697 for (;;) { 698 if (read_type(&fptr) == false) { 699 dest_demangle_data(&fptr); 700 701 return (false); 702 } 703 704 if (fptr.ptr == true) { 705 if (vector_str_push(&fptr.vec, "*", 1) == false) { 706 dest_demangle_data(&fptr); 707 708 return (false); 709 } 710 711 fptr.ptr = false; 712 } 713 714 if (fptr.ref == true) { 715 if (vector_str_push(&fptr.vec, "&", 1) == false) { 716 dest_demangle_data(&fptr); 717 718 return (false); 719 } 720 721 fptr.ref = false; 722 } 723 724 if (fptr.cnst == true) { 725 if (vector_str_push(&fptr.vec, " const", 6) == false) { 726 dest_demangle_data(&fptr); 727 728 return (false); 729 } 730 731 fptr.cnst = false; 732 } 733 734 if (*fptr.p == '_') 735 break; 736 737 if (vector_str_push(&fptr.vec, ", ", 2) == false) { 738 dest_demangle_data(&fptr); 739 740 return (false); 741 } 742 743 if (++lim > CPP_DEMANGLE_GNU2_TRY) { 744 745 dest_demangle_data(&fptr); 746 747 return (false); 748 } 749 } 750 751 arg_type = vector_str_get_flat(&fptr.vec, &arg_len); 752 /* skip '_' */ 753 d->p = fptr.p + 1; 754 755 dest_demangle_data(&fptr); 756 757 if (init_demangle_data(&fptr) == false) { 758 free(arg_type); 759 760 return (false); 761 } 762 763 fptr.p = d->p; 764 lim = 0; 765 766 if (read_type(&fptr) == false) { 767 free(arg_type); 768 dest_demangle_data(&fptr); 769 770 return (false); 771 } 772 773 rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len); 774 d->p = fptr.p; 775 776 777 dest_demangle_data(&fptr); 778 779 if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) { 780 free(rtn_type); 781 free(arg_type); 782 783 return (false); 784 } 785 786 free(rtn_type); 787 788 if (vector_str_push(&d->vec, " (*)(", 5) == false) { 789 free(arg_type); 790 791 return (false); 792 } 793 794 if (vector_str_push(&d->vec, arg_type, arg_len) == false) { 795 free(arg_type); 796 797 return (false); 798 } 799 800 free(arg_type); 801 802 return (vector_str_push(&d->vec, ")", 1)); 803 } 804 805 static bool 806 read_memptr(struct demangle_data *d) 807 { 808 struct demangle_data mptr; 809 size_t len; 810 bool rtn; 811 char *mptr_str; 812 813 if (d == NULL || d->p == NULL) 814 return (false); 815 816 if (init_demangle_data(&mptr) == false) 817 return (false); 818 819 rtn = false; 820 mptr_str = NULL; 821 822 mptr.p = d->p; 823 if (*mptr.p == 'Q') { 824 ++mptr.p; 825 826 if (read_qual_name(&mptr) == false) 827 goto clean; 828 } else if (read_class(&mptr) == false) 829 goto clean; 830 831 d->p = mptr.p; 832 833 if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL) 834 goto clean; 835 836 if (vector_str_push(&d->vec, mptr_str, len) == false) 837 goto clean; 838 839 if (vector_str_push(&d->vec, "::*", 3) == false) 840 goto clean; 841 842 rtn = true; 843 clean: 844 free(mptr_str); 845 dest_demangle_data(&mptr); 846 847 return (rtn); 848 } 849 850 static bool 851 read_op(struct demangle_data *d) 852 { 853 854 if (d == NULL) 855 return (false); 856 857 assert(d->p != NULL && "d->p (org str) is NULL"); 858 859 switch (SIMPLE_HASH(*(d->p), *(d->p+1))) { 860 case SIMPLE_HASH('m', 'l') : 861 d->p += 2; 862 return (vector_str_push(&d->vec, "operator*", 9)); 863 case SIMPLE_HASH('d', 'v') : 864 d->p += 2; 865 return (vector_str_push(&d->vec, "operator/", 9)); 866 case SIMPLE_HASH('m', 'd') : 867 d->p += 2; 868 return (vector_str_push(&d->vec, "operator%", 9)); 869 case SIMPLE_HASH('p', 'l') : 870 d->p += 2; 871 return (vector_str_push(&d->vec, "operator+", 9)); 872 case SIMPLE_HASH('m', 'i') : 873 d->p += 2; 874 return (vector_str_push(&d->vec, "operator-", 9)); 875 case SIMPLE_HASH('l', 's') : 876 d->p += 2; 877 return (vector_str_push(&d->vec, "operator<<", 10)); 878 case SIMPLE_HASH('r', 's') : 879 d->p += 2; 880 return (vector_str_push(&d->vec, "operator>>", 10)); 881 case SIMPLE_HASH('e', 'q') : 882 d->p += 2; 883 return (vector_str_push(&d->vec, "operator==", 10)); 884 case SIMPLE_HASH('n', 'e') : 885 d->p += 2; 886 return (vector_str_push(&d->vec, "operator!=", 10)); 887 case SIMPLE_HASH('l', 't') : 888 d->p += 2; 889 return (vector_str_push(&d->vec, "operator<", 9)); 890 case SIMPLE_HASH('g', 't') : 891 d->p += 2; 892 return (vector_str_push(&d->vec, "operator>", 9)); 893 case SIMPLE_HASH('l', 'e') : 894 d->p += 2; 895 return (vector_str_push(&d->vec, "operator<=", 10)); 896 case SIMPLE_HASH('g', 'e') : 897 d->p += 2; 898 return (vector_str_push(&d->vec, "operator>=", 10)); 899 case SIMPLE_HASH('a', 'd') : 900 d->p += 2; 901 if (*d->p == 'v') { 902 ++d->p; 903 return (vector_str_push(&d->vec, "operator/=", 904 10)); 905 } else 906 return (vector_str_push(&d->vec, "operator&", 9)); 907 case SIMPLE_HASH('o', 'r') : 908 d->p += 2; 909 return (vector_str_push(&d->vec, "operator|", 9)); 910 case SIMPLE_HASH('e', 'r') : 911 d->p += 2; 912 return (vector_str_push(&d->vec, "operator^", 9)); 913 case SIMPLE_HASH('a', 'a') : 914 d->p += 2; 915 if (*d->p == 'd') { 916 ++d->p; 917 return (vector_str_push(&d->vec, "operator&=", 918 10)); 919 } else 920 return (vector_str_push(&d->vec, "operator&&", 921 10)); 922 case SIMPLE_HASH('o', 'o') : 923 d->p += 2; 924 return (vector_str_push(&d->vec, "operator||", 10)); 925 case SIMPLE_HASH('n', 't') : 926 d->p += 2; 927 return (vector_str_push(&d->vec, "operator!", 9)); 928 case SIMPLE_HASH('c', 'o') : 929 d->p += 2; 930 return (vector_str_push(&d->vec, "operator~", 9)); 931 case SIMPLE_HASH('p', 'p') : 932 d->p += 2; 933 return (vector_str_push(&d->vec, "operator++", 10)); 934 case SIMPLE_HASH('m', 'm') : 935 d->p += 2; 936 return (vector_str_push(&d->vec, "operator--", 10)); 937 case SIMPLE_HASH('a', 's') : 938 d->p += 2; 939 return (vector_str_push(&d->vec, "operator=", 9)); 940 case SIMPLE_HASH('r', 'f') : 941 d->p += 2; 942 return (vector_str_push(&d->vec, "operator->", 10)); 943 case SIMPLE_HASH('a', 'p') : 944 /* apl */ 945 if (*(d->p + 2) != 'l') 946 return (false); 947 948 d->p += 3; 949 return (vector_str_push(&d->vec, "operator+=", 10)); 950 case SIMPLE_HASH('a', 'm') : 951 d->p += 2; 952 if (*d->p == 'i') { 953 ++d->p; 954 return (vector_str_push(&d->vec, "operator-=", 955 10)); 956 } else if (*d->p == 'u') { 957 ++d->p; 958 return (vector_str_push(&d->vec, "operator*=", 959 10)); 960 } else if (*d->p == 'd') { 961 ++d->p; 962 return (vector_str_push(&d->vec, "operator%=", 963 10)); 964 } 965 966 return (false); 967 case SIMPLE_HASH('a', 'l') : 968 /* als */ 969 if (*(d->p + 2) != 's') 970 return (false); 971 972 d->p += 3; 973 return (vector_str_push(&d->vec, "operator<<=", 11)); 974 case SIMPLE_HASH('a', 'r') : 975 /* ars */ 976 if (*(d->p + 2) != 's') 977 return (false); 978 979 d->p += 3; 980 return (vector_str_push(&d->vec, "operator>>=", 11)); 981 case SIMPLE_HASH('a', 'o') : 982 /* aor */ 983 if (*(d->p + 2) != 'r') 984 return (false); 985 986 d->p += 3; 987 return (vector_str_push(&d->vec, "operator|=", 10)); 988 case SIMPLE_HASH('a', 'e') : 989 /* aer */ 990 if (*(d->p + 2) != 'r') 991 return (false); 992 993 d->p += 3; 994 return (vector_str_push(&d->vec, "operator^=", 10)); 995 case SIMPLE_HASH('c', 'm') : 996 d->p += 2; 997 return (vector_str_push(&d->vec, "operator,", 9)); 998 case SIMPLE_HASH('r', 'm') : 999 d->p += 2; 1000 return (vector_str_push(&d->vec, "operator->*", 11)); 1001 case SIMPLE_HASH('c', 'l') : 1002 d->p += 2; 1003 return (vector_str_push(&d->vec, "()", 2)); 1004 case SIMPLE_HASH('v', 'c') : 1005 d->p += 2; 1006 return (vector_str_push(&d->vec, "[]", 2)); 1007 case SIMPLE_HASH('n', 'w') : 1008 d->p += 2; 1009 return (vector_str_push(&d->vec, "operator new()", 14)); 1010 case SIMPLE_HASH('d', 'l') : 1011 d->p += 2; 1012 return (vector_str_push(&d->vec, "operator delete()", 1013 17)); 1014 case SIMPLE_HASH('o', 'p') : 1015 /* __op<TO_TYPE>__<FROM_TYPE> */ 1016 d->p += 2; 1017 1018 d->type = ENCODE_OP_USER; 1019 1020 return (read_op_user(d)); 1021 case SIMPLE_HASH('t', 'f') : 1022 d->p += 2; 1023 d->type = ENCODE_OP_TF; 1024 1025 if (read_type(d) == false) 1026 return (false); 1027 1028 return (vector_str_push(&d->vec, " type_info function", 19)); 1029 case SIMPLE_HASH('t', 'i') : 1030 d->p += 2; 1031 d->type = ENCODE_OP_TI; 1032 1033 if (read_type(d) == false) 1034 return (false); 1035 1036 return (vector_str_push(&d->vec, " type_info node", 15)); 1037 default : 1038 return (false); 1039 }; 1040 } 1041 1042 static bool 1043 read_op_user(struct demangle_data *d) 1044 { 1045 struct demangle_data from, to; 1046 size_t from_len, to_len; 1047 bool rtn; 1048 char *from_str, *to_str; 1049 1050 if (d == NULL) 1051 return (false); 1052 1053 if (init_demangle_data(&from) == false) 1054 return (false); 1055 1056 rtn = false; 1057 from_str = NULL; 1058 to_str = NULL; 1059 if (init_demangle_data(&to) == false) 1060 goto clean; 1061 1062 to.p = d->p; 1063 if (*to.p == 'Q') { 1064 ++to.p; 1065 1066 if (read_qual_name(&to) == false) 1067 goto clean; 1068 1069 /* pop last '::' */ 1070 if (vector_str_pop(&to.vec) == false) 1071 goto clean; 1072 } else { 1073 if (read_class(&to) == false) 1074 goto clean; 1075 1076 /* skip '__' */ 1077 to.p += 2; 1078 } 1079 1080 if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL) 1081 goto clean; 1082 1083 from.p = to.p; 1084 if (*from.p == 'Q') { 1085 ++from.p; 1086 1087 if (read_qual_name(&from) == false) 1088 goto clean; 1089 1090 /* pop last '::' */ 1091 if (vector_str_pop(&from.vec) == false) 1092 goto clean; 1093 } else if (read_class(&from) == false) 1094 goto clean; 1095 1096 if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL) 1097 goto clean; 1098 1099 if (vector_str_push(&d->vec, from_str, from_len) == false) 1100 goto clean; 1101 1102 if (vector_str_push(&d->vec, "::operator ", 11) == false) 1103 goto clean; 1104 1105 if (vector_str_push(&d->vec, to_str, to_len) == false) 1106 goto clean; 1107 1108 rtn = vector_str_push(&d->vec, "()", 2); 1109 clean: 1110 free(to_str); 1111 free(from_str); 1112 dest_demangle_data(&to); 1113 dest_demangle_data(&from); 1114 1115 return (rtn); 1116 } 1117 1118 /* single digit + class names */ 1119 static bool 1120 read_qual_name(struct demangle_data *d) 1121 { 1122 int i; 1123 char num; 1124 1125 if (d == NULL) 1126 return (false); 1127 1128 assert(d->p != NULL && "d->p (org str) is NULL"); 1129 assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); 1130 1131 num = *d->p - 48; 1132 1133 assert(num > 0); 1134 1135 ++d->p; 1136 for (i = 0; i < num ; ++i) { 1137 if (read_class(d) == false) 1138 return (false); 1139 1140 if (vector_str_push(&d->vec, "::", 2) == false) 1141 return (false); 1142 } 1143 1144 if (*d->p != '\0') 1145 d->p = d->p + 2; 1146 1147 return (true); 1148 } 1149 1150 /* Return -1 at fail, 0 at success, and 1 at end */ 1151 static int 1152 read_subst(struct demangle_data *d) 1153 { 1154 size_t idx; 1155 char *str; 1156 1157 if (d == NULL) 1158 return (-1); 1159 1160 idx = strtol(d->p + 1, &str, 10); 1161 if (idx == 0 && (errno == EINVAL || errno == ERANGE)) 1162 return (-1); 1163 1164 assert(idx > 0); 1165 assert(str != NULL); 1166 1167 d->p = str; 1168 1169 if (vector_str_push(&d->vec, d->arg.container[idx - 1], 1170 strlen(d->arg.container[idx - 1])) == false) 1171 return (-1); 1172 1173 if (vector_str_push(&d->arg, d->arg.container[idx - 1], 1174 strlen(d->arg.container[idx - 1])) == false) 1175 return (-1); 1176 1177 if (*d->p == '\0') 1178 return (1); 1179 1180 return (0); 1181 } 1182 1183 static int 1184 read_subst_iter(struct demangle_data *d) 1185 { 1186 int i; 1187 size_t idx; 1188 char repeat; 1189 char *str; 1190 1191 if (d == NULL) 1192 return (-1); 1193 1194 ++d->p; 1195 assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); 1196 1197 repeat = *d->p - 48; 1198 1199 assert(repeat > 1); 1200 1201 ++d->p; 1202 1203 idx = strtol(d->p, &str, 10); 1204 if (idx == 0 && (errno == EINVAL || errno == ERANGE)) 1205 return (-1); 1206 1207 assert(idx > 0); 1208 assert(str != NULL); 1209 1210 d->p = str; 1211 1212 for (i = 0; i < repeat ; ++i) { 1213 if (vector_str_push(&d->vec, d->arg.container[idx - 1], 1214 strlen(d->arg.container[idx - 1])) == false) 1215 return (-1); 1216 1217 if (vector_str_push(&d->arg, d->arg.container[idx - 1], 1218 strlen(d->arg.container[idx - 1])) == false) 1219 return (-1); 1220 1221 if (i != repeat - 1 && 1222 vector_str_push(&d->vec, ", ", 2) == false) 1223 return (-1); 1224 } 1225 1226 if (*d->p == '\0') 1227 return (1); 1228 1229 return (0); 1230 } 1231 1232 static bool 1233 read_type(struct demangle_data *d) 1234 { 1235 1236 if (d == NULL) 1237 return (false); 1238 1239 assert(d->p != NULL && "d->p (org str) is NULL"); 1240 1241 while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' || 1242 *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' || 1243 *d->p == 'M') { 1244 switch (*d->p) { 1245 case 'U' : 1246 ++d->p; 1247 1248 if (vector_str_push(&d->vec, "unsigned ", 9) == false) 1249 return (false); 1250 1251 break; 1252 case 'C' : 1253 ++d->p; 1254 1255 if (*d->p == 'P') 1256 d->cnst = true; 1257 else { 1258 if (vector_str_push(&d->vec, "const ", 6) == 1259 false) 1260 return (false); 1261 } 1262 1263 break; 1264 case 'V' : 1265 ++d->p; 1266 1267 if (vector_str_push(&d->vec, "volatile ", 9) == false) 1268 return (false); 1269 1270 break; 1271 case 'S' : 1272 ++d->p; 1273 1274 if (vector_str_push(&d->vec, "signed ", 7) == false) 1275 return (false); 1276 1277 break; 1278 case 'P' : 1279 ++d->p; 1280 1281 if (*d->p == 'F') 1282 return (read_func_ptr(d)); 1283 else 1284 d->ptr = true; 1285 1286 break; 1287 case 'R' : 1288 ++d->p; 1289 1290 d->ref = true; 1291 1292 break; 1293 case 'F' : 1294 break; 1295 case 'A' : 1296 ++d->p; 1297 1298 if (read_array(d) == false) 1299 return (false); 1300 1301 break; 1302 case 'M' : 1303 ++d->p; 1304 1305 if (read_memptr(d) == false) 1306 return (false); 1307 1308 break; 1309 default : 1310 break; 1311 }; 1312 }; 1313 1314 if (ELFTC_ISDIGIT(*d->p)) 1315 return (read_class(d)); 1316 1317 switch (*d->p) { 1318 case 'Q' : 1319 ++d->p; 1320 1321 return (read_qual_name(d)); 1322 case 'v' : 1323 ++d->p; 1324 1325 return (vector_str_push(&d->vec, "void", 4)); 1326 case 'b': 1327 ++d->p; 1328 1329 return(vector_str_push(&d->vec, "bool", 4)); 1330 case 'c' : 1331 ++d->p; 1332 1333 return (vector_str_push(&d->vec, "char", 4)); 1334 case 's' : 1335 ++d->p; 1336 1337 return (vector_str_push(&d->vec, "short", 5)); 1338 case 'i' : 1339 ++d->p; 1340 1341 return (vector_str_push(&d->vec, "int", 3)); 1342 case 'l' : 1343 ++d->p; 1344 1345 return (vector_str_push(&d->vec, "long", 4)); 1346 case 'f' : 1347 ++d->p; 1348 1349 return (vector_str_push(&d->vec, "float", 5)); 1350 case 'd': 1351 ++d->p; 1352 1353 return (vector_str_push(&d->vec, "double", 6)); 1354 case 'r': 1355 ++d->p; 1356 1357 return (vector_str_push(&d->vec, "long double", 11)); 1358 case 'e': 1359 ++d->p; 1360 1361 return (vector_str_push(&d->vec, "...", 3)); 1362 case 'w': 1363 ++d->p; 1364 1365 return (vector_str_push(&d->vec, "wchar_t", 7)); 1366 case 'x': 1367 ++d->p; 1368 1369 return (vector_str_push(&d->vec, "long long", 9)); 1370 default: 1371 return (false); 1372 }; 1373 1374 /* NOTREACHED */ 1375 return (false); 1376 } 1377