]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libelftc/libelftc_dem_arm.c
Merge clang trunk r351319, resolve conflicts, and update FREEBSD-Xlist.
[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                         goto clean;
211
212                 free(arg);
213
214                 if (VEC_PUSH_STR(&d.vec, ", ") == false)
215                         goto clean;
216
217                 if (++try > CPP_DEMANGLE_ARM_TRY)
218                         goto clean;
219         }
220
221         /* end argument types */
222         if (VEC_PUSH_STR(&d.vec, ")") == false)
223                 goto clean;
224
225 flat:
226         rtn = vector_str_get_flat(&d.vec, NULL);
227 clean:
228         dest_demangle_data(&d);
229
230         return (rtn);
231 }
232
233 /**
234  * @brief Test input string is encoded by the ARM style.
235  *
236  * @return True if input string is encoded by the ARM style.
237  */
238 bool
239 is_cpp_mangled_ARM(const char *org)
240 {
241
242         if (org == NULL)
243                 return (false);
244
245         return (strstr(org, "__") != NULL);
246 }
247
248 static void
249 dest_cstring(struct cstring *s)
250 {
251
252         if (s == NULL)
253                 return;
254
255         free(s->buf);
256         s->buf = NULL;
257         s->size = 0;
258 }
259
260 static void
261 dest_demangle_data(struct demangle_data *d)
262 {
263
264         if (d != NULL) {
265                 vector_str_dest(&d->arg);
266                 vector_str_dest(&d->vec);
267
268                 dest_cstring(&d->array_str);
269         }
270 }
271
272 static bool
273 init_cstring(struct cstring *s, size_t len)
274 {
275
276         if (s == NULL || len <= 1)
277                 return (false);
278
279         if ((s->buf = malloc(sizeof(char) * len)) == NULL)
280                 return (false);
281
282         s->size = len - 1;
283
284         return (true);
285 }
286
287 static bool
288 init_demangle_data(struct demangle_data *d)
289 {
290
291         if (d == NULL)
292                 return (false);
293
294         d->ptr = false;
295         d->ref = false;
296         d->cnst = false;
297         d->array = false;
298
299         d->array_str.buf = NULL;
300         d->array_str.size = 0;
301
302         d->type = ENCODE_FUNC;
303
304         if (vector_str_init(&d->vec) == false)
305                 return (false);
306
307         if (vector_str_init(&d->arg) == false) {
308                 vector_str_dest(&d->vec);
309
310                 return (false);
311         }
312
313         return (true);
314 }
315
316 static bool
317 push_CTDT(const char *s, size_t l, struct vector_str *v)
318 {
319
320         if (s == NULL || l == 0 || v == NULL)
321                 return (false);
322
323         if (vector_str_push(v, s, l) == false)
324                 return (false);
325
326         assert(v->size > 1);
327         if (VEC_PUSH_STR(v, v->container[v->size - 2]) == false)
328                 return (false);
329
330         if (VEC_PUSH_STR(v, "()") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&d->vec, "::") == 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 (VEC_PUSH_STR(&fptr.vec, "*") == 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 (VEC_PUSH_STR(&fptr.vec, "&") == 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 (VEC_PUSH_STR(&fptr.vec, " const") == 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 (VEC_PUSH_STR(&fptr.vec, ", ") == 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 (VEC_PUSH_STR(&d->vec, " (*)(") == 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 (VEC_PUSH_STR(&d->vec, ")"));
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 (VEC_PUSH_STR(&d->vec, "::*") == 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 (VEC_PUSH_STR(&d->vec, "operator*"));
716         case SIMPLE_HASH('d', 'v') :
717                 d->p += 2;
718                 return (VEC_PUSH_STR(&d->vec, "operator/"));
719         case SIMPLE_HASH('m', 'd') :
720                 d->p += 2;
721                 return (VEC_PUSH_STR(&d->vec, "operator%"));
722         case SIMPLE_HASH('p', 'l') :
723                 d->p += 2;
724                 return (VEC_PUSH_STR(&d->vec, "operator+"));
725         case SIMPLE_HASH('m', 'i') :
726                 d->p += 2;
727                 return (VEC_PUSH_STR(&d->vec, "operator-"));
728         case SIMPLE_HASH('l', 's') :
729                 d->p += 2;
730                 return (VEC_PUSH_STR(&d->vec, "operator<<"));
731         case SIMPLE_HASH('r', 's') :
732                 d->p += 2;
733                 return (VEC_PUSH_STR(&d->vec, "operator>>"));
734         case SIMPLE_HASH('e', 'q') :
735                 d->p += 2;
736                 return (VEC_PUSH_STR(&d->vec, "operator=="));
737         case SIMPLE_HASH('n', 'e') :
738                 d->p += 2;
739                 return (VEC_PUSH_STR(&d->vec, "operator!="));
740         case SIMPLE_HASH('l', 't') :
741                 d->p += 2;
742                 return (VEC_PUSH_STR(&d->vec, "operator<"));
743         case SIMPLE_HASH('g', 't') :
744                 d->p += 2;
745                 return (VEC_PUSH_STR(&d->vec, "operator>"));
746         case SIMPLE_HASH('l', 'e') :
747                 d->p += 2;
748                 return (VEC_PUSH_STR(&d->vec, "operator<="));
749         case SIMPLE_HASH('g', 'e') :
750                 d->p += 2;
751                 return (VEC_PUSH_STR(&d->vec, "operator>="));
752         case SIMPLE_HASH('a', 'd') :
753                 d->p += 2;
754                 if (*d->p == 'v') {
755                         ++d->p;
756                         return (VEC_PUSH_STR(&d->vec, "operator/="));
757                 } else
758                         return (VEC_PUSH_STR(&d->vec, "operator&"));
759         case SIMPLE_HASH('o', 'r') :
760                 d->p += 2;
761                 return (VEC_PUSH_STR(&d->vec, "operator|"));
762         case SIMPLE_HASH('e', 'r') :
763                 d->p += 2;
764                 return (VEC_PUSH_STR(&d->vec, "operator^"));
765         case SIMPLE_HASH('a', 'a') :
766                 d->p += 2;
767                 if (*d->p == 'd') {
768                         ++d->p;
769                         return (VEC_PUSH_STR(&d->vec, "operator&="));
770                 } else
771                         return (VEC_PUSH_STR(&d->vec, "operator&&"));
772         case SIMPLE_HASH('o', 'o') :
773                 d->p += 2;
774                 return (VEC_PUSH_STR(&d->vec, "operator||"));
775         case SIMPLE_HASH('n', 't') :
776                 d->p += 2;
777                 return (VEC_PUSH_STR(&d->vec, "operator!"));
778         case SIMPLE_HASH('c', 'o') :
779                 d->p += 2;
780                 return (VEC_PUSH_STR(&d->vec, "operator~"));
781         case SIMPLE_HASH('p', 'p') :
782                 d->p += 2;
783                 return (VEC_PUSH_STR(&d->vec, "operator++"));
784         case SIMPLE_HASH('m', 'm') :
785                 d->p += 2;
786                 return (VEC_PUSH_STR(&d->vec, "operator--"));
787         case SIMPLE_HASH('a', 's') :
788                 d->p += 2;
789                 return (VEC_PUSH_STR(&d->vec, "operator="));
790         case SIMPLE_HASH('r', 'f') :
791                 d->p += 2;
792                 return (VEC_PUSH_STR(&d->vec, "operator->"));
793         case SIMPLE_HASH('a', 'p') :
794                 /* apl */
795                 if (*(d->p + 2) != 'l')
796                         return (false);
797
798                 d->p += 3;
799                 return (VEC_PUSH_STR(&d->vec, "operator+="));
800         case SIMPLE_HASH('a', 'm') :
801                 d->p += 2;
802                 if (*d->p == 'i') {
803                         ++d->p;
804                         return (VEC_PUSH_STR(&d->vec, "operator-="));
805                 } else if (*d->p == 'u') {
806                         ++d->p;
807                         return (VEC_PUSH_STR(&d->vec, "operator*="));
808                 } else if (*d->p == 'd') {
809                         ++d->p;
810                         return (VEC_PUSH_STR(&d->vec, "operator%="));
811                 }
812
813                 return (false);
814         case SIMPLE_HASH('a', 'l') :
815                 /* als */
816                 if (*(d->p + 2) != 's')
817                         return (false);
818
819                 d->p += 3;
820                 return (VEC_PUSH_STR(&d->vec, "operator<<="));
821         case SIMPLE_HASH('a', 'r') :
822                 /* ars */
823                 if (*(d->p + 2) != 's')
824                         return (false);
825
826                 d->p += 3;
827                 return (VEC_PUSH_STR(&d->vec, "operator>>="));
828         case SIMPLE_HASH('a', 'o') :
829                 /* aor */
830                 if (*(d->p + 2) != 'r')
831                         return (false);
832
833                 d->p += 3;
834                 return (VEC_PUSH_STR(&d->vec, "operator|="));
835         case SIMPLE_HASH('a', 'e') :
836                 /* aer */
837                 if (*(d->p + 2) != 'r')
838                         return (false);
839
840                 d->p += 3;
841                 return (VEC_PUSH_STR(&d->vec, "operator^="));
842         case SIMPLE_HASH('c', 'm') :
843                 d->p += 2;
844                 return (VEC_PUSH_STR(&d->vec, "operator,"));
845         case SIMPLE_HASH('r', 'm') :
846                 d->p += 2;
847                 return (VEC_PUSH_STR(&d->vec, "operator->*"));
848         case SIMPLE_HASH('c', 'l') :
849                 d->p += 2;
850                 return (VEC_PUSH_STR(&d->vec, "()"));
851         case SIMPLE_HASH('v', 'c') :
852                 d->p += 2;
853                 return (VEC_PUSH_STR(&d->vec, "[]"));
854         case SIMPLE_HASH('c', 't') :
855                 d->p += 4;
856                 d->type = ENCODE_OP_CT;
857
858                 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
859                         ++d->p;
860
861                         return (read_qual_name(d));
862                 } else if (ELFTC_ISDIGIT(*d->p))
863                         return (read_class(d));
864
865                 return (false);
866         case SIMPLE_HASH('d', 't') :
867                 d->p += 4;
868                 d->type = ENCODE_OP_DT;
869
870                 if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
871                         ++d->p;
872
873                         return (read_qual_name(d));
874                 } else if (ELFTC_ISDIGIT(*d->p))
875                         return (read_class(d));
876
877                 return (false);
878         case SIMPLE_HASH('n', 'w') :
879                 d->p += 2;
880                 return (VEC_PUSH_STR(&d->vec, "operator new()"));
881         case SIMPLE_HASH('d', 'l') :
882                 d->p += 2;
883                 return (VEC_PUSH_STR(&d->vec, "operator delete()"));
884         case SIMPLE_HASH('o', 'p') :
885                 /* __op<TO_TYPE>__<FROM_TYPE> */
886                 d->p += 2;
887
888                 d->type = ENCODE_OP_USER;
889
890                 return (read_op_user(d));
891         default :
892                 return (false);
893         };
894 }
895
896 static bool
897 read_op_user(struct demangle_data *d)
898 {
899         struct demangle_data from, to;
900         size_t from_len, to_len;
901         bool rtn;
902         char *from_str, *to_str;
903
904         if (d == NULL)
905                 return (false);
906
907         if (init_demangle_data(&from) == false)
908                 return (false);
909
910         rtn = false;
911         from_str = NULL;
912         to_str = NULL;
913         if (init_demangle_data(&to) == false)
914                 goto clean;
915
916         to.p = d->p;
917         if (*to.p == 'Q') {
918                 ++to.p;
919
920                 if (read_qual_name(&to) == false)
921                         goto clean;
922
923                 /* pop last '::' */
924                 if (vector_str_pop(&to.vec) == false)
925                         goto clean;
926         } else {
927                 if (read_class(&to) == false)
928                         goto clean;
929
930                 /* skip '__' */
931                 to.p += 2;
932         }
933
934         if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
935                 goto clean;
936
937         from.p = to.p;
938         if (*from.p == 'Q') {
939                 ++from.p;
940
941                 if (read_qual_name(&from) == false)
942                         goto clean;
943
944                 /* pop last '::' */
945                 if (vector_str_pop(&from.vec) == false)
946                         goto clean;
947         } else {
948                 if (read_class(&from) == false)
949                         goto clean;
950         }
951
952         if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
953                 goto clean;
954
955         if (vector_str_push(&d->vec, from_str, from_len) == false)
956                 goto clean;
957
958         if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
959                 return (false);
960
961         if (vector_str_push(&d->vec, to_str, to_len) == false)
962                 goto clean;
963
964         rtn = VEC_PUSH_STR(&d->vec, "()");
965 clean:
966         free(to_str);
967         free(from_str);
968         dest_demangle_data(&to);
969         dest_demangle_data(&from);
970
971         return (rtn);
972 }
973
974 /* single digit + class names */
975 static bool
976 read_qual_name(struct demangle_data *d)
977 {
978         int i;
979         char num;
980
981         if (d == NULL)
982                 return (false);
983
984         assert(d->p != NULL && "d->p (org str) is NULL");
985         assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
986
987         num = *d->p - 48;
988
989         assert(num > 0);
990
991         ++d->p;
992         for (i = 0; i < num ; ++i) {
993                 if (read_class(d) == false)
994                         return (false);
995
996                 if (VEC_PUSH_STR(&d->vec, "::") == false)
997                         return (false);
998         }
999
1000         if (*d->p != '\0')
1001                 d->p = d->p + 2;
1002
1003         return (true);
1004 }
1005
1006 /* Return -1 at fail, 0 at success, and 1 at end */
1007 static int
1008 read_subst(struct demangle_data *d)
1009 {
1010         size_t idx;
1011         char *str;
1012
1013         if (d == NULL)
1014                 return (-1);
1015
1016         idx = strtol(d->p + 1, &str, 10);
1017         if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1018                 return (-1);
1019
1020         assert(idx > 0);
1021         assert(str != NULL);
1022
1023         d->p = str;
1024
1025         if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1026                 return (-1);
1027
1028         if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1029                 return (-1);
1030
1031         if (*d->p == '\0')
1032                 return (1);
1033
1034         return (0);
1035 }
1036
1037 static int
1038 read_subst_iter(struct demangle_data *d)
1039 {
1040         int i;
1041         size_t idx;
1042         char repeat;
1043         char *str;
1044
1045         if (d == NULL)
1046                 return (-1);
1047
1048         ++d->p;
1049         assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1050
1051         repeat = *d->p - 48;
1052
1053         assert(repeat > 1);
1054
1055         ++d->p;
1056
1057         idx = strtol(d->p, &str, 10);
1058         if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1059                 return (-1);
1060
1061         assert(idx > 0);
1062         assert(str != NULL);
1063
1064         d->p = str;
1065
1066         for (i = 0; i < repeat ; ++i) {
1067                 if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1068                         return (-1);
1069
1070                 if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1071                         return (-1);
1072
1073                 if (i != repeat - 1 &&
1074                     VEC_PUSH_STR(&d->vec, ", ") == false)
1075                         return (-1);
1076         }
1077
1078         if (*d->p == '\0')
1079                 return (1);
1080
1081         return (0);
1082 }
1083
1084 static bool
1085 read_type(struct demangle_data *d)
1086 {
1087
1088         if (d == NULL)
1089                 return (false);
1090
1091         assert(d->p != NULL && "d->p (org str) is NULL");
1092
1093         while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
1094                *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
1095                *d->p == 'M') {
1096                 switch (*d->p) {
1097                 case 'U' :
1098                         ++d->p;
1099
1100                         if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
1101                                 return (false);
1102
1103                         break;
1104                 case 'C' :
1105                         ++d->p;
1106
1107                         if (*d->p == 'P')
1108                                 d->cnst = true;
1109                         else {
1110                                 if (VEC_PUSH_STR(&d->vec, "const ") ==
1111                                     false)
1112                                         return (false);
1113                         }
1114
1115                         break;
1116                 case 'V' :
1117                         ++d->p;
1118
1119                         if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
1120                                 return (false);
1121
1122                         break;
1123                 case 'S' :
1124                         ++d->p;
1125
1126                         if (VEC_PUSH_STR(&d->vec, "signed ") == false)
1127                                 return (false);
1128
1129                         break;
1130                 case 'P' :
1131                         ++d->p;
1132
1133                         if (*d->p == 'F')
1134                                 return (read_func_ptr(d));
1135                         else
1136                                 d->ptr = true;
1137
1138                         break;
1139                 case 'R' :
1140                         ++d->p;
1141
1142                         d->ref = true;
1143
1144                         break;
1145                 case 'F' :
1146                         break;
1147                 case 'A' :
1148                         ++d->p;
1149
1150                         if (read_array(d) == false)
1151                                 return (false);
1152
1153                         break;
1154                 case 'M' :
1155                         ++d->p;
1156
1157                         if (read_memptr(d) == false)
1158                                 return (false);
1159
1160                         break;
1161                 default :
1162                         break;
1163                 }
1164         }
1165
1166         if (ELFTC_ISDIGIT(*d->p))
1167                 return (read_class(d));
1168
1169         switch (*d->p) {
1170         case 'Q' :
1171                 ++d->p;
1172
1173                 return (read_qual_name(d));
1174         case 'v' :
1175                 ++d->p;
1176
1177                 return (VEC_PUSH_STR(&d->vec, "void"));
1178         case 'c' :
1179                 ++d->p;
1180
1181                 return (VEC_PUSH_STR(&d->vec, "char"));
1182         case 's' :
1183                 ++d->p;
1184
1185                 return (VEC_PUSH_STR(&d->vec, "short"));
1186         case 'i' :
1187                 ++d->p;
1188
1189                 return (VEC_PUSH_STR(&d->vec, "int"));
1190         case 'l' :
1191                 ++d->p;
1192
1193                 return (VEC_PUSH_STR(&d->vec, "long"));
1194         case 'f' :
1195                 ++d->p;
1196
1197                 return (VEC_PUSH_STR(&d->vec, "float"));
1198         case 'd':
1199                 ++d->p;
1200
1201                 return (VEC_PUSH_STR(&d->vec, "double"));
1202         case 'r':
1203                 ++d->p;
1204
1205                 return (VEC_PUSH_STR(&d->vec, "long double"));
1206         case 'e':
1207                 ++d->p;
1208
1209                 return (VEC_PUSH_STR(&d->vec, "..."));
1210         default:
1211                 return (false);
1212         };
1213
1214         /* NOTREACHED */
1215         return (false);
1216 }