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