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