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