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, *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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&fptr.vec, "*") == 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 (VEC_PUSH_STR(&fptr.vec, "&") == 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 (VEC_PUSH_STR(&fptr.vec, " const") == 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 (VEC_PUSH_STR(&fptr.vec, ", ") == 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 (VEC_PUSH_STR(&d->vec, " (*)(") == 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 (VEC_PUSH_STR(&d->vec, ")"));
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 (VEC_PUSH_STR(&d->vec, "::*") == 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 (VEC_PUSH_STR(&d->vec, "operator*"));
716 case SIMPLE_HASH('d', 'v') :
717 d->p += 2;
718 return (VEC_PUSH_STR(&d->vec, "operator/"));
719 case SIMPLE_HASH('m', 'd') :
720 d->p += 2;
721 return (VEC_PUSH_STR(&d->vec, "operator%"));
722 case SIMPLE_HASH('p', 'l') :
723 d->p += 2;
724 return (VEC_PUSH_STR(&d->vec, "operator+"));
725 case SIMPLE_HASH('m', 'i') :
726 d->p += 2;
727 return (VEC_PUSH_STR(&d->vec, "operator-"));
728 case SIMPLE_HASH('l', 's') :
729 d->p += 2;
730 return (VEC_PUSH_STR(&d->vec, "operator<<"));
731 case SIMPLE_HASH('r', 's') :
732 d->p += 2;
733 return (VEC_PUSH_STR(&d->vec, "operator>>"));
734 case SIMPLE_HASH('e', 'q') :
735 d->p += 2;
736 return (VEC_PUSH_STR(&d->vec, "operator=="));
737 case SIMPLE_HASH('n', 'e') :
738 d->p += 2;
739 return (VEC_PUSH_STR(&d->vec, "operator!="));
740 case SIMPLE_HASH('l', 't') :
741 d->p += 2;
742 return (VEC_PUSH_STR(&d->vec, "operator<"));
743 case SIMPLE_HASH('g', 't') :
744 d->p += 2;
745 return (VEC_PUSH_STR(&d->vec, "operator>"));
746 case SIMPLE_HASH('l', 'e') :
747 d->p += 2;
748 return (VEC_PUSH_STR(&d->vec, "operator<="));
749 case SIMPLE_HASH('g', 'e') :
750 d->p += 2;
751 return (VEC_PUSH_STR(&d->vec, "operator>="));
752 case SIMPLE_HASH('a', 'd') :
753 d->p += 2;
754 if (*d->p == 'v') {
755 ++d->p;
756 return (VEC_PUSH_STR(&d->vec, "operator/="));
757 } else
758 return (VEC_PUSH_STR(&d->vec, "operator&"));
759 case SIMPLE_HASH('o', 'r') :
760 d->p += 2;
761 return (VEC_PUSH_STR(&d->vec, "operator|"));
762 case SIMPLE_HASH('e', 'r') :
763 d->p += 2;
764 return (VEC_PUSH_STR(&d->vec, "operator^"));
765 case SIMPLE_HASH('a', 'a') :
766 d->p += 2;
767 if (*d->p == 'd') {
768 ++d->p;
769 return (VEC_PUSH_STR(&d->vec, "operator&="));
770 } else
771 return (VEC_PUSH_STR(&d->vec, "operator&&"));
772 case SIMPLE_HASH('o', 'o') :
773 d->p += 2;
774 return (VEC_PUSH_STR(&d->vec, "operator||"));
775 case SIMPLE_HASH('n', 't') :
776 d->p += 2;
777 return (VEC_PUSH_STR(&d->vec, "operator!"));
778 case SIMPLE_HASH('c', 'o') :
779 d->p += 2;
780 return (VEC_PUSH_STR(&d->vec, "operator~"));
781 case SIMPLE_HASH('p', 'p') :
782 d->p += 2;
783 return (VEC_PUSH_STR(&d->vec, "operator++"));
784 case SIMPLE_HASH('m', 'm') :
785 d->p += 2;
786 return (VEC_PUSH_STR(&d->vec, "operator--"));
787 case SIMPLE_HASH('a', 's') :
788 d->p += 2;
789 return (VEC_PUSH_STR(&d->vec, "operator="));
790 case SIMPLE_HASH('r', 'f') :
791 d->p += 2;
792 return (VEC_PUSH_STR(&d->vec, "operator->"));
793 case SIMPLE_HASH('a', 'p') :
794 /* apl */
795 if (*(d->p + 2) != 'l')
796 return (false);
797
798 d->p += 3;
799 return (VEC_PUSH_STR(&d->vec, "operator+="));
800 case SIMPLE_HASH('a', 'm') :
801 d->p += 2;
802 if (*d->p == 'i') {
803 ++d->p;
804 return (VEC_PUSH_STR(&d->vec, "operator-="));
805 } else if (*d->p == 'u') {
806 ++d->p;
807 return (VEC_PUSH_STR(&d->vec, "operator*="));
808 } else if (*d->p == 'd') {
809 ++d->p;
810 return (VEC_PUSH_STR(&d->vec, "operator%="));
811 }
812
813 return (false);
814 case SIMPLE_HASH('a', 'l') :
815 /* als */
816 if (*(d->p + 2) != 's')
817 return (false);
818
819 d->p += 3;
820 return (VEC_PUSH_STR(&d->vec, "operator<<="));
821 case SIMPLE_HASH('a', 'r') :
822 /* ars */
823 if (*(d->p + 2) != 's')
824 return (false);
825
826 d->p += 3;
827 return (VEC_PUSH_STR(&d->vec, "operator>>="));
828 case SIMPLE_HASH('a', 'o') :
829 /* aor */
830 if (*(d->p + 2) != 'r')
831 return (false);
832
833 d->p += 3;
834 return (VEC_PUSH_STR(&d->vec, "operator|="));
835 case SIMPLE_HASH('a', 'e') :
836 /* aer */
837 if (*(d->p + 2) != 'r')
838 return (false);
839
840 d->p += 3;
841 return (VEC_PUSH_STR(&d->vec, "operator^="));
842 case SIMPLE_HASH('c', 'm') :
843 d->p += 2;
844 return (VEC_PUSH_STR(&d->vec, "operator,"));
845 case SIMPLE_HASH('r', 'm') :
846 d->p += 2;
847 return (VEC_PUSH_STR(&d->vec, "operator->*"));
848 case SIMPLE_HASH('c', 'l') :
849 d->p += 2;
850 return (VEC_PUSH_STR(&d->vec, "()"));
851 case SIMPLE_HASH('v', 'c') :
852 d->p += 2;
853 return (VEC_PUSH_STR(&d->vec, "[]"));
854 case SIMPLE_HASH('c', 't') :
855 d->p += 4;
856 d->type = ENCODE_OP_CT;
857
858 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
859 ++d->p;
860
861 return (read_qual_name(d));
862 } else if (ELFTC_ISDIGIT(*d->p))
863 return (read_class(d));
864
865 return (false);
866 case SIMPLE_HASH('d', 't') :
867 d->p += 4;
868 d->type = ENCODE_OP_DT;
869
870 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
871 ++d->p;
872
873 return (read_qual_name(d));
874 } else if (ELFTC_ISDIGIT(*d->p))
875 return (read_class(d));
876
877 return (false);
878 case SIMPLE_HASH('n', 'w') :
879 d->p += 2;
880 return (VEC_PUSH_STR(&d->vec, "operator new()"));
881 case SIMPLE_HASH('d', 'l') :
882 d->p += 2;
883 return (VEC_PUSH_STR(&d->vec, "operator delete()"));
884 case SIMPLE_HASH('o', 'p') :
885 /* __op<TO_TYPE>__<FROM_TYPE> */
886 d->p += 2;
887
888 d->type = ENCODE_OP_USER;
889
890 return (read_op_user(d));
891 default :
892 return (false);
893 };
894 }
895
896 static bool
read_op_user(struct demangle_data * d)897 read_op_user(struct demangle_data *d)
898 {
899 struct demangle_data from, to;
900 size_t from_len, to_len;
901 bool rtn;
902 char *from_str, *to_str;
903
904 if (d == NULL)
905 return (false);
906
907 if (init_demangle_data(&from) == false)
908 return (false);
909
910 rtn = false;
911 from_str = NULL;
912 to_str = NULL;
913 if (init_demangle_data(&to) == false)
914 goto clean;
915
916 to.p = d->p;
917 if (*to.p == 'Q') {
918 ++to.p;
919
920 if (read_qual_name(&to) == false)
921 goto clean;
922
923 /* pop last '::' */
924 if (vector_str_pop(&to.vec) == false)
925 goto clean;
926 } else {
927 if (read_class(&to) == false)
928 goto clean;
929
930 /* skip '__' */
931 to.p += 2;
932 }
933
934 if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
935 goto clean;
936
937 from.p = to.p;
938 if (*from.p == 'Q') {
939 ++from.p;
940
941 if (read_qual_name(&from) == false)
942 goto clean;
943
944 /* pop last '::' */
945 if (vector_str_pop(&from.vec) == false)
946 goto clean;
947 } else {
948 if (read_class(&from) == false)
949 goto clean;
950 }
951
952 if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
953 goto clean;
954
955 if (vector_str_push(&d->vec, from_str, from_len) == false)
956 goto clean;
957
958 if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
959 goto clean;
960
961 if (vector_str_push(&d->vec, to_str, to_len) == false)
962 goto clean;
963
964 rtn = VEC_PUSH_STR(&d->vec, "()");
965 clean:
966 free(to_str);
967 free(from_str);
968 dest_demangle_data(&to);
969 dest_demangle_data(&from);
970
971 return (rtn);
972 }
973
974 /* single digit + class names */
975 static bool
read_qual_name(struct demangle_data * d)976 read_qual_name(struct demangle_data *d)
977 {
978 int i;
979 char num;
980
981 if (d == NULL)
982 return (false);
983
984 assert(d->p != NULL && "d->p (org str) is NULL");
985 assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
986
987 num = *d->p - 48;
988
989 assert(num > 0);
990
991 ++d->p;
992 for (i = 0; i < num ; ++i) {
993 if (read_class(d) == false)
994 return (false);
995
996 if (VEC_PUSH_STR(&d->vec, "::") == false)
997 return (false);
998 }
999
1000 if (*d->p != '\0')
1001 d->p = d->p + 2;
1002
1003 return (true);
1004 }
1005
1006 /* Return -1 at fail, 0 at success, and 1 at end */
1007 static int
read_subst(struct demangle_data * d)1008 read_subst(struct demangle_data *d)
1009 {
1010 size_t idx;
1011 char *str;
1012
1013 if (d == NULL)
1014 return (-1);
1015
1016 idx = strtol(d->p + 1, &str, 10);
1017 if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1018 return (-1);
1019
1020 assert(idx > 0);
1021 assert(str != NULL);
1022
1023 d->p = str;
1024
1025 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1026 return (-1);
1027
1028 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1029 return (-1);
1030
1031 if (*d->p == '\0')
1032 return (1);
1033
1034 return (0);
1035 }
1036
1037 static int
read_subst_iter(struct demangle_data * d)1038 read_subst_iter(struct demangle_data *d)
1039 {
1040 int i;
1041 size_t idx;
1042 char repeat;
1043 char *str;
1044
1045 if (d == NULL)
1046 return (-1);
1047
1048 ++d->p;
1049 assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1050
1051 repeat = *d->p - 48;
1052
1053 assert(repeat > 1);
1054
1055 ++d->p;
1056
1057 idx = strtol(d->p, &str, 10);
1058 if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1059 return (-1);
1060
1061 assert(idx > 0);
1062 assert(str != NULL);
1063
1064 d->p = str;
1065
1066 for (i = 0; i < repeat ; ++i) {
1067 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1068 return (-1);
1069
1070 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1071 return (-1);
1072
1073 if (i != repeat - 1 &&
1074 VEC_PUSH_STR(&d->vec, ", ") == false)
1075 return (-1);
1076 }
1077
1078 if (*d->p == '\0')
1079 return (1);
1080
1081 return (0);
1082 }
1083
1084 static bool
read_type(struct demangle_data * d)1085 read_type(struct demangle_data *d)
1086 {
1087
1088 if (d == NULL)
1089 return (false);
1090
1091 assert(d->p != NULL && "d->p (org str) is NULL");
1092
1093 while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
1094 *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
1095 *d->p == 'M') {
1096 switch (*d->p) {
1097 case 'U' :
1098 ++d->p;
1099
1100 if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
1101 return (false);
1102
1103 break;
1104 case 'C' :
1105 ++d->p;
1106
1107 if (*d->p == 'P')
1108 d->cnst = true;
1109 else {
1110 if (VEC_PUSH_STR(&d->vec, "const ") ==
1111 false)
1112 return (false);
1113 }
1114
1115 break;
1116 case 'V' :
1117 ++d->p;
1118
1119 if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
1120 return (false);
1121
1122 break;
1123 case 'S' :
1124 ++d->p;
1125
1126 if (VEC_PUSH_STR(&d->vec, "signed ") == false)
1127 return (false);
1128
1129 break;
1130 case 'P' :
1131 ++d->p;
1132
1133 if (*d->p == 'F')
1134 return (read_func_ptr(d));
1135 else
1136 d->ptr = true;
1137
1138 break;
1139 case 'R' :
1140 ++d->p;
1141
1142 d->ref = true;
1143
1144 break;
1145 case 'F' :
1146 break;
1147 case 'A' :
1148 ++d->p;
1149
1150 if (read_array(d) == false)
1151 return (false);
1152
1153 break;
1154 case 'M' :
1155 ++d->p;
1156
1157 if (read_memptr(d) == false)
1158 return (false);
1159
1160 break;
1161 default :
1162 break;
1163 }
1164 }
1165
1166 if (ELFTC_ISDIGIT(*d->p))
1167 return (read_class(d));
1168
1169 switch (*d->p) {
1170 case 'Q' :
1171 ++d->p;
1172
1173 return (read_qual_name(d));
1174 case 'v' :
1175 ++d->p;
1176
1177 return (VEC_PUSH_STR(&d->vec, "void"));
1178 case 'c' :
1179 ++d->p;
1180
1181 return (VEC_PUSH_STR(&d->vec, "char"));
1182 case 's' :
1183 ++d->p;
1184
1185 return (VEC_PUSH_STR(&d->vec, "short"));
1186 case 'i' :
1187 ++d->p;
1188
1189 return (VEC_PUSH_STR(&d->vec, "int"));
1190 case 'l' :
1191 ++d->p;
1192
1193 return (VEC_PUSH_STR(&d->vec, "long"));
1194 case 'f' :
1195 ++d->p;
1196
1197 return (VEC_PUSH_STR(&d->vec, "float"));
1198 case 'd':
1199 ++d->p;
1200
1201 return (VEC_PUSH_STR(&d->vec, "double"));
1202 case 'r':
1203 ++d->p;
1204
1205 return (VEC_PUSH_STR(&d->vec, "long double"));
1206 case 'e':
1207 ++d->p;
1208
1209 return (VEC_PUSH_STR(&d->vec, "..."));
1210 default:
1211 return (false);
1212 };
1213
1214 /* NOTREACHED */
1215 return (false);
1216 }
1217