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