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