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