]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
Update lldb to upstream trunk r242221.
[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 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 *
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
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
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
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
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
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
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
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 (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
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
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
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
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
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
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
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
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
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 }