2 * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/types.h>
38 #include "_libelftc.h"
40 ELFTC_VCSID("$Id: libelftc_dem_arm.c 3513 2016-12-29 07:04:22Z kaiwang27 $");
43 * @file cpp_demangle_arm.c
44 * @brief Decode function name encoding in ARM.
46 * Function name encoding in "The Annotated C++ Reference Manual".
48 * Ref : "The Annotated C++ Reference Manual", Margaet A.Ellis,
49 * Bjarne Stroustrup, AT&T Bell Laboratories 1990, pp 122-126.
53 ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER
61 struct demangle_data {
62 bool ptr, ref, cnst, array;
63 struct cstring array_str;
65 enum encode_type type;
66 struct vector_str vec;
67 struct vector_str arg;
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
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 *);
93 * @brief Decode the input string by the ARM style.
95 * @return New allocated demangled string or NULL if failed.
98 cpp_demangle_ARM(const char *org)
100 struct demangle_data d;
101 size_t arg_begin, arg_len;
108 if (init_demangle_data(&d) == false)
115 if (read_func_name(&d) == false)
118 if (d.type == ENCODE_OP_CT) {
119 if (push_CTDT("::", 2, &d.vec) == false)
125 if (d.type == ENCODE_OP_DT) {
126 if (push_CTDT("::~", 3, &d.vec) == false)
132 if (d.type == ENCODE_OP_USER)
140 /* start argument types */
141 if (VEC_PUSH_STR(&d.vec, "(") == false)
146 const int rtn_subst = read_subst(&d);
150 else if (rtn_subst == 1)
157 const int rtn_subst_iter = read_subst_iter(&d);
159 if (rtn_subst_iter == -1)
161 else if(rtn_subst_iter == 1)
167 arg_begin = d.vec.size;
169 if (read_type(&d) == false)
173 if (VEC_PUSH_STR(&d.vec, "*") == false)
180 if (VEC_PUSH_STR(&d.vec, "&") == false)
186 if (d.cnst == true) {
187 if (VEC_PUSH_STR(&d.vec, " const") == false)
193 if (d.array == true) {
194 if (vector_str_push(&d.vec, d.array_str.buf,
195 d.array_str.size) == false)
198 dest_cstring(&d.array_str);
205 if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,
209 if (vector_str_push(&d.arg, arg, arg_len) == false) {
216 if (VEC_PUSH_STR(&d.vec, ", ") == false)
219 if (++try > CPP_DEMANGLE_ARM_TRY)
223 /* end argument types */
224 if (VEC_PUSH_STR(&d.vec, ")") == false)
228 rtn = vector_str_get_flat(&d.vec, NULL);
230 dest_demangle_data(&d);
236 * @brief Test input string is encoded by the ARM style.
238 * @return True if input string is encoded by the ARM style.
241 is_cpp_mangled_ARM(const char *org)
247 return (strstr(org, "__") != NULL);
251 dest_cstring(struct cstring *s)
263 dest_demangle_data(struct demangle_data *d)
267 vector_str_dest(&d->arg);
268 vector_str_dest(&d->vec);
270 dest_cstring(&d->array_str);
275 init_cstring(struct cstring *s, size_t len)
278 if (s == NULL || len <= 1)
281 if ((s->buf = malloc(sizeof(char) * len)) == NULL)
290 init_demangle_data(struct demangle_data *d)
301 d->array_str.buf = NULL;
302 d->array_str.size = 0;
304 d->type = ENCODE_FUNC;
306 if (!vector_str_init(&d->vec))
309 if (!vector_str_init(&d->arg)) {
310 vector_str_dest(&d->vec);
318 push_CTDT(const char *s, size_t l, struct vector_str *v)
321 if (s == NULL || l == 0 || v == NULL)
324 if (vector_str_push(v, s, l) == false)
328 if (VEC_PUSH_STR(v, v->container[v->size - 2]) == false)
331 if (VEC_PUSH_STR(v, "()") == false)
338 read_array(struct demangle_data *d)
343 if (d == NULL || d->p == NULL)
353 if (ELFTC_ISDIGIT(*end) == 0)
365 dest_cstring(&d->array_str);
366 if (init_cstring(&d->array_str, len + 3) == false)
369 strncpy(d->array_str.buf + 1, d->p, len);
370 *d->array_str.buf = '[';
371 *(d->array_str.buf + len + 1) = ']';
380 read_class(struct demangle_data *d)
388 len = strtol(d->p, &str, 10);
389 if (len == 0 && (errno == EINVAL || errno == ERANGE))
395 if (vector_str_push(&d->vec, str, len) == false)
404 read_func(struct demangle_data *d)
413 assert(d->p != NULL && "d->p (org str) is NULL");
414 if ((delim = strstr(d->p, "__")) == NULL)
424 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
427 if (read_qual_name(d) == false)
429 } else if (ELFTC_ISDIGIT(*d->p)) {
430 if (read_class(d) == false)
433 if (VEC_PUSH_STR(&d->vec, "::") == false)
437 if (vector_str_push(&d->vec, name, len) == false)
444 read_func_name(struct demangle_data *d)
456 assert(d->p != NULL && "d->p (org str) is NULL");
458 if (*d->p == '_' && *(d->p + 1) == '_') {
462 if (read_op(d) == false)
465 if (d->type == ENCODE_OP_CT || d->type == ENCODE_OP_DT ||
466 d->type == ENCODE_OP_USER)
472 /* assume delimiter is removed */
473 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
476 assert(d->vec.size > 0);
478 len = strlen(d->vec.container[d->vec.size - 1]);
479 if ((op_name = malloc(sizeof(char) * (len + 1)))
483 snprintf(op_name, len + 1, "%s",
484 d->vec.container[d->vec.size - 1]);
485 vector_str_pop(&d->vec);
487 if (read_qual_name(d) == false)
490 if (VEC_PUSH_STR(&d->vec, "::") == false)
493 if (vector_str_push(&d->vec, op_name, len) == false)
497 } else if (ELFTC_ISDIGIT(*d->p)) {
498 assert(d->vec.size > 0);
500 len = strlen(d->vec.container[d->vec.size - 1]);
501 if ((op_name = malloc(sizeof(char) * (len + 1)))
505 snprintf(op_name, len + 1, "%s",
506 d->vec.container[d->vec.size - 1]);
507 vector_str_pop(&d->vec);
509 if (read_class(d) == false)
512 if (VEC_PUSH_STR(&d->vec, "::") == false)
515 if (vector_str_push(&d->vec, op_name, len) == false)
521 return (read_func(d));
529 /* Read function ptr type */
531 read_func_ptr(struct demangle_data *d)
533 struct demangle_data fptr;
534 size_t arg_len, rtn_len;
535 char *arg_type, *rtn_type;
541 if (init_demangle_data(&fptr) == false)
550 if (read_type(&fptr) == false) {
551 dest_demangle_data(&fptr);
556 if (fptr.ptr == true) {
557 if (VEC_PUSH_STR(&fptr.vec, "*") == false) {
558 dest_demangle_data(&fptr);
566 if (fptr.ref == true) {
567 if (VEC_PUSH_STR(&fptr.vec, "&") == false) {
568 dest_demangle_data(&fptr);
576 if (fptr.cnst == true) {
577 if (VEC_PUSH_STR(&fptr.vec, " const") == false) {
578 dest_demangle_data(&fptr);
589 if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {
590 dest_demangle_data(&fptr);
595 if (++lim > CPP_DEMANGLE_ARM_TRY) {
597 dest_demangle_data(&fptr);
603 arg_type = vector_str_get_flat(&fptr.vec, &arg_len);
607 dest_demangle_data(&fptr);
609 if (init_demangle_data(&fptr) == false) {
618 if (read_type(&fptr) == false) {
620 dest_demangle_data(&fptr);
625 rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);
629 dest_demangle_data(&fptr);
631 if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {
640 if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {
646 if (vector_str_push(&d->vec, arg_type, arg_len) == false) {
654 return (VEC_PUSH_STR(&d->vec, ")"));
658 read_memptr(struct demangle_data *d)
660 struct demangle_data mptr;
665 if (d == NULL || d->p == NULL)
668 if (init_demangle_data(&mptr) == false)
675 if (*mptr.p == 'Q') {
678 if (read_qual_name(&mptr) == false)
681 if (read_class(&mptr) == false)
687 if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)
690 if (vector_str_push(&d->vec, mptr_str, len) == false)
693 if (VEC_PUSH_STR(&d->vec, "::*") == false)
699 dest_demangle_data(&mptr);
705 read_op(struct demangle_data *d)
711 assert(d->p != NULL && "d->p (org str) is NULL");
713 switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {
714 case SIMPLE_HASH('m', 'l') :
716 return (VEC_PUSH_STR(&d->vec, "operator*"));
717 case SIMPLE_HASH('d', 'v') :
719 return (VEC_PUSH_STR(&d->vec, "operator/"));
720 case SIMPLE_HASH('m', 'd') :
722 return (VEC_PUSH_STR(&d->vec, "operator%"));
723 case SIMPLE_HASH('p', 'l') :
725 return (VEC_PUSH_STR(&d->vec, "operator+"));
726 case SIMPLE_HASH('m', 'i') :
728 return (VEC_PUSH_STR(&d->vec, "operator-"));
729 case SIMPLE_HASH('l', 's') :
731 return (VEC_PUSH_STR(&d->vec, "operator<<"));
732 case SIMPLE_HASH('r', 's') :
734 return (VEC_PUSH_STR(&d->vec, "operator>>"));
735 case SIMPLE_HASH('e', 'q') :
737 return (VEC_PUSH_STR(&d->vec, "operator=="));
738 case SIMPLE_HASH('n', 'e') :
740 return (VEC_PUSH_STR(&d->vec, "operator!="));
741 case SIMPLE_HASH('l', 't') :
743 return (VEC_PUSH_STR(&d->vec, "operator<"));
744 case SIMPLE_HASH('g', 't') :
746 return (VEC_PUSH_STR(&d->vec, "operator>"));
747 case SIMPLE_HASH('l', 'e') :
749 return (VEC_PUSH_STR(&d->vec, "operator<="));
750 case SIMPLE_HASH('g', 'e') :
752 return (VEC_PUSH_STR(&d->vec, "operator>="));
753 case SIMPLE_HASH('a', 'd') :
757 return (VEC_PUSH_STR(&d->vec, "operator/="));
759 return (VEC_PUSH_STR(&d->vec, "operator&"));
760 case SIMPLE_HASH('o', 'r') :
762 return (VEC_PUSH_STR(&d->vec, "operator|"));
763 case SIMPLE_HASH('e', 'r') :
765 return (VEC_PUSH_STR(&d->vec, "operator^"));
766 case SIMPLE_HASH('a', 'a') :
770 return (VEC_PUSH_STR(&d->vec, "operator&="));
772 return (VEC_PUSH_STR(&d->vec, "operator&&"));
773 case SIMPLE_HASH('o', 'o') :
775 return (VEC_PUSH_STR(&d->vec, "operator||"));
776 case SIMPLE_HASH('n', 't') :
778 return (VEC_PUSH_STR(&d->vec, "operator!"));
779 case SIMPLE_HASH('c', 'o') :
781 return (VEC_PUSH_STR(&d->vec, "operator~"));
782 case SIMPLE_HASH('p', 'p') :
784 return (VEC_PUSH_STR(&d->vec, "operator++"));
785 case SIMPLE_HASH('m', 'm') :
787 return (VEC_PUSH_STR(&d->vec, "operator--"));
788 case SIMPLE_HASH('a', 's') :
790 return (VEC_PUSH_STR(&d->vec, "operator="));
791 case SIMPLE_HASH('r', 'f') :
793 return (VEC_PUSH_STR(&d->vec, "operator->"));
794 case SIMPLE_HASH('a', 'p') :
796 if (*(d->p + 2) != 'l')
800 return (VEC_PUSH_STR(&d->vec, "operator+="));
801 case SIMPLE_HASH('a', 'm') :
805 return (VEC_PUSH_STR(&d->vec, "operator-="));
806 } else if (*d->p == 'u') {
808 return (VEC_PUSH_STR(&d->vec, "operator*="));
809 } else if (*d->p == 'd') {
811 return (VEC_PUSH_STR(&d->vec, "operator%="));
815 case SIMPLE_HASH('a', 'l') :
817 if (*(d->p + 2) != 's')
821 return (VEC_PUSH_STR(&d->vec, "operator<<="));
822 case SIMPLE_HASH('a', 'r') :
824 if (*(d->p + 2) != 's')
828 return (VEC_PUSH_STR(&d->vec, "operator>>="));
829 case SIMPLE_HASH('a', 'o') :
831 if (*(d->p + 2) != 'r')
835 return (VEC_PUSH_STR(&d->vec, "operator|="));
836 case SIMPLE_HASH('a', 'e') :
838 if (*(d->p + 2) != 'r')
842 return (VEC_PUSH_STR(&d->vec, "operator^="));
843 case SIMPLE_HASH('c', 'm') :
845 return (VEC_PUSH_STR(&d->vec, "operator,"));
846 case SIMPLE_HASH('r', 'm') :
848 return (VEC_PUSH_STR(&d->vec, "operator->*"));
849 case SIMPLE_HASH('c', 'l') :
851 return (VEC_PUSH_STR(&d->vec, "()"));
852 case SIMPLE_HASH('v', 'c') :
854 return (VEC_PUSH_STR(&d->vec, "[]"));
855 case SIMPLE_HASH('c', 't') :
857 d->type = ENCODE_OP_CT;
859 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
862 return (read_qual_name(d));
863 } else if (ELFTC_ISDIGIT(*d->p))
864 return (read_class(d));
867 case SIMPLE_HASH('d', 't') :
869 d->type = ENCODE_OP_DT;
871 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
874 return (read_qual_name(d));
875 } else if (ELFTC_ISDIGIT(*d->p))
876 return (read_class(d));
879 case SIMPLE_HASH('n', 'w') :
881 return (VEC_PUSH_STR(&d->vec, "operator new()"));
882 case SIMPLE_HASH('d', 'l') :
884 return (VEC_PUSH_STR(&d->vec, "operator delete()"));
885 case SIMPLE_HASH('o', 'p') :
886 /* __op<TO_TYPE>__<FROM_TYPE> */
889 d->type = ENCODE_OP_USER;
891 return (read_op_user(d));
898 read_op_user(struct demangle_data *d)
900 struct demangle_data from, to;
901 size_t from_len, to_len;
903 char *from_str, *to_str;
908 if (init_demangle_data(&from) == false)
914 if (init_demangle_data(&to) == false)
921 if (read_qual_name(&to) == false)
925 if (vector_str_pop(&to.vec) == false)
928 if (read_class(&to) == false)
935 if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
939 if (*from.p == 'Q') {
942 if (read_qual_name(&from) == false)
946 if (vector_str_pop(&from.vec) == false)
949 if (read_class(&from) == false)
953 if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
956 if (vector_str_push(&d->vec, from_str, from_len) == false)
959 if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
962 if (vector_str_push(&d->vec, to_str, to_len) == false)
965 rtn = VEC_PUSH_STR(&d->vec, "()");
969 dest_demangle_data(&to);
970 dest_demangle_data(&from);
975 /* single digit + class names */
977 read_qual_name(struct demangle_data *d)
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");
993 for (i = 0; i < num ; ++i) {
994 if (read_class(d) == false)
997 if (VEC_PUSH_STR(&d->vec, "::") == false)
1007 /* Return -1 at fail, 0 at success, and 1 at end */
1009 read_subst(struct demangle_data *d)
1017 idx = strtol(d->p + 1, &str, 10);
1018 if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1022 assert(str != NULL);
1026 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1029 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1039 read_subst_iter(struct demangle_data *d)
1050 assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1052 repeat = *d->p - 48;
1058 idx = strtol(d->p, &str, 10);
1059 if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1063 assert(str != NULL);
1067 for (i = 0; i < repeat ; ++i) {
1068 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1071 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1074 if (i != repeat - 1 &&
1075 VEC_PUSH_STR(&d->vec, ", ") == false)
1086 read_type(struct demangle_data *d)
1092 assert(d->p != NULL && "d->p (org str) is NULL");
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' ||
1101 if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
1111 if (VEC_PUSH_STR(&d->vec, "const ") ==
1120 if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
1127 if (VEC_PUSH_STR(&d->vec, "signed ") == false)
1135 return (read_func_ptr(d));
1151 if (read_array(d) == false)
1158 if (read_memptr(d) == false)
1167 if (ELFTC_ISDIGIT(*d->p))
1168 return (read_class(d));
1174 return (read_qual_name(d));
1178 return (VEC_PUSH_STR(&d->vec, "void"));
1182 return (VEC_PUSH_STR(&d->vec, "char"));
1186 return (VEC_PUSH_STR(&d->vec, "short"));
1190 return (VEC_PUSH_STR(&d->vec, "int"));
1194 return (VEC_PUSH_STR(&d->vec, "long"));
1198 return (VEC_PUSH_STR(&d->vec, "float"));
1202 return (VEC_PUSH_STR(&d->vec, "double"));
1206 return (VEC_PUSH_STR(&d->vec, "long double"));
1210 return (VEC_PUSH_STR(&d->vec, "..."));