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