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