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 			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;
237 flat:
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);
242 clean:
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  */
253 bool
254 is_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 
332 static void
333 dest_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 
344 static void
345 dest_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 
356 static bool
357 init_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 
371 static bool
372 init_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 
402 static bool
403 push_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 
417 static bool
418 read_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 
459 static bool
460 read_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 
485 static bool
486 read_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 
528 static bool
529 read_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));
671 clean:
672 	free(op_name);
673 
674 	return (rtn);
675 }
676 
677 /* Read function ptr type */
678 static bool
679 read_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 
805 static bool
806 read_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;
843 clean:
844 	free(mptr_str);
845 	dest_demangle_data(&mptr);
846 
847 	return (rtn);
848 }
849 
850 static bool
851 read_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 
1035 static bool
1036 read_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, "()");
1102 clean:
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 */
1112 static bool
1113 read_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 */
1144 static int
1145 read_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 
1174 static int
1175 read_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 
1221 static bool
1222 read_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 }
1366