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