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