]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
dialog: import dialog 1.3-20210117
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libelftc / libelftc_dem_gnu2.c
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }