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