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