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 <stdlib.h>
33 #include <string.h>
34 #include "elf_dem.h"
35 #include "String.h"
36 #include "msg.h"
37
38 /* This structure is used to keep
39 * track of pointers to argument
40 * descriptions in the mangled string.
41 * This is needed for N and T encodings
42 * to work.
43 */
44 typedef struct {
45 char *list[10];
46 int pos;
47 } Place;
48
49 static Place here;
50
51 /* Strings and flags needed by the argument demangles. The declarator
52 * is built up in ptr. Type modifiers are held in the flag fields.
53 * The type itself is passed in separately.
54 */
55 typedef struct {
56 String *ptr;
57 int Sign,Uns,Cons,Vol;
58 } Arg_Remem;
59
60 /* initialize Arg_Remem */
61 static void
mkar(Arg_Remem * r)62 mkar(Arg_Remem *r)
63 {
64 r->ptr = mk_String((String *)0);
65 r->Sign = r->Uns = r->Cons = r->Vol = 0;
66 }
67
68 /* free data for Arg_Remem */
69 static void
delar(Arg_Remem * r)70 delar(Arg_Remem *r)
71 {
72 free_String(r->ptr);
73 }
74
75 /* This routine formats a single argument
76 * on the buffer sptr.
77 * c is the type or class name, n is its length.
78 */
79 static void
nsetarg(String ** sptr,Arg_Remem * r,const char * c,int n)80 nsetarg(String ** sptr, Arg_Remem * r, const char * c, int n)
81 {
82 r->ptr = nprep_String(c, r->ptr, n);
83 if(r->Cons)
84 r->ptr = prep_String(MSG_ORIG(MSG_STR_CONST_1), r->ptr);
85 if(r->Vol)
86 r->ptr = prep_String(MSG_ORIG(MSG_STR_VOLATILE_1), r->ptr);
87 if(r->Uns)
88 r->ptr = prep_String(MSG_ORIG(MSG_STR_UNSIGNED), r->ptr);
89 else if(r->Sign)
90 r->ptr = prep_String(MSG_ORIG(MSG_STR_SIGNED), r->ptr);
91 *sptr = app_String(*sptr,PTR(r->ptr));
92 delar(r);
93 }
94
95 /* This routine formats a single argument
96 * on the buffer sptr.
97 * c is the null terminated type or class name.
98 */
99 static void
setarg(String ** sptr,Arg_Remem * r,const char * c)100 setarg(String ** sptr, Arg_Remem * r, const char * c)
101 {
102 nsetarg(sptr, r, c, ID_NAME_MAX);
103 }
104
105
106 /* Demangle a single function argument.
107 * Returns the number of characters processed from c.
108 */
109 int
demangle_doarg(String ** sptr,char * c)110 demangle_doarg(String **sptr, char *c)
111 {
112 int i;
113 Arg_Remem ar;
114 mkar(&ar);
115
116 if(here.pos < 10 && here.pos >= 0)
117 here.list[here.pos++] = c;
118
119 for(i=0;c[i];i++) {
120 /* Loop until you find a type.
121 Then call setarg and return.
122 */
123 switch(c[i]) {
124
125 case 'T':
126 {
127 Place tmp;
128 tmp = here;
129 here.pos = c[1] - '1';
130 if(here.pos < 0 || here.pos >= tmp.pos-1) {
131 delar(&ar);
132 return -1;
133 }
134 (void) demangle_doarg(sptr,here.list[here.pos]);
135 here = tmp;
136 delar(&ar);
137 return 2;
138 }
139 case 'N':
140 {
141 Place tmp;
142 int cycles,pos;
143 cycles = c[1] - '0'; pos = c[2] - '1';
144 here.pos += cycles - 1;
145 tmp = here;
146 if(cycles <= 1 || cycles > 9 || pos < 0 || pos >= tmp.pos-1) {
147 delar(&ar);
148 return -1;
149 }
150 while(cycles--) {
151 here = tmp;
152 here.pos = pos;
153 (void) demangle_doarg(sptr,here.list[here.pos]);
154 (*sptr) = app_String(*sptr,
155 MSG_ORIG(MSG_STR_COMMA));
156 }
157 *sptr = trunc_String(*sptr, 1);
158 here = tmp;
159 delar(&ar);
160 return 3;
161 }
162
163 /* Qualifiers to type names */
164 case 'S':
165 ar.Sign = 1;
166 break;
167 case 'U':
168 ar.Uns = 1;
169 break;
170 case 'C':
171 ar.Cons = 1;
172 break;
173 case 'V':
174 ar.Vol = 1;
175 break;
176
177 /* Pointers, references, and Member Pointers */
178 case 'P':
179 case 'R':
180 case 'M':
181 if(ar.Cons) {
182 ar.ptr = prep_String(MSG_ORIG(MSG_STR_CONST_2),
183 ar.ptr);
184 ar.Cons = 0;
185 }
186 if(ar.Vol) {
187 ar.ptr =
188 prep_String(MSG_ORIG(MSG_STR_VOLATILE_2),
189 ar.ptr);
190 ar.Vol = 0;
191 }
192 if(c[i] == 'P')
193 ar.ptr = prep_String(MSG_ORIG(MSG_STR_STAR),
194 ar.ptr);
195 else if(c[i] == 'R')
196 ar.ptr = prep_String(MSG_ORIG(MSG_STR_AMP),
197 ar.ptr);
198 else {
199 int cnt = 0;
200 char *s;
201 ar.ptr =
202 prep_String(MSG_ORIG(MSG_STR_DBLCOLSTAR),
203 ar.ptr);
204 /* Skip over the 'M' */
205 i++;
206 cnt = strtol(c+i, &s, 10);
207 i = s - c;
208 ar.ptr = nprep_String(c+i,ar.ptr,cnt);
209 ar.ptr = prep_String(MSG_ORIG(MSG_STR_SPACE),
210 ar.ptr);
211 i += cnt;
212 /* The loop increments i */
213 i--;
214 }
215 break;
216
217 /* Demangle for basic built-in types */
218 case 'i':
219 setarg(sptr, &ar, MSG_ORIG(MSG_STR_INT));
220 return i + 1;
221 case 'c':
222 setarg(sptr, &ar, MSG_ORIG(MSG_STR_CHAR));
223 return i + 1;
224 case 's':
225 setarg(sptr, &ar, MSG_ORIG(MSG_STR_SHORT));
226 return i + 1;
227 case 'l':
228 setarg(sptr, &ar, MSG_ORIG(MSG_STR_LONG));
229 return i + 1;
230 case 'f':
231 setarg(sptr, &ar, MSG_ORIG(MSG_STR_FLOAT));
232 return i + 1;
233 case 'd':
234 setarg(sptr, &ar, MSG_ORIG(MSG_STR_DOUBLE));
235 return i + 1;
236 case 'r':
237 setarg(sptr, &ar, MSG_ORIG(MSG_STR_LONGDOUBLE));
238 return i + 1;
239
240 /* Class encodings */
241 case '1': case '2': case '3':
242 case '4': case '5': case '6':
243 case '7': case '8': case '9':
244 {
245 int cnt = 0;
246 char *s;
247 cnt = strtol(c+i, &s, 10);
248 i = s - c;
249 if ((int) strlen(c+i) < cnt) {
250 delar(&ar);
251 return -1;
252 }
253 nsetarg(sptr,&ar,c+i,cnt);
254 return i+cnt;
255 }
256
257 /* Ellipsis and void */
258 case 'e':
259 setarg(sptr, &ar, MSG_ORIG(MSG_STR_ELIPSE));
260 return i + 1;
261 case 'v':
262 setarg(sptr, &ar, MSG_ORIG(MSG_STR_VOID));
263 return i + 1;
264
265 /* Arrays */
266 case 'A':
267 if(*PTR(ar.ptr)) {
268 ar.ptr = prep_String(MSG_ORIG(MSG_STR_OPENPAR),
269 ar.ptr);
270 ar.ptr = app_String(ar.ptr,
271 MSG_ORIG(MSG_STR_CLOSEPAR));
272 }
273 ar.ptr = app_String(ar.ptr, MSG_ORIG(MSG_STR_OPENBRAK));
274 {
275 int cnt = 0;
276 i++;
277 while(isdigit(c[i+cnt]))
278 cnt++;
279 ar.ptr = napp_String(ar.ptr,c+i,cnt);
280 i += cnt;
281 if(c[i] != '_') {
282 delar(&ar);
283 return -1;
284 }
285 }
286 ar.ptr = app_String(ar.ptr,
287 MSG_ORIG(MSG_STR_CLOSEBRAK));
288 break;
289
290 /* Functions
291 * This will always be called as a pointer
292 * to a function.
293 */
294 case 'F':
295 ar.ptr = prep_String(MSG_ORIG(MSG_STR_OPENPAR), ar.ptr);
296 ar.ptr = app_String(ar.ptr, MSG_ORIG(MSG_STR_CLOSEPAR));
297 {
298 Place tmp;
299 tmp = here;
300 i++;
301 i += demangle_doargs(&ar.ptr,c+i);
302 if(c[i] != '_') {
303 delar(&ar);
304 return -1;
305 }
306 here = tmp;
307 }
308 break;
309
310 /* Needed when this is called to demangle
311 * an argument of a pointer to a function.
312 */
313 case '_':
314 delar(&ar);
315 return 0;
316
317 default:
318 delar(&ar);
319 return -1;
320 }
321 }
322
323 /* Did the argument list terminate properly? */
324 {
325 int rc = 0;
326 if(*PTR(ar.ptr) || ar.Uns || ar.Sign || ar.Cons || ar.Vol)
327 rc = -1;
328 delar(&ar);
329 return rc;
330 }
331 }
332
333 /* This function is called to demangle
334 * an argument list.
335 * Returns the number of characters processed from c.
336 */
337 int
demangle_doargs(String ** sptr,char * c)338 demangle_doargs(String **sptr, char *c)
339 {
340 int i = 0, n = 0;
341 here.pos = 0;
342
343 *sptr = app_String(*sptr,MSG_ORIG(MSG_STR_OPENPAR));
344 while (*c && (i = demangle_doarg(sptr,c)) > 0) {
345 c += i;
346 n += i;
347 (*sptr) = app_String(*sptr,(*c && *c == 'e') ?
348 MSG_ORIG(MSG_STR_SPACE) : MSG_ORIG(MSG_STR_COMMA));
349 }
350
351 if(i < 0)
352 return -1;
353
354 *sptr = app_String(trunc_String(*sptr, 1), MSG_ORIG(MSG_STR_CLOSEPAR));
355
356 return n;
357 }
358