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 *
cpp_demangle_ARM(const char * org)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
is_cpp_mangled_ARM(const char * org)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
dest_cstring(struct cstring * s)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
dest_demangle_data(struct demangle_data * d)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
init_cstring(struct cstring * s,size_t len)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
init_demangle_data(struct demangle_data * d)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
push_CTDT(const char * s,size_t l,struct vector_str * v)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
read_array(struct demangle_data * d)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
read_class(struct demangle_data * d)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
read_func(struct demangle_data * d)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
read_func_name(struct demangle_data * d)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
read_func_ptr(struct demangle_data * d)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
read_memptr(struct demangle_data * d)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
read_op(struct demangle_data * d)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
read_op_user(struct demangle_data * d)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
read_qual_name(struct demangle_data * d)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
read_subst(struct demangle_data * d)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
read_subst_iter(struct demangle_data * d)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
read_type(struct demangle_data * d)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