]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
MFC r317075: Update ELF Tool Chain to upstream r3520
[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                         goto clean;
224
225                 free(arg);
226
227                 if (VEC_PUSH_STR(&d.vec, ", ") == false)
228                         goto clean;
229
230                 if (++try > CPP_DEMANGLE_GNU2_TRY)
231                         goto clean;
232         }
233
234         /* end argument types */
235         if (VEC_PUSH_STR(&d.vec, ")") == false)
236                 goto clean;
237 flat:
238         if (d.cnst_fn == true && VEC_PUSH_STR(&d.vec, " const") == false)
239                 goto clean;
240
241         rtn = vector_str_get_flat(&d.vec, NULL);
242 clean:
243         dest_demangle_data(&d);
244
245         return (rtn);
246 }
247
248 /**
249  * @brief Test input string is encoded by the GNU 2 style.
250  *
251  * @return True if input string is encoded by the GNU 2 style.
252  */
253 bool
254 is_cpp_mangled_gnu2(const char *org)
255 {
256         char *str;
257         bool rtn = false;
258
259         if (org == NULL)
260                 return (false);
261
262         /* search valid text to end */
263         str = strstr(org, "__");
264         while (str != NULL) {
265                 if (*(str + 2) != '\0') {
266                         if (*(str + 2) == 'C' ||
267                             *(str + 2) == 'F' ||
268                             *(str + 2) == 'Q' ||
269                             ELFTC_ISDIGIT(*(str + 2))) {
270                                 rtn |= true;
271                                 
272                                 break;
273                         }
274                         
275                         if (*(str + 3) != '\0') {
276                                 switch (SIMPLE_HASH(*(str + 2), *(str + 3))) {
277                                 case SIMPLE_HASH('m', 'l') :
278                                 case SIMPLE_HASH('d', 'v') :
279                                 case SIMPLE_HASH('m', 'd') :
280                                 case SIMPLE_HASH('p', 'l') :
281                                 case SIMPLE_HASH('m', 'i') :
282                                 case SIMPLE_HASH('l', 's') :
283                                 case SIMPLE_HASH('r', 's') :
284                                 case SIMPLE_HASH('e', 'q') :
285                                 case SIMPLE_HASH('n', 'e') :
286                                 case SIMPLE_HASH('l', 't') :
287                                 case SIMPLE_HASH('g', 't') :
288                                 case SIMPLE_HASH('l', 'e') :
289                                 case SIMPLE_HASH('g', 'e') :
290                                 case SIMPLE_HASH('a', 'd') :
291                                 case SIMPLE_HASH('o', 'r') :
292                                 case SIMPLE_HASH('e', 'r') :
293                                 case SIMPLE_HASH('a', 'a') :
294                                 case SIMPLE_HASH('o', 'o') :
295                                 case SIMPLE_HASH('n', 't') :
296                                 case SIMPLE_HASH('c', 'o') :
297                                 case SIMPLE_HASH('p', 'p') :
298                                 case SIMPLE_HASH('m', 'm') :
299                                 case SIMPLE_HASH('a', 's') :
300                                 case SIMPLE_HASH('r', 'f') :
301                                 case SIMPLE_HASH('a', 'p') :
302                                 case SIMPLE_HASH('a', 'm') :
303                                 case SIMPLE_HASH('a', 'l') :
304                                 case SIMPLE_HASH('a', 'r') :
305                                 case SIMPLE_HASH('a', 'o') :
306                                 case SIMPLE_HASH('a', 'e') :
307                                 case SIMPLE_HASH('c', 'm') :
308                                 case SIMPLE_HASH('r', 'm') :
309                                 case SIMPLE_HASH('c', 'l') :
310                                 case SIMPLE_HASH('v', 'c') :
311                                 case SIMPLE_HASH('n', 'w') :
312                                 case SIMPLE_HASH('d', 'l') :
313                                 case SIMPLE_HASH('o', 'p') :
314                                 case SIMPLE_HASH('t', 'f') :
315                                 case SIMPLE_HASH('t', 'i') :
316                                         rtn |= true;
317
318                                         break;
319                                 }
320                         }
321                 }
322
323                 str = strstr(str + 2, "__");
324         }
325
326         rtn |= strstr(org, "_$_") != NULL;
327         rtn |= strstr(org, "_vt$") != NULL;
328
329         return (rtn);
330 }
331
332 static void
333 dest_cstring(struct cstring *s)
334 {
335
336         if (s == NULL)
337                 return;
338
339         free(s->buf);
340         s->buf = NULL;
341         s->size = 0;
342 }
343
344 static void
345 dest_demangle_data(struct demangle_data *d)
346 {
347
348         if (d != NULL) {
349                 vector_str_dest(&d->arg);
350                 vector_str_dest(&d->vec);
351
352                 dest_cstring(&d->array_str);
353         }
354 }
355
356 static bool
357 init_cstring(struct cstring *s, size_t len)
358 {
359
360         if (s == NULL || len <= 1)
361                 return (false);
362
363         if ((s->buf = malloc(sizeof(char) * len)) == NULL)
364                 return (false);
365
366         s->size = len - 1;
367
368         return (true);
369 }
370
371 static bool
372 init_demangle_data(struct demangle_data *d)
373 {
374
375         if (d == NULL)
376                 return (false);
377
378         d->ptr = false;
379         d->ref = false;
380         d->cnst = false;
381         d->array = false;
382         d->cnst_fn = false;
383         d->class_name = false;
384
385         d->array_str.buf = NULL;
386         d->array_str.size = 0;
387
388         d->type = ENCODE_FUNC;
389
390         if (vector_str_init(&d->vec) == false)
391                 return (false);
392
393         if (vector_str_init(&d->arg) == false) {
394                 vector_str_dest(&d->vec);
395
396                 return (false);
397         }
398
399         return (true);
400 }
401
402 static bool
403 push_CTDT(const char *s, size_t l, struct vector_str *v)
404 {
405
406         if (s == NULL || l == 0 || v == NULL)
407                 return (false);
408
409         if (vector_str_push(v, s, l) == false)
410                 return (false);
411
412         assert(v->size > 1);
413
414         return (VEC_PUSH_STR(v, v->container[v->size - 2]));
415 }
416
417 static bool
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
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
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 (VEC_PUSH_STR(&d->vec, "::") == false)
522                         return (false);
523         }
524
525         return (vector_str_push(&d->vec, name, len));
526 }
527
528 static bool
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 (VEC_PUSH_STR(&d->vec, "__") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, " virtual table"));
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
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 (VEC_PUSH_STR(&fptr.vec, "*") == 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 (VEC_PUSH_STR(&fptr.vec, "&") == 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 (VEC_PUSH_STR(&fptr.vec, " const") == 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 (VEC_PUSH_STR(&fptr.vec, ", ") == 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 (VEC_PUSH_STR(&d->vec, " (*)(") == 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 (VEC_PUSH_STR(&d->vec, ")"));
803 }
804
805 static bool
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 (VEC_PUSH_STR(&d->vec, "::*") == 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
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 (VEC_PUSH_STR(&d->vec, "operator*"));
863         case SIMPLE_HASH('d', 'v') :
864                 d->p += 2;
865                 return (VEC_PUSH_STR(&d->vec, "operator/"));
866         case SIMPLE_HASH('m', 'd') :
867                 d->p += 2;
868                 return (VEC_PUSH_STR(&d->vec, "operator%"));
869         case SIMPLE_HASH('p', 'l') :
870                 d->p += 2;
871                 return (VEC_PUSH_STR(&d->vec, "operator+"));
872         case SIMPLE_HASH('m', 'i') :
873                 d->p += 2;
874                 return (VEC_PUSH_STR(&d->vec, "operator-"));
875         case SIMPLE_HASH('l', 's') :
876                 d->p += 2;
877                 return (VEC_PUSH_STR(&d->vec, "operator<<"));
878         case SIMPLE_HASH('r', 's') :
879                 d->p += 2;
880                 return (VEC_PUSH_STR(&d->vec, "operator>>"));
881         case SIMPLE_HASH('e', 'q') :
882                 d->p += 2;
883                 return (VEC_PUSH_STR(&d->vec, "operator=="));
884         case SIMPLE_HASH('n', 'e') :
885                 d->p += 2;
886                 return (VEC_PUSH_STR(&d->vec, "operator!="));
887         case SIMPLE_HASH('l', 't') :
888                 d->p += 2;
889                 return (VEC_PUSH_STR(&d->vec, "operator<"));
890         case SIMPLE_HASH('g', 't') :
891                 d->p += 2;
892                 return (VEC_PUSH_STR(&d->vec, "operator>"));
893         case SIMPLE_HASH('l', 'e') :
894                 d->p += 2;
895                 return (VEC_PUSH_STR(&d->vec, "operator<="));
896         case SIMPLE_HASH('g', 'e') :
897                 d->p += 2;
898                 return (VEC_PUSH_STR(&d->vec, "operator>="));
899         case SIMPLE_HASH('a', 'd') :
900                 d->p += 2;
901                 if (*d->p == 'v') {
902                         ++d->p;
903                         return (VEC_PUSH_STR(&d->vec, "operator/="));
904                 } else
905                         return (VEC_PUSH_STR(&d->vec, "operator&"));
906         case SIMPLE_HASH('o', 'r') :
907                 d->p += 2;
908                 return (VEC_PUSH_STR(&d->vec, "operator|"));
909         case SIMPLE_HASH('e', 'r') :
910                 d->p += 2;
911                 return (VEC_PUSH_STR(&d->vec, "operator^"));
912         case SIMPLE_HASH('a', 'a') :
913                 d->p += 2;
914                 if (*d->p == 'd') {
915                         ++d->p;
916                         return (VEC_PUSH_STR(&d->vec, "operator&="));
917                 } else
918                         return (VEC_PUSH_STR(&d->vec, "operator&&"));
919         case SIMPLE_HASH('o', 'o') :
920                 d->p += 2;
921                 return (VEC_PUSH_STR(&d->vec, "operator||"));
922         case SIMPLE_HASH('n', 't') :
923                 d->p += 2;
924                 return (VEC_PUSH_STR(&d->vec, "operator!"));
925         case SIMPLE_HASH('c', 'o') :
926                 d->p += 2;
927                 return (VEC_PUSH_STR(&d->vec, "operator~"));
928         case SIMPLE_HASH('p', 'p') :
929                 d->p += 2;
930                 return (VEC_PUSH_STR(&d->vec, "operator++"));
931         case SIMPLE_HASH('m', 'm') :
932                 d->p += 2;
933                 return (VEC_PUSH_STR(&d->vec, "operator--"));
934         case SIMPLE_HASH('a', 's') :
935                 d->p += 2;
936                 return (VEC_PUSH_STR(&d->vec, "operator="));
937         case SIMPLE_HASH('r', 'f') :
938                 d->p += 2;
939                 return (VEC_PUSH_STR(&d->vec, "operator->"));
940         case SIMPLE_HASH('a', 'p') :
941                 /* apl */
942                 if (*(d->p + 2) != 'l')
943                         return (false);
944
945                 d->p += 3;
946                 return (VEC_PUSH_STR(&d->vec, "operator+="));
947         case SIMPLE_HASH('a', 'm') :
948                 d->p += 2;
949                 if (*d->p == 'i') {
950                         ++d->p;
951                         return (VEC_PUSH_STR(&d->vec, "operator-="));
952                 } else if (*d->p == 'u') {
953                         ++d->p;
954                         return (VEC_PUSH_STR(&d->vec, "operator*="));
955                 } else if (*d->p == 'd') {
956                         ++d->p;
957                         return (VEC_PUSH_STR(&d->vec, "operator%="));
958                 }
959
960                 return (false);
961         case SIMPLE_HASH('a', 'l') :
962                 /* als */
963                 if (*(d->p + 2) != 's')
964                         return (false);
965
966                 d->p += 3;
967                 return (VEC_PUSH_STR(&d->vec, "operator<<="));
968         case SIMPLE_HASH('a', 'r') :
969                 /* ars */
970                 if (*(d->p + 2) != 's')
971                         return (false);
972
973                 d->p += 3;
974                 return (VEC_PUSH_STR(&d->vec, "operator>>="));
975         case SIMPLE_HASH('a', 'o') :
976                 /* aor */
977                 if (*(d->p + 2) != 'r')
978                         return (false);
979
980                 d->p += 3;
981                 return (VEC_PUSH_STR(&d->vec, "operator|="));
982         case SIMPLE_HASH('a', 'e') :
983                 /* aer */
984                 if (*(d->p + 2) != 'r')
985                         return (false);
986
987                 d->p += 3;
988                 return (VEC_PUSH_STR(&d->vec, "operator^="));
989         case SIMPLE_HASH('c', 'm') :
990                 d->p += 2;
991                 return (VEC_PUSH_STR(&d->vec, "operator,"));
992         case SIMPLE_HASH('r', 'm') :
993                 d->p += 2;
994                 return (VEC_PUSH_STR(&d->vec, "operator->*"));
995         case SIMPLE_HASH('c', 'l') :
996                 d->p += 2;
997                 return (VEC_PUSH_STR(&d->vec, "()"));
998         case SIMPLE_HASH('v', 'c') :
999                 d->p += 2;
1000                 return (VEC_PUSH_STR(&d->vec, "[]"));
1001         case SIMPLE_HASH('n', 'w') :
1002                 d->p += 2;
1003                 return (VEC_PUSH_STR(&d->vec, "operator new()"));
1004         case SIMPLE_HASH('d', 'l') :
1005                 d->p += 2;
1006                 return (VEC_PUSH_STR(&d->vec, "operator delete()"));
1007         case SIMPLE_HASH('o', 'p') :
1008                 /* __op<TO_TYPE>__<FROM_TYPE> */
1009                 d->p += 2;
1010
1011                 d->type = ENCODE_OP_USER;
1012
1013                 return (read_op_user(d));
1014         case SIMPLE_HASH('t', 'f') :
1015                 d->p += 2;
1016                 d->type = ENCODE_OP_TF;
1017
1018                 if (read_type(d) == false)
1019                         return (false);
1020
1021                 return (VEC_PUSH_STR(&d->vec, " type_info function"));
1022         case SIMPLE_HASH('t', 'i') :
1023                 d->p += 2;
1024                 d->type = ENCODE_OP_TI;
1025
1026                 if (read_type(d) == false)
1027                         return (false);
1028
1029                 return (VEC_PUSH_STR(&d->vec, " type_info node"));
1030         default :
1031                 return (false);
1032         };
1033 }
1034
1035 static bool
1036 read_op_user(struct demangle_data *d)
1037 {
1038         struct demangle_data from, to;
1039         size_t from_len, to_len;
1040         bool rtn;
1041         char *from_str, *to_str;
1042
1043         if (d == NULL)
1044                 return (false);
1045
1046         if (init_demangle_data(&from) == false)
1047                 return (false);
1048
1049         rtn = false;
1050         from_str = NULL;
1051         to_str = NULL;
1052         if (init_demangle_data(&to) == false)
1053                 goto clean;
1054
1055         to.p = d->p;
1056         if (*to.p == 'Q') {
1057                 ++to.p;
1058
1059                 if (read_qual_name(&to) == false)
1060                         goto clean;
1061
1062                 /* pop last '::' */
1063                 if (vector_str_pop(&to.vec) == false)
1064                         goto clean;
1065         } else {
1066                 if (read_class(&to) == false)
1067                         goto clean;
1068
1069                 /* skip '__' */
1070                 to.p += 2;
1071         }
1072
1073         if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
1074                 goto clean;
1075
1076         from.p = to.p;
1077         if (*from.p == 'Q') {
1078                 ++from.p;
1079
1080                 if (read_qual_name(&from) == false)
1081                         goto clean;
1082
1083                 /* pop last '::' */
1084                 if (vector_str_pop(&from.vec) == false)
1085                         goto clean;
1086         } else if (read_class(&from) == false)
1087                         goto clean;
1088
1089         if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
1090                 goto clean;
1091
1092         if (vector_str_push(&d->vec, from_str, from_len) == false)
1093                 goto clean;
1094
1095         if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
1096                 goto clean;
1097
1098         if (vector_str_push(&d->vec, to_str, to_len) == false)
1099                 goto clean;
1100
1101         rtn = VEC_PUSH_STR(&d->vec, "()");
1102 clean:
1103         free(to_str);
1104         free(from_str);
1105         dest_demangle_data(&to);
1106         dest_demangle_data(&from);
1107
1108         return (rtn);
1109 }
1110
1111 /* single digit + class names */
1112 static bool
1113 read_qual_name(struct demangle_data *d)
1114 {
1115         int i;
1116         char num;
1117
1118         if (d == NULL)
1119                 return (false);
1120
1121         assert(d->p != NULL && "d->p (org str) is NULL");
1122         assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1123
1124         num = *d->p - 48;
1125
1126         assert(num > 0);
1127
1128         ++d->p;
1129         for (i = 0; i < num ; ++i) {
1130                 if (read_class(d) == false)
1131                         return (false);
1132
1133                 if (VEC_PUSH_STR(&d->vec, "::") == false)
1134                         return (false);
1135         }
1136
1137         if (*d->p != '\0')
1138                 d->p = d->p + 2;
1139
1140         return (true);
1141 }
1142
1143 /* Return -1 at fail, 0 at success, and 1 at end */
1144 static int
1145 read_subst(struct demangle_data *d)
1146 {
1147         size_t idx;
1148         char *str;
1149
1150         if (d == NULL)
1151                 return (-1);
1152
1153         idx = strtol(d->p + 1, &str, 10);
1154         if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1155                 return (-1);
1156
1157         assert(idx > 0);
1158         assert(str != NULL);
1159
1160         d->p = str;
1161
1162         if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1163                 return (-1);
1164
1165         if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1166                 return (-1);
1167
1168         if (*d->p == '\0')
1169                 return (1);
1170
1171         return (0);
1172 }
1173
1174 static int
1175 read_subst_iter(struct demangle_data *d)
1176 {
1177         int i;
1178         size_t idx;
1179         char repeat;
1180         char *str;
1181
1182         if (d == NULL)
1183                 return (-1);
1184
1185         ++d->p;
1186         assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1187
1188         repeat = *d->p - 48;
1189
1190         assert(repeat > 1);
1191
1192         ++d->p;
1193
1194         idx = strtol(d->p, &str, 10);
1195         if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1196                 return (-1);
1197
1198         assert(idx > 0);
1199         assert(str != NULL);
1200
1201         d->p = str;
1202
1203         for (i = 0; i < repeat ; ++i) {
1204                 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1205                         return (-1);
1206
1207                 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1208                         return (-1);
1209
1210                 if (i != repeat - 1 &&
1211                     VEC_PUSH_STR(&d->vec, ", ") == false)
1212                         return (-1);
1213         }
1214
1215         if (*d->p == '\0')
1216                 return (1);
1217
1218         return (0);
1219 }
1220
1221 static bool
1222 read_type(struct demangle_data *d)
1223 {
1224
1225         if (d == NULL)
1226                 return (false);
1227
1228         assert(d->p != NULL && "d->p (org str) is NULL");
1229
1230         while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
1231                *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
1232                *d->p == 'M') {
1233                 switch (*d->p) {
1234                 case 'U' :
1235                         ++d->p;
1236
1237                         if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
1238                                 return (false);
1239
1240                         break;
1241                 case 'C' :
1242                         ++d->p;
1243
1244                         if (*d->p == 'P')
1245                                 d->cnst = true;
1246                         else {
1247                                 if (VEC_PUSH_STR(&d->vec, "const ") ==
1248                                     false)
1249                                         return (false);
1250                         }
1251
1252                         break;
1253                 case 'V' :
1254                         ++d->p;
1255
1256                         if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
1257                                 return (false);
1258
1259                         break;
1260                 case 'S' :
1261                         ++d->p;
1262
1263                         if (VEC_PUSH_STR(&d->vec, "signed ") == false)
1264                                 return (false);
1265
1266                         break;
1267                 case 'P' :
1268                         ++d->p;
1269
1270                         if (*d->p == 'F')
1271                                 return (read_func_ptr(d));
1272                         else
1273                                 d->ptr = true;
1274
1275                         break;
1276                 case 'R' :
1277                         ++d->p;
1278
1279                         d->ref = true;
1280
1281                         break;
1282                 case 'F' :
1283                         break;
1284                 case 'A' :
1285                         ++d->p;
1286
1287                         if (read_array(d) == false)
1288                                 return (false);
1289
1290                         break;
1291                 case 'M' :
1292                         ++d->p;
1293
1294                         if (read_memptr(d) == false)
1295                                 return (false);
1296
1297                         break;
1298                 default :
1299                         break;
1300                 }
1301         }
1302
1303         if (ELFTC_ISDIGIT(*d->p))
1304                 return (read_class(d));
1305
1306         switch (*d->p) {
1307         case 'Q' :
1308                 ++d->p;
1309
1310                 return (read_qual_name(d));
1311         case 'v' :
1312                 ++d->p;
1313
1314                 return (VEC_PUSH_STR(&d->vec, "void"));
1315         case 'b':
1316                 ++d->p;
1317
1318                 return(VEC_PUSH_STR(&d->vec, "bool"));
1319         case 'c' :
1320                 ++d->p;
1321
1322                 return (VEC_PUSH_STR(&d->vec, "char"));
1323         case 's' :
1324                 ++d->p;
1325
1326                 return (VEC_PUSH_STR(&d->vec, "short"));
1327         case 'i' :
1328                 ++d->p;
1329
1330                 return (VEC_PUSH_STR(&d->vec, "int"));
1331         case 'l' :
1332                 ++d->p;
1333
1334                 return (VEC_PUSH_STR(&d->vec, "long"));
1335         case 'f' :
1336                 ++d->p;
1337
1338                 return (VEC_PUSH_STR(&d->vec, "float"));
1339         case 'd':
1340                 ++d->p;
1341
1342                 return (VEC_PUSH_STR(&d->vec, "double"));
1343         case 'r':
1344                 ++d->p;
1345
1346                 return (VEC_PUSH_STR(&d->vec, "long double"));
1347         case 'e':
1348                 ++d->p;
1349
1350                 return (VEC_PUSH_STR(&d->vec, "..."));
1351         case 'w':
1352                 ++d->p;
1353
1354                 return (VEC_PUSH_STR(&d->vec, "wchar_t"));
1355         case 'x':
1356                 ++d->p;
1357
1358                 return (VEC_PUSH_STR(&d->vec, "long long"));
1359         default:
1360                 return (false);
1361         };
1362
1363         /* NOTREACHED */
1364         return (false);
1365 }