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