1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
25 *
26 *
27 * Copyright (c) 1998 by Sun Microsystems, Inc.
28 * All rights reserved.
29 */
30
31 #include <ctype.h>
32 #include <setjmp.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <thread.h>
36 #include "elf_dem.h"
37 #include "String.h"
38 #include "msg.h"
39
40 /*
41 * The variable "hold" contains the pointer to the array initially
42 * handed to demangle. It is returned if it is not possible to
43 * demangle the string. NULL is returned if a memory allocation
44 * problem is encountered. Thus one can do the following:
45 *
46 * char *mn = "Some mangled name";
47 * char *dm = mangle(mn);
48 * if (dm == NULL)
49 * printf("allocation error\n");
50 * else if (dm == mn)
51 * printf("name could not be demangled\n");
52 * else
53 * printf("demangled name is: %s\n",dm);
54 */
55 static char *hold;
56
57 /*
58 * this String is the working buffer for the demangle
59 * routine. A pointer into this String is returned
60 * from demangle when it is possible to demangle the
61 * String. For this reason, the pointer should not
62 * be saved between calls of demangle(), nor freed.
63 */
64 static String *s = 0;
65
66 static int
getint(char ** c)67 getint(char **c)
68 {
69 return (strtol(*c, c, 10));
70 }
71
72 /*
73 * If a mangled name has a __
74 * that is not at the very beginning
75 * of the string, then this routine
76 * is called to demangle that part
77 * of the name. All overloaded functions,
78 * and class members fall into this category.
79 *
80 * c should start with two underscores followed by a non-zero digit or an F.
81 */
82 static char *
second(char * c)83 second(char *c)
84 {
85 int n;
86 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
87 return (hold);
88 c += 2;
89
90 if (!(isdigit(*c) || *c == 'F'))
91 return (hold);
92
93 if (isdigit(*c)) {
94 /* a member */
95 n = getint(&c);
96 if (n == 0 || (int)strlen(c) < n)
97 return (hold);
98 s = prep_String(MSG_ORIG(MSG_STR_DBLCOL), s);
99 s = nprep_String(c, s, n);
100 c += n;
101 }
102 if (*c == 'F') {
103 /* an overloaded function */
104 switch (*++c) {
105 case '\0':
106 return (hold);
107 case 'v':
108 s = app_String(s, MSG_ORIG(MSG_STR_OPENCLOSEPAR));
109 break;
110 default:
111 if (demangle_doargs(&s, c) < 0)
112 return (hold);
113 }
114 }
115 return (PTR(s));
116 }
117
118 char *
demangle(char * c)119 demangle(char *c)
120 {
121 volatile int i = 0;
122 extern jmp_buf jbuf;
123 static mutex_t mlock = DEFAULTMUTEX;
124
125 (void) mutex_lock(&mlock);
126
127 if (setjmp(jbuf)) {
128 (void) mutex_unlock(&mlock);
129 return (0);
130 }
131
132 hold = c;
133 s = mk_String(s);
134 s = set_String(s, MSG_ORIG(MSG_STR_EMPTY));
135
136 if (c == 0 || *c == 0) {
137 c = hold;
138 (void) mutex_unlock(&mlock);
139 return (c);
140 }
141
142 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) != 0) {
143 /*
144 * If a name does not begin with a __
145 * but it does contain one, it is either
146 * a member or an overloaded function.
147 */
148 while (c[i] && strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
149 i++;
150 if (c[i]) {
151 /* Advance to first non-underscore */
152 while (c[i+2] == '_')
153 i++;
154 }
155 if (strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) == 0) {
156 /* Copy the simple name */
157 s = napp_String(s, c, i);
158 /* Process the signature */
159 c = second(c+i);
160 (void) mutex_unlock(&mlock);
161 return (c);
162 } else {
163 c = hold;
164 (void) mutex_unlock(&mlock);
165 return (c);
166 }
167 } else {
168 const char *x;
169 int oplen;
170
171 c += 2;
172
173 /*
174 * For automatic variables, or internal static
175 * variables, a __(number) is prepended to the
176 * name. If this is encountered, strip this off
177 * and return.
178 */
179 if (isdigit(*c)) {
180 while (isdigit(*c))
181 c++;
182 (void) mutex_unlock(&mlock);
183 return (c);
184 }
185
186 /*
187 * Handle operator functions -- this
188 * automatically calls second, since
189 * all operator functions are overloaded.
190 */
191 x = findop(c, &oplen);
192 if (x != NULL) {
193 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_1));
194 s = app_String(s, x);
195 c += oplen;
196 c = second(c);
197 (void) mutex_unlock(&mlock);
198 return (c);
199 }
200
201 /*
202 * Operator cast does not fit the mould
203 * of the other operators. Its type name
204 * is encoded. The cast function must
205 * take a void as an argument.
206 */
207 if (strncmp(c, MSG_ORIG(MSG_STR_OP), 2) == 0) {
208 int r;
209 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_2));
210 c += 2;
211 r = demangle_doarg(&s, c);
212 if (r < 0) {
213 c = hold;
214 (void) mutex_unlock(&mlock);
215 return (c);
216 }
217 c += r;
218 c = second(c);
219 (void) mutex_unlock(&mlock);
220 return (c);
221 }
222
223 /*
224 * Constructors and Destructors are also
225 * a special case of operator name. Note
226 * that the destructor, while overloaded,
227 * must always take the same arguments --
228 * none.
229 */
230 if ((*c == 'c' || *c == 'd') &&
231 strncmp(c+1, MSG_ORIG(MSG_STR_TDBLUNDBAR), 3) == 0) {
232 int n;
233 char *c2 = c+2;
234 char cx = c[0];
235 c += 4;
236 n = getint(&c);
237 if (n == 0) {
238 c = hold;
239 (void) mutex_unlock(&mlock);
240 return (c);
241 }
242 s = napp_String(s, c, n);
243 if (cx == 'd')
244 s = prep_String(MSG_ORIG(MSG_STR_TILDE), s);
245 c = second(c2);
246 (void) mutex_unlock(&mlock);
247 return (c);
248 }
249 c = hold;
250 (void) mutex_unlock(&mlock);
251 return (c);
252 }
253 }
254