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