source: rtems-tools/rtemstoolkit/elftoolchain/libelftc/libelftc_dem_gnu2.c @ 1f1a10f

5
Last change on this file since 1f1a10f was 1f1a10f, checked in by Chris Johns <chrisj@…>, on 05/23/18 at 08:39:54

elftoolchain: Add libelftc.

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