xref: /freebsd/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c (revision f81cdf24ba5436367377f7c8e8f51f6df2a75ca7)
1 /*-
2  * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 #include <assert.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <libelftc.h>
32 #include <limits.h>
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "_libelftc.h"
39 
40 ELFTC_VCSID("$Id: libelftc_dem_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