xref: /onnv-gate/usr/src/cmd/sgs/libelf/misc/args.c (revision 0:68f95e015346)
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